与多处理并行填写字典

Gáb*_*dős 6 python 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]
Run Code Online (Sandbox Code Playgroud)

但是,这个解决方案需要花费相同的时间,就像我只是迭代peptide_kd.keys()DataFrames逐一填充一样.为什么会这样?有没有办法并行填写所需的dicts并实际上提高速度?我在48核HPC上运行它.

Mik*_*rns 8

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

此解决方案不会dict跨进程共享要共享的副本,因此可以减少部分开销.对于像a这样的大型物体pandas.DataFrame,与简单操作的成本相比,它可能很重要x**2.类似地,产生a Process可能需要一些时间,并且您可以通过使用线程(即multiprocess.dummy代替multiprocess您最初发布的解决方案或我的上面的代码)来更快地(对于轻量级对象)执行上述操作.

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