内存映射随着时间的推移而减慢,替代方案?

fab*_*789 9 python unix performance numpy memory-mapped-files

我有大约700个矩阵存储在磁盘上,每个矩阵有大约70k行和300列.

我必须相对快速地加载这些矩阵的部分,每个矩阵大约1k行,到内存中的另一个矩阵.我发现这样做的最快方法是使用内存映射,最初我能够在0.02秒内加载1k行.但是,性能根本不一致,有时每个矩阵的加载时间长达1秒!

我的代码大致如下:

target = np.zeros((7000, 300))
target.fill(-1)  # allocate memory

for path in os.listdir(folder_with_memmaps):
    X = np.memmap(path, dtype=_DTYPE_MEMMAPS, mode='r', shape=(70000, 300))
    indices_in_target = ... # some magic
    indices_in_X = ... # some magic
    target[indices_in_target, :] = X[indices_in_X, :]
Run Code Online (Sandbox Code Playgroud)

随着时间的推移,我确定它绝对是随着时间的推移而减速的最后一条线.


Upadte:绘制加载时间会产生不同的结果.有一次它看起来像这样,即降级不是渐进的,而是在恰好400个文件之后跳跃.这可能是一些操作系统限制吗?

Plot1

但另一次看起来完全不同:

Plot2

经过几次测试后,第二个图似乎是性能开发的典型.


另外,我试着del X在循环之后,没有任何影响.也没有mmap通过X._mmap.close()工作访问底层Python .


有关为什么表现不一致的任何想法?有没有更快的替代品来存储和检索这些矩阵?

Ulr*_*ern 4

HDD 不擅长“为多个主机提供服务”——速度下降的程度可能比人们预期的要大得多。为了演示,我使用以下代码读取 Ubuntu 12.04 计算机的 HDD 上的备份文件(每个大约 50 MB):

import os, random, time

bdir = '/hdd/backup/'
fns = os.listdir(bdir)

while True:
  fn = random.choice(fns)
  if not fn.startswith("duplicity-full."):
    continue
  ts = time.time()
  with open(bdir+fn, 'rb') as f:
    c = f.read()
  print "MB/s: %.1f" %(len(c)/(1000000*(time.time()-ts)))
Run Code Online (Sandbox Code Playgroud)

运行这些“进程”之一给我带来了不错的读取性能:

MB/s: 148.6
MB/s: 169.1
MB/s: 184.1
MB/s: 188.1
MB/s: 185.3
MB/s: 146.2
Run Code Online (Sandbox Code Playgroud)

并行添加第二个这样的过程会使速度减慢一个数量级以上:

MB/s: 14.3
MB/s: 11.6
MB/s: 12.7
MB/s: 8.7
MB/s: 8.2
MB/s: 15.9
Run Code Online (Sandbox Code Playgroud)

我的猜测是(即使用其他硬盘)是性能不一致的原因。我的预感是 SSD 会做得更好。对于我的机器,对于 SSD 上的大文件,由于并行读取器进程而导致的速度减慢仅为两倍,从约 440 MB/s 降至约 220 MB/s。(请参阅我的评论。)