我正在尝试修改MATLAB中的Gauss-Seidel方法,以便能够在工作程序上并行执行我的线性系统Ax = b。我将两个嵌套的for循环都更改为parfor循环(因为没有依赖项)。首先,我实现了MATLAB作为Gauss-Seidel方法提供的相同问题,以查看其是否提供相同的值。它既可以串行方式也可以并行方式工作。后来,我尝试对具有b(1000,1)数组的A(1000,1000)矩阵执行相同的操作,但是我使用相同代码得到的结果并不相同,并且并行执行时间更长比串行运行更大。我是否可以将串行代码更改为并行正确的代码?你们中有人会建议一个更充分的解决方案吗?
A=[5 -2 3 0 6; -3 9 1 -2 7.4; 2 -1 -7 1 6.7; 4 3 -5 7 9; 2 3.5 6.1 -4 -8.1];
b=[-1 2 3 0.5 3.1]' ;
x=rand(5,1);
n=size(x,1);
normVal=inf;
tol=1e-3;
GaussItr=0;
plotGauss=[];
timeStart = tic;
while normVal>tol
x_old = x ;
for i=1:n
sigma = 0;
parfor j=1:i-1
sigma = sigma+A(i,j)*x(j);
end
parfor j=i+1:n
sigma = sigma +A(i,j)*x_old(j);
end
x(i)=(1/A(i,i))*(b(i)-sigma);
end
GaussItr=GaussItr+1;
normVal=norm(x_old-x);
plotGauss=[plotGauss;normVal];
end
timeEnd = toc(timeStart);
答案 0 :(得分:0)
在您编写代码时,您将收到以下警告:
plotGauss
在每次迭代中增加大小:
plotGauss=[plotGauss;normVal];
解决方案:用for循环替换while循环,提供合理的迭代次数,预初始化plotGauss数组,并在normVal(ii)<= tol
sigma
在迭代之间传递,因此您不能使其并行:
parfor j=1:i-1
sigma = sigma+A(i,j)*x(j);
end
解决方案:计算par中的乘法以将结果保存到临时数组中,然后 循环后的总和。
tmp = zeros(1,n);
...
parfor jj=1:ii-1
tmp(jj)= A(ii,jj)*x(jj);
end
sigma = sum(tmp(1:ii-1));
总结:
未经测试(对不起,我家里没有matlab)
MAX_ITER = 100;
A=[5 -2 3 0 6; -3 9 1 -2 7.4; 2 -1 -7 1 6.7; 4 3 -5 7 9; 2 3.5 6.1 -4 -8.1];
b=[-1 2 3 0.5 3.1]' ;
x=rand(5,1);
n=size(x,1);
normVal=inf;
tol=1e-3;
% GaussItr=0; => see below for loop
sigma = 0;
tmp = zeros(1,n);
plotGauss=nan*ones(1,MAX_ITER);
timeStart = tic;
for kk=1:MAX_ITER
x_old = x ;
for ii=1:n
parfor jj=1:ii-1
tmp(jj)= A(ii,jj)*x(jj);
end
tmp(ii) = 0; % to keep sigma as sum of all tmp elements
parfor jj=ii+1:n
tmp(jj)= A(ii,jj)*x_old(jk);
end
sigma = sum(tmp);
x(ii)=(1/A(ii,ii))*(b(ii)-sigma);
end
% GaussItr=GaussItr+1; => use kk index instead
normVal=norm(x_old-x);
plotGauss(kk) = normVal;
if normVal<=tol
break; % break the for loop if we already reached desire tolerance
end
end
timeEnd = toc(timeStart);
GaussItr = kk;
if normVal>tol
error('code finished after %d iterations without reaching desired tolerance',GaussItr);
end