Python標準ライブラリの一部であるマルチプロセッシングと呼ばれる素晴らしいモジュールがあります。他のCPUを利用するために、必要な数のコアにプロセスを生成します。ドキュメントにPoolオブジェクトを使用する例があります。以下は、その例の短縮版です。10の数値の二乗を計算して、作業プロセスの作業負荷を分散し、結果を表示します。
シンプルなワーカープール
from multiprocessing import Pool
def f(x):
return x*x
pool = Pool(processes=4)
print pool.map(f, range(10))
出力
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
私はあなたの問題を同じ種類の構造に分割するというより多くの挑戦をしました。私は仕事を達成するためにいくつかの中間関数を作成しなければなりませんでした。私はnumpyを持っていないので、あなたが置いたものの代わりにリストと辞書を使用しました。それらを置き換えて、コードを試すことができます。
より複雑なシナリオ
from multiprocessing import Pool
import time, pprint
def fun(av, bv):
time.sleep(0.1)
return (av, bv)
def data_stream(a, b):
for i, av in enumerate(a):
for j, bv in enumerate(b):
yield (i, j), (av, bv)
def proxy(args):
return args[0], fun(*args[1])
a = range(100, 400, 100)
b = range(100, 400, 100)
Y = {}
pool = Pool(processes=4)
results = pool.map(proxy, data_stream(a, b))
for k,v in results:
Y[k] = v
pprint.pprint(Y)
出力
{(0, 0): (100, 100),
(0, 1): (100, 200),
(0, 2): (100, 300),
(1, 0): (200, 100),
(1, 1): (200, 200),
(1, 2): (200, 300),
(2, 0): (300, 100),
(2, 1): (300, 200),
(2, 2): (300, 300)}
パフォーマンス
この例では、重い作業をシミュレートするために、ダミーの0.1秒の遅延を設定しました。ただし、この例でも、プールを実行するprocesses=1
と0.950秒で実行され、プールは0.352秒processes=4
で実行されます。マルチプロセッシングライブラリはさまざまな方法で使用できます。プールは1つの方法にすぎません。例を調べて実験することをお勧めします。
以下のコメントの1つに、パフォーマンスの向上に役立つpool.mapへのchunksize引数の使用についての言及がありました。パフォーマンスを実際に把握するには、内部で何が起こっているのかを一般的に理解することが重要です。基本的に、他のプロセスに渡すすべてのデータは、ピクルスにされて、ピクルスにされていない他のプロセスに渡される必要があります。その後、結果は同じプロセスを経てメインプロセスに戻ります。このプロセス間通信にはオーバーヘッドがあります。実験するときは、このことを覚えておいてください。