与多处理并行填充字典
Fill up a dictionary in parallel with multiprocessing
昨天我问了一个问题:
我得到了很好的答案,我实施了我标记为正确的答案中提到的解决方案。
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 上。
您在 (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
.
昨天我问了一个问题:
我得到了很好的答案,我实施了我标记为正确的答案中提到的解决方案。
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 上。
您在 (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
.