请考虑以下代码:
a=rand(10000); b=rand(10000);
tic; 2*(a<b); toc;
tic; 2.*(a<b); toc;
结果是:
Elapsed time is 0.938957 seconds.
Elapsed time is 0.426517 seconds.
为什么第二种情况比第一种情况快两倍?
编辑:我使用矩阵的任何大小获得相同的结果,无论你测试它的顺序如何
(a<b).*3.56 vs (a<b)*3.56
例如,但不是
(a.*b)*2 vs (a.*b).*2
要么
(a*b)*2 vs (a*b).*2
似乎有一个与逻辑数组的链接,因为我有相同的结果
(a&b)*2 vs (a&b).*2
电脑:R2015b,Windows 10 x64
3 回答
我建议对性能进行更严格的检查 . 将测试放在一个命名函数中,让MATLAB优化两段代码,并多次运行两个代码,选择最快的运行时 . 我的预感是他们应该花费相同的时间,虽然我现在无法检查合理的矩阵大小 . 这是我要做的:
更新
在我的R2012b上,两种方法之间似乎没有明显的区别 . 然而,正如其他人所指出的那样,R2015b及其新的执行引擎完全不同 .
虽然我仍然不确定答案,但让我收集@x1hgg1x(对这个答案和问题的评论)和@LuisMendo(in chat)的反馈,只是为了阐述我的无知:
如果
c
是logical
,c*3.56
是一个比c.*3.56
(有任何标量)慢的整数因子(线程数?),但如果c
是uint8
或double
则不是同样适用于矢量,而不仅仅是方形矩阵
如上所述on a MATLAB product page:
但是,看看
.*
和*
的文档,我看不出有关该问题的太多信息 . array vs matrix operations关于数组操作的注释,如.*
:doc of the matrix product *说
如我们所见,
A*B
和A.*B
的等价性是有争议的 . 嗯,它们在数学上是等价的,但是有些奇怪的事情正在发生 .由于上面的注释,以及只有
logical
数组出现性能差异这一事实,我认为这是一个未记录的功能 . 我和logical
只相关,每个只占1个字节,但加速并没有显示uint8
数组 . 我建议,由于logical
实际上只包含一位信息,因此可以进行一些内部优化 . 这仍然无法解释为什么mtimes
确实与times
vsmtimes
的内部运作无关 .有一件事是肯定的:
times
对于标量操作数实际上并没有回归mtimes
(也许它应该?) . 由于在R2012b中缺少整体效果,我相信上面提到的新执行引擎的优化数组操作分别处理逻辑数组,允许加速scalar.*logical_array
的特殊情况,但mtimes
缺少相同的优化 .对于背景,
*
运算符是矩阵运算符,而*.
是元素运算符(请参阅http://www.mathworks.com/help/matlab/matlab_prog/array-vs-matrix-operations.html) .在您的测试中,a和b是随机的1000x1000矩阵,它们评估为您想要使用这两种方法进行缩放的逻辑1000x1000矩阵 . 除了让Mathworks的开发人员告诉我们发生了什么之外,我认为我们只能猜测导致差异的原因(并回答你的问题) .
既然,我们不应该推测这些答案,我将在这里正式停止 . 然而,有趣的是你偶然发现了同样的事情 .
所以,非正式地,我怀疑你已经找到了一些额外的开销MATLAB正在实现处理
*
运算符的矩阵运算,这些运算符在元素运算符中被短路或旁路 .考虑以下
其中
a
和b
由上面的代码定义,并且d
为了解释而留作未知值,接下来 .当乘以矩阵时,第一矩阵中的列数需要与第二矩阵中的行数匹配 .
c
将是1000x1000矩阵,对,所以d
要么需要1000列(例如size(d,2)==1000
),要么需要是标量 . 在第二种情况下,d
必须是标量(否则将抛出错误) .另外,在进行乘法时,可能会有一些额外的准备(不多,但有些),因为您可以为最终产品中的每个位置正确获得总和 . 在这里,我们知道
d==2
并且它是一个标量,因此乘法可以在适当的位置完成 . 但是,我们知道因为我们看到了它 . 我不认为乘法算法在这里作为一个角落案例 - 看到d
是一个标量值 . 如果是,它将/应该只调用*.
例程 . 而且,也许这就是正在发生的事情,我们只是获得了一些级别的堆栈开销 . 当然是非官方的 .是的,2015b在标量和逻辑数组之间“ . *”更快: