填补了并行字典多处理
昨天我问了一个问题: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上运行它。
在(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
做到这一点。
感谢您的回答!我现在要试试这个,但首先我想问一些问题。我不明白所提到的“共享”数据框(我猜想的变量)之间的差异。为什么我的代码暗示我使用共享的DataFrame?我想要并行处理的工作就像你描述的那样,填写一个字典,然后以不同的方式使用它(读取它里面的数据),但不要改变它里面的任何东西。 –
我说你可能会看到共享内存数组的原因是,你从每个'Process'返回两个'DataFrame'实例。但是,很难指出您是否需要这样做,因为您仅提供元代码。 –
哦,我明白了。我需要两个'DataFrames'。返回其中两个是否有问题?分两步做这件事会容易吗? –
这可能是使用多处理的开销大于进行复杂函数处理的开销。也许'read_energies()'每次处理一个可变数字的数据框会让你调整一些事情,直到它变得有利。 – martineau