web-dev-qa-db-ja.com

PythonでParallel forループを実装する

次のようなPythonプログラムがあります。

total_error = []
for i in range(24):
    error = some_function_call(parameters1, parameters2)
    total_error += error

関数「some_function_call」には時間がかかり、関数の時間の複雑さを軽減する簡単な方法が見つかりません。並列タスクの実行中に実行時間を削減し、後でそれらをtotal_errorに追加する方法はありますか? poolとjoblibを使ってみましたが、どちらもうまく使えませんでした。

6

Python 3でconcurrent.futuresを使用することもできます。これはmultiprocessingよりもシンプルなインターフェイスです。- これを参照 違いの詳細については。

from concurrent import futures

total_error = 0

with futures.ProcessPoolExecutor() as pool:
  for error in pool.map(some_function_call, parameters1, parameters2):
    total_error += error

この場合、parameters1parameters2は、関数を実行する回数と同じサイズ(例では24回)のリストまたは反復可能でなければなりません。

paramters<1,2>がiterables/mappableではなく、関数を24回実行するだけの場合は、関数のジョブを必要な回数だけ送信し、後でコールバックを使用して結果を取得できます。

class TotalError:
    def __init__(self):
        self.value = 0

    def __call__(self, r):
        self.value += r.result()

total_error = TotalError()
with futures.ProcessPoolExecutor() as pool:
  for i in range(24):
    future_result = pool.submit(some_function_call, parameters1, parameters2)
    future_result.add_done_callback(total_error)

print(total_error.value)
5
Gerges

python multiprocessingを使用できます:

from multiprocessing import Pool, freeze_support, cpu_count
import os

all_args = [(parameters1, parameters2) for i in range(24)]

# call freeze_support() if in Windows
if os.name == "nt":
    freeze_support()

# you can use whatever, but your machine core count is usually a good choice (although maybe not the best)
pool = Pool(cpu_count()) 

def wrapped_some_function_call(args): 
    """
    we need to wrap the call to unpack the parameters 
    we build before as a Tuple for being able to use pool.map
    """ 
    sume_function_call(*args) 

results = pool.map(wrapped_some_function_call, all_args)
total_error = sum(results)
3
Netwave