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

最大大小未知时的MatLab内存分配,matlab,memory,dynamic,allocation,Matlab,Memory,Dynamic,Allocation,我正在尝试加速我在Matlab中编写的脚本,该脚本动态地为矩阵分配内存(基本上是从文件中读取一行数据并将其写入矩阵,然后读取另一行并为较大的矩阵分配更多内存以存储下一行)。我之所以这样做,而不是使用zeroes()或其他方法预先分配内存,是因为我不知道矩阵需要的确切大小来保存所有数据。我也不知道矩阵的最大大小,所以我不能预先分配一个最大大小,然后去掉我没有使用的内存。这对于少量数据来说很好,但现在我需要将脚本放大以读取数百万个数据点,而动态分配的实现速度太慢了 因此,这里是我加速脚本的尝试:我尝

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

因此,这里是我加速脚本的尝试:我尝试使用zeroes函数在大的块中分配内存,然后一旦块被填满,我就分配另一个大的块。以下是一些示例代码:

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
不幸的是,这不起作用,当我运行它时,我得到一个错误,上面写着“errorusingvertcat” 连接的矩阵的维数不一致。”


所以我的问题是:这种在大数据块中分配内存的方法实际上比增量动态分配快吗?为什么上面的代码不运行?谢谢您的帮助。

我建议您做的是,如果您知道行数,并且可以猜测足够多的可接受列,请使用
稀疏矩阵

% create a sparse matrix
mat = sparse(numRows,numCols)
稀疏矩阵不会存储所有零元素,它只存储指向非零索引的指针。这有助于节省大量空间。它们的使用和访问方式与任何其他矩阵相同。只有当您从一开始就真正需要矩阵格式时,才可以这样做

如果没有,您可以将所有操作都作为一个
单元来执行。预先分配一个
单元格数组
,其元素数与文件中的行数相同

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
添加

如果您正在使用稀疏矩阵方法,在完成后要修剪矩阵,因为您的矩阵可能会比需要的大,您可以轻松地修剪它,然后将其转换为常规矩阵

[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";
问题解决了

来自MATLAB论坛线程


请记住,最好事先预先分配所有内容,因为从技术上讲,在使用shai的方法时,您会大量重新分配大量内容,尤其是当它是一个大文件时

要解决错误,只需在分配时使用此语法即可

data = [data; zeroes(1000, size(data,2))];

您可能希望读取循环外的第一行,以便知道列的数量,并为
数据进行第一次分配

如果您希望按照编写的代码进行操作,我会将数据初始化替换为
数据=[]

data = zeros(1,1000); 

请记住@MZimmerman6的警告:
zero(1000)
生成一个1000 x 1000的数组。您可能希望将所有
zero
语句更改为
zero(…,Nc)
,其中Nc=以字符为单位的行长度。

执行zero(1000)时,您正在分配一个1000x1000的零矩阵。这可能就是代码没有运行的原因。至于分配速度,在matlab中预先分配总是很好的,但是在行中读取数据时,使用单元格来存储数据,而不是使用数组。这样你就不会有那么多问题了。或者使用稀疏矩阵。这在某种程度上取决于您使用的Matlab版本。最近的版本在动态内存分配方面表现得非常快。您可能希望通过“猜测”/估计非零矩阵的数量,为稀疏矩阵中的非零保留空间-zeros@Shai我不确定你的意思,稀疏矩阵将为你处理分配和其他任何事情。我的问题不太清楚,但我实际上不知道我需要多少行。Shai对我发布的代码的修复解决了我遇到的问题,并大大加快了我的脚本速度。不过,感谢您建议使用sparse()和指针,我没有想到这一点。现在我的问题已经解决了,我很好奇,我的方法是随着数据行数线性扩展,还是仅仅比动态添加新行好得多?我想我不明白为什么在块中分配内存更有效。我提出了一种获取文件行数的方法,它既快速又简单。我不知道Matlab有一个perl解释器,我想这种方法比我的方法更适合我需要读取的数据行数。我真的不明白为什么我的方法比重新分配每一步都要快(当然是这样)。是的,那是错误的,没有为零矩阵输入正确的列数。虽然行数未知,但我碰巧知道我需要多少列,但是单独阅读第一行也是一个很好的主意,可以使脚本更加通用,谢谢。