Python 多进程的 map 函数出现错误。

5
我有一个简单的多进程示例正在尝试创建。普通的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

腌制错误?这具体是什么意思?
1个回答

6
Pool.map的参数必须是可pickle序列化的。模块级别的函数是可pickle的, 但partial(f, y=y)在模块级别未定义,因此不可pickle。
这里有一个简单的解决方法:
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))

产生结果[11, 14, 19]。但需要注意的是,要获得这个结果,f必须使用def而不是lambda进行定义。我认为这是因为pickle依赖于“完全限定”的名称引用来查找函数对象值。


抱歉,我不太明白——我有另一个几乎完全相同的脚本,使用 partial,它确实有效,而这个却不行。什么是在模块级别定义的内容?啊,看到您的更新了——是的,def 与 lambda 正是一个有效,另一个无效的区别。谢谢! - Mittenchops

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接