Метод Гаусса-Зейделя для линейной системы Ax = b с параллельным набором инструментов MATLAB - PullRequest
0 голосов
/ 07 июля 2019

Я пытаюсь изменить метод Гаусса-Зейделя в MATLAB, чтобы иметь возможность параллельно выполнять мою линейную систему Ax = b над рабочими.Я изменяю оба цикла Nested for на циклы parfor (потому что нет зависимостей).Во-первых, я реализую ту же проблему, которую предоставляет MATLAB, как метод Гаусса-Зейделя, чтобы проверить, дает ли он те же значения.Он работал как в последовательном, так и в параллельном режиме.Позже я попытался сделать то же самое для матрицы A (1000,1000) с массивом b (1000,1), но результаты, которые я получаю, используя тот же код, не были одинаковыми, и время выполнения параллельно было намного большебольше, чем запустить его в сериале.Я изменяю серийный код на параллельный правильный?Кто-нибудь из вас предложит более подходящее решение?

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 голосов
/ 07 июля 2019
  1. i и j по умолчанию определены как комплексные числа, поэтому лучше использовать ii и jj.
  2. Matlab дает предупреждающие сообщения + примеры того, как их исправить, чтобы вы могли использовать его для исправления своего кода.

На ваш код вы получите предупреждения:

  • plotGauss увеличивает размер на каждой итерации:

    plotGauss=[plotGauss;normVal];

    Решение: заменить цикл while на цикл for, давая разумное количество итераций, предварительно инициализировать массив plotGauss и разорвать цикл for, когда normVal (ii) <= tol </p>

  • sigma передается между итерациями, поэтому вы не делаете его параллельным:

    parfor j=1:i-1
       sigma = sigma+A(i,j)*x(j);
    end

Решение: вычислить умножения в parfor для сохранения результатов во временном массиве, а затем сумма после цикла.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...