Matlab:从矩阵中删除行/列是否昂贵?

时间:2017-11-17 06:41:28

标签: matlab performance matrix memory

在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.009s,第二个为53.429(从矩阵中删除行)。我认为这基本上解决了这个问题: NO,从矩阵中删除行/列无法使用,因为它肯定涉及深度复制数据和重新分配内存。

此外,删除而不是行也不是一个好主意。正如我测试的那样,在上述复杂程度上,它仍然需要大约两分钟的时间:

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.

所以,故事的结尾:不要试图以这种方式删除列或行,除非你有一个非常小的矩阵。对于庞大的矩阵,请始终使用预分配。

1 个答案:

答案 0 :(得分:2)

这里有几个问题:

  1. 是否为删除分配了内存
  2. 行主要vs列主要内存访问
  3. 代码示例
  4. 预分配修改与删除?

1)如果不使用mex,则无法控制矩阵删除是否使用相同的内存。但是,您可以判断它是否发生。一种方法是用mex编写东西。或者,您可以激活format debug

N = 100000;
test_m = zeros(3, N);
t = evalc('disp(test_m)');
disp(t(1:100))
test_m(:,2:N-1) = [];
disp(t(1:100))

这将产生输出

Structure address = 1259f6da0
m = 3
n = 100000
pr = 15d6d2020
pi = 0
  Columns 1 through 9

     0 

Structure address = 1259f6b70
m = 3
n = 2
pr = 608001c95320
pi = 0
     0     0
     0     0
     0

     0 

请注意,为了使显示合理,我捕获了显示变量的输出,然后仅显示了其中的一部分。此输出,尤其是pr(指向实际数据的指针)指示发生了重新分配。我找不到任何未发生重新分配的情况。

2)正如某些注释中提到的和在问题中提到的那样,内存存储为以列为主。因此,当您删除列时,它可能比删除行更有效...

3)我不确定代码示例是否现实,但是一次性删除所有列或行会更有意义。这真的发生得很快。

N = 100000;
test_m = zeros(3, N);
test_m(:,2:N-1) = [];

4)最后,我不确定您的措辞指的是预分配修改还是删除。大图,最好避免在循环中删除行或列。而是保留一个数组,该数组指示应删除哪些列或行,然后一次性完成。