2017-03-17 7 views
0

WindowsのPython 3.5では、入力に適用される関数でいくつかの事前処理された変数を使用する必要があるマルチプロセッシングコードを設計しようとしています。
これらの変数を使用できるようにするには、それらをグローバル変数として扱います。Python - マルチプロセッシングコールの前に変更されたグローバル変数が元の状態として渡される

これは非並列アプローチで動作しますが、multiprocessing.Poolを使用すると、グローバルが初期化から変更されていない場合に発生する動作が示されます。

は、次のコードを検討:

from multiprocessing import Pool 

testlist = [] 


def f(x): 
    return x*x + testlist[0] 


def main(): 
    global testlist 
    input_iter = range(10) 
    testlist = [1, 2, 3, 4, 5] 
    for i in input_iter: 
     print(f(i)) 
    with Pool(2) as pool: 
     for i in pool.imap_unordered(f, input_iter): 
      print(i) 

if __name__ == '__main__': 
    main() 

単に機能f(x)正方形の入力を、グローバル変数testlistから要素を追加します。 testlistは、最初はグローバルに空のリストとして定義され、main()関数内にリスト[1, 2, 3, 4, 5]を含むように変更されます。このコードを実行する

は、単純なforループに対する所望の出力を生成しますが、マルチプロセッシングループがIndexErrorスローされます。Pool労働者に、testlist変数に値を含むように改変し、まだ空のリストですされていませんが。

1 
2 
5 
10 
17 
26 
37 
50 
65 
82 
multiprocessing.pool.RemoteTraceback: 
""" 
Traceback (most recent call last): 
    File "\lib\multiprocessing\pool.py", line 119, in worker 
    result = (True, func(*args, **kwds)) 
    File "progresstest.py", line 7, in f 
    return x*x + testlist[0] 
IndexError: list index out of range 
""" 

The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
    File "progresstest.py", line 21, in <module> 
    main() 
    File "progresstest.py", line 17, in main 
    for i in pool.imap_unordered(f, input_iter): 
    File "\lib\multiprocessing\pool.py", line 695, in next 
    raise value 
IndexError: list index out of range 

グローバル変数

Pool労働者のいずれかの創造に変更され、単純なループは、この割り当てが働いていることを示しています。何 IndexErrorforループにスローされません。プロセス間で状態を共有することはできませんが、この変数は並列実行の前に定義されており、変更されません。

どうしてですか? UNIXのようなオペレーティングシステムで

+0

これはPython 2または3ですか? –

+1

ここに投稿したコードをファイルに入れてPython 3で実行すると、期待どおりに動作します。コードを単純化して質問を投稿する際に、実際に問題の原因となっているビットを削除することも可能ですか? –

+1

あなたはWindows上にいるように聞こえます。マルチプロセッシングは、あなたが思うように動作しません。グローバル変数は、プロセス間でデータを共有する安全な方法ではありません。 – user2357112

答えて

2

multiprocessing(デフォルト)は、1つ以上の正確なコピーマスタープロセスのを作るためにPoolを作成するforkシステムコールを使用します。

ms-windowsでは、forkシステムコールはありません。したがって、multiprocessingは動作が異なります。それはをモジュールとしてインポートする新しいPythonプロセスを開始します。この場合、main()は呼び出されないため、グローバルは更新されません。

+0

これは私が見ていた振る舞いの違いを説明してくれました。ありがとうございます。私の場合、必要な変数を 'pool.imap_unordered'ではなく' pool.starmap'で並列関数に渡し、グローバル変数を避けてこの動作を避けることができます。 – Librarian

+0

'tuple'で変数をラップすることができます... –

関連する問題