我有一个很大的(75000 x 5 x 6000)3D数组存储为NumPy内存映射。如果我只是像这样迭代第一个维度:

import numpy as np
import time

a = np.memmap(r"S:\bin\Preprocessed\mtb.dat", dtype='float32', mode='r', shape=(75000, 5, 6000))
l = []
start = time.time()
index = np.arange(75000)
np.random.shuffle(index)
for i in np.array(index):
    l.append(np.array(a[i]) * 0.7)
print(time.time() - start)

>>> 0.503


迭代发生得非常快。但是,当我尝试在较大程序的上下文中迭代同一memmap时,对memmap的单个调用将花费多达0.1秒的时间,而提取所有75000条记录将花费近10分钟的时间。

较大的程序太长了,无法在此处重现,所以我的问题是:是否存在任何已知问题会导致memmap访问速度显着降低,或者是否可能在Python内存中保留了大量数据?

在较大的程序中,用法如下所示:

import time
array = np.memmap(self.path, dtype='float32', mode='r', shape=self.shape)
for i, (scenario_id, area) in enumerate(self.scenario_areas):
    address = scenario_matrix.lookup.get(scenario_id)
    if address:
        scenario_output = array[address]
        output_total = scenario_output * float(area)
        cumulative += output_total  # Add results to cumulative total
        contributions[int(scenario_id.split("cdl")[1])] = output_total[:2].sum()
del array


第二个示例需要十多分钟才能执行。只是将记录从memmap中拉出的脚本方案方案censing_output = array [address]的时间在0.0到0.5之间-半秒以拉出一条记录。

最佳答案

据我所知,没有任何可归因于python中memmap的限制,这些限制独立于一般的os级限制。因此,我想您可能是操作系统级别的内存瓶颈(可能是不同的大型mmap的缓存之间的交互),或者您的问题出在其他地方。

很好,您已经有一个参考实现,可以显示操作应该有多快。您将需要系统地测试不同的可能原因。以下是一些有助于确定原因的说明。

首先,在参考实现和上都使用cProfile,以更好地了解瓶颈在哪里。您将获得函数调用列表以及每个函数所花费的时间。这可能会导致意外的结果。一些猜测:


确实大部分时间都花在了您已发布的代码段中吗?如果不是这样,则分析可能会提示另一个方向。
self.scenario_areas是列表式的还是迭代器执行一些隐藏且昂贵的计算?
查找scenario_matrix.lookup.get(scenario_id)可能很慢。核实。
contributions是常规的python列表或dict,还是在幕后分配时做任何奇怪的事情?


仅当您确认确实在scenario_output = array[address]行中花费了时间时,我才开始假设mmap文件之间的交互。如果是这种情况,请开始注释掉涉及其他内存访问的部分代码,并反复分析该代码,以更好地了解发生的情况。

我希望这有帮助。

关于python - NumPy memmap性能问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42864320/

10-12 16:56