numpy.load 随机选择的文件比顺序选择的文件需要更长的时间来加载

Randomly selected file take longer to load with numpy.load than sequential ones

上下文

在训练神经网络时,我意识到当我增加数据集的大小(不改变批大小)时,每批花费的时间会增加。重要的是,我需要为每个数据点获取 20 .npy 个文件,这个数字不依赖于数据集大小

问题

训练从 2 秒/迭代变为 10 秒/迭代... 没有明显的理由说明为什么训练会花费更长的时间。但是,我设法找到了瓶颈。这似乎与 .npy 文件的加载有关。


要重现此行为,这里有一个小脚本,您可以 运行 生成 10,000 个虚拟 .npy 文件:

def path(i):
    return os.sep.join(('../datasets/test', str(i)))

def create_dummy_files(N=10000):
    for i in range(N):
        x = np.random.random((100, 100))
        np.save(path(random.getrandbits(128)), x)

那你可以运行下面两个脚本自己对比一下:

我测试了两个脚本,每个脚本 运行 都测试了 100 次(在第二个脚本中,我使用迭代计数作为 i 的值,因此不会加载相同的文件两次)。我用 time.time() 调用包裹了 np.load(path(s)) 行。 我没有对采样进行计时,只是对加载进行计时。以下是结果:


我假设这些时间与加载脚本时的 CPU 的 activity 有关。但是,它并不能解释这种差距。为什么这两个结果如此不同?与文件索引的方式有关吗?

Edit:我在 运行dom 示例脚本中打印了 S,复制了 20 个文件名的列表,然后再次 运行 S 作为按字面定义的列表。它所花费的时间与 'sequential' 脚本相当。这意味着它与 fs 中不连续的文件或其他任何文件无关。似乎 运行dom 采样被计入计时器,yet 时间定义为:

t = time.time()
np.load(path(s))
print(time.time() - t)

我也尝试用 cProfile 包装 np.load 独占 ):相同的结果。

我确实说过:

I tested both scripts and ran them 100 times each (in the 2nd script I used the iteration count as the value for i so the same files are not loaded twice)

但是正如tevemadar提到的那样

i should be randomized

我把第二个版本选择不同个文件的操作完全搞砸了。我的代码像这样对脚本计时 100 次:

for i in trange(100):
   if rand:
      S = random.sample(L, 20)
   else:
      S = L[i: i+20] # <- every loop there's only 1 new file added in the selection, 
                     #    19 files will have already been cached in the previous fetch

第二个脚本应该是S = L[100*i, 100*i+20]!

是的,当计时时,结果是可比较的。