1. ホーム
  2. python

[解決済み] マルチプロセシングpool.mapを複数の引数で使用する方法

2022-02-14 09:39:06

質問

Pythonでは multiprocessing ライブラリは pool.map は、複数の引数をサポートしていますか?

import multiprocessing

text = "test"

def harvester(text, case):
    X = case[0]
    text + str(X)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=6)
    case = RAW_DATASET
    pool.map(harvester(text, case), case, 1)
    pool.close()
    pool.join()

解決方法は?

この答えは、バージョンと状況に依存します。最近のバージョンの Python (3.3 以降) に対する最も一般的な答えは、最初に以下のように説明されました。 J.F.セバスチャン . 1 を使用しています。 Pool.starmap メソッドで、一連の引数タプルを受け取ります。そして、各タプルから自動的に引数を展開し、与えられた関数に渡します。

import multiprocessing
from itertools import product

def merge_names(a, b):
    return '{} & {}'.format(a, b)

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with multiprocessing.Pool(processes=3) as pool:
        results = pool.starmap(merge_names, product(names, repeat=2))
    print(results)

# Output: ['Brown & Brown', 'Brown & Wilson', 'Brown & Bartlett', ...

Pythonの以前のバージョンでは、明示的に引数をアンパックするヘルパー関数を書く必要があります。もし with を返すラッパーを書く必要があります。 Pool をコンテキストマネージャに変換します。(この記事は ミューオン という指摘がありました)。

import multiprocessing
from itertools import product
from contextlib import contextmanager

def merge_names(a, b):
    return '{} & {}'.format(a, b)

def merge_names_unpack(args):
    return merge_names(*args)

@contextmanager
def poolcontext(*args, **kwargs):
    pool = multiprocessing.Pool(*args, **kwargs)
    yield pool
    pool.terminate()

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with poolcontext(processes=3) as pool:
        results = pool.map(merge_names_unpack, product(names, repeat=2))
    print(results)

# Output: ['Brown & Brown', 'Brown & Wilson', 'Brown & Bartlett', ...

もっと単純なケースで、第2引数が固定されている場合は partial ただし、Python 2.7+のみ。

import multiprocessing
from functools import partial
from contextlib import contextmanager

@contextmanager
def poolcontext(*args, **kwargs):
    pool = multiprocessing.Pool(*args, **kwargs)
    yield pool
    pool.terminate()

def merge_names(a, b):
    return '{} & {}'.format(a, b)

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with poolcontext(processes=3) as pool:
        results = pool.map(partial(merge_names, b='Sons'), names)
    print(results)

# Output: ['Brown & Sons', 'Wilson & Sons', 'Bartlett & Sons', ...

1. この多くは、おそらく代わりに受理されるべきであった彼の回答に触発されたものです。しかし、これは一番上に貼り付けられているので、将来の読者のためにそれを改善するのが最善と思われました。