最大大小未知时的MatLab内存分配

时间:2013-08-05 14:21:49

标签: matlab memory dynamic allocation

我正在尝试加速我在Matlab中编写的脚本,该脚本动态地将内存分配给矩阵(基本上从文件中读取一行数据并将其写入矩阵,然后读取另一行并为其分配更多内存一个更大的矩阵来存储下一行)。我这样做的原因,而不是使用零()或其他东西预分配内存是因为我不知道矩阵需要保存所有数据的确切大小。我也不知道矩阵的最大大小,所以我不能只预先分配最大大小然后摆脱我没有使用的内存。这对于少量数据来说很好,但现在我需要扩展我的脚本来读取数百万个数据点,这种动态分配的实现速度太慢了。

所以这是我尝试加速脚本:我尝试使用零值函数在大块中分配内存,然后一旦块被填充,我分配另一个大块。以下是一些示例代码:

data = [];   
count = 0;

for ii = 1:num_filelines    
   if mod(count, 1000) == 0  
       data = [data; zeroes(1000)];  %after 1000 lines are read, allocate another 1000 line
   end  
   data(ii, :) = line_read(file);  %line_read reads a line of data from 'file'
end

不幸的是,这不起作用,当我运行它时,我收到错误说“使用vertcat时出错” 连接的矩阵的尺寸不一致。“

所以这是我的问题:这种在大块中分配内存的方法实际上比增量动态分配更快,还有为什么上面的代码没有运行?谢谢你的帮助。

3 个答案:

答案 0 :(得分:4)

我建议您做什么,如果您知道行数并且可以猜出足够多的可接受列,请使用sparse matrix

% create a sparse matrix
mat = sparse(numRows,numCols)

稀疏矩阵不会存储所有零元素,它只存储指向非零的索引。这可以帮助节省大量空间。它们的使用和访问方式与任何其他矩阵相同。只有从一开始就以矩阵格式真正需要它。

如果没有,您只需cell即可。使用与文件中的行一样多的元素预分配cell array

data = cell(1,numLines);
% get matrix from line
for i = 1:numLines
    % get matrix from line
    data{i} = lineData;
end
data = cell2mat(data);

此方法会将所有内容放入单元格数组中,该数组可以存储“动态”,然后转换为常规矩阵。

<强>加成

如果你正在使用稀疏矩阵方法,那么在完成后修剪矩阵,因为你的矩阵可能比必要的大,你可以轻松地修剪它,然后将它投射到常规矩阵。

[val,~] = max(sum(mat ~= 0,2));
mat(:,val:size(mat,2)) = [];
mat = full(mat); % use this only if you really need the full matrix

这将删除任何不必要的列,然后将其强制转换为包含0个元素的完整矩阵。我不建议将它投射到一个完整的矩阵,因为这需要更多的空间,但如果你真的需要它,请使用它。

更新

要轻松获取文件中的行数,请使用MATLAB的perl解释器

创建一个名为countlines.pl的文件并粘贴在下面的两行

while (<>) {};
print $.,"\n";

然后您可以在文件上运行此脚本,如下所示

numLines = str2double(perl('countlines.pl','data.csv'));

问题解决了。

来自MATLAB论坛帖子here

记住最好事先预先分配所有内容,因为从技术上讲,在执行shai的方法时,你会大量重新分配大量数据,特别是如果它是一个大文件。

答案 1 :(得分:1)

要解决您的错误,请在分配

时使用此语法
data = [data; zeroes(1000, size(data,2))];

您可能希望阅读循环外的第一行,以便了解列数并为data进行首次分配。

答案 2 :(得分:0)

如果您希望坚持使用您编写的代码,我会将您的数据初始化data = []替换为

data = zeros(1,1000); 

请记住来自@ MZimmerman6的警告:zeros(1000)会生成1000 x 1000阵列。您可能希望将所有zeros语句更改为zeros( ... ,Nc),其中Nc =字符行长度。