5

Python のモジュールを使用してコードを最適化しようとしていmultiprocessing.Poolますが、論理的に期待する速度向上の結果が得られません。

私が行っている主な方法は、多数のベクトルと固定された大きな疎行列の行列ベクトル積を計算することです。以下は、私が必要とするものを実行するおもちゃの例ですが、ランダムな行列を使用しています。

import time
import numpy as np
import scipy.sparse as sp

def calculate(vector, matrix = None):
    for i in range(50):
        v = matrix.dot(vector)
    return v

if __name__ == '__main__':
    N = 1e6
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr')
    t = time.time()
    res = []
    for i in range(10):
        res.append(calculate(np.random.rand(N), matrix = matrix))    
    print time.time() - t

メソッドは約30数秒で終了します。

さて、 の各要素の計算はresults他の計算の結果に依存しないため、並列計算を行うと処理が高速になると考えるのが自然です。アイデアは、4 つのプロセスを作成することであり、それぞれがいくつかの計算を行う場合、すべてのプロセスが完了するまでにかかる時間は約 1/2 減少するはず4です。これを行うために、次のコードを書きました。

import time
import numpy as np
import scipy.sparse as sp
from multiprocessing import Pool
from functools import partial

def calculate(vector, matrix = None):
    for i in range(50):
        v = matrix.dot(vector)
    return v

if __name__ == '__main__':
    N = 1e6
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr')

    t = time.time()
    input = []
    for i in range(10):
        input.append(np.random.rand(N))
    mp = partial(calculate, matrix = matrix)
    p = Pool(4)
    res = p.map(mp, input)
    print time.time() - t

20私の問題は、このコードの実行に数秒以上かかること2です。さらに悪いことに、プールにプロセスが含まれていても、パフォーマンスは向上しません! 8スピードアップが起こらない理由は何ですか?


:私の実際の方法はもっと時間がかかり、入力ベクトルはファイルに保存されます。ファイルを分割してから、ファイル4ごとに個別のプロセスでスクリプトを手動で実行すると、各プロセスはファイル全体の場合の 4 倍の速さで終了します (予想どおり)。このスピードアップ(明らかに可能です)がなぜ起こっていないのか混乱していますmultiprocessing.Pool


Edi : Multiprocessing.Pool により Numpy 行列の乗算が遅くなることがわかりました。この質問は関連している可能性があります。でもチェックしなきゃ。

4

1 に答える 1

0

試す:

p = Pool(4)
for i in range(10):
    input = np.random.rand(N)
    p.apply_async(calculate, args=(input, matrix)) # perform function calculate as new process with arguments input and matrix

p.close()  
p.join() # wait for all processes to complete

「部分的な」オブジェクトとマップがブロック動作を引き起こしていると思われます。(ただし、パーシャルは使用したことがないため、よくわかりません。)

「apply_async」(または「map_async」) は、具体的にはブロックしないマルチプロセッシング メソッドです (参照: Python multiprocessing.Pool: when to use apply, apply_async or map? )

一般に、このような「恥ずかしいほど並列の問題」では、apply_async が機能します。

編集:

完了したら、MySQL データベースに結果を書き込む傾向があります。それがあなたのアプローチでない場合、私が提供した実装は機能しません。どのエントリがどれであるかを追跡する方法としてリスト内の順序を使用したい場合は、おそらく「マップ」が正しい答えですが、「部分的な」オブジェクトには疑いが残ります。

于 2015-01-05T22:38:59.863 に答える