web-dev-qa-db-ja.com

multiprocessing.Pool:apply、apply_async、またはmapをいつ使用するか

Pool.applyPool.apply_asyncのユースケースの明確な例は見ていません。 Pool.map 私は主にPool.mapを使っています。他人の利点は何ですか?

236
Phyo Arkar Lwin

Pythonの昔には、任意の引数で関数を呼び出すには、applyを使用します。

apply(f,args,kwargs)

applyはまだPython2.7には存在しますがPython3には存在せず、一般的にはもう使用されていません。今日、

f(*args,**kwargs)

が好ましいです。 multiprocessing.Poolモジュールは同様のインターフェースを提供しようとします。

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

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

Pool.applyとは対照的に、Pool.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 __== '__main__':
    apply_async_with_callback()

次のような結果になるかもしれません。

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

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


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

ワーカープロセスのプールが多数の関数呼び出しを非同期的に実行するようにしたい場合は、Pool.apply_asyncを使用します。結果の順序が、Pool.apply_asyncへの呼び出しの順序と同じであるとは限りません。

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

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

351
unutbu

apply vs mapについて:

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

pool.map(f, iterable):このメソッドはイテラブルをいくつかのチャンクに分割し、それらを別々のタスクとしてプロセスプールに送ります。だからあなたはプール内のすべてのプロセスを利用する。

67
kakhkAtion