8

コンピューティングクラスターでの並列ジョブの基本的な管理にはpyroを使用します。各計算ノードですべてのコアを使用する責任があるクラスターに移動しました。(以前のクラスターでは、各コアは個別のノードでした。)Pythonマルチプロセッシングモジュールはこれに適しているようです。リモートプロセス通信にも使用できることに気づきました。誰かがリモートプロセス通信に両方のフレームワークを使用したことがあるなら、それらが互いにどのように積み重なっているかを聞いていただければ幸いです。マルチプロセッシングモジュールの明らかな利点は、2.6から組み込まれていることです。それとは別に、どちらが良いかを判断するのは難しいです。

4

1 に答える 1

15

編集:あなたが痛みを避けるように私は私の答えを変えています。マルチプロセッシングは未成熟であり、BaseManagerのドキュメントは正しくありません。実行時に共有オブジェクトをその場で作成したいオブジェクト指向の思想家の場合は、PYROを使用してください。そうしないと、非常に後悔します。 すべての愚かな例のように、事前に登録した共有キューを使用して関数型プログラミングを行っている場合は、GOODFORYOUです。

短い答え

マルチプロセッシング:

  • オブジェクト指向のリモートオブジェクトを実行するのが面倒だと感じる
  • 簡単な簡単な暗号(authkey)
  • ネットワーク経由またはプロセス間通信
  • Pyroのようなネームサーバーの余分な手間はありません(これを回避する方法があります)
  • 編集:マネージャーがインスタンス化されると、オブジェクトを「登録」できません!! ??
  • 編集:サーバーが起動されていない場合、クライアントは単に「接続に失敗しました」と言うのではなく、「無効な引数」例外をスローしますWTF !?
  • 編集: BaseManagerのドキュメントが正しくありません!「スタート」方式はありません!?!
  • 編集:それを使用する方法についてのごくわずかな例。

パイロ:

  • 単純なリモートオブジェクト
  • ネットワーク通信のみ(ローカルのみの場合はループバック)
  • 編集:これはうまくいきます、そしてそれはオブジェクト指向のオブジェクト共有が好きです、それは私をそれのようにします
  • 編集:なぜこれは、それをコピーしようとして惨めに失敗したマルチプロセッシングのがらくたの代わりに、標準ライブラリの一部ではないのですか?

編集:私がこれに初めて答えたとき、私はちょうど2.6マルチプロセッシングに飛び込んだところです。以下に示すコードでは、Textureクラスはプロキシとして登録および共有されていますが、その中の「data」属性はそうではありません。したがって、何が起こるかを推測すると、予想どおりに、各プロセスにはTextureプロキシ内に「data」属性の個別のコピーがあります。実行時に共有オブジェクトを作成するための適切なパターンを理解するために数え切れないほどの時間を費やし、レンガの壁にぶつかり続けました。それは非常に混乱し、苛立たしいものでした。たぶん私だけかもしれませんが、人々が試みたわずかな例を見てみると、そのようには見えません。

マルチプロセッシングライブラリを削除し、マルチプロセッシングがより成熟するまでPyroを優先するという苦痛な決断をしなければなりません。最初はPythonに組み込まれているマルチプロセッシングを学ぶことに興奮していましたが、今では完全にうんざりしていて、Python用のこのような美しいライブラリが存在することを喜んでPyroパッケージを何度もインストールしたいと思っています。

長い答え

私は過去のプロジェクトでPyroを使用しており、非常に満足しています。また、2.6で新しいマルチプロセッシングの作業を開始しました。

マルチプロセッシングでは、必要に応じて共有オブジェクトを作成できるようにするのが少し厄介であることがわかりました。若い頃、マルチプロセッシングモジュールは、オブジェクト指向ではなく、関数型プログラミングに適していたようです。しかし、これは可能であるため、完全に真実ではありません。私は「登録」呼び出しに制約されていると感じています。

例えば:

manager.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

server.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()

client.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())

私が説明している厄介さは、textTexture関数を登録してTextureManagerから特定の名前の関数を取得するserver.pyに由来します。これについて説明しているので、TextureManagerを共有可能なテクスチャを作成/取得する共有可能なオブジェクトにすると、厄介な問題が解消される可能性があります。ええ、私はまだ遊んでいますが、あなたはその考えを理解しています。パイロを使ってこの厄介な問題に遭遇したことは覚えていませんが、おそらく上記の例よりもクリーンな解決策があるでしょう。

于 2009-12-23T22:51:01.413 に答える