用pandas并行读取CSV会造成巨大的内存泄漏/进程僵尸

时间:2017-04-19 03:22:09

标签: python python-3.x csv pandas memory-leaks

我正在并行读取+1000个〜200Mb CSV并使用pandas保存修改后的CSV。这会产生许多僵尸进程,累积到+ 128Gb的RAM,从而破坏性能。

    csv_data = []
    c = zip(a, b)
    process_pool = Pool(cpu_count())
    for name_and_index in process_pool.starmap(load_and_process_csv, c):
        csv_data.append(name_and_index)
    process_pool.terminate()
    process_pool.close()
    process_pool.join()

这是我目前的解决方案。在您处理超过80个CSV之前,它似乎不会导致问题。

PS:即使游泳池完成了〜仍然占用了96Gb的RAM,你可以看到python进程占用RAM但没有做任何事情也没有被破坏。此外,我确切地知道池正在执行的功能正在运行完成。

我希望它具有足够的描述性。

2 个答案:

答案 0 :(得分:4)

Python的multiprocessing模块是基于流程的。所以你有很多过程是很自然的。

更糟糕的是,这些进程不共享内存,而是通过pickling/unpickling进行通信。因此,如果需要在处理之间传输大数据,它们会非常慢,这就发生在这里。

对于这种情况,由于处理与I/O相关,如果threading是瓶颈,则使用I/O模块的多线程可能会有更好的性能。线程共享内存,但它们也“共享”1个CPU内核,所以不能保证运行得更快,你应该尝试一下。

更新:如果多线程无效,则您没有多少选项。因为这种情况完全违背了Python并行处理架构的关键弱点。您可能想尝试dask(并行pandas):http://dask.readthedocs.io/en/latest/

答案 1 :(得分:0)

  

问题

process_pool = Pool(48)
for name_and_index in process_pool.starmap(load_and_process_csv, c):

我尝试了您的示例代码,但我无法启动更多一个 process。 您的代码看起来非同寻常,除此Pool(48)之外,processes也很多。 要开始超过一个 process,我必须更改为

process_pool = Pool(2)
c_list = [(a,b), (a,b)]
csv_data = process_pool.starmap(load_and_process_csv, c_list)
  

Python»3.6.1文档 multiprocessing.pool.Pool.starmap
     starmap(func,iterable [,chunksize])
      与map()类似,只是迭代的元素应该是作为参数解包的迭代。       因此,[(1,2),(3,4)]的可迭代导致[func(1,2),func(3,4)]。

由于我对(a, b)一无所知,请仔细检查以下内容是否适用于您。

  

Python»3.6.1文档 multiprocessing.html#all-start-methods
      明确地将资源传递给子进程       在使用fork start方法的Unix上,子进程可以使用全局资源在父进程中创建的共享资源。但是,最好将对象作为参数传递给子进程的构造函数。       除了使代码(可能)与Windows和其他启动方法兼容之外,这还确保只要子进程仍处于活动状态,对象就不会在父进程中进行垃圾回收。如果在父进程中对对象进行垃圾回收时释放某些资源,这可能很重要。

  

<强>问题
  我确切地知道池正在执行的功能正在运行完成。

     

终止()

Stops the worker processes immediately without completing outstanding work.  

请解释一下,为什么打电话给process_pool.terminate()