np.save生成的文件中的字节偏移是否总是128?

时间:2018-07-12 21:29:44

标签: python numpy

我一直在使用numpy memmaps,我注意到如果我生成了一些数据并将其像这样转储到磁盘中:

from os.path import join
import numpy as np
import tempfile

print('Generate dummy data')
N = 4
D = 3
x, y = np.meshgrid(np.arange(0, N), np.arange(0, N))
data = np.ascontiguousarray((np.dstack([x] * D) % 256).astype(np.uint8))

print('Make temp directory')
dpath = tempfile.mkdtemp()
mem_fpath = join(dpath, 'foo.npy')

print('Dump memmap')
np.save(mem_fpath, data)

然后,np.memmapnp.load产生的数据是不同的。

file1 = np.memmap(mem_fpath, dtype=data.dtype.name, shape=data.shape,
                  mode='r')
file2 = np.load(mem_fpath)
print('file1 =\n{!r}'.format(file1[0]))
print('file2 =\n{!r}'.format(file2[0]))

导致

file1 =
memmap([[147,  78,  85],
        [ 77,  80,  89],
        [  1,   0, 118],
        [  0, 123,  39]], dtype=uint8)
file2 =
array([[0, 0, 0],
       [1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]], dtype=uint8)

这让我感到困惑,但是最终我发现我需要将np.memmap中的offset参数设置为128才能起作用:

for i in range(0, 1000):
    file1 = np.memmap(mem_fpath, dtype=data.dtype.name, shape=data.shape,
                      offset=i, mode='r')
    if np.all(file1 == data):
        print('i = {!r}'.format(i))
        break

print('file1 =\n{!r}'.format(file1[0]))

得出结果

i = 128
file1 =
memmap([[0, 0, 0],
        [1, 1, 1],
        [2, 2, 2],
        [3, 3, 3]], dtype=uint8)

我的问题是,这128个数字是哪里来的。我检查了np.save文档,但没有看到对它的引用。我也尝试过修改数据的dtype和形状,但是我总是发现偏移量是128。我可以假设任何用np.save保存的单个数组都将始终具有128偏移量吗?如果没有,如何确定偏移量。

我问的原因是因为我发现从磁盘上较大的文件中裁剪小区域的特定用例中,使用np.memmap比np.load快得多。

谢谢您的帮助!

1 个答案:

答案 0 :(得分:2)

您所看到的128字节偏移量应视为实现的偶然现象。 NPY文件头的长度为required,是16的倍数,实现currently对齐到64个字节,因为16不足以在所有平台上进行内存映射。

128个字节将是一个非常常见的标头大小,因为标头中的样板大约需要64个字节,并且大多数数组的格式不够复杂,无法使用超过128个字节的标头来描述他们。但是,结构化数组很容易导致标头超过128个字节,并且由较早的NumPy版本或该格式的不同实现产生的NPY文件可能具有不同的对齐方式。