环绕我的头 IPython 平行
Wrapping My Head Around IPython Parallel
我正在努力思考在我的 python 代码中应用并行计算的基本概念。我已经阅读了很多关于 IPython parallel 的教程;但是,我似乎并不完全理解如何在一些基本 python 代码中优雅地应用它。例如下面的演示代码 my_script.py:
# 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')
我的问题:
有没有办法在所有命名空间中将 numpy 作为 np 包含一次而不是在这里包含两次? (一次在第一个上层导入中,然后在 execute() 中第二次。
与第一个问题相同,但针对 MyClass。有没有更优雅的方法将 MyClass 包含在所有命名空间中,而不是显式地将 class 类型作为变量推送?
您将如何以最优雅的方式编写上述代码pythonic/ipythonic?
我发现将 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]
、...
。 类 和并行进程不能很好地协同工作,因为 class 实例的主要思想是具有状态(以成员变量的形式),而有状态函数很难并行化。因此,作为并行化的一般方法,请尝试使用 dview.map()
,因为它负责将数组拆分为块并将其分发给客户端。它还强制传递的函数没有本地状态。如果你需要在每个进程中都有一个本地状态,使用问题2的方法。
我正在努力思考在我的 python 代码中应用并行计算的基本概念。我已经阅读了很多关于 IPython parallel 的教程;但是,我似乎并不完全理解如何在一些基本 python 代码中优雅地应用它。例如下面的演示代码 my_script.py:
# 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')
我的问题:
有没有办法在所有命名空间中将 numpy 作为 np 包含一次而不是在这里包含两次? (一次在第一个上层导入中,然后在 execute() 中第二次。
与第一个问题相同,但针对 MyClass。有没有更优雅的方法将 MyClass 包含在所有命名空间中,而不是显式地将 class 类型作为变量推送?
您将如何以最优雅的方式编写上述代码pythonic/ipythonic?
我发现将 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]
、...
。 类 和并行进程不能很好地协同工作,因为 class 实例的主要思想是具有状态(以成员变量的形式),而有状态函数很难并行化。因此,作为并行化的一般方法,请尝试使用 dview.map()
,因为它负责将数组拆分为块并将其分发给客户端。它还强制传递的函数没有本地状态。如果你需要在每个进程中都有一个本地状态,使用问题2的方法。