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
、次のとおりです。
- あなたのイテラブルは、それをリストに変換することでメモリが不足する/使用しすぎるほどの大きさです。
- すべての結果が完了する前に結果の処理を開始できるようにしたい。