Alternative to using Multi-level field struct

8 views (last 30 days)
I am taking two populated structs and re-ordering them, so that I can do an operation(such as fft), on the end-most field's elements, eg
bigNum=1e4;
for b=1:bigNum
for a=1:bigNum
val=Struct_A(a).dat(b);
Struct_B(b).dat(a)=val;
val2 = fft(Struct_B(b).dat(:);
end
end
I do this also with 3-layered field structures such as Struct_C(f).fielde(e).fieldd(d).dat.
  • Is there a more efficient way to handle this reordering?
  • Can I vectorize this or otherwise speed this up? I am using parfor loops, but, it seems just the idea of re-ordering structures is a bad paradigm when considering large data

Accepted Answer

Michael Van de Graaff
Michael Van de Graaff on 7 Jul 2022
I gave it shot.
n = 1000;
s(n) = struct();
for ii = 1:n
for jj = 1:n
s(ii).a(jj) = ii;%this is just building the original struct
end
end
tic
for ii = 1:n
for jj = 1:n
val = s(ii).a(jj);
s2(jj).a(ii) = val;% do the loop like you have
end
end
toc
Elapsed time is 0.660588 seconds.
%now lets try something without loops, should be faster for large n
tic
tmp = cell2mat(squeeze(struct2cell(s))).';
tmp2=mat2cell(tmp,ones(1,n),[n]);
s3 = cell2struct(tmp2,fieldnames(s),4);
toc
Elapsed time is 0.033685 seconds.
% and let's do a loop to ensure s2 and s3 are the same
s_diff = zeros(n);
for ii = 1:n
for jj = 1:n
s_diff(ii,jj) = s2(ii).a(jj)-s3(ii).a(jj);
end
end
if max(abs(s_diff(:)))==0
disp('success') %I got success
else
disp('failure')
end
success
  3 Comments
Science Machine
Science Machine on 8 Jul 2022
Edited: Science Machine on 8 Jul 2022
'While' keeping the data in its natual organiztion as eg
struct(index 1).field2(index2).field3(index3).dat(array or matrix)
each field is generally a different # of entries.
  • I was reading maybe multi-dimensional array?
Michael Van de Graaff
Michael Van de Graaff on 8 Jul 2022
"would be possible to eschew structures altogether?"
Are you familiar with cell arrays? That seems like precisely what you are looking for, as they can be n-dimsionsal and each cell can contain whatever data type, including arrays of differeing sizes. You don't get the built in clarity of the fieldnames, but a GPU don't need no fieldnames :D (I have literally no knowledge of how GPU implementations work fyi)

Sign in to comment.

More Answers (1)

Bruno Luong
Bruno Luong on 8 Jul 2022
Edited: Bruno Luong on 8 Jul 2022
It seems you just burry an array into nested structures for no apparent reason other than using struct with a fieldname for a sake of it speaks to you.
Undo that and think like a computer:
% Generate dummy data
a = 10; % your big number
b = 11; % another of your your big number
for i=1:a
for j=1:b
STRUCTA.A(i).B(j) = rand();
end
end
% Undo the thing to getback numerical array
a = length(STRUCTA.A);
b = length(STRUCTA.A(1).B);
AB=reshape([STRUCTA.A.B],[b,a]); % deepest nested length first, ...
% Simply work on the array, that how MATLAB should be used
% If you want to swap a/b dimension, transpose AB, no need for
% the ugly double for-loop as you do.
val2 = fft(AB,[],2)
val2 =
4.0661 + 0.0000i 0.0323 - 0.7934i -0.2520 - 0.6357i 0.4981 + 0.0308i -0.4295 - 0.9440i -1.0016 + 0.0000i -0.4295 + 0.9440i 0.4981 - 0.0308i -0.2520 + 0.6357i 0.0323 + 0.7934i 5.5655 + 0.0000i 0.4685 + 0.8790i 0.3279 + 0.0606i 0.1125 + 0.1375i 0.4377 - 0.4593i -1.2876 + 0.0000i 0.4377 + 0.4593i 0.1125 - 0.1375i 0.3279 - 0.0606i 0.4685 - 0.8790i 4.8333 + 0.0000i -0.5814 - 0.5989i 0.4646 - 0.5380i -0.1544 - 0.4535i -0.5136 - 0.3355i 1.9391 + 0.0000i -0.5136 + 0.3355i -0.1544 + 0.4535i 0.4646 + 0.5380i -0.5814 + 0.5989i 5.2862 + 0.0000i 0.7492 - 1.0385i 1.3908 + 0.8551i 0.2308 - 0.0047i -0.6972 + 0.4188i -0.5792 + 0.0000i -0.6972 - 0.4188i 0.2308 + 0.0047i 1.3908 - 0.8551i 0.7492 + 1.0385i 4.8983 + 0.0000i -0.4043 + 0.3373i 0.2988 - 0.9046i -0.4060 + 0.4049i 0.7049 - 0.6535i 0.2248 + 0.0000i 0.7049 + 0.6535i -0.4060 - 0.4049i 0.2988 + 0.9046i -0.4043 - 0.3373i 4.8601 + 0.0000i -0.2928 - 0.1440i -0.3565 - 0.5095i 0.4126 - 0.2177i -0.3226 + 0.0414i 1.4404 + 0.0000i -0.3226 - 0.0414i 0.4126 + 0.2177i -0.3565 + 0.5095i -0.2928 + 0.1440i 4.4551 + 0.0000i -1.6476 - 0.0270i 0.7631 - 0.6674i -0.2366 - 0.8680i -0.1395 - 0.1165i -0.4810 + 0.0000i -0.1395 + 0.1165i -0.2366 + 0.8680i 0.7631 + 0.6674i -1.6476 + 0.0270i 4.1921 + 0.0000i -0.6224 - 0.1522i 1.5197 - 0.6028i 0.5938 + 0.2190i 1.0945 - 0.7803i -0.1243 + 0.0000i 1.0945 + 0.7803i 0.5938 - 0.2190i 1.5197 + 0.6028i -0.6224 + 0.1522i 5.2778 + 0.0000i 0.2595 + 0.7150i -0.2160 - 0.3907i 1.0669 + 0.0340i 0.3649 - 0.8534i -0.3927 + 0.0000i 0.3649 + 0.8534i 1.0669 - 0.0340i -0.2160 + 0.3907i 0.2595 - 0.7150i 5.5209 + 0.0000i 1.3374 + 0.5652i -0.5742 + 0.1283i -0.1109 + 0.2116i 0.7891 + 0.7053i -0.8280 + 0.0000i 0.7891 - 0.7053i -0.1109 - 0.2116i -0.5742 - 0.1283i 1.3374 - 0.5652i 4.2459 + 0.0000i 0.6400 - 0.5771i 0.4029 + 0.8782i -0.1877 + 0.6045i -0.5498 - 0.5591i -1.6546 + 0.0000i -0.5498 + 0.5591i -0.1877 - 0.6045i 0.4029 - 0.8782i 0.6400 + 0.5771i
  2 Comments
Science Machine
Science Machine on 8 Jul 2022
Can this be done with 3 or more levels? i have a more complicated structure like myStr(i).angle(theta).radius(r).dat(1:xLocation) and since there are so many parameters, I needed to organize that somehow. Several times, depending on the operation, I have to juggle the entries.
From your example, I tried
function strTest3()
% Gen data
a = 3; %
b = 5; %
c = 7; %
for i=1:a
for j=1:b
for k=1:c
%STRUCTA.A(i).B(j) = i*j;
STRUCTA.A(i).B(j).C(k) = i*j*k;
end
end
end
% Undo
a = length(STRUCTA.A);
b = length(STRUCTA.A(1).B);
c = length(STRUCTA.A(1).B(1).C);
AB=reshape([STRUCTA.A.B],[b,a]); % this works
ABC=reshape([STRUCTA.A.B.C],[c,b,a]); % this produces error
val2 = fft(AB,[],2)
end
Bruno Luong
Bruno Luong on 8 Jul 2022
Edited: Bruno Luong on 8 Jul 2022
With three (four) levels you have to do 2-step
...
AB = [STRUCTA.A.B];
ABC = reshape([AB.C],[c b a]);
...

Sign in to comment.

Tags

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!