繁体   English   中英

当 dtype=object 时,迭代读取大型 numpy 保存文件(即使用生成器)

[英]Reading a large numpy save file iteratively (i.e. with a generator) when the dtype=object

我有一个很大的 numpy 保存文件(可能比内存大)。 dtypeobject (它是一个可变长度 numpy 数组的 numpy 数组)。

我可以避免将整个文件读入内存吗?
例如,构建一个生成器来迭代地读取元素。

使用标准 numpy dtypes np.load(filename, mmap_mode='r')可以解决问题,但您不能将mmap_mode与对象数据类型一起使用。

我有机会通过阅读器流式传输字节吗? 还是我不知道的另一个技巧?

非对象数据类型的基本格式是头块(具有形状、数据类型、步幅等),后跟其数据缓冲区的字节副本。

换句话说,类似于这个序列:

In [129]: x
Out[129]: 
array([[1, 2, 3],
       [4, 5, 6]])
In [130]: x.tostring()
Out[130]: b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00'
In [132]: np.frombuffer(__, dtype=int)
Out[132]: array([1, 2, 3, 4, 5, 6])

但是,如果我将 dtype 更改为 object:

In [134]: X = x.astype(object)
In [135]: X
Out[135]: 
array([[1, 2, 3],
       [4, 5, 6]], dtype=object)
In [136]: X.tostring()
Out[136]: b'`\x1bO\x08p\x1bO\x08\x80\x1bO\x08\x90\x1bO\x08\xa0\x1bO\x08\xb0\x1bO\x08'

这些数据缓冲区字节指向内存中的位置。 由于这些是小整数,因此它们可能指向唯一的缓存值

In [137]: id(1)
Out[137]: 139402080
In [138]: id(2)
Out[138]: 139402096

如果元素是数组,它们将指向存储在内存中其他地方的那些数组(指向ndarray对象,而不是它们的数据缓冲区)。

处理这样的对象np.save使用pickle。 现在ndarray的泡菜是它的save字符串。 我不知道np.save把这些字符串放在哪里。 也许它是成行的,也许使用指向文件中后者的指针。

您/我们必须研究np.save (和函数调用)以确定如何保存这些数据。 我已经足够了解如何从文件中保存和加载多个数组,但没有关注对象 dtype 布局。 相关代码在numpy/lib/npyio.py , numpy/lib/format.py

format文件有一个关于保存格式的文档块。

np.save
   format.write_array

如果非对象write_array使用array.tofile(fp) 如果object ,它使用pickle.dump(array, fp)

同样read_array使用np.fromfile(fp, dtype) pickle.load np.fromfile(fp, dtype)pickle.load

所以这意味着我们需要深入研究array pickle.dump是如何完成的。

您可能想看看 numpy memmap。

来自官方文档:

内存映射文件用于访问磁盘上大文件的小段,而无需将整个文件读入内存。 NumPy 的 memmap 是类似数组的对象。 这与 Python 的 mmap 模块不同,后者使用类文件对象。

https://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM