2

(ネットワーク分析ライブラリ)を使用していくつかの遅い計算を行っておりnetworkx、プールワーカーを使用してそれをいくらか高速化しようとしています。計算は独立しているため、並列化は比較的簡単です。

def computeInfoPooled(G,num_list):
    pool=Pool(processes=4)

    def f(k):
        curr_stat={}
        curr_stat[k]=slow_function(k,G)
        return curr_stat

    result = pool.map(f,num_list)

    return result

ここで、コンソールで次を実行しました。

computed_result=computeInfoPooled(G)

このコードで 4 つのプロセスが作成され、別のプロセスで num_list のすべての項目 (数値) を指定して f が呼び出されることを期待します。num_list に 4 つ以上の数値 (私の場合は約 300) が含まれている場合、同時に 4 つを実行し、プールされたワーカーの 1 つが完了するまで残りをキューに入れます。

コードを実行したときに発生したのは、多くの python.exe が生成された (またはフォークされた、何が起こっているのかわからない) ことであり、無限に多くのプロセスが作成されているように見えたので、マシンのプラグを抜く必要がありました。

私が間違っていることと、それを修正する方法はありますか?

4

2 に答える 2

1

Windowsでは必要です

if __name__ == '__main__':
    computed_result = computeInfoPooled(G)

フォーク爆弾を起動せずにスクリプトをインポート可能にするため。(ドキュメントの「メインモジュールの安全なインポート」というタイトルのセクションをお読みください。

また、Windowsでは、インタラクティブインタプリタからマルチプロセッシングモジュールを使用できない場合があることに注意してください。ドキュメントの上部にある警告を参照してください:

このパッケージ内の機能には、メインモジュールが子によってインポート可能である必要があります。これはプログラミングガイドラインでカバーされていますが、ここで指摘する価値があります。これは、マルチプロセッシングなどの一部の例を意味します。プールの例は、インタラクティブインタープリターでは機能しません。(私の強調。)

代わりに、スクリプトをファイルに保存します。たとえばscript.py、コマンドラインから実行します。

python script.py

さらに、引数をpool.map選択可能にする必要があります。関数fはモジュールレベルで定義する必要があります(選択可能にするために内部computeInfoPooledではありません:

def f(k):
    curr_stat = slow_function(k, G)
    return k, curr_stat


def computeInfoPooled(G, num_list):
    pool = Pool(processes=4)
    result = pool.map(f, num_list)
    return dict(result)

if __name__ == '__main__':
    computed_result = computeInfoPooled(G)

ちなみに、fdictを返す場合は、dictpool.map(f, ...)のリストを返します。特に、各dictにはキーと値のペアが1つしかないため、それが必要かどうかはわかりません。

代わりに、f(key、value)タプルpool.map(f, ...)を返すようにすると、タプルのリストが返され、これをでdictに変換できますdict(result)

于 2013-03-01T20:42:50.840 に答える
0

これについては、 Windowsのプログラミング ガイドライン のドキュメントで説明されています。

プラットフォームによっては、関数を呼び出すために、各プロセスで新しいインタープリターとimportモジュールを起動する必要がある場合があります。f(Windowsでは、常にそうする必要があります。)それがモジュールの場合、4つのプロセスなどのまったく新しいプールを作成するimport行を含むすべてのトップレベルコードが実行されます。computed_result=computeInfoPooled(G)

これは、同じファイルをモジュールとしてインポート可能にし、スクリプトとして実行可能にする他のケースと同じ方法で回避できます。

def computeInfoPooled(G,num_list):
    pool=Pool(processes=4)

    def f(k):
        curr_stat={}
        curr_stat[k]=slow_function(k,G)
        return curr_stat

    result = pool.map(f,num_list)

    return result

if __name__ == '__main__':
    computed_result=computeInfoPooled(G)

あなたの編集とコメントcomputeInfoPooled(G)から、対話型インタープリターからの呼び出しを行うことでその問題が解決することを期待しているようです。同じリンクされたドキュメント セクションでは、なぜそれが機能しないのかを詳細に説明しています

このパッケージ内の機能では、メインモジュールが子によってインポート可能である必要があります。これはプログラミング ガイドラインで説明されていますが、ここで指摘する価値があります。これは、 multiprocessing.Pool の例など、一部の例が対話型インタープリターでは機能しないことを意味します。

これが正しい理由を理解したい場合は、リンクされたドキュメントを読む必要があります (またimport、 、pickle、およびmultiprocessingすべての機能について少し理解する必要があります)。

于 2013-03-01T20:38:54.287 に答える