【问题标题】:Memory-Mapping Slows Down Over Time, Alternatives?内存映射会随着时间的推移而减慢,替代方案?
【发布时间】:2016-05-21 15:53:26
【问题描述】:

我在磁盘上存储了大约 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, :]

通过逐行计时,我确定它肯定是随着时间的推移减慢的最后一行。


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

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

经过几次测试后,第二个情节似乎是性能发展的典型。


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


关于为什么性能不一致的任何想法?是否有更快的替代方法来存储和检索这些矩阵?

【问题讨论】:

  • 当您移至下一个文件时,基础mmap 文件似乎没有被关闭。这是一个疯狂的猜测,但我会尝试在循环末尾添加一个del Xnp.memmap 的代码是 Python 可读的,但 mmap.mmap 的代码不是。
  • 索引的范围是多少?它们是否已排序? IE。 indices_in_Xnp.arange(1000) 还是 np.random.shuffe(np.arange(0, 70000, 70)) 很重要。另外,尝试使时间与操作系统文件缓存效果无关:unix.stackexchange.com/q/87908
  • @morningsun 感谢您的回复。我尝试对indices_in_Xindices_in_target 进行排序,我认为它略微改善了基线,但看似随机的退化补丁仍然存在。同样不幸的是,我正在使用共享服务器并且没有任何 sudo 权限,所以我无法清除任何缓存。
  • 既然这是共享服务器,那么其他用户正在做的事情导致性能不一致的可能性有多大?如果有可能,是否有一段时间您可以在服务器上没有其他人的情况下测试您的代码?
  • 这些加载时间是否包括程序启动,或者它们是否包含在您的代码中?您如何控制测试的文件数量?

标签: python performance unix numpy memory-mapped-files


【解决方案1】:

HDD 不擅长“为多个主设备提供服务”——减速可能比人们预期的要大得多。为了演示,我使用这段代码读取了我的 Ubuntu 12.04 机器硬盘上的备份文件(每个大约 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)))

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

MB/s: 148.6
MB/s: 169.1
MB/s: 184.1
MB/s: 188.1
MB/s: 185.3
MB/s: 146.2

并行添加第二个这样的过程会使事情变慢一个数量级以上:

MB/s: 14.3
MB/s: 11.6
MB/s: 12.7
MB/s: 8.7
MB/s: 8.2
MB/s: 15.9

我的猜测是这(即其他硬盘使用)是您性能不一致的原因。我的预感是 SSD 会做得更好。对于我的机器,对于 SSD 上的大文件,由于并行读取器进程导致的减速只有两倍,从大约 440 MB/s 到大约 220 MB/s。 (见我的评论。)

【讨论】:

  • 感谢您的意见。我请求访问带有 SSD 的服务器,看看情况如何
  • 我刚刚用一些大文件对我的 SSD 进行了快速测试。一个进程:约440 MB/s;与第二个进程并行:大约 220 MB/s。所以在这种情况下,SSD 在“服务两个主”方面比 HDD 好得多。
  • 假设浮点数(4 字节)就足够了,如果不压缩 700 个矩阵大约需要 59 GB,那么在强大的服务器上可以实现“全主存”解决方案。 Gary 的建议 (bcolz) 或其他压缩可能有助于磁盘或主内存解决方案。
  • 你好。因此,正如您所例外的那样,SSD 让事情变得更快、更一致!所以我愿意相信“为> 1个主人服务”是问题所在。关于“所有主内存”的解决方案:我现在实际上有 700 个可用的演出(!)但我必须在第二步中转换矩阵以使其维度更高,所以我无法加载所有矩阵 和 i> 立即将转换后的内容保存在内存中,即使内存量如此荒谬。
【解决方案2】:

您可以考虑使用 bcolz 。它压缩磁盘和内存中的数字数据以加快速度。您可能必须转置矩阵以获得稀疏读取,因为 bcolz 按列而不是按行存储内容。

【讨论】:

  • 谢谢!听起来很有希望。使用 SSD 可以获得相当合理的性能,如果现在实施 bcolz 是否值得,我将不得不向我的主管咨询。
猜你喜欢
  • 2014-02-04
  • 2018-06-25
  • 1970-01-01
  • 2017-11-02
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-17
相关资源
最近更新 更多