python.multiprocessing.sharedctypes.RawArray
を使用して、複数のプロセス間で大量の配列を共有します。そして、私はこの配列が大きければ(> 1または2Gb)、初期化するのが非常に遅くなり、読み書きする時間が非常に遅くなることに気付きました。(読み書き時間は予測できず、時にはかなり速く、スロー)。Pythonの共有メモリへの書き込みは非常に遅い
私は、わずか1つのプロセスを使用する小さなサンプルスクリプトを作成しました。共有配列を初期化し、それを何度も書きます。これらの操作を行う時間を測定します。私は私のPC上で、次の取得このコードを実行すると
import argparse
import ctypes
import multiprocessing as mp
import multiprocessing.sharedctypes as mpsc
import numpy as np
import time
def main():
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-c', '--block-count', type=int, default=1,
help='Number of blocks to write')
parser.add_argument('-w', '--block-width', type=int, default=20000,
help='Block width')
parser.add_argument('-d', '--block-depth', type=int, default=15000,
help='Block depth')
args = parser.parse_args()
blocks = args.block_count
blockwidth = args.block_width
depth = args.block_depth
start = time.perf_counter()
shared_array = mpsc.RawArray(ctypes.c_uint16, blocks*blockwidth*depth)
finish = time.perf_counter()
print('Init shared array of size {:.2f} Gb: {:.2f} s'.format(blocks*blockwidth*depth*ctypes.sizeof(ctypes.c_uint16)/1024/1024/1024, (finish-start)))
numpy_array = np.ctypeslib.as_array(shared_array).reshape(blocks*blockwidth, depth)
start = time.perf_counter()
for i in range(blocks):
begin = time.perf_counter()
numpy_array[i*blockwidth:(i+1)*blockwidth, :] = np.ones((blockwidth, depth), dtype=np.uint16)
end = time.perf_counter()
print('Write = %.2f s' % (end-begin))
finish = time.perf_counter()
print('Total time = %.2f s' % (finish-start))
if __name__ == '__main__':
main()
は:最後のケースでは
$ python shared-minimal.py -c 1
Init shared array of size 0.56 Gb: 0.36 s
Write = 0.13 s
Total time = 0.13 s
$ python shared-minimal.py -c 2
Init shared array of size 1.12 Gb: 0.72 s
Write = 0.12 s
Write = 0.13 s
Total time = 0.25 s
$ python shared-minimal.py -c 4
Init shared array of size 2.24 Gb: 5.40 s
Write = 1.17 s
Write = 1.17 s
Write = 1.17 s
Write = 1.57 s
Total time = 5.08 s
、配列のサイズが2 GB以上で、初期化時には、配列のサイズに直線的に依存しませんアレイにセーブサイズスライスを割り当てることは、5倍以上遅くなります。
なぜ起こるのだろうか。私はPython 3.5を使ってUbuntu 16.04でスクリプトを実行しています。私はまた、iotopを使用して、アレイに初期化して書き込みを行うときに、共有配列と同じサイズのディスク書き込みアクティビティがあることに気付きましたが、実際のファイルが作成されているか、それがすべきであると仮定する)。一般的に私のシステムは、大規模な共有アレイの場合でも応答性が低下します。交換はありません。top
、ipcs -mu
、vmstat
で確認してください。
システムには2GBの物理メモリがありますか?それは交換のように聞こえる。 – pvg
@pvgには16GBのメモリがあり、64GBのメモリを搭載したコンピュータでもテストしました。結果は必ずしも同じではありませんが、16GBの物理メモリを搭載したコンピュータでは、共有アレイが1.5GB以上になるとスローダウンが著しくなり、64GB共有アレイを搭載したマシンでは約6.5GBになります。また、私は 'top'と' ipcs -mu'を実行しようとしましたが、スワップの使用に変化は見られません。 –
おそらく、 'vmstat'のようなものや、実際のスワップインとアウトを追跡するためのものが必要です。メモリアクセス時間はさまざまな理由で非線形に変化する可能性がありますが、スワップ以外の方法でディスクアクセスや非応答システムについて説明するのは難しいです。 – pvg