1

我使用来自 Ipython.parallel 的 loadbalancedview 在可迭代对象上调用函数,即

from IPython.parallel import Client
from functools import partial

rc = Client()
lview = rc.load_balanced_view()
lview.block = True

def func(arg0, arg1, arg2):
    return func2(arg0) + arg1 + arg2

def func2(arg0):
    return 2*arg0

answer = lview.map(partial(func, arg1=A, arg2=B), iterable_data)

func 调用 func2 的事实是否使 func 不能并行执行(即 GIL 是否发挥作用?)我假设当您调用 map 时,每个集群节点都会获得 func 的副本,但它们是否也会获得 func2 的副本. 此外,我使用 functools.partial 的事实是否会导致任何问题?

4

1 回答 1

4

func 调用 func2 的事实是否使 func 不能并行执行(即 GIL 是否发挥作用?)

一点也不。GIL 在这里根本不相关,也与 IPython.parallel 中的并行性无关。GIL 仅在每个引擎内或客户端进程本身内协调线程时出现。

我假设当您调用 map 时,每个集群节点都会获得 func 的副本,但它们是否也会获得 func2 的副本。

应该,但这实际上是您的代码会出现问题的地方。IPython 不会自动跟踪闭包和交互式命名空间中的代码依赖关系,因此您将看到:

AttributeError: 'DummyMod' object has no attribute 'func'

这是因为partial(func, arg1=A, arg2=B)包含对 的引用__main__.func,而不是本地func本身的代码。当部分到达引擎时,它被反序列化并被__main__.func请求,但未定义(是引擎上__main__的交互式命名空间)。您可以简单地通过确保在引擎上定义和来解决这个问题:funcfunc2

rc[:].push(dict(func=func, func2=func2))

此时,您的map行为应该符合预期。

如果您指示 IPython 使用增强的酸洗库dill它将更接近不必手动发送引用,但它并不涵盖所有情况。

于 2014-04-06T23:17:50.773 回答