2016-08-23 8 views
0

私はマルチプロセッシングで奇妙な動作に遭遇しました。マルチプロセッシングでグローバル変数が認識されませんか?

マルチプロセスから呼び出される関数でグローバル変数を使用しようとすると、グローバル変数が表示されません。

例:

import multiprocessing 

def func(useless_variable): 
    print(variable) 

useless_list = [1,2,3,4,5,6] 
p = multiprocessing.Pool(processes=multiprocessing.cpu_count()) 
variable = "asd" 

func(useless_list) 

for x in p.imap_unordered(func, useless_list): 
    pass 

出力:あなたが初めて見たよう

asd 
multiprocessing.pool.RemoteTraceback: 
""" 
Traceback (most recent call last): 
    File "/usr/lib/python3.4/multiprocessing/pool.py", line 119, in worker 
    result = (True, func(*args, **kwds)) 
    File "pywork/asd.py", line 4, in func 
    print(variable) 
NameError: name 'variable' is not defined 
""" 

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

Traceback (most recent call last): 
    File "pywork/asd.py", line 11, in <module> 
    for x in p.imap_unordered(func, useless_list): 
    File "/usr/lib/python3.4/multiprocessing/pool.py", line 689, in next 
    raise value 
NameError: name 'variable' is not defined 

私は単に予想通り、それはasdを印刷funcを呼び出します。しかし、私がマルチプロセッシングで非常に同じ関数を呼び出すと、変数variableは存在しません。

マルチプロセッシングはグローバル変数を無視しますか?どうすればこのことができますか?

答えて

1

multiprocessingPoolPoolが作成された時点で、そのワーカープロセスがフォーク(またはWindows上でフォークを模倣するように意図された方法で生成)します。 forkは、子プロセスで親メモリをコピーオンライトとしてマップしますが、それらの間に永続的な結合を作成しません。 forkの後に、親で行われた変更は子では表示されず、その逆もあります。 Poolの作成後に定義された変数は使用できません。また、Poolの作成前に変数に加えた変更は、ワーカーに反映されません。

通常、Poolを使用すると、変更可能なグローバル状態が完全に回避されます。あなたはimapの関数に渡される必要なすべてのデータを引数として渡して(子にシリアル化されて送信されるため、状態は正しい)、関数returnにはグローバルを変更する代わりに新しいデータがありますそれはそれを直列化し、それが親プロセスに送って使用するのに適していると見なします。

Managersはオプションですが、通常は正しいオプションはPoolです。 Poolが作成される前から、またはグローバル状態をまったく使用せずに引数を使用して新しい値を返す前に、読み取り専用のグローバルのみを見ているワーカーに固執したいと思っています。

1

すべてのコンテキストがコピーされたときに、managersを使用してオブジェクト間のオブジェクトを拡張する必要があります。official documentationsをチェックして、状態チェックthisを管理してください。

関連する問題