IPython并行负载均衡视图的GIL
我使用Ipython.parallel中的负载均衡视图来对一个可迭代对象调用一个函数,也就是这样:
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会不会造成什么问题呢?
1 个回答
4
函数调用另一个函数会不会影响并行执行?也就是说,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__
是引擎上的交互命名空间)。你可以通过确保func
和func2
在引擎上被定义来解决这个问题:
rc[:].push(dict(func=func, func2=func2))
到那时,你的map
应该会按预期工作。
如果你指示IPython使用增强的序列化库dill,那么就能更接近于不需要手动发送引用,但这并不能覆盖所有情况。