我有一个包含列表的字典my_dict
,以及一个带有很多键的可迭代keys
,我想在其上运行一个函数:
for key in keys:
if key in my_dict:
my_dict[key].append(my_fun(key, params))
else:
my_dict[key] = [my_fun(key, params)]
my_fun
很慢。我如何平行化这个循环?
只是:
import multiprocessing
def _process_key(key):
if key in my_dict:
my_dict[key].append(my_fun(key, params))
else:
my_dict[key] = [my_fun(key, params)]
if __name__ == '__main__':
with Pool(5) as p:
p.map(_process_key, keys)
答案 0 :(得分:2)
dict
位于父内存空间中,因此您需要在那里更新它。 pool.map
遍历worker函数返回的任何内容,因此只需让它以有用的形式返回即可。 collections.defaultdict
是帮助您创建项目的助手,因此您可以
import multiprocessing
import collections
def _process_key(key):
return key, my_fun(key, params)
if __name__ == '__main__':
with Pool(5) as p:
my_dict = collections.defaultdict(list)
for key, val in p.map(_process_key, keys):
my_dict[key].append(val)
答案 1 :(得分:0)
由于GIL,Python不擅长 CPU绑定多线程。如果要加速CPU绑定计算,请使用multiprocessing
。
我会将字典中的键分成尽可能多的列表。然后我将这些列表与原始字典或其相关部分一起传递给子进程(如果值是大对象图)。
子进程将返回部分结果,主进程将合并为单个结果。
对于 I / O绑定的计算,相同的方法可以使用threading
,这可能更快,因为数据将直接在线程之间共享。
以上是非常通用的。我不知道如何最好地划分您的密钥空间以实现均匀负载和最大加速;你必须做实验。