2

我在一台有很多 RAM 的机器上有一个框架,它生成带有一个非常大且专门命名的矩阵的 MAT 文件。这个矩阵的计算只进行一次并且需要很多时间。最后将其存储到磁盘上的 MAT 文件中。

在使用阶段,应加载此 MAT 文件。问题是我不需要所有数据 - 只需要从该矩阵中选择某些列。

例如,我在大小为 [500x250000] 的文件 crfh.mat 中有一个矩阵“符号”并键入 double。我可能有兴趣仅使用该矩阵中的“ids”加载向量:

符号(:,ID)

有没有办法做到这一点?我在网上搜索,似乎没有人表示需要这种功能。我正在考虑编写一个 MEX 函数 select_mat() ,例如:

sign_sub = select_mat(mat_file, var_name, ids);

4

2 回答 2

3

如果您有一个非常大的矩阵,您只想加载其中的一部分,我不会将其保存为 .MAT 文件。将矩阵写入自己的二进制文件会更有效。然后,您可以使用FSEEK 之类的函数跳到文件中的各个索引点并仅读取您需要的内容。例如,让我们首先使用函数FWRITE将较小的样本矩阵保存到二进制文件中:

>> M = magic(5)  %# A sample matrix
M =
    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9

>> fid = fopen('bigmatrix.dat','w');  %# Open the file for writing
>> fwrite(fid,size(M),'uint8','l');   %# Write the matrix size (needed later) as
                                      %#   2 unsigned 8-bit (1-byte) integers
>> fwrite(fid,M,'uint8','l');         %# Write the matrix data as unsigned 8-bit
                                      %#   (1-byte) integers
>> fclose(fid);                       %# Close the file

现在,我们可以使用函数FREADFSEEK仅读取第三列:

>> colIndex = 3;
>> fid = fopen('bigmatrix.dat','r');    %# Open the file for reading
>> sizeM = fread(fid,2,'uint8','l');    %# Read the first two bytes to get the
                                        %#   size of the matrix in the file
>> fseek(fid,sizeM(1)*(colIndex-1),0);  %# Seek forward by an amount of two
                                        %#   columns worth of bytes
>> colData = fread(fid,sizeM(1),'uint8','l');  %# Read column 3 data
>> fclose(fid);                         %# Close the file
>> disp(colData)                        %# Confirm that the right column was read
     1
     7
    13
    19
    25

这只是一个简单的例子。您可能希望将其他信息写入文件(即标题信息),例如矩阵中每个值的字节大小或数据类型。这看起来似乎比将内容转储到 .MAT 文件需要更多的工作,而且确实如此,但如果文件 IO 操作的效率是一个大问题,那么在这种情况下,最好创建自己的文件格式来处理数据。

于 2011-03-17T18:56:06.300 回答
2

.mat您可以从具有多个变量的文件中加载特定变量。但是,我认为您不能只从 MATLAB 的变量中加载一组任意索引。

也就是说,如果您的问题属于您只需要访问特定行/列的类型,那么我可能会为您提供解决方法。

您可以从矩阵创建一个struct,将每列作为单独的字段,然后.mat使用选项保存文件,-struct以便将每个字段保存为单独的变量。这样,你就可以拿出你想要的那个。

dummy=randn(100,200);%# this is a test matrix
[dim1,dim2]=size(dummy);

dummyCell=mat2cell(dummy,dim1,ones(dim2,1));%# create a cell from the matrix
fieldNames=strcat(repmat({'col'},1,dim2),cellfun(@num2str,mat2cell(1:dim2,1,ones(dim2,1)),'UniformOutput',false));%# generate fieldnames for the struct

dummyStruct=cell2struct(dummyCell,fieldNames,2);%# create the struct
save('myDummyFile','-struct','dummyStruct')

我不知道直接将矩阵转换为结构的方法。因此,您首先将每一列拆分为单元格(排序是因为您指出您需要访问这些列。如果您需要行,则必须进行切换)。这是在单元格中dummyCell。现在要保存到结构,我们需要生成字段名称。这是在字符串单元格中fieldNames。它生成表单的字段名称col1col2等等...如果需要,您可以将其命名为有意义的名称。然后我们通过将每个单元格分配给相应的字段名称来将 转换cell为 a 。struct最后使用选项保存 mat 文件,该-struct选项告诉 MATLAB 将每个字段保存为单独的变量。所有这些都应该在您的程序保存巨大的 mat 文件时完成。现在,如果您需要访问,请说col52,你需要做的就是load('myDummyFile','col52')。如果需要,您还可以加载多个。

请记住,如果您对索引要求(即每行/每列)有一个顺序,如果您需要访问矩阵中的任意索引,这将很有效,那么这将不起作用。创建单元/结构并保存它时可能会有一些相关的开销。但是,如果您只保存一次,但经常访问,这将得到回报。

如果您的矩阵很大(按照今天的标准,500x250000 并不是那么大),您必须注意这种方法的内存问题,因为我们将整个矩阵复制到一个单元格和结构中。我一步一步地编写它,以便更清楚地理解,但是您可以通过创建一个单元格dummy并将其分配给自身来减少重复,对于结构也是如此。但是,这只会将副本数量减少 1,因为 Matlab 仍然必须将变量复制到内存中以在操作后分配给自身。

于 2011-03-17T18:29:31.680 回答