Faster for loops/or how to cut some time

1 vue (au cours des 30 derniers jours)
Happy_Shovel
Happy_Shovel le 21 Oct 2021
Réponse apportée : Jan le 22 Oct 2021
Hello! I have the following problem: I have two arrays, call them a and b. I want to compute the maximum value of a scalar that comes from the following function F, applied to different combinations of a and b.
function Fstat=F(a,b)
T1=length(a);
T2=length(b);
T=T1+T2;
eta=[a;b];
eta=eta-mean(eta);
Z=[repmat(-T/T1,T1,1);repmat(T/T2,T2,1)].*eta;
[be,~,r]=regress(eta,[ones(T,1),Z]);
varb=T*mean((Z.*r).^2)/sum(Z.^2)^2;
Fstat=be(2)^2/varb;
end
The combinations, however, are not at random. I need to take windows of their values that go from 20% of the length of the arrays, to 50% of their length, starting from each possible position, and combining them (that is, I don't need random combinations of them, but windows). To put it short, the preallocated possible arrays can be put in cells through the following code:
function Y=using_cells1(a,W)
T=length(a);
for i=1:T-W
Y{i}=a(i:W+i);
end
end
and:
function [Yc,Yp]=using_cells2(a,b)
Tc=length(a);
Tp=length(b);
lbc=0.2*Tc;
ubc=0.5*Tc;
lbp=0.2*Tp;
ubp=0.5*Tp;
Wc=round(lbc:ubc);
Wp=round(lbp:ubp);
for i=1:length(Wc)
Yc{i}=using_cells1(a,Wc(i));
end
for i=1:length(Wp)
Yp{i}=using_cells1(b,Wp(i));
end
end
Which means that I will have two "variables" for both of the arrays, the starting position of the array, and their length. This makes it such that running a loop for the two arrays becomes extremely slow for high dimensions of either of them.
a=randn(50,1);
b=randn(50,1);
tic
[aa,bb]=using_cells2(a,b);
eloopC=length(aa);
eloopP=length(bb);
for i=1:(eloopC)
for j=1:(eloopP)
for k=1:(length(aa{i}))
for l=1:(length(bb{j}))
fstats(i,k,j,l)=F(aa{i}{1,k},bb{j}{1,l});
end
end
end
end
[~, position] = max(fstats(:));
[p1,p2,p3,p4] = ind2sub(size(fstats),position);
toc
Is there any way I can cut time?
I posted a similar question before, using sums as an example, and the answers I recieved turned out to be sum specific. So I posted the full function I need to effectively use, I hope there is no problem with that.
  2 commentaires
Jan
Jan le 22 Oct 2021
Modifié(e) : Jan le 22 Oct 2021
In you other question the pre-allocation of the output was mentioned already. The editor mentions the problem already by underlining the concerned variables.
Happy_Shovel
Happy_Shovel le 22 Oct 2021
You're certainly right. Preallocating doesn't substantially cut the time though. I sincerely appreciate your help btw! Your previous reply was super helpful!

Connectez-vous pour commenter.

Réponse acceptée

Jan
Jan le 22 Oct 2021
a=randn(50,1);
b=randn(50,1);
tic
[aa,bb]=using_cells2(a,b);
eloopC=length(aa);
eloopP=length(bb);
for i=1:(eloopC)
for j=1:(eloopP)
for k=1:(length(aa{i}))
for l=1:(length(bb{j}))
fstats(i,k,j,l)=F(aa{i}{1,k},bb{j}{1,l});
end
end
end
end
[~, position] = max(fstats(:));
[p1,p2,p3,p4] = ind2sub(size(fstats),position);
toc
% Tiny modifications to let the code run 10% faster:
% - pre-allocation
% - sum(X)/numel(X) instead of mean(X) in F2()
tic
[aa,bb] = using_cells2(a,b);
eloopC = length(aa);
eloopP = length(bb);
fstats = zeros(eloopC, eloopP, eloopC, eloopP); % Pre-allocation
for i = 1:eloopC
for j = 1:eloopP
bbj = bb{j}; % Indexing a cell needs time
for k = 1:length(aa{i})
aaik = aa{i}{1,k}; % Indexing a cell needs time
for l = 1:length(bb{j})
fstats(i,k,j,l) = F2(aaik, bbj{l});
end
end
end
end
[~, position] = max(fstats(:));
[p1,p2,p3,p4] = ind2sub(size(fstats),position);
toc
function Y=using_cells1(a,W)
T = length(a);
Y = cell(1, T - W);
for i = 1:T-W
Y{i} = a(i:W+i);
end
end
function [Yc,Yp]=using_cells2(a,b)
Tc=length(a);
Tp=length(b);
lbc=0.2*Tc;
ubc=0.5*Tc;
lbp=0.2*Tp;
ubp=0.5*Tp;
Wc=round(lbc:ubc);
Wp=round(lbp:ubp);
Yc = cell(1, length(Wc));
for i = 1:length(Wc)
Yc{i} = using_cells1(a, Wc(i));
end
Yp = cell(1, length(Wp));
for i = 1:length(Wp)
Yp{i} = using_cells1(b, Wp(i));
end
end
function Fstat=F(a,b)
T1=length(a);
T2=length(b);
T=T1+T2;
eta=[a;b];
eta=eta-mean(eta);
Z=[repmat(-T/T1,T1,1);repmat(T/T2,T2,1)].*eta;
[be,~,r]=regress(eta,[ones(T,1),Z]);
varb=T*mean((Z.*r).^2)/sum(Z.^2)^2;
Fstat=be(2)^2/varb;
end
function Fstat = F2(a,b)
T1 = length(a);
T2 = length(b);
T = T1+T2;
eta = [a; b];
eta = eta - sum(eta) / numel(eta);
Z = [repmat(-T/T1,T1,1); repmat(T/T2,T2,1)] .* eta;
[be,~,r] = regress(eta, [ones(T,1),Z]);
varb = T * sum((Z.*r) .^ 2) / numel(Z) / sum(Z.^2)^2;
Fstat = be(2)^2 / varb;
end
I do not have the Statistic and Machienlerning Toolbox, so I cannot run regress() locally. Use the profiler to find the bottleneck of the code. If this is regress(), try to write a leaner function to solve the calculations.

Plus de réponses (0)

Catégories

En savoir plus sur Mathematics dans Help Center et File Exchange

Tags

Produits

Community Treasure Hunt

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

Start Hunting!

Translated by