Pythonのmultiprocessing
パッケージの使用方法を学習しようとしていますが、map_async
とimap
の違いがわかりません。 map_async
とimap
の両方が非同期に実行されることに気付きました。それで、あるものを他のものよりもいつ使うべきですか?そして、map_async
によって返された結果を取得するにはどうすればよいですか?
このようなものを使用する必要がありますか?
def test():
result = pool.map_async()
pool.close()
pool.join()
return result.get()
result=test()
for i in result:
print i
imap
/imap_unordered
とmap
/map_async
には2つの重要な違いがあります。
map
は、イテラブルをリストに変換し(既にリストではない場合)、チャンクに分割し、それらのチャンクをPool
のワーカープロセスに送信することにより、イテラブルを消費します。反復可能オブジェクトをチャンクに分割すると、特に反復可能オブジェクトが大きい場合は、プロセス間で反復可能オブジェクトの各アイテムを1つのアイテムに渡すよりもパフォーマンスが向上します。ただし、イテラブルをチャンク化するためにリストに変換すると、リスト全体をメモリに保持する必要があるため、メモリコストが非常に高くなる可能性があります。
imap
は、指定した反復可能変数をリストに変換したり、チャンクに分割したりしません(デフォルト)。繰り返し可能な要素を一度に1つずつ繰り返し、それぞれをワーカープロセスに送信します。これは、イテラブル全体をリストに変換するメモリヒットを受け取らないことを意味しますが、チャンクがないため、大きなイテラブルのパフォーマンスが低下することも意味します。ただし、これはデフォルトの1よりも大きいchunksize
引数を渡すことで軽減できます。
imap
/imap_unordered
とmap
/map_async
のもう1つの大きな違いは、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 __== "__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_unordered
ではなくimap
/map_async
を使用する主な理由は次のとおりです。