multiprocessing.Pool:map_asyncとimapの違いは何ですか?


184

私は、Pythonの使用方法を学習しようとしているmultiprocessingパッケージを、私は違いを理解していないmap_asyncimapmap_asyncimapが非同期で実行されていることに気付きました。では、どちらをいつ使用すればよいですか?そして、どのようにして返された結果を取得する必要がありますmap_asyncか?

このようなものを使用する必要がありますか?

def test():
    result = pool.map_async()
    pool.close()
    pool.join()
    return result.get()

result=test()
for i in result:
    print i

回答:


492

imap/ imap_unorderedmap/の間には2つの重要な違いがありますmap_async

  1. 彼らが渡す反復可能オブジェクトを消費する方法。
  2. 彼らがあなたに結果を返す方法。

map反復可能オブジェクトをリストに変換し(すでにリストでない場合)、それをチャンクに分割し、それらのチャンクをのワーカープロセスに送信することにより、反復可能オブジェクトを消費しますPool。反復可能オブジェクトをチャンクに分割すると、特に反復可能オブジェクトが大きい場合に、プロセス間で反復可能オブジェクトの各アイテムを1つずつ渡すよりもパフォーマンスが向上します。ただし、リスト全体をメモリに保持する必要があるため、反復可能オブジェクトをリストに変換してチャンク化すると、メモリコストが非常に高くなる可能性があります。

imap与えるイテラブルをリストに変えたり、チャンクに分割したりしません(デフォルト)。一度に1つの反復可能な要素を反復処理し、それぞれをワーカープロセスに送信します。これは、イテラブル全体をリストに変換するというメモリヒットが発生しないことを意味しますが、チャンクが不足しているため、大きなイテラブルではパフォーマンスが低下します。chunksizeただし、デフォルトの1より大きい引数を渡すことでこれを軽減できます。

間の他の主要な違いは、imap/ imap_unorderedmap/ map_async、とのことですimap/ imap_unordered、あなたがすぐにではなく終了するためにそれらのすべてを待つことよりも、彼らはしている準備などとして、労働者からの結果の受信を開始することができます。を使用するmap_asyncと、AsyncResultはすぐに返されますが、すべてのオブジェクトが処理されるまで実際にそのオブジェクトから結果を取得することはできません。処理が完了すると、同じリストが返されますmapmap実際にはとして内部的に実装されていますmap_async(...).get())。部分的な結果を得る方法はありません。あなたは結果全体を持っているか、何も持っていません。

imapそして、imap_unorderedどちらもすぐにイテラブルを返します。を使用imapすると、入力イテラブルの順序を維持したまま、準備が整うとすぐにイテラブルから結果が生成されます。ではimap_unordered、反復可能な入力の順序に関係なく、準備が整うとすぐに結果が生成されます。だから、これがあるとしましょう:

import multiprocessing
import time

def func(x):
    time.sleep(x)
    return x + 2

if __name__ == "__main__":    
    p = multiprocessing.Pool()
    start = time.time()
    for x in p.imap(func, [1,5,3]):
        print("{} (Time elapsed: {}s)".format(x, int(time.time() - start)))

これは出力します:

3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)

p.imap_unordered代わりにを使用するとp.imap、次のように表示されます。

3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)

p.mapまたはを使用するとp.map_async().get()、次のように表示されます。

3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)

だから、使用する主な理由imap/ imap_unorderedオーバーはmap_async、次のとおりです。

  1. あなたのイテラブルは、それをリストに変換することでメモリが不足する/使用しすぎるほどの大きさです。
  2. すべての結果が完了する前に結果の処理を開始できるようにしたい。

1
applyとapply_asyncはどうですか?
Harsh Daftary、2015年

10
@HarshDaftaryはapply、単一のタスクをワーカープロセスに送信し、完了するまでブロックします。apply_async単一のタスクをワークプロセスに送信し、すぐにAsyncResultオブジェクトを返します。オブジェクトは、タスクが完了して結果を取得するのを待つために使用できます。apply呼び出すだけで実装されますapply_async(...).get()
dano

51
これPool、既存の退屈な説明ではなく、公式ドキュメントに記載する必要がある種類の説明です。

@danoバックグラウンドで関数を実行したいが、リソースに制限があり、関数を必要な回数だけ実行できず、関数の追加の実行をキューに入れたい。私がそれをどのようにすべきかについて何か考えがありますか?ここに質問があります。私の質問を見て、どうすればよいのかについてのヒント(または、より良い答え)を教えていただけませんか?
アミール

1
@BallpointBen完了するとすぐに次の作業に移ります。注文は親プロセスで処理されます。
dano
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.