2017-04-14 11 views
2

私はクラスのインスタンスをいくつも持っています。メソッドを呼び出すことによってそれぞれのインスタンスを変更したいと思います。ただし、このメソッドはシステムコマンドを呼び出すため、戻りに時間がかかりますので、いくつか並行して実行したいと思います。私はこれが非常に簡単なことだと思ったが、私は困惑している。ここで私が達成したいものと類似している例です。メソッドの呼び出しを並列化してオブジェクトを変更する

import os 

class SquareMe(): 
    def __init__(self, x): 
     self.val = x 
    def square(self): 
     os.system('sleep 10') # I'll call a slow program 
     self.val = self.val **2 

if __name__ == '__main__': 
    objs = [SquareMe(x) for x in range(4)] 
    for obj in objs: 
     obj.square() # this is where I want to parallelize it 
    print([obj.val for obj in objs]) 

このコードは動作します(これは[0、1、4、9]印刷し)、それが実行するために40秒かかります。私は約10秒間それを取得しようとしています。

私は理解したように、square()を評価する前にオブジェクトをpickleします。つまり、各オブジェクトのコピーが変更され、オリジナルはそのまま残ります。私は解決策が自己を返し、元のものを上書きするだろうと思ったが、それが可能であればそれは単純ではない。私はスレッドを見て、私がそこで同じ問題に遭遇するという印象を得ました。

私はasync(私はpython 3.5を使用しています)を使用してみました。私が知ることから、システムコール(「スリープ10」を含む)はブロックされています。つまり、非同期ではスピードアップしません。

これを行うにはシンプルでエレガントな、pythonicな方法がありますか?

+0

私はあなたがツイスト(https://twistedmatrix.com/trac/)が、確かにそう答えとして、それを投稿していないですないですして実行可能な解決策を見つけることができる期待する:ここで私がなってしまったものです。 –

+0

私はGIL、PythonとWindowsを実行するとforkが許されないという事実と、多くの場合、オブジェクトがマルチプロセッシングで実現されるという事実に悩まされているので、この質問に必ず従います。マルチプロセッシングと共有numpy配列の問題を私に教えてはいけません。計算量の多いものでは、私は頻繁にCythonに行く必要があります。これは、開いたMPを通してマルチプロセスできます。 –

+0

オブジェクトの修正を2つの部分に分けることができます.1つは高価ですが、オブジェクトに密接に結びつける必要はありません(例:外部コードへの呼び出し)。安価で実際のオブジェクトの変更?そうであれば、おそらく高価な部分を 'マルチプロセッシング'で並列化し、メインプロセスの安い部分だけを残すことができます。オブジェクトのデータを更新するか、外部コードへの引数を抽出するのが高価な部分など、パーツを分離する簡単な方法がない場合は、良い解決策はないと思います。 – Blckknght

答えて

0

正しいコードを見つけたら、マルチプロセッシングと 'return self'を使うのはかなり簡単です。

import os 
import multiprocessing 

class SquareMe(): 
    def __init__(self, x): 
     self.val = x 
    def square(self): 
     os.system('sleep 10') # I'll call another program, which take a while 
     self.val = self.val **2 
     return self 

if __name__ == '__main__': 
    objs = [SquareMe(x) for x in range(4)] 
    pool = multiprocessing.Pool(4) 
    objs = pool.map(SquareMe.square, objs) 
    pool.close() 
    pool.join() 
    print([obj.val for obj in objs]) 
+0

あなたのコードは** _ pickle.PicklingErrorを与えます:<関数SquareMe.squareを0xf7025104でpickleできません>:__main__の属性検索が失敗しました** – stovfl

関連する問題