賞金を見たばかりなので、もう一度やり直してください;)
基本的に、エラーメッセージはそれが言ったことを意味すると思います-マルチプロセッシング共有メモリ配列は引数として渡すことができません(ピクルスによって)。データをシリアル化することは意味がありません。重要なのは、データが共有メモリであるということです。したがって、共有アレイをグローバルにする必要があります。私の最初の答えのように、モジュールの属性としてそれを置くのは良いことだと思いますが、あなたの例ではそれをグローバル変数として残すだけでもうまくいきます。フォークの前にデータを設定したくないというあなたのポイントを取り入れて、ここに修正された例があります。複数の可能な共有配列が必要な場合(そしてそれが引数としてtoShareを渡したい理由です)、同様に共有配列のグローバルリストを作成し、インデックスをcount_itに渡すことができます(これはになりfor c in toShare[i]:
ます)。
from sys import stdin
from multiprocessing import Pool, Array, Process
def count_it( key ):
count = 0
for c in toShare:
if c == key:
count += 1
return count
if __name__ == '__main__':
# allocate shared array - want lock=False in this case since we
# aren't writing to it and want to allow multiple processes to access
# at the same time - I think with lock=True there would be little or
# no speedup
maxLength = 50
toShare = Array('c', maxLength, lock=False)
# fork
pool = Pool()
# can set data after fork
testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"
if len(testData) > maxLength:
raise ValueError, "Shared array too small to hold data"
toShare[:len(testData)] = testData
print pool.map( count_it, ["a", "b", "s", "d"] )
[編集:フォークを使用していないため、上記はWindowsでは機能しません。ただし、以下はWindowsでも機能し、プールを使用しているため、これが必要なものに最も近いと思います。
from sys import stdin
from multiprocessing import Pool, Array, Process
import mymodule
def count_it( key ):
count = 0
for c in mymodule.toShare:
if c == key:
count += 1
return count
def initProcess(share):
mymodule.toShare = share
if __name__ == '__main__':
# allocate shared array - want lock=False in this case since we
# aren't writing to it and want to allow multiple processes to access
# at the same time - I think with lock=True there would be little or
# no speedup
maxLength = 50
toShare = Array('c', maxLength, lock=False)
# fork
pool = Pool(initializer=initProcess,initargs=(toShare,))
# can set data after fork
testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"
if len(testData) > maxLength:
raise ValueError, "Shared array too small to hold data"
toShare[:len(testData)] = testData
print pool.map( count_it, ["a", "b", "s", "d"] )
マップが配列をピクルスしない理由はわかりませんが、プロセスとプールはピクルスします-おそらく、Windowsでのサブプロセスの初期化の時点で転送されたと思います。ただし、データはフォーク後も設定されていることに注意してください。