当前位置: 首页 > 面试题库 >

Python多处理内存使用情况

楚勇
2023-03-14
问题内容

我写了一个程序,可以总结如下:

def loadHugeData():
    #load it
    return data

def processHugeData(data, res_queue):
    for item in data:
        #process it
        res_queue.put(result)
    res_queue.put("END")

def writeOutput(outFile, res_queue):
    with open(outFile, 'w') as f
        res=res_queue.get()
        while res!='END':
            f.write(res)
            res=res_queue.get()

res_queue = multiprocessing.Queue()

if __name__ == '__main__':
    data=loadHugeData()
    p = multiprocessing.Process(target=writeOutput, args=(outFile, res_queue))
    p.start()
    processHugeData(data, res_queue)
    p.join()

实际代码(尤其是writeOutput())要复杂得多。writeOutput()仅使用将其当作参数的这些值(意味着它不引用data

基本上,它将巨大的数据集加载到内存中并进行处理。输出的写操作委托给一个子进程(它实际上写到多个文件中,这需要很多时间)。因此,每次处理一个数据项时,它都会通过res_queue发送到子流程,然后该子流程根据需要将结果写入文件中。

子流程不需要访问,读取或修改loadHugeData()以任何方式加载的数据。子流程只需要使用主流程通过它发送的内容res_queue。这导致我遇到了问题。

在我看来,子流程将其保存在庞大数据集的副本上(使用时检查内存使用情况top)。这是真的?如果是这样,那我该如何避免id(本质上使用双倍内存)?

我正在使用Python 2.6,程序正在Linux上运行。


问题答案:

multiprocessing模块有效地基于fork系统调用,该系统调用创建当前进程的副本。由于您要在之前fork(或创建multiprocessing.Process)加载大量数据,因此子进程将继承数据的副本。

但是,如果您所运行的操作系统实现了COW(写时复制),那么除非您在父进程或子进程(父进程和子进程)中都修改了数据,否则物理内存中实际上只有一个副本。将
共享 相同的物理内存页面,尽管它们位于不同的虚拟地址空间中);即使这样,也只会为更改分配额外的内存(以pagesize增量为单位)。

您可以通过multiprocessing.Process在加载大量数据之前进行调用来避免这种情况。这样,当您在父级中加载数据时,其他内存分配将不会反映在子级进程中。



 类似资料:
  • 程序每天使用的内存在增加。有人能搞清楚是怎么回事吗? 当作业超出运行方法的范围时,内存应该是空闲的,对吗?

  • 问题内容: 当redis达到“最大内存”条件时,它将允许客户端进行读取,但不能进行写入。 当然,这将导致致命错误……有什么方法可以使Rails处理缓存的读或写错误,因此,如果缓存发生问题(可用性,读取,写入等),它将继续以如果缓存设置为“关闭”? 问题答案: 您可以告诉redis在内存已满时要遵守的不同行为。 默认是 也许最好的选择是’volatile-ttl’,并确保所有缓存都包括:expire

  • 我已经读了一些关于我的问题的帖子(比如这篇文章),但没有一篇能解决这个问题。在我的Flask应用程序中,我使用内置在多处理中的Python(在16个物理核心上)并行下载了32-64个图像,如下所示: 下载工作正常,除了内存使用外,速度显著提高。在下载过程中,Python分配了大约100GB的RAM,尽管实际只使用了大约2GB。每个进程分配超过6 gb的RAM,仅用于下载最多4个图像,每个图像的容量

  • 问题内容: 我想在共享内存中使用一个numpy数组,以便与多处理模块一起使用。困难是像numpy数组一样使用它,而不仅仅是ctypes数组。 这将产生如下输出: 可以ctypes方式访问该数组,例如arr[i]说得通。但是,它不是一个numpy数组,因此我无法执行,或。我想一个解决方案是将数组转换为数组。但是(除了无法完成这项工作外),我不相信会再共享它。 对于必须解决的常见问题,似乎将有一个标准

  • 问题内容: 我在此处的注释中读到,更改列表时执行切片分配具有更高的内存效率。例如, 应该比 因为前者会替换现有列表中的元素,而后者会创建一个新列表并重新绑定到该新列表,从而将旧列表保留在内存中,直到可以对其进行垃圾回收为止。对两者进行基准测试以提高速度,后者则要快一些: 这就是我所期望的,因为重新绑定变量应该比替换列表中的元素更快。但是,我找不到任何支持内存使用声明的官方文档,也不确定如何进行基准