# how to avoid 'two for loop'?

7 views (last 30 days)
octopus_love on 14 Mar 2017
Edited: Jan on 14 Mar 2017
I don't know how to avoid using for loop, because It takes a lot of time to calculate.
Below is the code to change.
for i = 1 : 26
for j = 1 : 86400
B(86400*(i-1)+j , :) = A(26*(j-1)+i, :);
end
end
I find solutions instead of for loop, like 'repmat' or 'bsxfun', ... but I have no ideas how to shorten the time.

Akira Agata on 14 Mar 2017
Edited: Akira Agata on 14 Mar 2017
How about using a matrix indexing technique as follows:
for i = 1:26
idx_a = 26*((1:86400)-1) + i;
idx_b = 86400*(i-1)+(1:86400);
B(idx_b,:) = A(idx_a,:);
end
##### 2 CommentsShowHide 1 older comment
Jan on 14 Mar 2017
It is interesting and important, that your method is faster than the fully vectorized version:
indexB = bsxfun(@plus, 86400 * (0:25), (1:86400).');
indexA = bsxfun(@plus, 26 * (0:86399).', 1:26);
B(indexB, :) = A(indexA, :);
Creating the large index arrays is expensive.
Your version can be accelerated by using the colon expressions directly for indexing:
for i = 1:26
t = 86400*(i-1);
B((t+1):(t+86400), :) = A(i:26:(86399*26 + i), :);
end
Then Matlab does not check for each element if it is an allowed index (>=0, integer, <=numel(X)). This decreases the runtime from 0.23 to 0.20 seconds.

Jan on 14 Mar 2017
Edited: Jan on 14 Mar 2017
If B is pre-allocated, the computing time is:
A = rand(2246400, 5); % Test data
tic;
B = zeros(size(A));
for i = 1 : 26
for j = 1 : 86400
B(86400*(i-1)+j , :) = A(26*(j-1)+i, :);
end
end
toc
% Elapsed time: 1.37 sec
With the auto-expanding of R2016b:
B(86400 * (0:25) + (1:86400).', :) = A(26 * (0:86399).' + (1:26), :);
Without auto-expanding for R<=2016b:
indexB = bsxfun(@plus, 86400 * (0:25), (1:86400).');
indexA = bsxfun(@plus, 26 * (0:86399).', 1:26);
B(indexB, :) = A(indexA, :);
% Elapsed time: 0.24sec
Akira Agata's code is not completely vectorized and uses 0.23 sec, so it is slightly faster then the complete vectorization. Nice! The creation of the large index matrices wastes a lot of time.
But now take the problem for the viewpoint of permuting the blocks of the array:
AA = reshape(A, 26, 86400, []);
AA = permute(AA, [2,1,3]);
B = reshape(AA, 86400*26, []);
% Elapsed time: 0.16 sec
The internal methods for permuting (a kind of transposing in multi-dim arrays) are faster than the explicit indexing. In addition the programmer has less chances for typos.