【问题标题】:Fill up a dictionary in parallel with multiprocessing与多处理并行填充字典
【发布时间】:2016-11-18 11:54:40
【问题描述】:

昨天我问了一个问题:Reading data in parallel with multiprocess

我得到了很好的答案,并且我实施了我标记为正确的答案中提到的解决方案。

def read_energies(motif):
    os.chdir("blabla/working_directory")
    complx_ener = pd.DataFrame()
    # complex function to fill that dataframe 
    lig_ener = pd.DataFrame()
    # complex function to fill that dataframe 
    return motif, complx_ener, lig_ener

COMPLEX_ENERGIS = {}
LIGAND_ENERGIES = {}
p = multiprocessing.Pool(processes=CPU)
for x in p.imap_unordered(read_energies, peptide_kd.keys()):
    COMPLEX_ENERGIS[x[0]] = x[1]
    LIGAND_ENERGIES[x[0]] = x[2]

但是,此解决方案所花费的时间与我仅遍历 peptide_kd.keys() 并一一填充 DataFrames 所花费的时间相同。为什么呢?有没有办法并行填充所需的字典并实际提高速度?我在 48 核 HPC 上运行它。

【问题讨论】:

  • 可能是使用多处理的开销比做复杂函数处理的开销大。也许让read_energies() 每次处理一个可变数量的数据帧可以让你调整到合适的程度,如果它变得有利的话。

标签: python multiprocess


【解决方案1】:

在 (1) 启动每个进程和 (2) 必须在多个进程之间复制 pandas.DataFrame (等等)时会产生大量开销。如果您只需要并行填充dict,我建议使用共享内存dict。如果没有键会被覆盖,那么这很容易,您不必担心锁。

(注意我在下面使用multiprocess,它是multiprocessing 的一个分支——但只有这样我才能从解释器中演示,否则,您必须从__main__ 执行以下操作)。

>>> from multiprocess import Process, Manager
>>> 
>>> def f(d, x):
...   d[x] = x**2
... 
>>> manager = Manager()
>>> d = manager.dict()
>>> job = [Process(target=f, args=(d, i)) for i in range(5)]
>>> _ = [p.start() for p in job]
>>> _ = [p.join() for p in job]
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

此解决方案不会复制dict 以跨进程共享,因此会减少部分开销。对于像pandas.DataFrame 这样的大对象,与像x**2 这样的简单操作的成本相比,它可能是显着的。同样,生成Process 可能需要一些时间,并且您也许可以通过使用线程(即来自multiprocess.dummy 而不是multiprocess 对于您最初发布的解决方案或我上面的解决方案)更快地完成上述操作(对于轻量级对象) )。

如果您确实需要共享DataFrames(正如您的代码所建议的而不是问题所要求的那样),您可以通过创建共享内存numpy.ndarray 来实现。

【讨论】:

  • 感谢您的回答!我现在要试试这个,但首先我想问一些问题。我不明白提到的shared 数据帧(我猜是变量)之间的区别。为什么我的代码暗示我使用共享 DataFrame?我想要并行执行的工作就像您描述的那样,填写字典,然后以不同的方式使用它(读取其中的数据),但不要更改其中的任何内容。
  • 我说您可能会查看共享内存数组的原因是您从每个 Process 返回两个 DataFrame 实例。但是,很难指出您是否需要这样做,因为您只提供了元代码。
  • 哦,我明白了。我需要两个DataFrames。退回其中两个有问题吗?分两个单独的步骤执行此操作会更容易吗?
  • 不,两者都退货没有问题,只是价格昂贵。但是,您可以创建两个不返回的共享内存数组……然后相应地填写DataFrame.values
  • 我只想再次感谢您的出色回答,我花了一些时间才完全理解它(我是一名生物工程师,我现在正在学习高效编码)但我学到了很多由此。很遗憾我不能给你更多的支持:)
猜你喜欢
  • 2020-09-19
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 2016-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
相关资源
最近更新 更多