简体   繁体   中英

MATLAB - Help speed up the code

I need your help to speed up my MATLAB code. Line 17 is the most expensive part. It is because of the two nested loops. I need help with removing the loops and rewrite it into just one matrix multiplication expression. Note that I have taken dKdx as a cell, which is causing problems to replace nested loops with simple matrix multiplication term. Any ideas? Below if a simplified code. May be dKdx doesn't need to be an cell? Idea behind cell was to be able to store lot of matrices of size [2*(nelx+1) (nely+1),2 (nelx+1)*(nely+1)].

    clc
    nelx = 16; nely = 8;
    dKdx = cell(2*(nelx+1)*(nely+1),1);
    Hess = zeros(nelx*nely,nelx*nely);
    U = rand(2*(nelx+1)*(nely+1),1);
    dUdx = rand(2*(nelx+1)*(nely+1),nelx*nely);

    for elx = 1:nelx
        for ely = 1:nely
            elm = nely*(elx-1)+ely;               
            dKdx{elm,1} = rand(2*(nelx+1)*(nely+1),2*(nelx+1)*(nely+1));
        end
    end

    for i = 1:nelx*nely    
        for j = i:nelx*nely
            Hess(i,j) = U'*dKdx{j,1}*dUdx(:,i);
            if i ~= j
                Hess(j,i) = Hess(i,j);
            end
        end
    end

Here's one way to get it:

  B = reshape(U'*cell2mat(dKdx'),[size(U,1) nelx*nely]);
  C = B'*dUdx;
  Hess=tril(C)+triu(C',1);

In my machine this code runs 6-7 times faster than the for loop one. I wonder if there are other even faster ways...

It may not be surprising that the hessian is the bottleneck. You have to calculate O(n^2) matrix elements, and you are doing O(n^3) work per matrix element, so that's O(n^5), which is worse than inverting the matrix (unless I am misunderstanding your code).

Having said that, it seems like you should be able to replace the dKdx{j,1}*dUdx(:,i) matrix/vector multiplication in the inner loop with a single matrix/matrix multiplication dKdx{j,1}*dUdx in the outer loop, then just pull out the particular column that you need in the inner loop (you would need to j first too). I don't have time to try this myself right now, but perhaps it will help you.

Another thought: are you sure there isn't some structure in your matrices that you can take advantage of to reduce the number of matrix multiplies?

Update

In the process of trying to make my idea work, I came up with the following:

Hess2 = zeros(nelx*nely,nelx*nely);
for j=1:nelx*nely
    Hess2(j,:) = U'*dKdx{j,1}*dUdx;
end
Hess2 = tril(Hess2)+triu(Hess2',1);

On my machine this is 25 times faster, but Nate's is 80 times faster, so he beats me!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM