我需要实现一个利用任意包进行计算的多处理池。为此,我使用的是Python和joblib 0.9.0。这段代码基本上就是我想要的结构。
import numpy as np
from joblib import pool
def someComputation(x):
return np.interp(x, [-1, 1], [-1, 1])
if __name__ == '__main__':
some_set_of_numbers = [-1,-0.5,0,0.5,1]
the_pool = pool.Pool(processes=2)
solutions = [the_pool.apply_async(someComputation, (x,)) for x in some_set_of_numbers]
print(solutions[0].get())
在运行 Anaconda 4.3.1 Python 3.6.0(以及带有虚拟环境 3.5 和 3.4)的 Windows 10 和 Red Hat Enterprise Linux 上,我得到"np"从未被传递到引发错误的 someComputing() 函数中
File "C:Anaconda3libsite-packagesmultiprocessing_on_dillpool.py", line 608, in get
raise self._value
NameError: name 'np' is not defined
但是,在我的运行 Python 3.5 和相同 joblib 的 Mac OS X 10.11.6 上,我得到了具有完全相同代码的预期输出"-1"。这个问题本质上是相同的,但它处理的是悲哀而不是 joblib。一般答案是在函数中包含 numpy import 语句
from joblib import pool
def someComputation(x):
import numpy as np
return np.interp(x, [-1, 1], [-1, 1])
if __name__ == '__main__':
some_set_of_numbers = [-1,-0.5,0,0.5,1]
the_pool = pool.Pool(processes=2)
solutions = [the_pool.apply_async(someComputation, (x,)) for x in some_set_of_numbers]
print(solutions[0].get())
这解决了Windows和Linux机器上的问题,它们现在按预期输出"-1",但这个解决方案似乎很笨拙。有什么理由为什么第一段代码可以在Mac上运行,而不是Windows或Linux?我最终需要在 Linux 机器上运行此代码,那么是否有任何修复不包括将 import 语句放入函数内部?
编辑:
经过进一步调查,我发现了几年前提出的一种旧解决方法,该解决方法似乎是导致该问题的原因。在 joblib/pool.py 中,我将第 44 行从
from multiprocessing.pool import Pool
自
from multiprocessing_on_dill.pool import Pool
支持任意函数的酸洗。出于某种原因,此更改是真正导致Windows和Linux问题的原因,但是Mac机器运行良好。使用多处理而不是multiprocessing_on_dill解决了上述问题,但代码不适用于我的大多数情况,因为它们无法被腌制。
我不确定确切的问题是什么,但似乎将全局范围转移到运行任务的子进程存在一些问题。通过将名称np
绑定为函数参数,可以避免名称错误:
def someComputation(x, np=np):
return np.interp(x, [-1, 1], [-1, 1])
这样做的优点是不需要在每次运行函数时都调用导入机制。名称np
将在模块加载期间首次计算函数时绑定到函数。