我想并行执行一个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'。
答案 0 :(得分:2)
对象Mult
在创建时没有字段。因此可以使用库存pickle
库进行酸洗。然后,当您调用lambdify
时,会向包含_lambdify
表达式的对象添加lambda
属性,该表达式无法进行腌制。这会导致map
函数
这解释了为什么在调用lambdify
之前你可以挑选对象并使用Pool.map
以及为什么它在通话后失败。
取消注释lambdify
中的行时,不会将该属性添加到类中,并且在调用Mult
后仍可以对lambdify
对象进行pickle。
答案 1 :(得分:1)
尽管我还没有完全探索这一点,但我只是想记录一下,使用loky而不是多处理时,相同的示例也能很好地工作:
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]