我已经编写了一些代码来并行执行一些计算 (joblib) 并使用计算结果更新字典。该代码由调用生成器函数的主函数和并行运行的计算函数组成。计算结果(键值对)由计算函数的每个实例添加到在主函数和市场中创建的字典中作为全局。
下面是我的代码的简化版本,说明了上述过程。
当一切运行时,结果字典 (d_result) 是空的,但它应该已经填充了计算函数生成的结果。为什么会这样?
import numpy as np
from joblib import Parallel, delayed
def do_calc(d, r, pair_index): # function to be run in parallel
data_1 = d[str(r)][pair_index, 1]
data_2 = d[str(r)][pair_index, 2]
result_name = str(data_1) + " ^ " + str(data_2)
result = data_1 ** data_2
d_result[result_name] = result
# d_result.setdefault(result_name, []).append(result) ## same result as above
def compute_indices(d): # generator function
for r in d:
num_pairs = d[str(r)].shape[0]
for pair_index in range(num_pairs):
yield r, pair_index
def process(): # main function
global d_result
d_result = {}
r1 = np.array([['ab', 1, 2], ['vw', 10, 12]], dtype=object)
r2 = np.array([['ac', 1, 3], ['vx', 10, 13]], dtype=object)
r3 = np.array([['ad', 1, 4], ['vy', 10, 14]], dtype=object)
r4 = np.array([['ae', 1, 5], ['vz', 10, 15]], dtype=object)
d = {'r1': r1, 'r2': r2, 'r3': r3, 'r4': r4}
Parallel(n_jobs=4)(delayed(do_calc)(d, r, pair_index) for r, pair_index in (compute_indices)(d))
print(d_result)
process()
最佳答案
很高兴您的程序可以运行。但是我认为您忽略了一些重要的事情,如果您将您的示例用作更大程序的基础,您可能会遇到麻烦。
我扫描了 joblib 的文档,发现它是基于 Python 多处理模块构建的。所以 multiprocessing programming guidelines申请。
一开始我想不通为什么你的新程序运行成功而原来的程序运行失败。原因如下(来自上面的链接):“请记住,如果在子进程中运行的代码试图访问全局变量,那么它看到的值(如果有的话)可能与父进程中的值不同Process.start 被调用时的进程。”这是因为至少在概念上,每个子进程都有自己的 Python 解释器副本。在每个子进程中,必须导入该进程使用的代码。如果该代码声明了全局变量,那么这两个进程将拥有这些全局变量的单独副本,即使您阅读代码时看起来并不是那样。所以当你原来程序的子进程往全局的d_result
里放数据的时候,其实和父进程里的d_result
是不同的对象。再次来自文档:“确保新的 Python 解释器可以安全地导入主模块,而不会导致意外的副作用(例如启动新进程)。
例如,在 Windows 下运行以下模块将失败并出现 RuntimeError:
from multiprocessing import Process
def foo():
print 'hello'
p = Process(target=foo)
p.start()
相反,应该使用 if __name__ == '__main__'
来保护程序的入口点。”
因此,在最后一行之前向您的程序(第二个版本)添加一行代码很重要:
if __name__ == "__main__":
process()
如果不这样做,可能会导致一些您不想花时间处理的讨厌的错误。
关于Python,添加 key :value to dictionary in parallelised loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43200878/