多处理占用内存

时间:2018-10-08 11:20:34

标签: python multiprocessing

我正在尝试利用python中的多重处理来处理非常大的数据帧。实际上,我已经注意到,当我运行以下代码时,内存消耗正在增加。 在代码中,数据帧(df)在所有进程之间共享,并且每个进程都使用它根据一些过滤器从大型df中提取subDF。大df包含大约600万条记录。

def prob(optimalK, mapping_dictionary,df,url):
  subDF = df.loc[df['URL'] == url]
  tmp_c = 0 * optimalK;
  mapping_dictionary[url] = tmp_c

def grouper(n, iterable, padvalue=None):
  return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)

if __name__ == '__main__':
   .............
   uniqueURLs = df.URL.unique();
   manager = Manager()
   mapping_dictionary=manager.dict()
   numCores = multiprocessing.cpu_count()
   print(numCores)
   pool = Pool(processes=numCores)

   for chunk in grouper(1000, uniqueURLs):
     print("Start Processing 1000 .... ");
     func = partial(prob, optimalK, mapping_dictionary,df)
     pool.map(func, chunk)
     print("End Processing 1000.... ");

   pool.close()
   pool.join()

有趣的是,我注意到真正导致内存消耗的原因是prob函数中的这一行-> subDF = df.loc [df ['URL'] == url]

我不确定.loc为什么会增加这么多的内存消耗。有人可以建议一种更有效的方法来实现.loc的相同目的,以及如何使我的代码运行得更快....

1 个答案:

答案 0 :(得分:1)

不幸的是,Python存在GIL问题(您可以通过Google来解决)。简而言之,这意味着没有两个Python线程可以同时处理数据结构。它只是使实现Python解释器的方式更简单,更健壮。

因此,解决方案通常是使用多个进程而不是线程。

但是,使用进程的缺点是它们共享内存(即使您这样称呼)。如果应该使用相同的数据 ,那么他们都需要单独的副本。

这特别意味着两件事:①内存已满(如您所注意到),并且②在一个进程中写入不会更改另一进程的数据结构。

因此,通常我会建议切换到线程(它们确实共享数据结构)来解决该问题,但是如开头所述,由于GIL问题,几个线程通常不会加快速度< / em>在Python中。相反,它们用于实现对各种源的反应性或用于实现需要并行性的算法。

因此,在您的情况下,如果可以的话,我建议忍受内存消耗或切换到另一种语言,或者搜索是否可以找到一个能立即满足您需要的Python模块(在内部使用线程或更聪明的子处理。

但是,如果由于大量网络流量(将大量查询发送到各种服务器)而使您的工作花费很长时间并且需要加快速度,那么使用线程代替子进程可能是您的理想解决方案,因为网络流量意味着在等待网络运行期间,其他线程可以很好地运行。