2017-12-23 31 views
1

グローバル変数が "子"プロセスにどのように伝達されるかを理解するための小さなPythonプログラムを作成しました。Pythonのマルチプロセッシングモジュールと共有グローバル変数を変更する

import time 
import random 

shared_var = range(12) 

def f(x): 
    global shared_var 
    time.sleep(1+random.random()) 
    shared_var[x] = 100 
    print x, multiprocessing.current_process(), shared_var 
    return x*x 

if __name__ == '__main__': 
    pool = multiprocessing.Pool(4) 
    results = pool.map(f, range(8)) 
    print results 
    print shared_var 

私はそれを実行すると、私は取得

3 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 4, 5, 6, 7, 8, 9, 10, 11] 
0 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 
2 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 6, 7, 8, 9, 10, 11] 
1 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 
4 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 100, 5, 6, 7, 8, 9, 10, 11] 
5 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 100, 6, 7, 8, 9, 10, 11] 
6 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 100, 7, 8, 9, 10, 11] 
7 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 6, 100, 8, 9, 10, 11] 
[0, 1, 4, 9, 16, 25, 36, 49] 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 

子プロセスは、グローバル変数を変更して以来、これは、論理的であるので、メカニズムが作るコピー・オン・ライトその子プロセスが変更されたときにそれはコピーされ、したがって、変更は生成されたプロセスでのみ表示されます。

import multiprocessing 
import time 
import random 

shared_var = range(12) 

def f(x): 
    global shared_var 
    time.sleep(1+random.random()) 
    shared_var[x] = 100 
    print x, multiprocessing.current_process(), shared_var, id(shared_var) 
    return x*x 

if __name__ == '__main__': 
    pool = multiprocessing.Pool(4) 
    results = pool.map(f, range(8)) 
    print results 
    print shared_var, id(shared_var) 

となった:

3 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968 
0 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968 
1 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968 
2 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968 
6 <Process(PoolWorker-2, started daemon)> [0, 100, 2, 3, 4, 5, 100, 7, 8, 9, 10, 11] 4504973968 
7 <Process(PoolWorker-3, started daemon)> [0, 1, 100, 3, 4, 5, 6, 100, 8, 9, 10, 11] 4504973968 
4 <Process(PoolWorker-4, started daemon)> [0, 1, 2, 100, 100, 5, 6, 7, 8, 9, 10, 11] 4504973968 
5 <Process(PoolWorker-1, started daemon)> [100, 1, 2, 3, 4, 100, 6, 7, 8, 9, 10, 11] 4504973968 
[0, 1, 4, 9, 16, 25, 36, 49] 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 4504973968 

(メインスレッド内と内のすべての変数の識別子、私は変数の識別子を印刷するには、コードを変更したとき

私の驚きでした生成されたプロセス)は同じですが、私は各プロセスのコピーを期待していました...

なぜ私はこれらの結果を得たのですか?また、multiprocessingが作成したProcessによって読み書きされているグローバル変数をどのように処理するかについての参考文献も素晴らしいでしょう。ありがとう!

答えて

1

私はメモリに関するいくつかの混乱があると思います。マルチスレッドを使用せずにマルチプロセッシングを使用するので、各ワーカーは独自の仮想メモリ空​​間を持つ別々のプロセスで実行されます。したがって、各プロセスには最初からshared_varのコピーがあります。これは、各呼び出しでf(x)に変更され、__main__の実際の変数は影響を受けません。

プロセス間でメモリを共有する章については、the docsを確認できます。 multiprocessing.Arrayを使用してください。

私は100%アドレスが同じであるとは思っていませんが、新しいプロセスがそれぞれメインプロセスをフォークし、そのメモリレイアウトをコピーすることによって生成されるので、仮想メモリのアドレスはそれぞれ同じです子供のもちろん、物理メモリのアドレスは異なります。そのため、同じidが表示されますが、値は異なります。

+0

変数は常に子プロセスにコピーされますか?私はそれが変更されたときにのみコピーされたと思った?カスタムクラスでも同じことが起こりますか?その場合... "コピー"メソッドが呼び出されていますか? –

+0

ああああ、1つのコメントで非常に多くの質問:) 1.正しい2.私はフォークの内部を知らないが、結果が同じであるかどうかは、あなたがimmiediatelyをコピーするかどうか、または最初の書き込み3. Pythonは非常に無関係ですwrtカスタムと非カスタムのクラスはすべてオブジェクトです。だから私の推測です:はい。 4.私はその質問を理解していない。これはC++ではなく、コピーコンストラクタの概念はありません。 Pythonでメモリ管理に関するセパレートの質問を投稿してもよろしいでしょうか、自分よりも知識のある方がもっと情報を提供します。これはエキサイティングなトピックです! – Pavel

関連する問題