我想将硬盘上的一个大的 Fortran 记录(12G)映射到 numpy 数组。 (映射而不是加载以节省内存。)
Fortran 记录中存储的数据不是连续的,因为它是由记录标记划分的。记录结构为“标记、数据、标记、数据、...、数据、标记”。数据区域和标记的长度是已知的。
标记之间的数据长度不是4字节的倍数,否则我可以将每个数据区域映射到一个数组。
可以通过在memmap中设置offset来跳过第一个标记,是否可以跳过其他标记并将数据映射到数组?
对可能出现的含糊表达表示歉意,并感谢您提供任何解决方案或建议。
5 月 15 日编辑
这些是 Fortran 未格式化的文件。 record中存储的数据是一个(1024^3)*3 float32数组(12Gb)。
大于2GB的变长记录的记录布局如下所示:
(详情参见这里 -> [记录类型] -> [可变长度记录]部分。)
在我的例子中,除了最后一个,每个子记录的长度都是 2147483639 字节,并且间隔 8 个字节(如上图所示,前一个子记录的结束标记和后一个子记录的开始标记,8 个字节总共)。
我们可以看到第一个子记录以某个浮点数的前 3 个字节结束,第二个子记录以其余 1 个字节开始,即 2147483639 mod 4 =3。
可以使用
numpy.memmap
:
offset = 0
data1 = np.memmap('tmp', dtype='i', mode='r+', order='F',
offset=0, shape=(size1))
offset += size1*byte_size
data2 = np.memmap('tmp', dtype='i', mode='r+', order='F',
offset=offset, shape=(size2))
offset += size1*byte_size
data3 = np.memmap('tmp', dtype='i', mode='r+', order='F',
offset=offset, shape=(size3))
您需要根据数据类型设置
byte_size
。例如:
int32
需要byte_size=32/8
int16
byte_size=16/8
如果整个数组的数据类型是恒定的,您可以将数据加载到二维数组中,如下所示:
shape = (total_length/size,size)
data = np.memmap('tmp', dtype='i', mode='r+', order='F', shape=shape)
您可以根据需要更改
memmap
对象。甚至可以使数组共享相同的元素,在这种情况下,所有相应的数组都会感知共享元素中所做的更改。
其他参考: