Pool.map()内で複数のパラメーターを受け入れる関数を使用する方法が必要です。私の理解では、pool.map()のターゲット関数はパラメーターとして反復可能なものを1つだけ持つことができますが、他のパラメーターも渡すことができる方法はありますか?この場合、Lock()やロギング情報などのいくつかの構成変数をターゲット関数に渡す必要があります。
私はいくつかの研究を試みましたが、部分的な機能を使用して機能させることができると思いますか?しかし、私はこれらがどのように機能するかを完全には理解していません。どんな助けも大歓迎です!これが私がやりたいことの簡単な例です:
def target(items, lock):
for item in items:
# Do cool stuff
if (... some condition here ...):
lock.acquire()
# Write to stdout or logfile, etc.
lock.release()
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
pool.map(target(PASS PARAMS HERE), iterable)
pool.close()
pool.join()
これには functools.partial
を使用できます(疑わしい):
from functools import partial
def target(lock, iterable_item):
for item in iterable_item:
# Do cool stuff
if (... some condition here ...):
lock.acquire()
# Write to stdout or logfile, etc.
lock.release()
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
l = multiprocessing.Lock()
func = partial(target, l)
pool.map(func, iterable)
pool.close()
pool.join()
例:
def f(a, b, c):
print("{} {} {}".format(a, b, c))
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
a = "hi"
b = "there"
func = partial(f, a, b)
pool.map(func, iterable)
pool.close()
pool.join()
if __== "__main__":
main()
出力:
hi there 1
hi there 2
hi there 3
hi there 4
hi there 5
multiprocessing
にあるpathos
のフォークと同様に、複数の引数を許可するマップ関数を使用できます。
>>> from pathos.multiprocessing import ProcessingPool as Pool
>>>
>>> def add_and_subtract(x,y):
... return x+y, x-y
...
>>> res = Pool().map(add_and_subtract, range(0,20,2), range(-5,5,1))
>>> res
[(-5, 5), (-2, 6), (1, 7), (4, 8), (7, 9), (10, 10), (13, 11), (16, 12), (19, 13), (22, 14)]
>>> Pool().map(add_and_subtract, *Zip(*res))
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)]
pathos
を使用すると、複数の入力を持つ階層的な並列マップを簡単にネストできるため、例を拡張してそれを示すことができます。
>>> from pathos.multiprocessing import ThreadingPool as TPool
>>>
>>> res = TPool().amap(add_and_subtract, *Zip(*Pool().map(add_and_subtract, range(0,20,2), range(-5,5,1))))
>>> res.get()
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)]
さらに楽しいのは、プールに渡すことができるネストされた関数を作成することです。 pathos
はdill
を使用するため、これは可能です。これは、Pythonのほとんどすべてをシリアル化できます。
>>> def build_fun_things(f, g):
... def do_fun_things(x, y):
... return f(x,y), g(x,y)
... return do_fun_things
...
>>> def add(x,y):
... return x+y
...
>>> def sub(x,y):
... return x-y
...
>>> neato = build_fun_things(add, sub)
>>>
>>> res = TPool().imap(neato, *Zip(*Pool().map(neato, range(0,20,2), range(-5,5,1))))
>>> list(res)
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)]
ただし、標準ライブラリの外部に移動できない場合は、これを別の方法で行う必要があります。その場合の最善の策は、次のようにmultiprocessing.starmap
を使用することです: Python multiprocessing pool.map for multiple arguments (@Roberto OPの投稿に対するコメント)
ここでpathos
を取得: https://github.com/uqfoundation
functools.partial
へのアクセス権がない場合は、これにもラッパー関数を使用できます。
def target(lock):
def wrapped_func(items):
for item in items:
# Do cool stuff
if (... some condition here ...):
lock.acquire()
# Write to stdout or logfile, etc.
lock.release()
return wrapped_func
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
lck = multiprocessing.Lock()
pool.map(target(lck), iterable)
pool.close()
pool.join()
これにより、target()
がロック(または任意のパラメーター)を受け入れる関数になり、反復可能オブジェクトを入力として取り込む関数を返しますが、他のすべてのパラメーターを引き続き使用できます。それが最終的にpool.map()
に渡され、問題なく実行されるはずです。