Matlab性能:比算算慢

Rod*_*uis 11 performance matlab jit operators octave

前一阵子我提供了这个问题的答案.

目标:计算此矩阵中值[3 6]范围内的值的数量:

A = [2 3 4 5 6 7;
     7 6 5 4 3 2]
Run Code Online (Sandbox Code Playgroud)

我想出了12种不同的方法:

count = numel(A( A(:)>3 & A(:)<6 ))      %# (1)
count = length(A( A(:)>3 & A(:)<6 ))     %# (2)
count = nnz( A(:)>3 & A(:)<6 )           %# (3)
count = sum( A(:)>3 & A(:)<6 )           %# (4)

Ac = A(:);
count = numel(A( Ac>3 & Ac<6 ))          %# (5,6,7,8)
%# prevents double expansion
%# similar for length(), nnz(), sum(),
%# in the same order as (1)-(4)

count = numel(A( abs(A-(6+3)/2)<3/2 ))   %# (9,10,11,12)
%# prevents double comparison and & 
%# similar for length(), nnz(), sum()
%# in the same order as (1)-(4)
Run Code Online (Sandbox Code Playgroud)

所以,我决定找出最快的.测试代码:

A = randi(10, 50);
tic
for ii = 1:1e5

    %# method is inserted here

end
toc
Run Code Online (Sandbox Code Playgroud)

结果(最好的5次运行,全部以秒为单位):

%# ( 1): 2.981446
%# ( 2): 3.006602
%# ( 3): 3.077083
%# ( 4): 2.619057
%# ( 5): 3.011029
%# ( 6): 2.868021
%# ( 7): 3.149641
%# ( 8): 2.457988
%# ( 9): 1.675575
%# (10): 1.675384
%# (11): 2.442607
%# (12): 1.222510
Run Code Online (Sandbox Code Playgroud)

所以这似乎count = sum(( abs(A(:)-(6+3)/2) < (3/2) ));是去这里最快的方式......

我交换一个<有两个部门,一个加法和一个abs,执行时间不到一半!有没有人解释为什么会这样?

JIT编译器可能用内存中的单个值替换了分区/添加,但是仍然存在abs......分支错误预测?对于像这样简单的事情似乎很愚蠢......

Ivo*_*ops 6

A(:)>3 & A(:)<6表达需要评估两个条件,而abs(A(:)-(6+3)/2) < 3/2)仅评估一个一个.

对于非常紧凑的计算密集型循环,这会产生很大的不同.即使没有分支错误预测,分支本身也相对昂贵.这就是为什么,例如,循环展开作为一种优化技术.