我需要你的帮助来加速我的MATLAB代码。 17号线是最昂贵的部分。这是因为两个嵌套循环。我需要帮助删除循环并将其重写为一个矩阵乘法表达式。请注意,我已将dKdx作为单元格,这会导致用简单的矩阵乘法项替换嵌套循环的问题。有任何想法吗? 下面是一个简化的代码。可能dKdx不需要是一个细胞?细胞背后的想法是能够存储大量的基质[2 *(nelx + 1)(nely + 1),2 (nelx + 1)*(nely + 1)]。< / p>
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
答案 0 :(得分:3)
这是获得它的一种方法:
B = reshape(U'*cell2mat(dKdx'),[size(U,1) nelx*nely]);
C = B'*dUdx;
Hess=tril(C)+triu(C',1);
在我的机器中,这段代码的运行速度比for循环码快6-7倍。我想知道是否还有其他更快的方法......
答案 1 :(得分:2)
粗麻布是瓶颈可能并不奇怪。你必须计算O(n ^ 2)个矩阵元素,并且你每个矩阵元素都在进行O(n ^ 3)工作,所以这是O(n ^ 5),这比反转矩阵更糟糕(除非我误解你的码)。
话虽如此,看起来你应该能够在外循环中用单个矩阵/矩阵乘法dKdx{j,1}*dUdx(:,i)
替换内循环中的dKdx{j,1}*dUdx
矩阵/向量乘法,然后只需拉在内循环中你需要的特定列(你首先需要j
)。我现在没有时间自己尝试,但也许它会对你有帮助。
另一个想法:你确定你的矩阵中没有一些结构可以利用它来减少矩阵乘法的次数吗?
<强>更新强>
在尝试让我的想法发挥作用的过程中,我想出了以下内容:
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);
在我的机器上,这速度提高了25倍,但Nate的速度提高了80倍,所以他打败了我!