【发布时间】:2017-11-17 06:41:27
【问题描述】:
在 MATLAB 中将行/列附加到矩阵中似乎是一件值得考虑的事情。例如,当我尝试将一列附加到具有多行多列的矩阵 A 时,例如
A = [A, added_col]
Matlab 会警告我,因为这必须在内存中制作 A 的副本,所以我最好使用预分配来提高速度。这是可以理解的,因为A中的底层数据占用了一块连续的内存。
我的问题是,删除行/列会导致类似的问题吗?比如去掉A的第二行:
A(2,:) = []
此操作是否就地进行?我真的不确定,因为一方面它似乎没有为内存中的数据腾出任何新空间,另一方面,A 的行将不连续存储(因为删除了第 2 行)。
那么内部会发生什么?这种操作是否足够有效以在实践中使用?谢谢!
刚刚用100000的复杂度测试了一下:
clc; clear;
N = 100000;
A = zeros(N, 3);
t1 = tic;
for ii = 1:N
A(ii, :) = [1 2 3];
end
t2 = toc;
还有
clc; clear;
N = 100000;
A = zeros(N, 3);
t1 = tic;
for ii = (N-1):-1:2
A(ii, :) = [];
end
t2 = toc;
结果:第一个(修改预分配矩阵)为 0.009 秒,第二个(从矩阵中删除行)为 53.429 秒。我认为这基本上解决了这个问题:不,从矩阵中删除行/列效率不高,因为它肯定涉及深度复制数据和重新分配内存。
此外,删除 columns 而不是行也不是一个好主意。正如我测试的那样,在上述复杂度范围内,它仍然需要大约两分钟:
N = 100000;
test_m = zeros(3, N);
tic
for ii = (N - 1):-1:2
test_m(:, ii) = [];
end
toc
% result: 105.436595 seconds.
% This was run on a different machine than the previous examples.
% But is still enough evidence that dynamically resizing a big matrix is a BAD idea.
所以,故事的结尾:不要尝试以这种方式删除列或行,除非你有一个非常小的矩阵。对于庞大的矩阵,请始终使用预分配。
【问题讨论】:
-
由于 MATLAB 将数据存储在 column-major(按列)编号方案中,因此删除列应该更有效。
-
@rahnema1 谢谢。但是内存的重新分配是不可避免的吗?
-
不一定!它可能会根据索引的类型使用不同的方法。例如,删除第一列只需要一次调用memmove 而无需重新分配。或者以更优化的方式,它可能不需要 memmove 并使用偏移量来表示数据的开始。
-
@rahnema1 不幸的是,当我测试它时,情况并非如此。执行列删除至少需要几十秒。
-
最好提供您的测试结果。例如,一个删除第一列的测试和另一个删除最后一列的测试以及第一行和最后一行的相同测试。
标签: matlab performance matrix memory