使用分布式群集的Python多处理

时间:2014-11-12 00:02:35

标签: python multiprocessing distributed-computing

我正在寻找一个python包,它不仅可以跨单个计算机中的不同内核进行多处理,还可以跨多个计算机分布。分布式计算有许多不同的python包,但大多数似乎需要更改代码才能运行(例如,前缀表明对象在远程计算机上)。具体来说,我希望尽可能接近多处理pool.map函数。因此,例如,如果在一台机器上脚本是:

from multiprocessing import Pool
pool = Pool(processes = 8)
resultlist = pool.map(function, arglist)

然后,分布式集群的伪代码将是:

from distprocess import Connect, Pool, Cluster

pool1 = Pool(processes = 8)
c = Connect(ipaddress)
pool2 = c.Pool(processes = 4)
cluster = Cluster([pool1, pool2])
resultlist = cluster.map(function, arglist)

4 个答案:

答案 0 :(得分:10)

如果你想要一个非常简单的解决方案,那就没有了。

但是,有一个解决方案具有multiprocessing接口 - pathos - 它能够通过并行映射建立与远程服务器的连接,并进行多处理。

如果你想拥有一个ssh-tunneled连接,你可以这样做......或者你可以使用安全性较低的方法,你也可以这样做。

>>> # establish a ssh tunnel
>>> from pathos.core import connect
>>> tunnel = connect('remote.computer.com', port=1234)
>>> tunnel       
Tunnel('-q -N -L55774:remote.computer.com:1234 remote.computer.com')
>>> tunnel._lport
55774
>>> tunnel._rport
1234
>>> 
>>> # define some function to run in parallel
>>> def sleepy_squared(x):
...   from time import sleep
...   sleep(1.0)
...   return x**2
... 
>>> # build a pool of servers and execute the parallel map
>>> from pathos.pp import ParallelPythonPool as Pool
>>> p = Pool(8, servers=('localhost:55774',))
>>> p.servers
('localhost:55774',)
>>> y = p.map(sleepy_squared, x)
>>> y
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

或者,您可以配置直接连接(无ssh)

>>> p = Pool(8, servers=('remote.computer.com:5678',))
# use an asynchronous parallel map
>>> res = p.amap(sleepy_squared, x)
>>> res.get()
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

它有点挑剔,要使远程服务器正常工作,您必须事先启动在指定端口remote.computer.com上运行的服务器 - 并且您必须确保这两个设置在您的localhost和远程主机上将允许直接连接或ssh-tunneled连接。此外,您需要在每台主机上运行相同版本的pathospathos pp分叉。此外,对于ssh,您需要运行ssh-agent以允许使用ssh进行无密码登录。

但是,希望它一切正常......如果您的功能代码可以通过dill.source.importable传输到远程主机。

仅供参考,pathos早就应该发布,基本上,在新的稳定版本被删除之前,需要解决一些错误和界面更改。

答案 1 :(得分:9)

我建议您查看Ray,其目的就是做到这一点。

Ray使用相同的语法来并行化单机多核设置中的代码,就像在分布式设置中一样。如果您愿意使用for循环而不是地图调用,那么您的示例将如下所示。

import ray
import time

ray.init()

@ray.remote
def function(x):
    time.sleep(0.1)
    return x

arglist = [1, 2, 3, 4]

result_ids = [function.remote(x) for x in arglist]
resultlist = ray.get(result_ids)

这将使用您在本地拥有的多个核心并行运行四个任务。要在群集上运行相同的示例,唯一可以更改的行是对ray.init()的调用。可以找到相关文档here

请注意,我正在帮助开发Ray

答案 2 :(得分:8)

这里的派对有点晚了,但由于我也在寻找类似的解决方案,而且这个问题仍然没有得到回答,我想我会贡献我的发现。

我最终使用SCOOP。它提供了一个并行映射实现,可以跨多个主机跨多个内核工作。如果需要,它还可以在调用期间回退到Python的串行map函数。

在SCOOP的介绍页面中,它引用了以下功能:

  

SCOOP的特点和优势超过期货,多处理和   类似的模块如下:

     
      
  • 通过网络利用多台计算机的强大功能;
  •   
  • 能够在任务中生成多个任务;
  •   
  • API与PEP-3148;
  • 兼容   
  • 只需稍加修改即可并行化串行代码;
  •   
  • 高效的负载平衡。
  •   

它确实有一些怪癖(函数/类必须是可选择的),并且如果它们不共享相同的文件系统架构,那么在多个主机上顺利运行的设置可能会很乏味,但总的来说我是&#39 ;我对结果非常满意。为了我们的目的,做了相当多的Numpy& Cython,它提供了出色的性能。

希望这会有所帮助。

答案 3 :(得分:0)

你看过disco吗?

特点:

  • Map / Reduce范例
  • Python编程
  • 分布式共享磁盘
  • ssh underlaying transport
  • 网络和控制台界面
  • 易于添加/阻止/删除节点
  • 启动从属节点,无需用户干预
  • 从属节点在发生故障时自动重启
  • 很好的文档。在Install Guide之后我能够在几分钟内启动一个2机器集群(我唯一需要做的就是创建$ DISCO_HOME / root文件夹以便连接到WebUI,我想是因为日志文件错误创建)。

迪斯科文档中的一个简单示例:

from disco.core import Job, result_iterator

def map(line, params):
    for word in line.split():
        yield word, 1

def reduce(iter, params):
    from disco.util import kvgroup
    for word, counts in kvgroup(sorted(iter)):
        yield word, sum(counts)

if __name__ == '__main__':
    job = Job().run(input=["http://discoproject.org/media/text/chekhov.txt"],
                    map=map,
                    reduce=reduce)
    for word, count in result_iterator(job.wait(show=True)):
        print(word, count)