Parfor, how do I use the variable within the loop correctly?

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:
Capture.JPG
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

답변 (1개)

Edric Ellis
Edric Ellis 2020년 1월 16일
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

Thanks!
I thought it might be something to do with that! I couldn't quite understand the document.
I tried like this, but stil same error
fvalagg(i,1:length([formparams(j,1),ID(i),length(Qstayandtrip),fval]))=[formparams(j,1),ID(i),length(Qstayandtrip),fval];
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
Hmmmm I thought it would be something like that.
It seems like parfor doesn't allow having anything that sets the size of the output within the loop.
Even what you suggested gets an error "valid indices for "updatedRow" are restricted in PARFOR loops.
I think the method to make this work has to not set the size within the loop?
updatedRow(1:numToAssignThisRow) = 7;
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...)

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

질문:

2020년 1월 15일

댓글:

2020년 1월 16일

Community Treasure Hunt

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

Start Hunting!

Translated by