multiprocessing.Pool:apply、apply_asyncまたはmapを使用する場合


回答:


424

Pythonの昔、任意の引数で関数を呼び出すには、次のようにしますapply

apply(f,args,kwargs)

applyPython3にはありませんが、Python2.7にはまだ存在し、通常は使用されていません。今日、

f(*args,**kwargs)

推奨されます。multiprocessing.Poolモジュールは、同様のインタフェースを提供しようとします。

Pool.applyPython applyに似ていますが、関数呼び出しが別のプロセスで実行される点が異なります。Pool.apply関数が完了するまでブロックします。

Pool.apply_asyncまた、Pythonの組み込みと似applyていますが、呼び出しが結果を待つのではなく、すぐに戻る点が異なります。AsyncResultオブジェクトが返されます。そのget()メソッドを呼び出して、関数呼び出しの結果を取得します。get()メソッドのブロック機能が完了するまで。したがって、pool.apply(func, args, kwargs)と同等pool.apply_async(func, args, kwargs).get()です。

とは対照的にPool.applyPool.apply_asyncメソッドにはコールバックもあり、コールバックが指定されている場合は、関数が完了したときに呼び出されます。これはを呼び出す代わりに使用できますget()

例えば:

import multiprocessing as mp
import time

def foo_pool(x):
    time.sleep(2)
    return x*x

result_list = []
def log_result(result):
    # This is called whenever foo_pool(i) returns a result.
    # result_list is modified only by the main process, not the pool workers.
    result_list.append(result)

def apply_async_with_callback():
    pool = mp.Pool()
    for i in range(10):
        pool.apply_async(foo_pool, args = (i, ), callback = log_result)
    pool.close()
    pool.join()
    print(result_list)

if __name__ == '__main__':
    apply_async_with_callback()

次のような結果が得られる場合があります

[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]

とは異なりpool.map、結果の順序はpool.apply_async呼び出しが行われた順序と一致しない場合があります。


したがって、別のプロセスで関数を実行する必要があるが、その関数が戻るまで現在のプロセスをブロックする場合は、を使用しますPool.apply。のようにPool.applyPool.map完全な結果が返されるまでブロックします。

ワーカープロセスのプールで多くの関数呼び出しを非同期に実行する場合は、を使用しますPool.apply_asyncオーダーの結果のはへの呼び出しの順序と同じであることが保証されていませんPool.apply_async

複数の異なる関数を呼び出すことができることにも注意してくださいPool.apply_async(すべての呼び出しで同じ関数を使用する必要はありません)。

対照的にPool.map、同じ関数を多くの引数に適用します。ただし、とは異なりPool.apply_async、結果は引数の順序に対応する順序で返されます。


11
Windowsのif __name__=="__main__"apply_async_with_callback()にあるべきですか?
jfs

3
どうもありがとう。map_asyncはどうですか?
Phyo Arkar Lwin、2011

38
multiprocessing / pool.pyの中を見ると、Pool.map(func,iterable)と同等であることがわかりますPool.map_async(func,iterable).get()。関係はそうPool.mapPool.map_asyncの場合と同様であるPool.applyPool.apply_asyncasync非ながらコマンドは、すぐに返すasyncコマンドをブロックします。asyncコマンドは、コールバックを持っています。
unutbu

7
使用間で決定するPool.mapPool.applyするときに使用する決定に類似しているmapか、applyPythonで。仕事に合ったツールを使用するだけです。使用の間の決定asyncおよび非asyncバージョンにすると、呼び出しは現在のプロセスをブロックする場合、および/またはあなたがコールバックを使用する場合に依存します。
unutbu

6
@falsePockets:はい。を呼び出すたびにオブジェクトがapply_async返されApplyResultます。そのApplyResultgetメソッドを呼び出すと、関連付けられた関数の戻り値が返されます(またはmp.TimeoutError呼び出しがタイムアウトになると発生します)。したがって、ApplyResultsを順序付きリストに入れると、それらのgetメソッドを呼び出すと、同じ順序で結果が返されます。pool.mapただし、この状況で使用できます。
unutbu

75

apply対についてmap

pool.apply(f, args)fプールのワーカーの1つでのみ実行されます。したがって、プール内のプロセスの1つが実行されますf(args)

pool.map(f, iterable):このメソッドは、イテラブルをいくつかのチャンクに分割し、個別のタスクとしてプロセスプールに送信します。したがって、プール内のすべてのプロセスを利用できます。



うーん...良い質問です。正直に言うと、私は今までに発電機とのプールを使用していないが、このスレッドは役に立つかもしれません:stackoverflow.com/questions/5318936/...
kakhkAtion

@kakhkAtion適用に関して、ワーカーの1つだけが関数を実行する場合、残りのワーカーは何をしますか?残りのワーカーにタスクを実行させるには、applyを複数回呼び出す必要がありますか?
Moondra 2017

3
そうだね。非同期でワーカーをランチしたい場合は、pool.apply_asyncもご覧ください。"pool_applyは結果が準備できるまでブロックするので、apply_async()は並列処理を行うのに適しています"
kakhkAtion

1
プロセスが4つあるが、apply_async()8回呼び出した場合はどうなりますか?キューで自動的に処理されますか?
サラバナバラギラマチャンドラン

31

ここでの違いを示すためにテーブル形式の概要がありPool.applyPool.apply_asyncPool.mapPool.map_async。いずれかを選択するときは、複数引数、同時実行性、ブロック化、および順序付けを考慮する必要があります。

                  | Multi-args   Concurrence    Blocking     Ordered-results
---------------------------------------------------------------------
Pool.map          | no           yes            yes          yes
Pool.map_async    | no           yes            no           yes
Pool.apply        | yes          no             yes          no
Pool.apply_async  | yes          yes            no           no
Pool.starmap      | yes          yes            yes          yes
Pool.starmap_async| yes          yes            no           no

ノート:

  • Pool.imapおよびPool.imap_async– mapおよびmap_asyncのレイジーバージョン。

  • Pool.starmap メソッドは、複数の引数を受け入れる以外はmapメソッドとよく似ています。

  • Asyncメソッドはすべてのプロセスを一度に送信し、完了したら結果を取得します。getメソッドを使用して結果を取得します。

  • Pool.map(またはPool.apply)メソッドは、Pythonの組み込みマップ(または適用)と非常によく似ています。すべてのプロセスが完了して結果が返されるまで、メインプロセスをブロックします。

例:

地図

一度にジョブのリストが呼び出されます

results = pool.map(func, [1, 2, 3])

適用する

1つのジョブに対してのみ呼び出すことができます

for x, y in [[1, 1], [2, 2]]:
    results.append(pool.apply(func, (x, y)))

def collect_result(result):
    results.append(result)

map_async

一度にジョブのリストが呼び出されます

pool.map_async(func, jobs, callback=collect_result)

apply_async

1つのジョブに対してのみ呼び出すことができ、バックグラウンドで並列にジョブを実行します

for x, y in [[1, 1], [2, 2]]:
    pool.apply_async(worker, (x, y), callback=collect_result)

スターマップ

pool.map複数の引数をサポートするバリアントです

pool.starmap(func, [(1, 1), (2, 1), (3, 1)])

starmap_async

反復可能な反復可能オブジェクトを反復処理し、unterableをアンパックしてfuncを呼び出すstarmap()とmap_async()の組み合わせ。結果オブジェクトを返します。

pool.starmap_async(calculate_worker, [(1, 1), (2, 1), (3, 1)], callback=collect_result)

参照:

ここで完全なドキュメントを検索:https : //docs.python.org/3/library/multiprocessing.html


2
Pool.starmap()がブロックしている
アランエヴァンジェリスタ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.