MATLAB并行工具箱的线性系统Ax = b的Gauss-Seidel方法

时间:2019-07-06 23:34:23

标签: matlab parallel-processing

我正在尝试修改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);

1 个答案:

答案 0 :(得分:0)

  1. i和j默认情况下定义为复数,因此最好使用ii和jj。
  2. matlab提供警告消息和示例,说明如何修复它们,以便您可以使用它来修复代码。

在您编写代码时,您将收到以下警告:

  • plotGauss在每次迭代中增加大小:

    plotGauss=[plotGauss;normVal];

    解决方案:用for循环替换while循环,提供合理的迭代次数,预初始化plotGauss数组,并在normVal(ii)<= tol

  • 时中断for循环
  • 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