MATLAB Answers

0

Forloop taking too long to execute in code

Asked by Sriparna Sen on 9 Sep 2019
Latest activity Commented on by Bob Nbob
on 9 Sep 2019
My code is trying to take data that is saved in a 4D matrix 175 x 121 x 139 x 12 and another 4D matrix 175 x 121 x139 x 13 (these two 4D matrices represent differnet subject groups in an experiment) and compare same cell across the two groups in the 175 x 121 x 139 matrix. The forloop I am using is taking forever to run (30 minute, and not even half was run through). Is there any way to revise the code?
%% Grab Data
test = xff('rest-rainbow');
%The first 12 subjects are blind, the next 13 are sighted, therefore I am
%creating two separate groups for them here. Please enter the number of
%subjects you have in each condition here:
num_subj_bl = 12;
num_subj_si = 13;
blind = test.Map(1:12);
sighted = test.Map(13:25);
[Dim1, Dim2, Dim3] = size(blind(1).VMPData);
fmap = zeros(175, 121, 139);
for a= 1:Dim1
for b= 1:Dim2
for c= 1:Dim3
%These first 3 forloops loop through each unique voxel in the 175 x 121 X
%139 3D matrix that is generated for each subject
%These forloops loop through each individual subject in the blind and
%sighted conditions and put the corresponding voxels across all the
%subjects in a column vector. Therefore, voxel (1,1,1) across all 12 blind
%subjects will be put in the vector blind_vox and voxel (1,1,1) across all
%13 sighted subjects will be put in the vector sighted_vox.
blind_vox = [];
sighted_vox = [];
for x= 1:num_subj_bl
vox = blind(x).VMPData(a,b,c);
blind_vox = [blind_vox;vox];
end
for y= 1:num_subj_si
vox1= sighted(y).VMPData(a,b,c);
sighted_vox = [sighted_vox;vox];
end
%Padcat takes the uneven column vectors since they both have a
%different number of subjects and turns them into even column
%vectors by padding the smaller vector with NaN values
vect_for_BF = padcat(blind_vox, sighted_vox);
%This runs the BF test on the 2 column matrix
[p,stats] = vartestn(vect_for_BF,'TestType','BrownForsythe','Display','off');
%This will contain the f values for all the BF tests run
fmap(a,b,c) = stats.fstat;
end
end
end

  0 Comments

Sign in to comment.

1 Answer

Answer by Bob Nbob
on 9 Sep 2019
 Accepted Answer

Some things that I have noticed.
[Dim1, Dim2, Dim3] = size(blind(1).VMPData);
fmap = zeros(175, 121, 139);
Might be smart to replace the specific sizes of the zeros array with your sizes, or the size command isn't really helping you at all.
for x= 1:num_subj_bl
vox = blind(x).VMPData(a,b,c);
blind_vox = [blind_vox;vox];
end
for y= 1:num_subj_si
vox1= sighted(y).VMPData(a,b,c);
sighted_vox = [sighted_vox;vox];
end
Both of these loops can be replaced with a reshape.
In looking things over a bit more closely, it seems like the bottle neck is vartestn. I am not familiar with the command, so I don't know if this will work, but what about reshaping all of the values into a single large n x 2 array and only running the command once? Maybe something like the following:
blind(x).VMPData(a,b,c) = nan(Dim1,Dim2,Dim3); % Pad array for same size, makes reshape easier
blind_vox = reshape([blind(:).VMPData],[],1);
sighted_vox = reshape([sighted(:).VMPData],[],1);
[p,stats] = vartestn([blind_vox,sighted_vox],'TestType','BrownForsythe','Display','off');
fmap = reshape([stats.fstat],Dim1,Dim2,Dim3);
This is a pretty rough first thought, so it likely won't work perfectly, but it should give you an idea of what I had in mind.

  2 Comments

Hi! Thanks for taking the time to answer my question! Vartestn is definitely the bottleneck, however I can't create a nx2 aray and only run the command once on all the data because I am trying to generate an F statistic for each individual cell inside of the 3D 175x121x139 matrix, therefore need to run vartestn for each unique point in this 3D matrix across all subjects.
If that is the case then I do not know any way of avoiding the triple for loops. You could look into parfor, but I do not have any experience utilizing the parallel computing box and wouldn't be able to help you.
For the record, it would be possible to clean up the appearance of your code a bit by using arrayfun, but arrayfun is ultimately still just a series of for loops, and isn't likely to speed up the process at all.

Sign in to comment.