【问题标题】:Wrapping My Head Around IPython Parallel把我的头绕在 IPython Parallel 上
【发布时间】:2015-01-22 00:03:29
【问题描述】:

我正试图围绕在我的 Python 代码中应用并行计算的基本概念展开思考。我已经阅读了很多关于 IPython 并行的教程;但是,我似乎并不完全理解如何在一些基本的 python 代码中优雅地应用它。例如my_script.py中的demo代码如下:

# imports
import numpy as np
from IPython.parallel import Client

# class definition
class MyClass():
    def do_something(self, x, y):
        return np.sum(x, y)

# some variables
x = [1, 2, 3, 4, 5, 6, 7, 8 ,9, 10]
y = [1, 2, 3, 4, 5, 6, 7, 8 ,9, 10]

# create client and direct view to all engines available
client = Client()
dview = client[:]
dview.block = True

# here is what i'm currently doing to achieve parallelism
dview.execute('import numpy as np')
dview['MyClass'] = MyClass
dview.scatter('x', x)
dview.scatter('y', y)
dview.execute('my = MyClass()')
dview.execute('z = my.do_something(x, y)')
z = dview.gather('z')

我的问题:

  1. 有没有办法在所有命名空间中将 numpy 作为 np 一次而不是两次? (一次在第一个上部导入中,然后在第二次在 execute() 中。

  2. 与第一个问题相同,但针对 MyClass。有没有更优雅的方式将 MyClass 包含在所有命名空间中,而不是显式地将类类型作为变量推送?

  3. 您将如何以最优雅的 pythonic/ipythonic 方式编写上面的代码?

【问题讨论】:

    标签: python parallel-processing ipython


    【解决方案1】:

    我发现将 IPython 视为负责在进程之间移动数据是很有帮助的,但通常不是代码。值得注意的例外是函数(map()apply())。

    问题 1:我认为只导入一次 numpy 是不可能的,因为您的主进程和客户端进程并不相同。对于更具可读性的代码,您可以执行以下操作:

    from IPython.parallel import Client
    
    client = Client()  # create client and direct view to all engines available
    dview = client[:]
    dview.block = True
    
    with dview.sync_imports():  # import on all client processes 
        import numpy  # `import numpy as np` does not work
    
    def f(x , y):
        """ return x**2 + y """
        return numpy.power(x, 2) + y
    
    x = np.arange(5)
    y = 1000 * np.arange(5)
    zz = dview.map(f, x, y) # execute f() in parallel on different clients
    print(zz)  # gives: [0, 1001, 2004, 3009, 4016]
    

    查看IPython manual 为什么import numpy as np 不起作用。

    问题 2:在我看来,我认为最干净的方法是将 MyClass 放在一个单独的文件中,然后像上面的 numpy 一样导入它。原因是并行处理(MyClass)和管理(分发和收集数据)应该分开。可以说,这也是一个品味问题。

    问题 3:您的方法 do_something() 不起作用,因为 np.sum() 汇总了单个数组的元素。所以我假设你想并行计算x[0]+y[0]x[1]+y[1]...。类和并行进程不能很好地协同工作,因为类实例的主要思想是具有状态(以成员变量的形式)并且有状态的函数很难并行化。因此,作为并行化的一般方法,请尝试使用dview.map(),因为它负责将数组拆分为块并将其分发给客户端。它还强制传递的函数没有本地状态。如果你需要在每个进程中都有一个本地状态,请使用问题2的方法。

    【讨论】:

      猜你喜欢
      • 2017-09-27
      • 2017-07-26
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 2016-09-17
      • 1970-01-01
      相关资源
      最近更新 更多