加快矩阵计算
Speed up matrix calculation
我正在研究线性模型预测控制,我需要为控制器计算一些矩阵,只是..计算其中一个需要很多时间,我想问一下是否有更好的方法对这个计算进行编码。我正在使用 MATLAB,但我也理解 FORTRAN。
好吧,我想计算一个矩阵 (Φ),但是我这样做需要花费很多时间来计算它。 Φ 矩阵的形式(右边的):
MPC_matrices.
Here 是我找到这张图片的书,以备不时之需(尤其是第 8 页)。
现在,我在 MATLAB 中编写的代码如下所示:(在 EDIT 之后移动)
考虑到我将有相当大的 NS、Np 和 Nc 变量,进行此计算将花费大量时间。有没有优化的方法(或者至少比我的方法更好)来加速这个计算?
编辑
在考虑了@Daniel 和 user2682877 的评论后,我测试了这个
clear;clc
Np = 80;
Nc = Np / 2;
m = 3;
q = 1;
Niter = 30;
MAT = zeros(Niter,5);
for I=1:Niter
NS = 10 * I;
A = rand(NS,NS);
B = rand(NS,m);
C = rand(1,NS);
tic
Phi1 = zeros(Np*q,Nc*m);
CB = C * B;
for i=1:Np
for j=1:Nc
if j<i
Phi1( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = C * A^(i-1-(j-1)) * B;
elseif j==i
Phi1( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = CB;
end
end
end
t1 = toc;
%大牛的建议
tic
Phi2=zeros(Np*q,Nc*m);
CB = C * B;
for diffij=0:Np-1
if diffij>0
F=C * A^diffij * B;
else
F=CB;
end
for i=max(1,diffij+1):min(Np,Nc+diffij)
j=i-diffij;
Phi2( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = F;
end
end
t2 = toc;
% user2682877 建议
tic
Phi3=zeros(Np*q,Nc*m);
temp = B;
% 1st column
Phi3( (q*1-(q-1)):(q*1) , (m*1-(m-1)):(m*1) ) = C * B;
for i=2:Np
% reusing temp
temp = A * temp;
Phi3( (q*i-(q-1)):(q*i) , (m*1-(m-1)):(m*1) ) = C * temp;
end
% remaining columns
for j=2:Nc
for i=j:Nc
Phi3( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) =...
Phi3( (q*(i-j+1)-(q-1)):(q*(i-j+1)) , (m*1-(m-1)):(m*1) );
end
end
t3 = toc;
MAT(I,:) = [I, NS, t1, t2 ,t3];
fprintf('I iteration = %g \n', I);
end
figure(1)
clf(1)
hold on
plot(MAT(:,2),MAT(:,3),'b')
plot(MAT(:,2),MAT(:,4),'r')
plot(MAT(:,2),MAT(:,5),'g')
hold off
legend('My <Unfortunate> Idea','Daniel`s suggestion','user2682877 suggestion')
xlabel('NS variable')
ylabel('Time, s')
这是结果图:
请记住,现在 NS = 300
, 但是 随着我升级我的模型(我打算在状态 space 中包含越来越多的方程和变量model)这个变量(主要是NS和Np)会越来越大。
@Daniel 的第二条评论,我知道我执行的计算比我应该做的要多,但是我缺乏经验限制了我升级这个的想法。
@durasm 的评论,我对parfor不是很熟悉,但是我会测试一下。
参考答案:我会尽快测试您的建议(...)并回复您。
结果
很明显,我最初的想法只比这里建议的要差一点。谢谢你们!你帮了大忙!
您的计算结果有限C * A^(i-1-(j-1)) * B
,这仅取决于 i 和 j 之间的差异。不重复计算了,我的方案是迭代这个差值和i,然后根据这两个变量计算j。
Phi=zeros(Np*q,Nc*m);
CB = C * B;
for diffij=0:Np-1
if diffij>0
F=C * A^diffij * B;
else
F=CB;
end
for i=max(1,diffij+1):min(Np,Nc+diffij)
j=i-diffij;
Phi( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = F;
end
end
性能比较:
也许你可以试试这个:
Phi=zeros(Np*q,Nc*m);
temp = B;
% 1st column
Phi( (q*1-(q-1)):(q*1) , (m*1-(m-1)):(m*1) ) = C * B;
for i=2:Np
% reusing temp
temp = A * temp;
Phi( (q*i-(q-1)):(q*i) , (m*1-(m-1)):(m*1) ) = C * temp;
end
% remaining columns
for j=2:Nc
for i=j:Np
Phi( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = Phi( (q*(i-j+1)-(q-1)):(q*(i-j+1)) , (m*1-(m-1)):(m*1) );
end
end
我正在研究线性模型预测控制,我需要为控制器计算一些矩阵,只是..计算其中一个需要很多时间,我想问一下是否有更好的方法对这个计算进行编码。我正在使用 MATLAB,但我也理解 FORTRAN。
好吧,我想计算一个矩阵 (Φ),但是我这样做需要花费很多时间来计算它。 Φ 矩阵的形式(右边的):
MPC_matrices.
Here 是我找到这张图片的书,以备不时之需(尤其是第 8 页)。
现在,我在 MATLAB 中编写的代码如下所示:(在 EDIT 之后移动)
考虑到我将有相当大的 NS、Np 和 Nc 变量,进行此计算将花费大量时间。有没有优化的方法(或者至少比我的方法更好)来加速这个计算?
编辑
在考虑了@Daniel 和 user2682877 的评论后,我测试了这个
clear;clc
Np = 80;
Nc = Np / 2;
m = 3;
q = 1;
Niter = 30;
MAT = zeros(Niter,5);
for I=1:Niter
NS = 10 * I;
A = rand(NS,NS);
B = rand(NS,m);
C = rand(1,NS);
tic
Phi1 = zeros(Np*q,Nc*m);
CB = C * B;
for i=1:Np
for j=1:Nc
if j<i
Phi1( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = C * A^(i-1-(j-1)) * B;
elseif j==i
Phi1( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = CB;
end
end
end
t1 = toc;
%大牛的建议
tic
Phi2=zeros(Np*q,Nc*m);
CB = C * B;
for diffij=0:Np-1
if diffij>0
F=C * A^diffij * B;
else
F=CB;
end
for i=max(1,diffij+1):min(Np,Nc+diffij)
j=i-diffij;
Phi2( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = F;
end
end
t2 = toc;
% user2682877 建议
tic
Phi3=zeros(Np*q,Nc*m);
temp = B;
% 1st column
Phi3( (q*1-(q-1)):(q*1) , (m*1-(m-1)):(m*1) ) = C * B;
for i=2:Np
% reusing temp
temp = A * temp;
Phi3( (q*i-(q-1)):(q*i) , (m*1-(m-1)):(m*1) ) = C * temp;
end
% remaining columns
for j=2:Nc
for i=j:Nc
Phi3( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) =...
Phi3( (q*(i-j+1)-(q-1)):(q*(i-j+1)) , (m*1-(m-1)):(m*1) );
end
end
t3 = toc;
MAT(I,:) = [I, NS, t1, t2 ,t3];
fprintf('I iteration = %g \n', I);
end
figure(1)
clf(1)
hold on
plot(MAT(:,2),MAT(:,3),'b')
plot(MAT(:,2),MAT(:,4),'r')
plot(MAT(:,2),MAT(:,5),'g')
hold off
legend('My <Unfortunate> Idea','Daniel`s suggestion','user2682877 suggestion')
xlabel('NS variable')
ylabel('Time, s')
这是结果图:
请记住,现在 NS = 300
, 但是 随着我升级我的模型(我打算在状态 space 中包含越来越多的方程和变量model)这个变量(主要是NS和Np)会越来越大。
@Daniel 的第二条评论,我知道我执行的计算比我应该做的要多,但是我缺乏经验限制了我升级这个的想法。
@durasm 的评论,我对parfor不是很熟悉,但是我会测试一下。
参考答案:我会尽快测试您的建议(...)并回复您。
结果 很明显,我最初的想法只比这里建议的要差一点。谢谢你们!你帮了大忙!
您的计算结果有限C * A^(i-1-(j-1)) * B
,这仅取决于 i 和 j 之间的差异。不重复计算了,我的方案是迭代这个差值和i,然后根据这两个变量计算j。
Phi=zeros(Np*q,Nc*m);
CB = C * B;
for diffij=0:Np-1
if diffij>0
F=C * A^diffij * B;
else
F=CB;
end
for i=max(1,diffij+1):min(Np,Nc+diffij)
j=i-diffij;
Phi( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = F;
end
end
性能比较:
也许你可以试试这个:
Phi=zeros(Np*q,Nc*m);
temp = B;
% 1st column
Phi( (q*1-(q-1)):(q*1) , (m*1-(m-1)):(m*1) ) = C * B;
for i=2:Np
% reusing temp
temp = A * temp;
Phi( (q*i-(q-1)):(q*i) , (m*1-(m-1)):(m*1) ) = C * temp;
end
% remaining columns
for j=2:Nc
for i=j:Np
Phi( (q*i-(q-1)):(q*i) , (m*j-(m-1)):(m*j) ) = Phi( (q*(i-j+1)-(q-1)):(q*(i-j+1)) , (m*1-(m-1)):(m*1) );
end
end