用Python写入共享内存非常慢
作者:互联网
我使用python.multiprocessing.sharedctypes.RawArray在多个进程之间共享大型numpy数组.而且我注意到,当此数组很大(大于1或2 Gb)时,初始化变得非常慢,读/写也变得很慢(读/写时间是不可预测的,有时非常快,有时非常快非常慢).
我制作了一个小的示例脚本,该脚本仅使用一个进程,初始化一个共享数组,并多次写入该数组.并衡量执行这些操作的时间.
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()
当我运行此代码时,我在PC上得到以下信息:
$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检查.
解决方法:
经过更多研究后,我发现python实际上在/ tmp中创建了以pymp-开头的文件夹,尽管使用文件查看器在其中看不到任何文件,但是它看起来确实像/ tmp /被python用于共享内存.清空文件兑现后,性能似乎正在下降.
最后可行的解决方案是将/ tmp挂载为tmpfs:
sudo mount -t tmpfs tmpfs /tmp
并且,如果使用最新的docker,请在docker run命令中提供–tmpfs / tmp参数.
完成此操作后,将在RAM中完成读/写操作,并且性能快速稳定.
我仍然想知道为什么/ tmp用于共享内存,而不是/ dev / shm,它已经被当作tmpfs并应该用于共享内存.
标签:python,performance,numpy,linux,shared-memory 来源: https://codeday.me/bug/20191012/1900763.html