1. ホーム
  2. python

[解決済み] マルチプロセッシングにおける共有メモリ・オブジェクト

2022-05-10 11:41:26

質問

メモリ上に大きなnumpy配列があり、その中に関数 func があり、この巨大な配列を(他のいくつかのパラメータと一緒に)入力として受け取ります。 func は異なるパラメータで並列に実行することができる。例えば

def func(arr, param):
    # do stuff to arr, param

# build array arr

pool = Pool(processes = 6)
results = [pool.apply_async(func, [arr, param]) for param in all_params]
output = [res.get() for res in results]

マルチプロセッシングライブラリを使用すると、巨大な配列は異なるプロセスに複数回コピーされます。

異なるプロセスで同じ配列を共有する方法はありますか?この配列オブジェクトは読み取り専用で、決して変更されることはありません。

もっと複雑なのは、arrが配列ではなく、任意のpythonオブジェクトである場合、それを共有する方法はありますか?

[編集済み]です。

回答を読ませていただきましたが、まだ少し混乱しています。fork()はcopy-on-writeなので、pythonマルチプロセッシングライブラリで新しいプロセスを生成するときに追加のコストを呼び出さないはずです。しかし、次のコードは、巨大なオーバーヘッドがあることを示唆しています。

from multiprocessing import Pool, Manager
import numpy as np; 
import time

def f(arr):
    return len(arr)

t = time.time()
arr = np.arange(10000000)
print "construct array = ", time.time() - t;


pool = Pool(processes = 6)

t = time.time()
res = pool.apply_async(f, [arr,])
res.get()
print "multiprocessing overhead = ", time.time() - t;

を出力します(ちなみに、配列のサイズが大きくなるとコストが増えるので、やはりメモリコピーに関連するオーバーヘッドがあると思われます)。

construct array =  0.0178790092468
multiprocessing overhead =  0.252444982529

配列をコピーしていないのに、なぜこのような巨大なオーバーヘッドがあるのでしょうか?また、共有メモリはどの部分を節約してくれるのでしょうか?

どのように解決するのですか?

コピーオンライトを使用するオペレーティングシステムを使用している場合 fork() セマンティクスを使用するオペレーティング システム (一般的な Unix など) を使用している場合、データ構造を決して変更しない限り、追加のメモリを占有することなくすべての子プロセスで利用できます。 特別なことをする必要はありません (オブジェクトを変更しないことを絶対に確認すること以外は)。

最も効率的なのは あなた を行うことができます。 は、配列を効率的な配列構造にパックすることでしょう ( numpy または array で囲みます)、それを共有メモリに配置し、それを multiprocessing.Array でラップし、それを関数に渡します。 この回答は、その方法を示しています .

もしあなたが 書き込み可能 共有オブジェクトが必要な場合は、何らかの同期やロックで包む必要があります。 multiprocessing これを行うための2つの方法 : 共有メモリ (単純な値、配列、ctypes に適しています) を使用する方法、または Manager プロキシでは、1 つのプロセスがメモリを保持し、マネージャが他のプロセスから (ネットワーク上でも) そのメモリへのアクセスを調停します。

Manager アプローチは任意の Python オブジェクトで使用できますが、オブジェクトをシリアライズ/デシリアライズしてプロセス間で送信する必要があるため、共有メモリを使用した同等品よりも遅くなります。

には Pythonで利用できる豊富な並列処理ライブラリやアプローチがあります。 . multiprocessing は優秀でよくまとまったライブラリですが、特別なニーズがある場合は、他のアプローチの方がよいかもしれません。