我有一个大的矩阵A,它是1GB的双倍值,当我将它重塑为不同的尺寸时,它的速度非常快。
A=rand(128,1024,1024);
tic;B=reshape(A,1024,128,1024);toc
Elapsed time is 0.000011 seconds.
怎么这么快?另一个观察结果是,运行该代码并存储两个1GB的矩阵后,MATLAB使用的内存少于应有的内存:Memory used by MATLAB: 1878 MB (1.969e+09 bytes)
答案 0 :(得分:25)
良好表现的解释
Matlab尽可能使用copy-on-write。如果编写像B=A
这样的表达式,MATLAB不会复制A,而是变量A
和B
都是对同一数据结构的引用。只有修改了两个变量中的一个,MATLAB才会创建副本。
现在讨论reshape
的特例。这看起来像A和B不一样,但在内存中它们是。保存数据的基础数组不受reshape
操作的影响,不需要移动任何内容:all(A(:)==B(:))
。调用reshape时,MATLAB必须做的就是创建一个新的引用,并用矩阵的新维度对其进行注释。 重塑矩阵只不过是创建一个对输入数据的新引用,它使用新维度进行注释。重塑的运行时间小于1μs或大致是B=A
这两个简单赋值所需的时间。对于所有实际应用,零时间操作。
>> tic;for i=1:1000;B=reshape(A,1024,128,1024);end;toc
Elapsed time is 0.000724 seconds.
>> tic;for i=1:1000;B=A;end;toc
Elapsed time is 0.000307 seconds.
不知道这样的引用到底有多大,但我们可以假设它在几个字节之内。
其他零成本操作
已知具有几乎零成本(运行时和内存)的函数:
B=reshape(A,sz)
B=A(:)
B=A.'
- 仅适用于向量B=A'
- 仅适用于实数的数字without the attribute complex
。请改用.'
。B=permute(A,p)
- 仅适用于all(A(:)==B(:))
。 1 B=ipermute(A,p)
- 仅适用于all(A(:)==B(:))
。 1 B=squeeze(A)
1 shiftdim
- 仅适用于all(A(:)==B(:))
的情况,其中: 1
“昂贵”的功能,无论它们是否触及内存中的表示(all(A(:)==B(:))
都是真的)
B(1:numel(A))=A;
2 (:)
以外的右侧索引,包括B=A(1:end);
和B=A(:,:,:);
2 1 在1μs和1ms之间,运行时间明显慢于reshape
。可能是因为一些不断的计算开销。内存消耗几乎为零,运行时独立于输入大小。没有此注释的操作的运行时间低于1μs,大致相当于reshape
。
2 OCTAVE零成本