8

我使用pyro对计算集群上的并行作业进行基本管理。我刚搬到一个集群,我将负责使用每个计算节点上的所有内核。(在以前的集群中,每个核心都是一个单独的节点。)python多处理模块似乎很适合这个。我注意到它也可以用于远程进程通信。如果有人使用这两种框架进行远程进程通信,我会很高兴听到它们如何相互叠加。多处理模块的明显好处是它是 2.6 内置的。除此之外,我很难说哪个更好。

4

1 回答 1

15

编辑:我正在改变我的答案,这样你就可以避免痛苦。multiprocessing 不成熟,BaseManager 上的文档是INCORRECT,如果您是一个面向对象的思想家,想要在运行时动态创建共享对象,请使用 PYRO 否则您会后悔的! 如果您只是使用共享队列进行函数式编程,您可以像所有愚蠢的示例一样预先注册,这对您有好处。

简答

多处理:

  • 做面向对象的远程对象感觉很尴尬
  • 轻松轻松的加密货币(authkey)
  • 通过网络或只是进程间通信
  • 没有像 Pyro 那样的域名服务器额外麻烦(有办法解决这个问题)
  • 编辑:一旦经理被实例化,就不能“注册”对象!!???
  • 编辑:如果服务器没有启动,客户端会抛出一些“无效参数”异常,而不是仅仅说“连接失败”WTF!?
  • 编辑: BaseManager 文档不正确!没有“开始”的方法!?!
  • 编辑:关于如何使用它的例子很少。

火焰兵:

  • 简单的远程对象
  • 仅网络通信(仅本地环回)
  • 编辑:这个东西很好用,它喜欢面向对象的对象共享,这让我喜欢它
  • 编辑:为什么这不是标准库的一部分,而不是试图复制它并惨遭失败的多处理废话?

编辑:我第一次回答这个问题时,我刚刚涉足 2.6 多处理。在下面显示的代码中,Texture 类已注册并作为代理共享,但其中的“数据”属性不是。所以猜猜会发生什么,每个进程在纹理代理内部都有一个单独的“数据”属性副本,尽管您可能期望什么。我只是花了无数的时间试图找出在运行时创建共享对象的好模式,我一直在碰壁。这非常令人困惑和沮丧。也许只有我一个人,但环顾四周,人们尝试过的很少的例子看起来并不像这样。

我不得不做出放弃多处理库并更喜欢 Pyro 的痛苦决定,直到多处理更加成熟。虽然最初我很高兴学习 python 中内置的多处理,但我现在彻底厌恶它,宁愿多次安装 Pyro 包,高兴地看到这样一个漂亮的 python 库存在。

长答案

我在过去的项目中使用过 Pyro,并且对它非常满意。我也开始使用 2.6 中的新多处理。

对于多处理,我发现允许根据需要创建共享对象有点尴尬。看起来,多处理模块在其年轻时更适合函数式编程,而不是面向对象。然而,这并不完全正确,因为它是可能的,我只是感觉受到“注册”调用的限制。

例如:

经理.py:

from multiprocessing import Process
from multiprocessing.managers import BaseManager

class Texture(object):
   def __init__(self, data):
        self.data = data

   def setData(self, data):
      print "Calling set data %s" % (data)
      self.data = data

   def getData(self):
      return self.data

class TextureManager(BaseManager):
   def __init__(self, address=None, authkey=''):
      BaseManager.__init__(self, address, authkey)
      self.textures = {}

   def addTexture(self, name, texture):
      self.textures[name] = texture

   def hasTexture(self, name):
      return name in self.textures

服务器.py:

from multiprocessing import Process
from multiprocessing.managers import BaseManager
from manager import Texture, TextureManager

manager = TextureManager(address=('', 50000), authkey='hello')

def getTexture(name):
   if manager.hasTexture(name):
      return manager.textures[name]
   else:
      texture = Texture([0]*100)
      manager.addTexture(name, texture)
      manager.register(name, lambda: texture)

TextureManager.register("getTexture", getTexture)


if __name__ == "__main__":
   server = manager.get_server()
   server.serve_forever()

客户端.py:

from multiprocessing import Process
from multiprocessing.managers import BaseManager
from manager import Texture, TextureManager

if __name__ == "__main__":
   manager = TextureManager(address=('127.0.0.1', 50000), authkey='hello')
   manager.connect()
   TextureManager.register("getTexture")
   texture = manager.getTexture("texture2")
   data = [2] * 100
   texture.setData(data)
   print "data = %s" % (texture.getData())

我所描述的尴尬来自于 server.py,我在其中注册了一个 getTexture 函数以从 TextureManager 中检索某个名称的函数。当我正在讨论这个问题时,如果我将 TextureManager 设置为创建/检索可共享纹理的可共享对象,则可能会消除尴尬。嗯,我还在玩,但你明白了。我不记得使用 pyro 遇到过这种尴尬,但可能有一个比上面的例子更干净的解决方案。

于 2009-12-23T22:51:01.413 回答