Performance of cell arrays, multi-dimensional arrays, structure arrays, and multiple variables
Mostra commenti meno recenti
I've found that the performance of cell Arrays, multi-dimensional arrays, and structure arrays are all far slower than the use of multiple independent variables. Thus, my optimized codes have been using super long if-statements and functions which completely write out which variables are needed or not. The code is thus faster than using the other methods, but the code is also quite messy. A reproduction of the independent variables approach using 'eval' also doesn't work because of the way eval is executed by MATLAB.
Is there another way to do this without writing out each variable? Perhaps there I could use cell arrays but pass an argument which results in MATLAB treating them in a faster way... This might not seem like a big deal, but my codes take dozens of hours to execute (itt>1000), which becomes many days when the other 'MATLAB-preferred' methods are used.
Here is a code showing this performance. Values of ytessel and xtessel can be changed as you please, but changing these values requires manually changing the code for the fastest method (independent variables).
%%model prep
ytessel = 4;
xtessel = 4;
nnum = 72*1;
ynum = nnum*ytessel;
xnum = nnum*xtessel;
itt = 5;
totemit = rand(ynum,xnum);
T = zeros(ynum,xnum);
for y=1:nnum
for x=1:nnum
dT_depot{y,x} = rand(ynum,xnum);
end
end
%%CELL ARRAYS
tic
for i=1:itt
for yt=1:ytessel
for xt=1:xtessel
A{yt,xt} = zeros(ynum,xnum);
end
end
for y=1:nnum
for x=1:nnum
dT = dT_depot{y,x};
for yt=1:ytessel
for xt=1:xtessel
A{yt,xt} = A{yt,xt} + dT.*totemit(y+(yt-1)*nnum,x+(xt-1)*nnum);
end
end
end
end
end
disp(sprintf('Time: %f (Cell Array Method)',toc));
%%4D Matrix
tic
for i=1:itt
C = zeros(ynum,xnum,ytessel,xtessel);
for y=1:nnum
for x=1:nnum
for yt=1:ytessel
for xt=1:xtessel
dT = dT_depot{y,x};
C(:,:,yt,xt) = C(:,:,yt,xt) + dT.*totemit(y+(yt-1)*nnum,x+(xt-1)*nnum);
end
end
end
end
end
disp(sprintf('Time: %f (4D Array Method)',toc));
%%Independent Variables
D11 = zeros(ynum,xnum); D12 = zeros(ynum,xnum); D13 = zeros(ynum,xnum); D14 = zeros(ynum,xnum);
D21 = zeros(ynum,xnum); D22 = zeros(ynum,xnum); D23 = zeros(ynum,xnum); D24 = zeros(ynum,xnum);
D31 = zeros(ynum,xnum); D32 = zeros(ynum,xnum); D33 = zeros(ynum,xnum); D34 = zeros(ynum,xnum);
D41 = zeros(ynum,xnum); D42 = zeros(ynum,xnum); D43 = zeros(ynum,xnum); D44 = zeros(ynum,xnum);
tic
for i=1:itt
D11(:) = 0; D12(:) = 0; D13(:) = 0; D14(:) = 0;
D21(:) = 0; D22(:) = 0; D23(:) = 0; D24(:) = 0;
D31(:) = 0; D32(:) = 0; D33(:) = 0; D34(:) = 0;
D41(:) = 0; D42(:) = 0; D43(:) = 0; D44(:) = 0;
for y=1:nnum
for x=1:nnum
curdepot = dT_depot{y,x};
D11 = D11 + curdepot.*totemit(y, x);
D21 = D21 + curdepot.*totemit(y+nnum, x);
D31 = D31 + curdepot.*totemit(y+nnum*2,x);
D41 = D41 + curdepot.*totemit(y+nnum*3,x);
D12 = D12 + curdepot.*totemit(y, x+nnum);
D22 = D22 + curdepot.*totemit(y+nnum, x+nnum);
D32 = D32 + curdepot.*totemit(y+nnum*2,x+nnum);
D42 = D42 + curdepot.*totemit(y+nnum*3,x+nnum);
D13 = D13 + curdepot.*totemit(y,x+nnum*2);
D23 = D23 + curdepot.*totemit(y+nnum,x+nnum*2);
D33 = D33 + curdepot.*totemit(y+nnum*2,x+nnum*2);
D43 = D43 + curdepot.*totemit(y+nnum*3,x+nnum*2);
D14 = D14 + curdepot.*totemit(y,x+nnum*3);
D24 = D24 + curdepot.*totemit(y+nnum,x+nnum*3);
D34 = D34 + curdepot.*totemit(y+nnum*2,x+nnum*3);
D44 = D44 + curdepot.*totemit(y+nnum*3,x+nnum*3);
end
end
end
disp(sprintf('Time: %f (Independent Variables Method)',toc));
%%STRUCT ARRAYS
for yt=1:ytessel
for xt=1:xtessel
DD(yt,xt).dat = zeros(ynum,xnum);
end
end
tic
for i=1:itt
for yt=1:ytessel
for xt=1:xtessel
DD(yt,xt).dat = zeros(ynum,xnum);
end
end
for y=1:nnum
for x=1:nnum
curdepot = dT_depot{y,x};
for yt=1:ytessel
for xt=1:xtessel
DD(yt,xt).dat = DD(yt,xt).dat + curdepot.*totemit(y+(yt-1)*nnum,x+(xt-1)*nnum);
end
end
end
end
end
disp(sprintf('Time: %f (Structure Arrays Method)',toc));
%%Eval Method
for yt=1:ytessel
for xt=1:xtessel
eval(['D' num2str(yt) num2str(xt) '=zeros(ynum,xnum);']);
end
end
tic
for i=1:itt
for yt=1:ytessel
for xt=1:xtessel
eval(['D' num2str(yt) num2str(xt) '(:)=0;']);
end
end
for y=1:nnum
for x=1:nnum
curdepot = dT_depot{y,x};
for yt=1:ytessel
for xt=1:xtessel
eval(['D' num2str(yt) num2str(xt) '=D' num2str(yt) num2str(xt) '+curdepot.*totemit(y+nnum*' num2str(yt-1) ',x+nnum*' num2str(xt-1) ');']);
end
end
end
end
end
disp(sprintf('Time: %f (Eval Method)',toc));
Output:
Time: 16.279780 (Cell Array Method)
Time: 79.975502 (4D Array Method)
Time: 7.808595 (4D Independent Variables Method)
Time: 20.406543 (Structure Arrays Method)
Time: 127.129048 (Eval Method)
8 Commenti
Jos (10584)
il 8 Feb 2018
This is rather an unfair comparison. In your independent variables method you pre-allocate all arrays before the tic.
Matt J
il 8 Feb 2018
In addition to what Jos said, you would never use loops for operations like this. They are abundantly vectorizable.
@Christopher: the comparisons are apples with oranges:
- You do not preallocate cell array A, which makes the cell array version meaningless.
- You define your independent variables D11, D12, etc, using zeros before tic (and then within the tic-toc simply redefine all their elements to be zero), but for the ND matrix you call zeros after the tic call.
- Ditto for structure DD: instead of simply redefining all elements of the field to be zero (fast, like you do with your independent variables) you call zeros again after tic (slow).
I would suggest that using a properly preallocated cell array might be worth investigating. And if you want a fair comparison either move all calls to zeros before the timing or add zeros to the independent variables after tic.
Christopher
il 8 Feb 2018
Modificato: Christopher
il 8 Feb 2018
Christopher
il 8 Feb 2018
"On this subject, I think it's quite odd that Mathworks hasn't simply implemented an eval-type function which just tells MATLAB to literally write out the expressions before compiling"
This would make no real difference, because you underestimate the performance enhancement of MATLAB's JIT engine. Whereas normal code is evaluated just once and the JIT engine can optimize in any relevant ways that it can, with eval each iteration still has to be evaluated again anyway. There is no way around this because the statement cannot be determined until the code is run.
However you are quite welcome to tell TMW your idea. Please let us know their reply.
Jan
il 8 Feb 2018
I know that MATLAB's for-loops are notoriously inefficient, ...
This is an old rumor from the times before the JIT was introduced: R6.5 in 2002.
Jos (10584)
il 8 Feb 2018
I know that MATLAB's for-loops are notoriously inefficient, ...
Fake news! :D
Risposta accettata
Più risposte (0)
Categorie
Scopri di più su Loops and Conditional Statements in Centro assistenza e File Exchange
Prodotti
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!