[英]Passing sympy lambda to multiprocessing.Pool.map
我想并行执行一个 sympy lambda 函数。 我不知道:
lambdify
的第一个返回的注释,为什么它会起作用显然,降价预处理器需要在代码上方一行文本,所以这是代码:
from multiprocessing import Pool
import sympy
from sympy.abc import x
def f(m):
return m.lambdify()(1)
class Mult():
def lambdify(self):
# return sympy.lambdify(x, 2*x, 'numpy')
self._lambdify = sympy.lambdify(x, 2 * x, 'numpy')
return self._lambdify
if __name__ == '__main__':
with Pool() as pool:
m = Mult()
print(pool.map(f, [m]))
print(pool.map(f, [m]))
print(f(m))
print(pool.map(f, [m]))
它打印:
[2]
[2]
2
PicklingError: Can't pickle <function <lambda> at 0x000000000DF0D048>: attribute lookup <lambda> on numpy failed
(我削减了追溯)
如果我取消注释,它会正常工作:
[2]
[2]
2
[2]
我只在 Windows 上进行了测试,它与 'numexpr' 而不是 'numpy' 的工作方式完全相同。
对象Mult
在创建时没有字段。 因此,它可以使用常备pickle
库进行腌制。 然后,当您调用lambdify
,您将_lambdify
属性添加到包含无法腌制的lambda
表达式的对象。 这会导致map
功能失败
这解释了为什么在调用lambdify
之前您可以pickle 对象并使用Pool.map
以及为什么它在调用后失败。 当您取消对lambdify
的行进行lambdify
,您不会将该属性添加到类中,并且在调用lambdify
后仍然可以腌制Mult
对象。
虽然我还没有完全探索这个,但我只是想记录一下,当使用 loky 而不是 multiprocessing 时,同一个例子工作得很好:
from loky import get_reusable_executor
import sympy
from sympy.abc import x
def f(m):
return m.lambdify()(1)
class Mult():
def lambdify(self):
# return sympy.lambdify(x, 2*x, 'numpy')
self._lambdify = sympy.lambdify(x, 2 * x, 'numpy')
return self._lambdify
executor = get_reusable_executor()
m = Mult()
print('pool.map(f, [m])', list(executor.map(f, [m])))
print('pool.map(f, [m])', list(executor.map(f, [m])))
print('f(m)', f(m))
print('pool.map(f, [m])', list(executor.map(f, [m])))
带输出
pool.map(f, [m]) [2]
pool.map(f, [m]) [2]
f(m) 2
pool.map(f, [m]) [2]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.