For loop vectorisation having structure arrays
조회 수: 3 (최근 30일)
이전 댓글 표시
Hi,
I'm still having trouble converting for loops into vectorised form. This time, I have a code snippet which generates two arrays (array2 & array3) using a for loop. Unfortunately, I couldn't manage to get a vectorised solution. I'd be more than happy to get your help.
Thanks in advance,
Mel
array2 = zeros(height(array1),1);
array3 = zeros(height(array1),1);
for i = 1:length(array1)
temp_s1 = array1(i);
idx = [struct_data1(:).cid].' == temp_s1;
temp_s2 = struct_data1(idx);
array2(i) = temp_s2([struct_data1(idx).group2].'== 1).group1;
array3(i) = struct_data2([struct_data2(:).cid].' == temp_s1).gid;
end
댓글 수: 2
Walter Roberson
2023년 3월 11일
array2(i) = temp_s2([struct_data1(idx).group2].'== 1).group1;
That assumes that you will get exactly one match from the == 1 in that line, and that the group1 returned is a scalar.
As outside observers, we have no particular reason to expect that you will ever sometimes get 0 matches or sometimes get more than one match.
We can guess that idx might have more than one true entry since you [struct_data1(idx).group2] which is code that is compatible with the possibility that more than one entry in struct_data1 is being referred to.
채택된 답변
Jan
2023년 3월 12일
편집: Jan
2023년 3월 12일
What is the prupose of a vectorization here? Remember that vectorized code creates temporary arrays usually and this is expensive. Therefore loops are faster in many cases.
Avoid repeated work instead:
c1 = [struct_data1(:).cid].'; % Do this once only
c2 = [struct_data1(:).group2].';
c3 = [struct_data2(:).cid].';
for i = 1:length(array1)
temp_s1 = array1(i);
idx = (c1 == temp_s1);
temp_s2 = struct_data1(idx);
array2(i) = temp_s2(c2(idx) == 1).group1;
array3(i) = struct_data2(c3 == temp_s1).gid;
end
In my local Matlabr R2018b this reduces the runtime from 38 sec of the original to 0.4 sec.
Further 10% faster:
[~, index] = ismember(array1, c3);
array2 = zeros(size(array1, 1),1);
array3 = zeros(size(array1, 1),1);
for i = 1:length(array1)
temp_s1 = array1(i);
idx = (c1 == temp_s1);
temp_s2 = struct_data1(idx);
array2(i) = temp_s2(c2(idx) == 1).group1;
array3(i) = struct_data2(index(i)).gid;
end
댓글 수: 4
Jan
2023년 3월 13일
My first suggestion offered a speedup of a factor 100. The version 4 with ismembc2 is again 260 times faster. 26'000 is a satisfying acceleration and it is based on simplifications of the code, not a vectorization.
Most of the time in the fastest version is spent for combining the scalar fields of the struct to vectors. This shows, that the chosen representation of the data as structs might by clear and clean, but a bunch of vectors will be more efficient.
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!