Isn't vectorization more efficent than looping?

13 views (last 30 days)
As far as I know, vectorized computation works faster than loop. However, the given loop above is working faster than vectorized one. Am I missing sth about subject and is there a better way, namely computationally more efficient way, to extract data from dataset.
best regards.
%loop imp.
for l = 1:length(distVect)
proj(in1,in2) = proj(in1,in2) + distVect(l)*attenuationData(rowData(l),columnData(l));
end
% vector implementation
proj(in1,in2)=distVect*attenuationData( sub2ind(size(attenuationData),rowData,columnData))';
  5 Comments
Aziz Kavas
Aziz Kavas on 10 Dec 2020
I see 'Walter Roberson' has metioned about it already. Therefore, I want to understand the standarts for fast computation. Thanks a lot :)
Walter Roberson
Walter Roberson on 10 Dec 2020
Mathworks recommends that you do not use the details of any particular release's JIT compiler, as those details change between releases. They recommend that you should instead write simple code, as simple code is easier for the automated analysis to find optimizations for. They do recommend vectorization, but when that vectorization goes beyond pure arithematic calculations, you can start to lose out... like that equivalent of find() I showed, where the vectorized form required three full-array operations whereas the loop find() form only requires one scan through the full matrix.

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 10 Dec 2020
Vectorization is not always faster than for .
Sometimes vectorization requires that you construct multiple intermediate arrays, with it taking time and memory to construct them. The computation of the arrays is not always straight-forward.
In your vectorized code, you have to calculate the linear indexes with sub2ind() and then you use the linear indexes to do actual indexing -- one computational step at the MATLAB level, followed by indexing at the level below MATLAB; whereas simple indexing can be done at the level below MATLAB and so can be faster.
Another example of a case where for loops can be faster:
Suppose you need to find the index of the first non-zero value per column. You can for that with a find(data(:,COLUMN),1,'first') and hope that the implementation is optimized for the 1, 'first' case.
There is also a vectorized implementation:
sum(cumprod(~data,1),1)+1
This works, but it requires multiple mathematical passes through the entire array: first to take the logical negation, then to take the cumprod, then to take the sum per column. This would only be faster if MATLAB can realize that the task can be split up between cores, each core getting a range of columns to work with -- and if the number of cores is high enough and the arrays are large enough to make it worth doing.
There are, oddly enough, even some cases where MATLAB can examine the pattern of a for loop and determine from it that the code is an example of one of the common linear algebra patterns, and call fast libraries -- cases that MATLAB would not be able to recognize if the code was put into purely vectorized form.
So vectorization is not always faster.
  3 Comments
Walter Roberson
Walter Roberson on 10 Dec 2020
>> which subsref(3,struct())
built-in (/Applications/MATLAB_R2020b.app/toolbox/matlab/ops/subsref)
Therefore if you invoke
attenuationData(rowData(l),columnData(l))
then the subscripting effort with two indices is done using built-in (compiled) code.
>> which sub2ind(3,5)
/Applications/MATLAB_R2020b.app/toolbox/matlab/elmat/sub2ind.m
Therefore when you invoke sub2ind(size(attenuationData),rowData,columnData) the sub2ind() calculation is done using MATLAB code, not using built-in code. There are checks for datatype and size validity done at the MATLAB level, and the calculations are done at the MATLAB level, with the result being linear indices (double precision numbers)
attenuationData( sub2ind(size(attenuationData),rowData,columnData))
is then indexing the array attenuationData by the calculated subscripts, and as indicated at the beginning, that is handled using built-in functions.
Therefore when you do the above, you have some calculations done in MATLAB code, and the results are then used in built-in code. Whereas when you do the two-dimensional subscripting in the loop, it is all built-in code -- and the JIT can optimize out some of the checks to make it more efficient to do the (l) subscripting .
As MATLAB code is less efficient than built-in code, it follows that using the sub2ind() approach can end up being slower than direct indexing with a loop.
Also, the sub2ind approach requires allocating a temporary memory array to hold the result of converting to linear indices, using the array, and then deallocating it. The direct indexing approach in theory does too, to allocate the scalars resulting from the rowData(l), but I would think it likely that would be optimized away by the JIT in the scalar case.
Are you vectorizing the indexing the wrong way? No -- but not all vectorization is faster.
You can get a performance boost by replacing the sub2ind() with the equivalent mathematical calculation:
rowData + size(attenuationData,2) * (columnData - 1)

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!