Параллельная реализация алгоритма Якоби занимает слишком много времени - PullRequest
0 голосов
/ 21 мая 2019

Я реализовал параллельную версию метода Якоби для разрешения линейной системы. Выполняя некоторые тесты, я заметил, что время выполнения функции параллельно очень велико по сравнению со временем выполнения последовательной функции. Это странно, потому что метод Якоби должен быть быстрее при выполнении в параллельной реализации.

Я думаю, что я делаю что-то не так в коде:

function [x,niter,resrel] = Parallel_Jacobi(A,b,TOL,MAXITER)
[n, m] = size(A); 
D = 1./spdiags(A,0);
B = speye(n)-A./spdiags(A,0);
C= D.*b;
x0=sparse(zeros(length(A),1));
spmd

    cod_vett=codistributor1d(1,codistributor1d.unsetPartition,[n,1]);
    cod_mat=codistributor1d(1,codistributor1d.unsetPartition,[n,m]);

    B= codistributed(B,cod_mat);
    C= codistributed(C,cod_vett);
    x= codistributed(B*x0 + C,cod_vett);

    Niter = 1; 
    TOLX = TOL;  
    while(norm(x-x0,Inf) > norm(x0,Inf)*TOLX && Niter < MAXITER)
        if(TOL*norm(x,Inf) > realmin)
            TOLX = norm(x,Inf)*TOL;
        else
            TOLX = realmin;
        end    
        x0 = x;
        x = B*x0 + C;
        Niter=Niter+1;
    end
end
Niter=Niter{1}; 
x=gather(x);
end

Ниже приведены тесты

%sequential Jacobi
format long;
A = gallery('poisson',20);
tic;
x= jacobi(A,ones(400,1),1e-6,2000000);
toc;
Elapsed time is 0.009054 seconds.
%parallel Jacobi
format long;
A = gallery('poisson',20);
tic;
x= Parallel_Jacobi(A,ones(400,1),1e-6,2000000);
toc;
Elapsed time is 11.484130 seconds.

Я рассчитал функцию parpool с 1,2,3 и 4 рабочими (у меня четырехъядерный процессор), и результат следующий:

%Test
format long;
A = gallery('poisson',20);
delete(gcp('nocreate'));
tic
%parpool(1/2/3/4) means that i executed 4 tests that differ only for the 
%argument in the function: first parpool(1), second parpool(2) and so on.
parpool(1/2/3/4);
toc
tic;
x= Parallel_Jacobi(A,ones(400,1),1e-6,2000000);
toc;

4 workers: parpool=13.322899 seconds, function=23.772271 

3 workers: parpool=10.911769 seconds, function=16.402633 

2 workers: parpool=9.371729 seconds, function=12.945154 

1 worker: parpool=8.460357 seconds, function=7.982958 .

Чем меньше работников, тем лучше время. Что, как сказал @Adriaan, вероятно, связано с накладными расходами.

Значит ли это, что в этом случае последовательная функция всегда быстрее, чем параллельная функция? Или есть лучший способ реализовать параллельный?

В этом вопросе говорится, что производительность в параллельном режиме лучше, когда число итераций велико. В моем случае, с этим тестом, есть только 32 итерации.

Последовательная реализация метода Якоби такова:

function [x,niter,resrel] = jacobi(A,b,TOL,MAXITER)
n = size(A,1); 
D = 1./spdiags(A,0);
B = speye(n)-A./spdiags(A,0);
C= D.*b;

x0=sparse(zeros(length(A),1));
x = B*x0 + C;
Niter = 1; 
TOLX = TOL;  

while(norm(x-x0,Inf) > norm(x0,Inf)*TOLX && Niter < MAXITER) 
    if(TOL*norm(x,Inf) > realmin)
        TOLX = norm(x,Inf)*TOL;
    else
        TOLX = realmin;
    end    

    x0 = x;
    x = B*x0 + C;

    Niter=Niter+1;
end
end

Я синхронизировал код с функцией timeit, и результаты таковы (входные данные такие же, как и у предыдущего):

4 рабочих: 11.693473075964102

3 рабочих: 9.221281335264003

2 рабочих: 9.150417240778545

1 работник: 6.047181992020434

последовательный: 0,002893932969688

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...