How can I reduce the execution time when calculating mean values within a 3 times loop?

1 次查看(过去 30 天)
Deal all, good morning!
I would like to ask your help regarding to a computational problem that I have. I'm trying to calculate 10 minutes values on a daily basis. So my original file is something like this: [year DoY time(minutes) value]
2010 132 150 1.52
2010 132 151 2.5
2010 132 153 3.4
...
2013 365 1440 0.2
So I have to calculate the ten minute mean values for each year and each day of the year. I created a code with with 3 loops in it. The first one for the year, the second one for the day and the third one for the minutes. It looks more or less like this: for y=2010:2013 idy=find(year==y) if ~isempty(idy) for d=1:366 idd=find(doy(idy)==d) if ~isempty(idd) for m=1:10:1440 idm=find(m(idd(idy))==m if ~isempty(idm) mean=[mean; y d m mean(value(idy(idd(idm))))]; end end end end end end
Now, where is the problem?!
It takes days to run and at the end matlab stucks so I have to exit and I can never get to the results...
Any sugestions would be really really APRECIATED!!!
Thank you in advance.
Cheers,
Melina
  1 个评论
Melina Maria
Melina Maria 2014-7-1
Sorry, the code looks like ...
for year=2004:2014
idy=[];
idy=find(NILU.y==year);
if ~isempty(idy)
for day=1:366
iddoy=[];
iddoy=find(NILU.doy(idy)==day);
if ~isempty(iddoy)
for lo=1:10:1440
idmi=[];
idmi=find(NILU.dt(idy(iddoy))>=lo & NILU.dt(idy(iddoy))<lo+10);
if~isempty(idmi)
TENNILU=[TENNILU;year day mean(NILU.dt(idy(iddoy(idmi)))) mean(NILU.sza(idy(iddoy(idmi)))) mean(NILU.tot(idy(iddoy(idmi)))) mean(NILU.par(idy(iddoy(idmi)))) mean(NILU.alg(idy(iddoy(idmi)))) mean(NILU.flmine(idy(iddoy(idmi)))) length(idy(iddoy(idmi)))];
end
end
end
end
end
end

请先登录,再进行评论。

采纳的回答

Titus Edelhofer
Titus Edelhofer 2014-7-1
Hi,
I would suggest to preallocate TENNILU and take some of the operations out of the loops:
TENNILU = zeros((2014-2004+1)*366*144, 9);
counter = 0;
for year = ...
for day=1:366
iddoy = find(NILU.doy(idy)==day);
if ~isempty(iddoy)
idydoy = idy(iddoy);
for lo=1:10:1440
idmi=find(NILU.dt(idydoy))>=lo & NILU.dt(idydoy))<lo+10);
if ~isempty(idmi)
counter = counter + 1;
id = idy(iddoy(idmi);
TENNILU(counter,:) = [year day mean(NILU.dt(id)) mean(NILU.sza(id) ...];
end
...
end
% delete the empty rows at the end
TENNILU(counter+1:end,:) = [];
Does this help to reduce the time?
Titus
  1 个评论
Melina Maria
Melina Maria 2014-7-1
Thank you Titus!
I've got your point and I'm gonna try it!
Melina.
P.S. Would it be convinient to set TENnilu=[ ] at the beginning, before the first loop instead of setting TENNILU = zeros((2014-2004+1)*366*144, 9)?

请先登录,再进行评论。

更多回答(2 个)

amanita
amanita 2014-7-1
You can also use a parfor somewhere (if it is possible) but you will have to change your code a little bit.
  3 个评论
amanita
amanita 2014-7-1
You need independent jobs, so if you use parfor in your outer loop you will need to create N TENNILU's, where N is the total number of years (e.g you can create a cell for TENNILU, preallocate TENNILU{year} after the parfor year and set your counter to zero). If you use parfor you will also need to create a parallel pool (parpool)

请先登录,再进行评论。


Andrei Bobrov
Andrei Bobrov 2014-7-1
one way
d = [2010 132 150 1.52
2010 132 151 2.5
2010 132 153 3.4
2012 20 289 4.69
2013 365 1440 0.2];
sdate = addtodate(datenum(d(:,1),1,1),d(:,2) + d(:,3)/1440,'day');
b = datevec(sdate(1));
c = ceil(b(end)*.1)*10;
dte = datenum([[b(1:4),floor(b(5)*.1)*10,0];[c(1:4),ceil(c(5)*.1)*10,0]]);
z = addtodate(sdate(1),(0:10:ceil(diff(dte)*144)*10)','minute');
out = [datevec(z),accumarray(ii,d(:,end),size(z),@mean)];

类别

Help CenterFile Exchange 中查找有关 Matrix Indexing 的更多信息

产品

Community Treasure Hunt

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

Start Hunting!

Translated by