将 sympy lambda 传递给多处理.池地图



我想并行执行一个sympy lambda函数。 我不知道:

  • 为什么它并行工作,尽管它是一个 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之前可以挑选对象并使用Pool.map,以及为什么它在调用后失败。 当你取消注释lambdify中的行时,你不会将属性添加到类中,并且Mult对象在调用lambdify后仍然可以被酸洗。

虽然我还没有完全探索这一点,但我只想记录在案的是,当使用 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]

相关内容

  • 没有找到相关文章

最新更新