私はPythonにまったく精通していませんが、通常RubyまたはJSです。ただし、Pythonを実行するシステムでベンチマークスクリプトを記述する必要があります。私がやろうとしていることは、ファイルサイズとスレッド数を取得し、ランダムバッファーを書き込む小さなスクリプトこれは、2時間いじった後に得られたものです。
from multiprocessing import Pool
import os, sys
def writeBuf(buf):
def write(n):
f = open(os.path.join(directory, 'n' + str(n)), 'w')
try:
f.write(buf)
f.flush()
os.fsync(f.fileno)
finally:
f.close()
return write
if __name__ == '__main__':
targetDir = sys.argv[1]
numThreads = int(sys.argv[2])
numKiloBytes = int(sys.argv[3])
numFiles = int(102400 / numKiloBytes)
buf = os.urandom(numKiloBytes * 1024)
directory = os.path.join(targetDir, str(numKiloBytes) + 'k')
if not os.path.exists(directory):
os.makedirs(directory)
with Pool(processes=numThreads) as pool:
pool.map(writeBuf(buf), range(numFiles))
しかし、それはエラーをスローします:AttributeError: Can't pickle local object 'writeBuf.<locals>.write'
以前にクロージャーなしでwrite
を使用しようとしましたが、__name__ == '__main__'
パーツ内で関数を定義しようとするとエラーが発生しました。 if
を省略するとエラーにもなり、Pool
が機能するためにはエラーが必要であると読みました。
小さなスクリプトが巨大な試練に変わったはずですが、誰かが私を正しい方向に向けることができますか?
理論的には、python cann't pickle functions。(詳細については、 Ca n't pickle Function) を参照してください)
実際には、pythonは、関数の名前とモジュールをピクルス化して、関数を渡すことが機能するようにします。ただし、あなたの場合、渡そうとしている関数は、writeBuf
。
代わりに:
writeBuf
ラッパーを削除します。write
関数のクロージャー(buf
およびdirectory
)を使用せず、代わりにwrite
に必要なすべてをパラメーターとして指定してください。結果:
def write(args):
directory, buf, n = args
with open(os.path.join(directory, 'n' + str(n)), 'w') as f:
# might as well use with-statements ;)
f.write(buf)
f.flush()
os.fsync(f.fileno)
if __name__ == '__main__':
...
with Pool(processes=numThreads) as pool:
nargs = [(directory, buf, n) for n in range(numFiles)]
pool.map(write, nargs)