Adding values to a vector

Dear Matlab forum, I have a vector, T for which I would like to add values to certain indices in a loop. My simplified code is:
T=zeros(10,1)
for iter=1:100
r=[some indices]; % the indices change each loop and are somewhat random
E=[some values for the indices]; % length(E)==length(r)
T(r)=T(r)+E;
end
The issue I am having is that r may contain a multiple occurrences of given index within a single iteration, for example r=[1 4 2 4], and E could be=[2 2 2 2]. I would like to add BOTH values of E to the index 4, but my above code only adds the last one and ignores the first. What is the most efficient way to solve this issue? Thank you very much, -Eli

 채택된 답변

Matt Fig
Matt Fig 2011년 6월 30일

0 개 추천

It has to be done in a loop? You could put a nested loop in there and loop over r...
%
%
EDIT
Here is one way to do it.
T = 1:5;
r = [1 1 1 3 4];
E = [3 3 2 2 5];
T = T + accumarray(r.',E.',[5 1]).'
But it might be slower than using a loop... In fact, since you say that T is 20,000 times longer than r, I would bet this was slower than a loop.
%
%
%
%
EDIT2 The timings report...
Have a look for yourself. Of course some of the accumarray solution could be sped of if the r and E could be made column vectors, which would avoid the transposition, but I doubt that will be much faster...
function [] = accum_loop
T = 1:2e7;
rand('twister',33)
tic
for ii = 1:100
r = ceil(rand(1,1000)*2e7);
E = ceil(rand(1,1000)*10);
for jj = 1:length(r)
T(r(jj)) = T(r(jj)) + E(jj);
end
end
toc
T2 = 1:2e7;
rand('twister',33)
tic
for ii = 1:100
r = ceil(rand(1,1000)*2e7);
E = ceil(rand(1,1000)*10);
T2 = T2 + accumarray(r.',E.',[2e7 1]).' ;
% T2 = T2 + accumarray(r.',E.',[2e7 1],@sum,0,true).' ;
end
toc
isequal(T,T2)
I get, as it stands:
Elapsed time is 0.016339 seconds.
Elapsed time is 7.278608 seconds.
And with your modifications (function handles are slow!):
Elapsed time is 0.016107 seconds.
Elapsed time is 23.642409 seconds.

댓글 수: 13

Eli
Eli 2011년 6월 30일
Yes this is a possibility, but I am looking for the most efficient solution because the vectors are VERY large.
-Eli
Eli
Eli 2011년 6월 30일
...by large I mean that T has a length of 2E7 and r has a length of 1000, and the loop may be tens of thousands of iterations. I am trying to minimize the amount of times I call T.
-Eli
Matt Fig
Matt Fig 2011년 7월 1일
See my edit.
Eli
Eli 2011년 7월 1일
that is interesting. accumarray might be the answer I've been looking for, but as you said I should do a speed check. What if I utilized more of the accumarray inputs:
accumarray(r.',E.',[5 1],@sum,0,logical(1))
would the sparse array be more appropriate?
Sean de Wolski
Sean de Wolski 2011년 7월 1일
You'll have to time test that on your machine since it's system dependent...
Matt Fig
Matt Fig 2011년 7월 1일
I posted results for win 7 64, r2007b.
Eli
Eli 2011년 7월 1일
It turns out the loop is faster, but still not as fast as I would like.
I think the best approach might be to run a loop over the length of r, where I consolidate the the values of E and the indices of r. After this, I could just call T once as before:
T(r*)=T(r*)+E*; % where I r and E have been replaced by r* and E* and no longer have repeated indices. Any ideas of what that loop could look like?
Thanks again,
-Eli
Eli
Eli 2011년 7월 1일
Could I somehow employ the command 'unique'?
Matt Fig
Matt Fig 2011년 7월 1일
Did you look at my timings? Do you get similar values? If you come up with a way to make r* and E* that is more efficient than ACCUMARRAY, post it!
Eli
Eli 2011년 7월 1일
Matt, I don't get similar values, but the order of performance is the same (ie, loop is the best).
Thanks for the help.
Matt Fig
Matt Fig 2011년 7월 1일
I implemented this, in place of the ACCUMARRAY line and the T2 assignment:
ur = unique(r);
uE = zeros(size(ur));
for jj = 1:length(ur)
uE(jj) = sum(E(r==ur(jj)));
end
T2(ur) = T2(ur) + uE;
and found a significant speed increase. But it is still slower than the other loop...
Eli
Eli 2011년 7월 1일
Matt,
your above speed test actually brought to my attention that it was another part of my code that was especially time consuming, rather than adding values t T. I will use the loop that you suggested.
The part of my code that needed adjusting was setting the values of r and E. In my code, r and E are selected each iteration from a subset of a much larger two column array (about the length of T), called trac. I was wondering why your time test was so much faster than mine, and it's because of those lines of code. I was able to split trac into a structure of all the r and E vectors I will need before the loop and then just choose them in the loop. This brings my time to around yours. and I'm happy with the speed now.
Thanks for all the help,
-Eli
Matt Fig
Matt Fig 2011년 7월 1일
You're welcome. In the future you should use the profiler to see where the bottleneck in your code is hiding.
help profile
This is an invaluable tool for helping speed up slow code.

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

추가 답변 (1개)

Jan
Jan 2011년 7월 1일

1 개 추천

Try to use a LOGICAL vector for r, which has 2 advantages:
  1. The vector needs less memory such that the allocation is faster
  2. LOGICAL indices do not need a boundary check for each element, such that the copy is faster. The index is applied twice in "T(r)=T(r)+E;"

댓글 수: 1

Eli
Eli 2011년 7월 1일
Jan, I'm not sure I understand how this would work. r can contain multiple occurrences of given index within a single iteration. Therefore I don't see how I can use a logical vector.

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

카테고리

도움말 센터File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

질문:

Eli
2011년 6월 30일

Community Treasure Hunt

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

Start Hunting!

Translated by