- avoid repeated calculations
- pre-allocate the output
how to vectorize a for-loop or use parfor to speed it up?
2 次查看(过去 30 天)
显示 更早的评论
I have this for loop right now:
for x = 2:Nx_max-1
for y = 2:Ny_max-1
lp(x,y,t1) = (1/(2*h^2))*dxy(x,y)*p(x+1,y+1,t1) + ...
(dxx(x,y)/(h^2) - vx(x,y)/(2*h) - (x-Nx-1)/(2*gamma))* p(x+1,y,t1) - ...
(1/(2*h^2))*dxy(x,y)*p(x+1,y-1,t1) + (dyy(x,y)/(h^2) - ...
vy(x,y)/(2*h) - (y-Ny-1)/(2*gamma))*p(x,y+1,t1) - ...
(2*dxx(x,y) + 2*dyy(x,y))*(1/h^2)*p(x,y,t1) + ...
(dyy(x,y)/(h^2) + vy(x,y)/(2*h) +(y-Ny-1)/(2*gamma))*p(x,y-1,t1) - ...
(dxy(x,y)/(2*h^2))*p(x-1,y+1,t1) +(dxx(x,y)/(h^2) +vx(x,y)/(2*h) +...
(x-Nx-1)/(2*gamma))*p(x-1,y,t1) + (dxy(x,y)/(2*h^2))*p(x-1,y-1,t1);
end
end
I asked a question previously where I didn't actually write out the full function here, and I was recommended to vectorize it for speed by replacing x by 2:(Nx_max-1) and y by 2:(Ny_max-1). This is causing problems because it looks like the multiplications would cause it to be matrix multiplication instead of multiplying the specific elements of the matrix that I'm interested in mylitplying together. And I also have a section where there ends up being a vector (2:(Nx_max-1)) multiplying a matrix. I don't want the end result to be a vector (as it would in regular matlab notation), I want each element of the matrix in that case to be multiplied by its x value.
Is there a way to vectorize this or somehow speed up the process?
I had thought about parallel computation, but it looks like I can't nest parfor loops.
Any suggestions would be appreciated
0 个评论
回答(1 个)
Jan
2014-8-10
编辑:Jan
2014-8-10
An elementwise multiplication is performed by the .* operator, while * is a matrix multiplication. This should solve your problem already. Please post your trial to vectorize the code instead of letting us create it from scratch.
An optimization of code depends on the input values. It matters if Nx_max is 10 or 1e7. It matters if dxy and gamma are arrays or functions. So please post a version of your code, which can be started by copy&paste. Otherwise suggestions contains a lot of guessing.
But if guessing is required, consider the standard tips fopr loop optimization at first:
E.g. (1/(2*h^2)) is calculated nearly Ny_max * Nx_max times. So better create a variable before the loop to carry the result. So befpre creating the vectorized version, measure the speed with a cleaner version like this:
hs = h^2;
h2 = 2 * h;
hs2 = 2 * hs;
c1 = 1/hs2;
g2 = 2 * gamma;
lp = zeros(Nx_max-1, Ny_max-1, t1);
for x = 2:Nx_max-1
c2 = (x-Nx-1)/g2;
for y = 2:Ny_max-1
lp(x,y,t1) = c1 * dxy(x,y) * p(x+1,y+1,t1) + ...
(dxx(x,y) / hs - vx(x,y) / h2 - c2) * p(x+1,y,t1) - ...
c1 * dxy(x,y) * p(x+1,y-1,t1) + ...
(dyy(x,y)/hs - vy(x,y)/h2 - (y-Ny-1)/g2) * p(x,y+1,t1) - ...
(2 * dxx(x,y) + 2 * dyy(x,y)) * p(x,y,t1) / hs + ...
(dyy(x,y)/hs + vy(x,y)/h2 +(y-Ny-1)/g2) * p(x,y-1,t1) - ...
dxy(x,y) / hs2 * p(x-1,y+1,t1) + ...
(dxx(x,y)/hs + vx(x,y) / h2 + c2) * p(x-1,y,t1) + ...
dxy(x,y) / hs2 * p(x-1,y-1,t1);
end
end
Then, in a next step, replace the loop over x by replacing all "x" by "(2:Nx_max-1)" and the operators "*" and "/" by their elementwise versions ".*" and "./". Test, if the result is still not changed except for rounding errors. Fix "(2:Nx_max-1)+1" to the faster "3:Nx_max", because in the 2nd version the index vector is not calculated exlicitly.
Finally you can try to replace the inner loop also, but perform a speed test afterwards. A complete vectorization is not necessarily the fastest version.
4 个评论
Jan
2014-8-10
Here a guessed version of a vectorized outer loop:
hs = h^2;
h2 = 2 * h;
hs2 = 2 * hs;
g2 = 2 * gamma;
Nx1 = Nx_max - 1;
Nx2 = Nx_max - 2;
c2 = ((2 - Nx-1):(Nx_max - 2 - Nx)) / g2;
lp = zeros(Nx1, Ny_max-1, t1);
for y = 2:Ny_max-1
c3 = dxy(2:Nx1,y) ./ hs2;
c4 = dxy(2:Nx1,y) ./ hs2;
c5 = vy(2:Nx1,y) ./ h2;
c6 = vx(2:Nx1,y) ./ h2;
c7 = dyy(2:Nx1,y) ./ hs;
lp(2:Nx1, y, t1) = ...
c3 .* p(3:Nx_max,y+1,t1) + ...
(dxx(2:Nx1,y) ./ hs - c6 - c2) .* p(3:Nx_max,y,t1) - ...
c3 .* p(3:Nx_max,y-1,t1) + ...
(c7 - c5 - (y-Ny-1) ./ g2) .* p(2:Nx1,y+1,t1) - ...
(dxx(2:Nx1,y) + dyy(2:Nx1,y)) .* p(2:Nx1,y,t1) .* (2 ./ hs) + ...
(c7 + c5 + (y-Ny-1) ./ g2) .* p(2:Nx1,y-1,t1) - ...
c4 .* p(1:Nx2,y+1,t1) + ...
(dxx(2:Nx1,y) ./ hs + c6 + c2) .* p(1:Nx2,y,t1) + ...
c4 .* p(1:Nx2,y-1,t1);
end
Unfortunately I'm in doubt that this produces still the same results, because this kind of editing is prone to typos. But you see the strategy and can replace the repeated calculations step by step by your own and check, if teh results are not changed.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Loops and Conditional Statements 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!