繁体   English   中英

将 sympy lambda 传递给 multiprocessing.Pool.map

[英]Passing sympy lambda to multiprocessing.Pool.map

我想并行执行一个 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之前您可以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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM