Fastest way for variable row indexing

조회 수: 14 (최근 30일)
Adrian
Adrian 2017년 3월 19일
댓글: Adrian 2017년 3월 25일
Hi all, I am trying to speed up my code, but cannot find a faster way than a loop and I think there should be one (probably). So the problem is the following: I have a 2D array V and need to set a variable amount of consecutive columns to A and the rest to B (for simplicity). Variable means each row is different and up to where each row has to be set to A is stored in L. So currently it looks like this:
for c = 1 : size(V,1)
V(c,:) = [repmat(A,1,L(c)) repmat(B,1,size(V,2)-L(c))]
end
So does anyone know a faster solution? If the index would be identical per row it would be easily achievable using repmat or bsxfun, but I could not figure out a way to use indices of different length for every row of the matrix. Same for sub2ind which only seems to work if the indices per row have the same length. Btw., only speed matters, the solution can be ugly ;) Any help would be greatly appreciated!
  댓글 수: 2
Image Analyst
Image Analyst 2017년 3월 19일
Give a small numerical example with values for L, V, B, and A. Also let us know what version of MATLAB you have, especially if it's R2016b or later.
Adrian
Adrian 2017년 3월 19일
Version is currently 2016a, but could update if that should help. Here is a small example:
A = 1;
B = 2;
L = [ceil(rand(200,1)*100)];
V = nan(200,100);
tic
for c = 1 : size(V,1)
V(c,:) = [repmat(A,1,L(c)) repmat(B,1,size(V,2)-L(c))];
end
toc
imagesc(V)
The actual array is much larger, and this has to be done thousands until millions of times, so it would be great to gain some speed here. Thanks! :)

댓글을 달려면 로그인하십시오.

답변 (2개)

Philip Borghesani
Philip Borghesani 2017년 3월 19일
I made two changes to your code on my machine it is a bit faster:
  1. Avoid using repmat and concatination instead use direct assignment.
  2. Work with a transposed matrix and transpose when done.
The second change will help more or less depending on the image size and processor memory caching configuration. Larger images will make a bigger difference.
A = 1;
B = 2;
L = ceil(rand(1,2000)*1000);
V = nan(1000,2000);
tic
for c = 1 : size(V,2)
V(1:L(c),c) = A;
V(L(c)+1:end,c) = B;
end
V=V';
toc
imagesc(V)
  댓글 수: 2
Walter Roberson
Walter Roberson 2017년 3월 19일
zeros() is faster than nan()
Adrian
Adrian 2017년 3월 19일
Thanks for the replies. Did not know about the change in speed with transpose. Unfortunately, the example is a simplification: there are more values that have to be set per row (not only A,B but usually 4 to 5). In that case repmat is a bit faster on my system. I was wondering if there is any way to index rows with variable columns directly and avoid a loop at all? Or is this simply not possible?
This here is the realistic case (sorry for not posting this before, did not anticipate that it might depend on this):
A = 1;
B = 2;
C = 3;
D = 4;
L1 = 150;
L2 = [ceil(rand(100000,1)*1500)];
V = ones(100000,4000);
dims=size(V);
tic
for c = 1 : dims(1)
V(c,:) = [repmat(A,1,L1) repmat(B,1,L2(c)) repmat(C,1,L2(c)) repmat(D,1,dims(2)-(L1+L2(c)*2))];
end
toc
imagesc(V)
Here, direct indexing and transpose is a bit slower than repmat. The problem is the transpose, which takes most of the time. Indeed, initializing with ones or zeros is a bit faster when the indexing is included into the tic/toc, otherwise, zeros is slower (no idea why).

댓글을 달려면 로그인하십시오.


Walter Roberson
Walter Roberson 2017년 3월 20일
If you have R2015a or later, try repelem()
  댓글 수: 3
Walter Roberson
Walter Roberson 2017년 3월 24일
%these can be set up ahead of time
M = 200; N = 100;
T = 1 : N;
%you could change these each loop iteration if desired
A = 1;
B = 2;
%if A and B are constant you could initialize this outside the loop
W = A + zeros(M, N);
%this would be done each loop, for sure.
L = ceil(rand(M,1)*N);
V = W;
V( bsxfun( @lt, L, T) ) = B; %your one-liner.
Adrian
Adrian 2017년 3월 25일
Hi Walter, that is indeed a very elegant way of solving the 2-element case (only A & B), it seems difficult with more than two elements. Unfortunately, it is relatively slow (2.7x slower compared to repelem, 1.6x compared to repmat in a loop). So I guess, the fastest way is using a loop and repelem currently...

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Matrix Indexing에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by