Isn't vectorization more efficent than looping?

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

It is unclear to my why you need to call the sum( ) function ... it looks like you may have an inner product inside of it. Also, can you give us all of the variable sizes involved?
Sorry for inconvenience. I have corrected it. For dimensions u can assume that Proj is a scalar distVect is 1xN attenuationData is MxM rowData and columnData is 1xN and contain related indexes. If further detail is required i can post whole code with related data.
"As far as I know, vectorized computation works faster than loop."
No, there is no such simple conclusion. Which is faster depends on the algorithm, the size of the data, the required intermediate arrays, the MATLAB version (JIT engine and also functions can change quite a lot) and no doubt many other factors. Whoever told you that vectorization is faster gave you bad information.
I see 'Walter Roberson' has metioned about it already. Therefore, I want to understand the standarts for fast computation. Thanks a lot :)
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

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

Initially, thanks for such rich answer.
Dear sir, when I compare those 2 code, logic wise, I noticed that only possible difference, operation wise, is transpose operation, namely,
attenuationData( sub2ind(size(attenuationData),rowData,columnData))'
when I run such operation repeatively on a large array I could not notice significant time difference for it. What I wanted to ask is that such operation could be the reason for such a computation load. Secondly, is there any documentation about programming habits for fast computation.
Another point, you said that '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.', namely, my code was not proper for vectorized operation. If it is, what is wrong about it, so how should it be. Or did I just misunderstand what you mean.
Finally, can you advise a better way to write this loop?
Best Regards.
>> 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!