Parfor, how do I use the variable within the loop correctly?
Show older comments
I'm trying to use parfor on a set of data called ID. There is no need for ID(1) to be computed before ID(2) is computed, and so on.
Is started off using a for loop, and in that I had it so it compiled the data by adding on a new row at each iteration. So result(i,:)=result sort of way.
I get error messages like so:

parfor i=1:length(ID)
[indvd,indvst,indvet,indvolanduse,indvdlanduse,indvparkingtype,indvhomeorigin,indvdestaddress,indvolandprop,indvdlandprop,indvparkprop,indvoparkprop,indvdparkprop,indvhomepark]= ExtractIndv(ID(i),datadrivers,datatripd,datatripst,datatripet,datalanduse,dataolanduse,datadlanduse,dataparkingtype,dataoriginhome,datadestaddress,propsland,propspark,OnstreetOther,OffstreetShopcarpark,OffstreetPrivateresidential);
[fval,fvalEV,Q,C,QC,G,R,GR,SV,VS,GS,B,GSB,SG,I,SGI,SH,H,HB,Y,YF,dfstayandtrip,Qstayandtrip,QCstayandtrip,Gstayandtrip,GRstayandtrip,soeEVA,soeEVD,soeESSA,soeESSD,soeEVAstayandtrip,soeEVDstayandtrip,soeESSAstayandtrip,soeESSDstayandtrip,stayandtripsum,timeatstayandtrip,SVstayandtrip,VSstayandtrip,GSstayandtrip,GSBstayandtrip,SGstayandtrip,SGIstayandtrip,SHstayandtrip,PVstayandtrip,Hstayandtrip,Ystayandtrip,YFstayandtrip,dfstay,Qstay,QCstay,Gstay,GRstay,soeEVAstay,soeEVDstay,soeESSAstay,soeESSDstay,staysum,timeatstay,SVstay,VSstay,GSstay,GSBstay,SGstay,SGIstay,SHstay,PVstay,Hstay,Ystay,YFstay,dftrip,Qtrip,QCtrip,Gtrip,GRtrip,soeEVAtrip,soeEVDtrip,soeESSAtrip,soeESSDtrip,tripsum,timeattrip,SVtrip,VStrip,GStrip,GSBtrip,SGtrip,SGItrip,SHtrip,PVtrip,Htrip,Ytrip,YFtrip,EVESSintegrated,housenum,houseincome,houseborough,DoS,DoT,DoST]= PopulationRun7(ID(i),IDindex,indvd,indvst,indvet,indvolanduse,indvdlanduse,indvparkingtype,indvolandprop,indvdlandprop,indvparkprop,indvoparkprop,indvdparkprop,indvhomepark,res,PVgen,H2Gprice,ResEnPrice,IDhouseperpark,IDhouseper,datahousenum,datahouseincome,datahouseborough,resenergyweight,rescost,EVspecs,soeEV0,soeEVmin,soeESScap,soeESS0,V2Hyn,V2Gyn,H2Gyn,PVyn,PVsize,PVseason,intgsystem,loopdays,ResEnPriceScenario,H2GPriceScenario,V2GPriceScenario);
[basecost,basefval,basefvaladj,basekWheff,indvparkprop]=Baseline(dfstay,Qstay,DoS,EVspecs,soeEV0,indvoparkprop,indvdparkprop,loopdays);
% fill in scenario ID as first column of aggregated data
fvalagg(i,1)=formparams(j,1);
fvalEVagg(i,1)=formparams(j,1);
Qagg(i,1)=formparams(j,1);
fvalagg(i,2)=ID(i);
fvalEVagg(i,2)=ID(i);
Qagg(i,2)=ID(i);
fvalagg(i,3)=length(Qstayandtrip);
fvalEVagg(i,3)=length(Qstayandtrip);
Qagg(i,3)=length(Qstayandtrip);
fvalagg(i,4)=fval;
fvalEVagg(i,4)=fvalEV;
Qagg(i,4:length(Q)+3)=Q;
end
Answers (1)
Edric Ellis
on 16 Jan 2020
The problem here seems to be that you're making multiple assignments to e.g. fvalagg. A stripped-down version of your code is something like this:
parfor i = 1:N
% ... do stuff
fvalagg(i, 1) = something;
fvalagg(i, 2) = someOtherThing;
end
This doesn't meet the requirements for fvalagg because you're making multiple assignments. The requirements are documented here, but basically you simply need to combine stuff into a single assignment, more like this:
parfor i = 1:N
% ... do stuff
fvalagg(i, :) = [something, someOtherThing];
end
4 Comments
In-chan Kim
on 16 Jan 2020
Edric Ellis
on 16 Jan 2020
Your second subscript there isn't in the right form for slicing as per the doc page to which I linked. If for some reason the number of columns your going to fill in the row can't be determined up-front, then I'd suggest making yourself a whole new row, assigning into that, and then assigning that row into your output variable. Like this:
N = 5;
output = NaN(5); % pre-allocate with NaN
parfor i = 1:N
% This is how many elements we're going to assign this iteration
numToAssignThisRow = randi(N);
% Grab the original values using a "sliced" index expression
updatedRow = output(i, :);
% Overwrite just some of those values into a local variable
updatedRow(1:numToAssignThisRow) = 7;
% Put the row back using a "sliced" index expression
output(i, :) = updatedRow;
end
In-chan Kim
on 16 Jan 2020
Edric Ellis
on 16 Jan 2020
To make updatedRow work correctly, it is required that you make a "complete" assignment to it on each iteration (not in any conditional blocks etc.). Only then can parfor decide that you're not doing anything order-dependent. That's why I wrote updatedRow = output(i,:) - that completely overwrites updatedRow. The code as I entered works correctly here for me on R2019b. If you use exactly that code, in which release do you see a failure? (There have been some improvements to the parfor machinery over the years, but I thought the code I wrote didn't actually depend on any of those...)
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!