我正在尝试创建一个简单的多处理示例。普通的map()函数版本可以工作,但当更改为Pool.map时,我得到了一个奇怪的错误:
from multiprocessing import Pool
from functools import partial
x = [1,2,3]
y = 10
f = lambda x,y: x**2+y
# ordinary map works:
map(partial(f,y=y),x)
# [11, 14, 19]
# multiprocessing map does not
p = Pool(4)
p.map(partial(f, y=y), x)
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 504, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 319, in _handle_tasks
put(task)
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
酸洗错误?这到底是什么?
Pool.map
的参数必须是可拾取的。模块级函数是可拾取的,但partial(f, y=y)
未在模块级定义,因此不可拾取。
有一个简单的解决方法:
def g(x, y=y):
return f(x, y)
p.map(g, x)
使用functools.partial
生成的函数过去是不可拾取的。但是,使用Python2.7或更高版本,您也可以使用functools.partial:定义g
(在模块级别)
import multiprocessing as mp
import functools
def f(x, y):
return x**2 + y
x = [1,2,3]
y = 10
g = functools.partial(f, y=y)
if __name__ == '__main__':
p = mp.Pool()
print(p.map(g, x))
得到CCD_ 5。但要得到这个结果,必须用def
而不是lambda
定义f
。我认为这是因为pickle
依赖于"完全限定"的名称引用来查找函数对象值。