我有一个关于子矩阵分配的计算时间的问题。 我曾经有过这样的代码:
B_tot(1:6,pos:pos+2) = [ddx 0 0;0 ddy 0;0 0 ddz;ddy ddx 0;0 ddz ddy;ddz 0 ddx];
根据Matlab分析器,这条线需要3.91秒(执行超过800,000次)。我觉得它需要很长时间,所以我用它取而代之:
B_tot(1,pos) = ddx;
B_tot(2,pos+1) = ddy;
B_tot(3,pos+2) = ddz;
B_tot(4,pos) = ddy;
B_tot(4,pos+1) = ddx;
B_tot(5,pos+1) = ddz;
B_tot(5,pos+2) = ddy;
B_tot(6,pos) = ddz;
B_tot(6,pos+2) = ddx;
计算时间仅为0.22秒,因此速度更快。
我现在的问题是:为什么子矩阵的分配速度要慢得多,我是否可以用漂亮的方式编写这样的分配,这仍然不是很耗时?
编辑: 我制作了一个可重复的代码用于比较:
tic
for i = 1:10000
B_tot = zeros(6,24);
for j = 1:8
ddx = 1;
ddy = 2;
ddz = 3;
pos = j*3-2;
B_tot(1:6,pos:pos+2) = [ddx 0 0;0 ddy 0;0 0 ddz;ddy ddx 0;0 ddz ddy;ddz 0 ddx];
end
end
toc
tic
for i = 1:10000
B_tot = zeros(6,24);
for j = 1:8
ddx = 1;
ddy = 2;
ddz = 3;
pos = j*3-2;
B_tot(1,pos) = ddx;
B_tot(2,pos+1) = ddy;
B_tot(3,pos+2) = ddz;
B_tot(4,pos) = ddy;
B_tot(4,pos+1) = ddx;
B_tot(5,pos+1) = ddz;
B_tot(5,pos+2) = ddy;
B_tot(6,pos) = ddz;
B_tot(6,pos+2) = ddx;
end
end
toc
tic
for i = 1:10000
B_tot = zeros(6,24);
for j = 1:8
ddx = 1;
ddy = 2;
ddz = 3;
pos = j*3-2;
B_tot(sub2ind(size(B_tot),[1 2 3 4 4 5 5 6 6],pos+[0,1,2,0,1,1,2,0,2]))=[ddx,ddy,ddz,ddy,ddx,ddz,ddy,ddz,ddx];
end
end
toc
输出:
Elapsed time is 0.287602 seconds.
Elapsed time is 0.012062 seconds.
Elapsed time is 0.510040 seconds.
答案 0 :(得分:0)
使用Octave 4.0,我看到了运行脚本的时间:
Elapsed time is 2.30614 seconds.
Elapsed time is 3.02992 seconds.
Elapsed time is 1.84936 seconds.
Wolfie的版本是最快的,单元素索引是最慢的!
Octave的JIT(如果有的话)不如MATLAB好,因此时间相对较慢。
我认为你在这里看到的是MATLAB的JIT在某种程度上更好地针对单元素索引进行了优化。还要注意
B_tot(1:6,pos:pos+2) = [ddx 0 0;0 ddy 0;0 0 ddz;ddy ddx 0;0 ddz ddy;ddz 0 ddx];
创建一个矩阵,将值复制到其中,然后索引到B_tot
并复制那里的值。当然,这可以优化执行,但他们可能没有这样做。
另请注意,您将在不同版本的MATLAB中看到非常不同的时序。我确信旧版本的MATLAB将显示类似于我现在使用Octave的时序。但是,未来版本的MATLAB很可能会为这些时序显示不同的顺序,因为它们会进一步改进JIT并优化更多语法案例。
答案 1 :(得分:-1)
子矩阵分配的底层实现由循环组成。循环总是慢于线性编程流程。如果你要进入assambler层,循环看起来有点像这样。
Pos Operation
1 load variable1, variable2
2 cmp = compare variable1, variable2
3 if cmp : goto pos 4, else : goto pos 17
4 load something
5 operate on something
...
16 goto pos 1
17 load something_else
虽然线性程序至少可以减少四次操作。
......我知道这不是真正的汇编程序,但我不知道语法。