从磁盘预取numpy数组?

时间:2016-03-15 01:19:48

标签: python python-2.7 numpy pickle shelve

我正在使用一堆并非全部适合RAM的numpy数组,所以我需要定期将它们保存到磁盘并从磁盘加载。

通常,我知道我需要提前阅读哪些内容,所以我想通过发布类似" prefetch"来隐藏延迟。提前指示。

我该怎么做?

There is a similar question related to TensorFlow:  但是,我没有使用TensorFlow,因此我不想创建它的依赖项。)

3 个答案:

答案 0 :(得分:3)

如果您在类UNIX系统上使用Python 3.3+,则可以在打开文件后使用os.posix_fadvise启动预取。例如:

with open(filepath, 'rb') as f:
    os.posix_fadvise(f.fileno(), 0, os.stat(f.fileno()).st_size, os.POSIX_FADV_WILLNEED)

    ... do other stuff ...

    # If you're lucky, OS has asynchronously prefetched file contents
    stuff = pickle.load(f)

除此之外,Python不直接提供任何用于显式预取的API,但您可以使用ctypes手动加载操作系统相应的预取功能,或使用后台线程除了读取和丢弃块之外什么都不做从文件中提高数据在系统缓存中的几率。

答案 1 :(得分:0)

[免责声明:这里无耻的自我宣传:-)] 我编写了一个应该对此有所帮助的库,它与python 2.7兼容:documentation / repository

您可以使用其prefetch函数执行其所说的内容,预取一些值:

files = ['file1.npy', 'file2.npy', 'file3.npy']

def next_to_preload(current_idx):
    return (current_idx + 1) % 3

loaded = seqtools.smap(np.load, files)  # behaves like a list but elements are computed on-demand
preloaded = seqtool.prefetch(
    loaded, 
    max_buffered=10,
    direction=(0, next_to_preload))

for i in range(3):
    print(preloaded[i])

如果您想从线程切换到进程等,还有一些选项。

请注意,提取与根据next_to_preload设置的项目不同的项目将重置缓冲区。

答案 2 :(得分:0)

您可以在读取模式下加载numpy数组文件(file_name.npy)。这不会在RAM或计算内存中桥接文件,但会在RAM中获得引用,并且只会在磁盘内存中引用阵列文件。 我们可以像在RAM本身中提取一样对数组进行迭代,但是在读取模式下加载numpy文件的好处是计算和迭代不会影响运行时内存。

import numpy as np

FILE_PATH = "path/file_name.npy"
numpy_array = np.load(file_path, mmap_mode='r')
# to do operations on numpy array with the same dimension of matrix(axis=0)
numpy_array = np.append(numpy_array, calculated_new_matrix, axis = 0)
# to save the file back into the same file path
np.save(FILE_PATH, numpy_array)

这可以节省运行时内存,并且您还可以在batch_size中运行numpy数组操作(对于大型数组文件),以节省计算复杂性和内存以提高效率。