为什么在Matlab.*运算符在某些情况下比标量更快?

x1h*_*g1x 5 performance matlab

请考虑以下代码:

a=rand(10000); b=rand(10000);
tic; 2*(a<b); toc;
tic; 2.*(a<b); toc;    
Run Code Online (Sandbox Code Playgroud)

结果是:

Elapsed time is 0.938957 seconds.
Elapsed time is 0.426517 seconds.
Run Code Online (Sandbox Code Playgroud)

为什么第二种情况比第一种情况快两倍?

编辑:我使用矩阵的任何大小获得相同的结果,无论你测试它的顺序如何

(a<b).*3.56 vs (a<b)*3.56
Run Code Online (Sandbox Code Playgroud)

例如,但不是

(a.*b)*2 vs (a.*b).*2
Run Code Online (Sandbox Code Playgroud)

要么

(a*b)*2 vs (a*b).*2
Run Code Online (Sandbox Code Playgroud)

似乎有一个与逻辑数组的链接,因为我有相同的结果

(a&b)*2 vs (a&b).*2
Run Code Online (Sandbox Code Playgroud)

电脑:R2015b,Windows 10 x64

And*_*eak 6

我建议对性能进行更严格的检查.将测试放在一个命名函数中,让MATLAB优化两段代码,并多次运行两个代码,选择最快的运行时.我的预感是他们应该花费相同的时间,虽然我现在无法检查合理的矩阵大小.这是我要做的:

function product_timing(N)

a=rand(N);
b=rand(N);

tmin=inf;
for k=1:10
    tic;
    res1=2*(a<b);
    t=toc;

    if t<tmin
        tmin=t;
    end
end

disp(tmin);


tmin=inf;
for k=1:10
    tic;
    res2=2.*(a<b);
    t=toc;

    if t<tmin
        tmin=t;
    end
end
Run Code Online (Sandbox Code Playgroud)

更新

在我的R2012b上,两种方法之间似乎没有明显的区别.然而,正如其他人所指出的那样,R2015b及其新的执行引擎完全不同.

虽然我仍然不确定答案,但让我收集@ x1hgg1x的反馈(对这个答案和问题的评论)和@LuisMendo(在聊天中),只是为了详细说明我的无知:

  • c*3.56是一个整数因子(线程数?)的时间比c.*3.56(有任何标量)慢,如果clogical,但不是如果cuint8double
  • 矢量也是如此,而不仅仅是方形矩阵

正如在MATLAB产品页面上所述:

使用重新设计的MATLAB®执行引擎更快地运行程序.

改进的体系结构使用所有MATLAB代码的即时(JIT)编译和单个执行路径.该引擎提供了改进的语言质量,并为未来的增强提供了平台.

具体的性能改进包括:

...

元素智慧数学运算

许多元素数学运算的执行得到优化.这些操作是对数组的逐元素算术运算,如下所示:

>> b = ((a+1).*a)./(5-a);

然而,在寻找的文档.**,我看不到有关的问题太多信息.关于数组操作的数组与矩阵运算的注释,如.*:

如果一个操作数是标量而另一个不是标量,则MATLAB将标量应用于另一个操作数的每个元素.此属性称为标量扩展,因为标量扩展为与另一个输入大小相同的数组,然后操作将像通常使用两个数组一样执行.

矩阵产品*文档

如果至少有一个输入是标量,那么A*B相当于A.*B并且是可交换的.

正如我们看到的,对等A*BA.*B是值得商榷的.嗯,它们在数学上是等价的,但是有些奇怪的事情正在发生.

由于上面的注释,以及仅为logical阵列产生性能差异的事实,我认为这是一个未记录的功能.我原以为它与logicals只相关,每个占用1个字节,但加速并不表现在uint8阵列上.我建议,因为logicals实际上只包含一个信息,所以可以进行一些内部优化.这仍然无法解释为什么mtimes不这样做,这肯定与timesvs 的内部运作有关mtimes.

有一件事是肯定的:times实际上并没有依靠mtimes标量操作数(也许它应该?).由于在R2012b中缺少整体效果,我相信上面提到的新执行引擎的优化数组操作分别处理逻辑数组,允许特殊情况scalar.*logical_array加速,但缺少相同的优化mtimes.