python - 如何在 IPython.parallel 中使用交互式定义的类?

标签 python parallel-processing ipython ipython-notebook

上下文

在连接到集群的笔记本上的交互式原型(prototype)开发中,我想定义一个在客户端中都可用的类 __main__ session 并在集群引擎节点上进行交互式更新,以便能够通过将此类实例的参数传递给 LoadBalanced View 来移动该类的实例。下面演示了典型的用户 session :

首先设置并行集群环境:

>>> from IPython.parallel import Client
>>> rc = Client()
>>> lview = rc.load_balanced_view()
>>> rc[:]
<DirectView [0, 1, 2]>

在笔记本单元格中,让我们定义我们正在交互式编辑的组件的代码片段:

>>> class MyClass(object):
...     def __init__(self, parameter):
...         self.parameter = parameter
...
...     def update_something(self, some_data):
...         # do something smart here with some_data & internal state
...
...     def compute_something(self, other_data):
...         # do something smart here with other data & internal state
...         return something
...

在下一个单元格中,让我们创建一个脚本来构建此类的实例,然后使用集群环境的负载平衡 View 根据各种输入参数评估我们的组件:

>>> def process(obj, some_data, other_data):
...     obj.update_something(some_data)
...     return obj.compute_something(other_data)
...
>>> tasks = []
>>> some_instances = [MyClass(i) for i in range(10)]
>>> for obj in some_instances:
...    for some_data in data_source_1:
...         for other_data in data_source_2:
...             ar = lview.apply_async(process, obj, some_data, other_data)
...             tasks.append(ar)
...
>>> # wait for computation to end
>>> results = [ar.get() for ar in tasks] 

问题

这显然是行不通的,因为负载平衡 View 的引擎将无法解开作为第一个参数传递给 process 的实例。功能。过程函数定义本身已成功传递,因为我假设 apply_async执行字节码自省(introspection)以对其进行 pickle(通过访问函数的 .code 属性),然后对剩余的参数进行简单的 pickle。

可能的解决方案(对我不起作用)

  • 另一种解决方案是使用 %%px持有类定义的细胞上的细胞魔法 MyClass .但是,这会阻止我在也进行调度的客户端脚本中构建类实例。我需要将单元格内容复制并粘贴到没有 %%px 的其他单元格中magic(或者用 magic 执行单元格两次,而在没有 magic 的情况下执行一次单元格)但是当我仍在迭代开发和评估设置中编辑类的方法时,这是乏味的。

  • 另一种解决方案是将类定义嵌入到 process 中。函数,但我发现这不切实际,因为我想稍后在笔记本中的其他函数中重用该类定义。

  • 或者,我可以停止使用一个类,只使用可以通过将 then 作为第一个参数传递给 apply_async 传递给引擎的函数。 .但是我也不喜欢那样,因为我想以面向对象的方式对我的代码进行原型(prototype)设计,以便以后从笔记本中提取并将生成的类包含在面向对象的库中。 notebook session 用作协作原型(prototype)制作工具,用于在使用 http://nbviewer.ipython.org 的开发人员之间交流想法出版商。

  • 最后的选择是在文件系统上的文件上的 python 模块中编写我的类,然后使用 NFS 等将该文件传送到引擎 PYTHONPATH。这行得通,但阻止我只在笔记本环境中工作,这违背了笔记本中交互式原型(prototype)设计的全部目的。

那么基本上,有没有办法以交互方式定义一个类,然后将其定义传递给引擎?

应该可以使用 inspect.getsource 来 pickle 一个类定义在客户端然后将源发送到引擎并使用 eval内置但不幸的是源代码检查不适用于 DummyMod 中定义的类内置模块:

TypeError: <IPython.core.interactiveshell.DummyMod object at 0x10c2c4e50> is a built-in class

有没有办法改为检查类定义的字节码?

或者是否可以使用 %%px魔术以便在客户端和每个引擎上本地执行单元格的内容?

最佳答案

感谢您提出详细问题(并在 Twitter 上联系我)。

首先,也许它应该被认为是一个错误,你不能只推送类, 因为简单的解决方案应该是

rc[:]['MyClass'] = MyClass

但是 pickling 交互定义的类只会产生一个引用('\x80\x02c__main__\nMyClass\nq\x01.'),给你的 DummyMod AttributeError。 这可能可以在 IPython 的序列化中在内部修复。

但是,关于一个实际可行的解决方案。

将本地执行添加到 %%px 非常简单,只需:

def pxlocal(line, cell):
    ip = get_ipython()
    ip.run_cell_magic("px", line, cell)
    ip.run_cell(cell)
get_ipython().register_magic_function(pxlocal, "cell")

现在你有一个 %%pxlocal 魔法,除了在本地运行单元之外,它还运行 %%px

那么你所要做的就是:

%%pxlocal

class MyClass(object):
    # etc

在任何地方定义你的类。 我将向 %%px 添加一个 --local 标志,因此不需要这个额外的步骤。

一个完整的,有效的 example notebook .

关于python - 如何在 IPython.parallel 中使用交互式定义的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14184621/

相关文章:

tensorflow - 在 Jupyter 中可视化 TensorFlow 图不起作用

python - 如何在 Jupyter Notebook 的引擎上正确导入模块以进行并行处理?

python - 使用python的UDP套接字编程

python - 奥杜 : Acces a column from many2one

python - 为什么我不能在类方法中使用 python 模块 concurrent.futures?

linux - 沙箱允许多个进程打开同一个端口

c++ - Openmp:所有线程由于一个线程的延迟而停止

python - 如何从github有效地将代码导入ipython

python - 使用 skimage 导入过滤器时出现问题

python - 流: How to distribute reinforcement vehicles (RL) vehicles uniformly?