imap/ imap_unorderedとmap/の間には2つの重要な違いがありますmap_async。
- 彼らが渡す反復可能オブジェクトを消費する方法。
- 彼らがあなたに結果を返す方法。
map反復可能オブジェクトをリストに変換し(すでにリストでない場合)、それをチャンクに分割し、それらのチャンクをのワーカープロセスに送信することにより、反復可能オブジェクトを消費しますPool。反復可能オブジェクトをチャンクに分割すると、特に反復可能オブジェクトが大きい場合に、プロセス間で反復可能オブジェクトの各アイテムを1つずつ渡すよりもパフォーマンスが向上します。ただし、リスト全体をメモリに保持する必要があるため、反復可能オブジェクトをリストに変換してチャンク化すると、メモリコストが非常に高くなる可能性があります。
imap与えるイテラブルをリストに変えたり、チャンクに分割したりしません(デフォルト)。一度に1つの反復可能な要素を反復処理し、それぞれをワーカープロセスに送信します。これは、イテラブル全体をリストに変換するというメモリヒットが発生しないことを意味しますが、チャンクが不足しているため、大きなイテラブルではパフォーマンスが低下します。chunksizeただし、デフォルトの1より大きい引数を渡すことでこれを軽減できます。
間の他の主要な違いは、imap/ imap_unorderedとmap/ map_async、とのことですimap/ imap_unordered、あなたがすぐにではなく終了するためにそれらのすべてを待つことよりも、彼らはしている準備などとして、労働者からの結果の受信を開始することができます。を使用するmap_asyncと、AsyncResultはすぐに返されますが、すべてのオブジェクトが処理されるまで実際にそのオブジェクトから結果を取得することはできません。処理が完了すると、同じリストが返されますmap(map実際にはとして内部的に実装されています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、次のとおりです。
- あなたのイテラブルは、それをリストに変換することでメモリが不足する/使用しすぎるほどの大きさです。
- すべての結果が完了する前に結果の処理を開始できるようにしたい。