MATLAB中的内存映射文件?
Posted
技术标签:
【中文标题】MATLAB中的内存映射文件?【英文标题】:Memory map file in MATLAB? 【发布时间】:2014-01-06 15:12:08 【问题描述】:我决定使用 memmapfile,因为我的数据(通常为 30Gb 到 60Gb)太大而无法放入计算机的内存中。
我的数据文件包含两列数据,对应于两个传感器的输出,我有 .bin 和 .txt 两种格式。
m=memmapfile('G:\E-Stress Research\Data\2013-12-18\LD101_3\EPS/LD101_3.bin','format','int32')
m.data(1)
我使用上面的代码将我的数据内存映射到变量“m”,但我不知道要使用什么数据格式(int8','int16','int32','int64','uint8',' uint16'、'uint32'、'uint64'、'single' 和 'double')。 事实上,我尝试了 MATLAB 支持的所有列出的数据格式,但是当我使用 m.data(index number) 时,我从来没有得到我所期望的一对数字(2 列数据),这个数字也将是根据我使用的格式而有所不同。
如果有人对 memmapfile 有经验,请帮助我。
Here 是我的数据文件的一些较小版本,因此人们可以了解我的数据的结构:
干杯 詹姆斯
【问题讨论】:
假设你有一个普通的二进制文件,没有结构。所有的数据都简单的写成一行,类似于X(:)
将矩阵转换为向量。你有任何信息如何编写二进制文件吗?如果没有,请尝试创建小示例 .txt 和 .bin 文件并上传。
看来使用'Format'
选项可以指定“数组形状”。
@DanielR 我不知道二进制文件是怎么写的,但是我创建了一些相对较小的文件并上传了它们:dropbox.com/sh/rzut4zbrert9fm0/q9SiZYmrdG
@A.Donda 我认为定义数组形状的问题是我有两列数据但长度未知;这还能用吗?
使用常规数据时,如果数据大小未知,可以使用reshape(data,2,[])
,[]
是一个占位符,表示使用任何适合的函数,' 中可能有类似的选项格式化函数
【参考方案1】:
memmapfile
是为读取二进制文件而设计的,这就是您在处理文本文件时遇到问题的原因。那里的数据是字符,因此您必须将它们作为字符读取,然后将它们解析为数字。更多内容如下。
二进制文件似乎不仅仅包含以二进制格式写入的浮点值流。我也在文件中看到标识符(字符串)和其他内容。您阅读该文件的唯一希望是联系创建二进制文件的设备制造商,并询问他们如何读取此类文件。可能会有一个 SDK,或者至少是格式的描述。您可能需要对此进行调查,因为您的文本文件中的浮点数可能会被截断,也就是说,与直接读取浮点数的二进制表示相比,您会丢失精度。
好的,那么如何使用memmapfile
读取您的文件? This post 提供了一些提示。
首先我们以'uint8'
的形式打开您的文件(注意没有'char'
选项,因此作为一种解决方法,我们将文件内容读入相同大小的数据类型):
m = memmapfile('RTL5_57.txt','Format','uint8'); % uint8 is default, you could leave that off
我们可以通过将读取的数据转换为 char 来将读取的 uint8 数据渲染为字符:
c = char(m.Data(1:19)).' % read the first three lines. NB: transpose just for getting nice output, don't use it in your code
c =
0.398516 0.063440
0.399611 0.063284
0.398985 0.061253
由于文件中的每一行都具有相同的长度(数字为 2*8 个字符,换行符为 1 个制表符,换行符为 2 个字符 = 19 个字符),我们可以通过读取 N*19
值从文件中读取 N
行.所以m.Data(1:19)
给你第一行,m.Data(20:38)
第二行,m.Data(20:57)
第二和第三行。一次读多少就读多少。
然后我们必须将读入的数据解析成浮点数:
f = sscanf(c,'%f')
f =
0.3985
0.0634
0.3996
0.0633
0.3990
0.0613
现在剩下的就是将它们重塑为两列格式
d = reshape(f,2,[]).'
d =
0.3985 0.0634
0.3996 0.0633
0.3990 0.0613
比使用memmapfile
更简单的方法:
您不需要使用memmapfile
来解决您的问题,而且我认为这会使事情变得更加复杂。您可以简单地使用fopen
后跟fread
:
fid = fopen('RTL5_57.txt');
c = fread(fid,Nlines*19,'*char');
% now sscanf and reshape as above
% NB: one can read the values the text file directly with f = fscanf(fid,'%f',Nlines*19).
% However, in testing, I have found calling fread followed by sscanf to be faster
% which will make a significant difference when reading such large files.
使用它,您可以一次读取Nlines
值对,处理它们,然后再次调用fread
以读取下一个Nlines
。 fread
记住它在文件中的位置(就像 fscanf
一样),所以只需使用相同的调用来获取下一行。因此很容易编写一个循环来处理整个文件,如果您在文件末尾,请使用feof(fid)
进行测试。
建议使用更简单的方法here:使用textscan
。稍微修改他们的示例代码:
Nlines = 10000;
% describe the format of the data
% for more information, see the textscan reference page
format = '%f\t%f';
fid = fopen('RTL5_57.txt');
while ~feof(fid)
C = textscan(fid, format, Nlines, 'CollectOutput', true);
d = C1; % immediately clear C at this point if you need the memory!
% process d
end
fclose(fid);
再次注意,fread
后跟 sscanf
将是最快的。但是请注意,只要文本文件中有一行与您的格式不完全匹配,fread
方法就会终止。另一方面,textscan
可以容忍空白更改,因此更加健壮。
【讨论】:
以上是关于MATLAB中的内存映射文件?的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核 内存管理内存映射相关数据结构 ⑥ ( 文件映射 虚拟内存区域 | vm_area_struct | vm_operations_struct | 匿名映射 虚拟内存区域 )