Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why in Matlab .* operator is faster than * for a scalar in some case?

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

like image 280
x1hgg1x Avatar asked Jan 16 '16 21:01

x1hgg1x


People also ask

What is scalar operation in MATLAB?

MATLAB - Scalar Operations of Matrices. When you add, subtract, multiply or divide a matrix by a number, this is called the scalar operation.

How to use Matlab * operator for non-scalar multiplication?

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.

Why is MATLAB faster at doing XXX than other programs?

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.

What is the * operator in MATLAB?

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.


1 Answers

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

Update

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
  • the same holds true for vectors, not just square matrices

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 logicals only occupying 1 byte each, but the speed-up doesn't manifest with uint8 arrays. I suggest that since logicals 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.

like image 124