Python多处理内存使用情况

Fab*_*aze 10 python linux memory-management multiprocessing

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

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()
Run Code Online (Sandbox Code Playgroud)

真正的代码(特别是writeOutput())要复杂得多.writeOutput()仅使用它作为参数的这些值(意味着它不引用data)

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

子进程不需要以loadHugeData()任何方式访问,读取或修改加载的数据.子流程只需要使用主流程发送它的内容res_queue.这引出了我的问题和疑问.

在我看来,子流程将它放在庞大数据集的副本上(当检查内存使用情况时top).这是真的?如果是这样,我怎么能避免id(基本上使用双内存)?

我使用的是Python 2.6,程序在linux上运行.

ise*_*dev 22

multiprocessing模块实际上基于fork系统调用,该调用创建当前进程的副本.由于您在fork创建(或创建multiprocessing.Process)之前加载了大量数据,因此子进程会继承数据的副本.

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

您可以multiprocessing.Process在加载大量数据之前通过调用来避免这种情况.然后,当您在父进程中加载​​数据时,额外的内存分配将不会反映在子进程中.

  • 另请注意,每个Python对象都包含一个引用计数,只要访问该对象就会对其进行修改.因此,只需读取数据结构就可以导致COW复制. (8认同)
  • 做得比我快。Linux 是 COW,所以父进程写入数据的那一刻,数据将被复制。如果父进程只读取数据,那么将只有一个数据实例 **BUT** top(我几乎可以肯定)将数据显示为属于两个进程。meminfo 应该提供更准确的内存使用数字。 (3认同)
  • Ty的答案.在加载数据之前调用`multiprocessing.Process`似乎已经解决了这个问题.我会研究`meminfo`. (3认同)