3

新しいプロセスが生成されると、インポートされたモジュール変数はどうなりますか?

IE

with concurrent.futures.ProcessPoolExecutor(max_workers=settings.MAX_PROCESSES) as executor:
    for stuff in executor.map(foo, paths):

どこ:

  def foo(str):
  x = someOtherModule.fooBar()

foob​​ar は、someOtherModule の開始時に宣言されたものにアクセスしています。

someOtherModule.py:

 myHat='green'
 def fooBar():
   return myHat

具体的には、関数の外側の上部に初期化されたpy4jゲートウェイを持つモジュール(Yと呼ばれる)があります。モジュール X では、一度に複数のファイルをロードしています。ロード後にデータを並べ替える関数は、ゲートウェイを使用する Y の関数を使用します。

このデザインはpythonicですか?新しいプロセスが生成されるたびに Y モジュールをインポートする必要がありますか? または、これを行うより良い方法はありますか?

4

2 に答える 2

3

Linux ではfork、子のスポーンに使用されるため、コピー オン ライト セマンティクスを使用して、親のグローバル スコープ内にあるものはすべて子でも使用できます。

Windows では、親プロセスimportのモジュールでモジュール レベルにあるものはすべて__main__、子プロセスに再インポートされます。

これは、次のような親モジュール ( と呼びましょうsomeModule) がある場合を意味します。

import someOtherModule
import concurrent.futures

def foo(str):
    x = someOtherModule.fooBar()

if __name__ == "__main__":
    with concurrent.futures.ProcessPoolExecutor(max_workers=settings.MAX_PROCESSES) as executor:
        for stuff in executor.map(foo, paths):
            # stuff

someOtherModuleのようになります。

myHat='green'
def fooBar():
    return myHat

この例でsomeModuleは、__main__がスクリプトのモジュールです。したがって、Linux では、myHat子で取得するインスタンスは、 のインスタンスのコピー オン ライト バージョンになりsomeModuleます。Windows では、各子プロセスはsomeModuleロードされるとすぐに再インポートされ、その結果、someOtherModule再インポートも行われます。

Gatewayこれがあなたが望む動作であるかどうかを確信できるかどうかを判断するのに十分なpy4jオブジェクトについて私は知りません。オブジェクトがピクル可能な場合、Gateway代わりに各子に明示的に渡すことができますが、multiprocessing.Pool代わりにa を使用する必要がありconcurrent.futures.ProcessPoolExecutorます。

import someOtherModule
import multiprocessing

def foo(str):
    x = someOtherModule.fooBar()

def init(hat):
    someOtherModule.myHat = hat

if __name__ == "__main__":
    hat = someOtherModule.myHat
    pool = multiprocessing.Pool(settings.MAX_PROCESSES,
                                initializer=init, initargs=(hat,))
    for stuff in pool.map(foo, paths):
            # stuff

ただし、ユースケースのためにこれを行う必要があるようには見えません。おそらく、再インポートを使用しても問題ありません。

于 2015-03-23T17:17:39.903 に答える
2

新しいプロセスを作成するfork()と、プロセス全体とスタック、メモリ空間などを複製する a が呼び出されます。これが、コピーにコストがかかるため、マルチプロセッシングがマルチスレッドよりも高価であると見なされる理由です。

あなたの質問に答えるために、すべての「インポートされたモジュール変数」が複製されます。必要に応じて変更できますが、元の親プロセスにはこの変更は表示されません。

編集: これは Unix ベースのシステム専用です。Unix + Windowsの回答に対するDanoの回答を参照してください。

于 2015-03-23T04:42:18.143 に答える