Как использовать SPMD для разных входных переменных и сохранять выходные данные по порядку?

Я использую алгоритм имитации отжига для оптимизации своей проблемы, я должен сделать это для 100 различных входных переменных и сохранить выходные данные для всех переменных по порядку. проблема в том, что я не знаю, как реализовать spmd в моем коде для выполнения параллельных вычислений, чтобы каждый ввод выполнялся на одном ядре ЦП, а окончательные результаты сохранялись в матрице со 100 строками. Я пытался поставить его перед первым циклом for, но он возвращает только составной элемент, состоящий из 4 элементов, так как мой процессор имеет 4 ядра. Вот мой код

spmd
for v=1:100
posmat=loading_param(Matrix,v);
nvar=size(posmat,2); 
popsize=50;
maxiter=20;
T0=1000;
Tf=1;
Tdamp=((T0-Tf)/maxiter);
nn=5;
T=T0;

%% initial population
tic
emp.var=[];
emp.fit=inf;
pop=repmat(emp,popsize,1);
    for i=1:popsize
     pop(i).var=randperm(nvar);
     pop_double=pop(i).var;
     posmat_new=tabdil(nvar,pop_double,posmat);
     dis=cij(posmat_new);
     pop(i).fit=fittness(dis);
    end
   [value,index]=min([pop.fit]);
   gpop=pop(index);

%% algorithm main loop 
BEST=zeros(maxiter,1);

for iter=1:maxiter
    for i=1:popsize
        bnpop=emp;
        for j=1:nn

            npop=create_new_pop(pop(j),nvar,posmat);

            if npop.fit<bnpop.fit
                bnpop=npop;

            end

        end

        if bnpop.fit<pop(i).fit
            pop(i)=bnpop;
        else
            E=bnpop.fit-pop(i).fit;
            pr=exp(-E/T);
            if rand<pr
                pop(i)=bnpop;
            end
        end
    end

    T=T-Tdamp;


 [value,index]=min([pop.fit]);
 if value<gpop.fit
 gpop=pop(index);

 BEST(iter)=gpop.fit;
 disp([ 'iter= ' num2str(iter) 'BEST=' num2str(BEST(iter))])
 end
end



%% algorithm results

disp([ ' Best solution=' num2str(gpop.var)])
disp([ ' Best fittness=' num2str(gpop.fit)])
disp([ ' Best time=' num2str(toc)])

bnpop_all(d,:)=bnpop.var;
d=d+1;

end %end of main for loop
end % end of spmd

person omid kiasat    schedule 27.08.2018    source источник


Ответы (1)


Из документации на spmd:

Значения, возвращаемые из тела оператора spmd, преобразуются в объекты Composite на клиент МАТЛАБ. Составной объект содержит ссылки на значения, хранящиеся в удаленных рабочих процессах MATLAB, и эти значения можно получить с помощью индексации массива ячеек. Фактические данные о рабочих процессах остаются доступными для последующего spmd выполнения до тех пор, пока Composite существует на клиенте, а параллельный пул остается открытым.

Таким образом, вывод представляет собой композит из 4 элементов, поскольку у вас 4 ядра ЦП, поэтому output{1} дает вам первый элемент, output{2} второй и т. д. Просто объедините их, чтобы получить результат в одной матрице.

Ваш код на этом этапе просто запускается четыре раза, один полный цикл из 100 итераций for на каждого работника. Более простой способ решить эту проблему — использовать parfor вместо spmd, как вы можете оставьте свою петлю такой же. Если вы хотите использовать spmd, сначала разрежьте v на четыре части (по 25 элементов в каждой), а затем на каждом воркере переберите только эти 25 элементов.

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

person Adriaan    schedule 27.08.2018
comment
Спасибо за ваш ответ, я уже знаю, где находится узкое место, именно там, где вы уже сказали, вложенный цикл начинается с ‹for iter=1:maxiter›. правильно ли изменить внутренний цикл‹ для j=1:nn› на ‹j=1:nn›? - person omid kiasat; 27.08.2018