web-dev-qa-db-ja.com

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

Pythonのmultiprocessingパッケージの使用方法を学習しようとしていますが、map_asyncimapの違いがわかりません。 map_asyncimapの両方が非同期に実行されることに気付きました。それで、あるものを他のものよりもいつ使うべきですか?そして、map_asyncによって返された結果を取得するにはどうすればよいですか?

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

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

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

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

  1. 彼らがあなたに渡す反復可能なものを消費する方法。
  2. 結果を返す方法。

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

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

imap/imap_unorderedmap/map_asyncのもう1つの大きな違いは、imap/_imap_unorderedを使用すると、作業者が準備ができた後すぐに結果を受け取ることができることです。それらがすべて終了するのを待ちます。 map_asyncを使用すると、AsyncResultがすぐに返されますが、すべてのオブジェクトが処理されるまでそのオブジェクトから結果を取得することはできません。その時点で、mapと同じリストを返します(mapは、実際にはmap_async(...).get()として内部的に実装されています。部分的な結果を取得する方法はありません。結果全体が得られるか、まったく得られません。

imapimap_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を使用する主な理由は次のとおりです。

  1. あなたのイテラブルは十分に大きいので、それをリストに変換すると、メモリを使い果たしてしまいます。
  2. allの結果が完了する前に、結果の処理を開始できるようにします。
388
dano