24

joblib ドキュメントには、次の警告が含まれています。

Windows では、joblib.Parallel を使用するときにサブプロセスの再帰的な生成を回避するために、コードのメイン ループを保護することが重要です。つまり、次のようなコードを書く必要があります。

import ....

def function1(...):
    ...

def function2(...):
    ...

... if __name__ == '__main__':
    # do stuff with imports and functions defined about
    ...

「if __name__ == '__main__'」ブロックの外でコードを実行するべきではなく、インポートと定義のみを実行する必要があります。

joblib.Parallel最初は、これは、渡された関数がモジュールを再帰的に呼び出すという時折の奇妙なケースを防ぐためのものだと思っていました。ただし、なぜこれが Windows でのみリスクになるのか、私には理解できません。さらに、この回答は、メイン ループを保護できなかったために、非常に単純な非再帰的な問題の場合よりもコードの実行が数倍遅くなったことを示しているようです。

好奇心から、Windows ボックスのメイン ループを保護せずに、joblib ドキュメントから非常に単純な並列ループの例を実行しました。ターミナルを閉じるまで、次のエラーが表示されました。

ImportError: [joblib] Attempting to do parallel computing without protecting your import on a system that does not suppo
rt forking. To use parallel-computing in a script, you must protect you main loop using "if __name__ == '__main__'". Ple
ase see the joblib documentation on Parallel for more information

私の質問は、 joblib の Windows 実装では、どのような場合でもメイン ループを保護する必要があるということです。

これが超基本的な質問である場合はお詫び申し上げます。私は並列化の世界に慣れていないので、いくつかの基本的な概念が欠けているだけかもしれませんが、この問題が明示的に議論されている場所を見つけることができませんでした。

最後に、これは純粋に学術的なものであることに注意してください。この方法でコードを書くことが一般的に良い習慣である理由を理解しており、joblib に関係なくそうし続けるでしょう。

4

2 に答える 2

29

Windows にはfork(). __main__この制限のため、Windows は、子で親の状態を再作成するために、生成するすべての子プロセスでモジュールを再インポートする必要があります。これは、モジュール レベルで新しいプロセスを生成するコードがある場合、すべての子プロセスで再帰的に実行されることを意味します。if __name__ == "__main__"ガードは、モジュール スコープのコードが子プロセスで再実行されるのを防ぐために使用されます。

これは、モジュールを再インポートせずに、親プロセスと同じ状態を維持する子プロセスをフォークできるようにするため、Linux では必要ありませfork()__main__

于 2015-04-09T18:44:51.780 に答える