For loop vectorisation having structure arrays

2 Ansichten (letzte 30 Tage)
Melanie VT
Melanie VT am 11 Mär. 2023
Kommentiert: Melanie VT am 13 Mär. 2023
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 Kommentare
Walter Roberson
Walter Roberson am 11 Mär. 2023
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.
Melanie VT
Melanie VT am 12 Mär. 2023
I get what you mean @Walter Roberson! Thank you for drawing my attention to this matter🙏🏼

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Jan
Jan am 12 Mär. 2023
Bearbeitet: Jan am 12 Mär. 2023
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 Kommentare
Jan
Jan am 13 Mär. 2023
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.
Melanie VT
Melanie VT am 13 Mär. 2023
That's a splendid job @Jan! My hat's off to you👒 I can't literally thank you enough. You're providing not only solutions but also capacity strengthening! This is why you're an L10-MVP, I guess. From now on, I will build my codes with this logic. Thanks a million; it's really exceptional🙏🏻

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Loops and Conditional Statements finden Sie in Help Center und File Exchange

Produkte


Version

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by