Consider the following code :
a=rand(10000); b=rand(10000);
tic; 2*(a<b); toc;
tic; 2.*(a<b); toc;
The result is :
Elapsed time is 0.938957 seconds.
Elapsed time is 0.426517 seconds.
Why the second case is twice faster than the first case ?
Edit : I obtain the same result with any size of the matrix, whatever the order you test it, with
(a<b).*3.56 vs (a<b)*3.56
for example, but not with
(a.*b)*2 vs (a.*b).*2
or
(a*b)*2 vs (a*b).*2
It seems there is a link with the logical array, because I have the same result with
(a&b)*2 vs (a&b).*2
Computer : R2015b, Windows 10 x64
MATLAB - Scalar Operations of Matrices. When you add, subtract, multiply or divide a matrix by a number, this is called the scalar operation.
MATLAB * multiplication for non-scalar matrices A and B, the size of the matrices must be equal. The representation of rows of A must equal the representation of columns of B. Let’s consider matrices A and B and can calculate the product of these two matrices. MATLAB * operator under the arithmetic operator’s community.
The general answer to "Why is matlab faster at doing xxx than other programs" is that matlab has a lot of built in, optimized functions. The other programs that are used often do not have these functions so people apply their own creative solutions, which are suprisingly slower than professionally optimized code.
MATLAB * operator under the arithmetic operator’s community. MATLAB has two varieties of arithmetic operators; Array Operations: It’s an arrangement of objects and numbers in rows and columns. An array is also a helpful presentation of multiplication concepts in mathematics and executes element-wise operations.
I suggest performing a more strict check of performance. Put your test in a named function to let MATLAB optimize both pieces of code, and run both codes several times, choosing the quickest runtime. My hunch is that they should take the same amount of time, although I can't check right now with reasonable matrix sizes. Here's what I'd do:
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
On my R2012b there doesn't seem to be a marked difference between the two methods. However, as others have indicated, R2015b with its new execution engine makes all the difference.
While I'm still unsure about the answer, let me collect the feedback from @x1hgg1x (comments on both this answer and question) and @LuisMendo (in chat), just to elaborate on my ignorance:
c*3.56
is an integer factor (number of threads?) of times slower than c.*3.56
(with any scalar) if c
is logical
, but not if c
is uint8
or double
As it's stated on a MATLAB product page:
Run your programs faster with the redesigned MATLAB® execution engine.
The improved architecture uses just-in-time (JIT) compilation of all MATLAB code with a single execution pathway. The engine offers improved language quality and provides a platform for future enhancements.
Specific performance improvements include those made to:
...
Element-Wise Math Operations
The execution of many element-wise math operations is optimized. These operations are element-by-element arithmetic operations on arrays such as the following:
>> b = ((a+1).*a)./(5-a);
However, looking at the docs of .*
and *
, I can't see too much information relating to the problem. A note from array vs matrix operations concerning array operations like .*
:
If one operand is a scalar and the other is not, then MATLAB applies the scalar to every element of the other operand. This property is known as scalar expansion because the scalar expands into an array of the same size as the other input, then the operation executes as it normally does with two arrays.
And the doc of the matrix product *
says
If at least one input is scalar, then A*B is equivalent to A.*B and is commutative.
As we see, the equivalence of A*B
and A.*B
is arguable. Well, they are equivalent mathematically, but something strange is going on.
Due to the above notes, and the fact that the performance difference only arises for logical
arrays, I would consider this an undocumented feature. I would've thought that it's related to logical
s only occupying 1 byte each, but the speed-up doesn't manifest with uint8
arrays. I suggest that since logical
s actually contain information in a single bit, some internal optimization is possible. This still doesn't explain why mtimes
doesn't do this, and it's surely related to the internal workings of times
vs mtimes
.
One thing is sure: times
doesn't actually fall back on mtimes
for scalar operands (maybe it should?). Since in R2012b the whole effect is missing, I believe that the optimized array operations of the new execution engine mentioned above treat logical arrays separately, allowing the special case of scalar.*logical_array
to be sped up, but the same optimization is missing from mtimes
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With