Home - Templet-language/mpiruntime GitHub Wiki
Дамир,
Предлагаю внести ещё одно упрощение в текущую реализацию с MPI. Мы предполагали следующую схему выполения:
int main(int argc, char*argv[])
{
engine e(argc,argv); // дочерние процессы выполняют код до этой команды
// конструируем процессы
prc1 p1=e.prc1();
prc2 p2=e.prc2();
.................
// связываем их
p1.port1(p2.port2());
.................
// инициализируем процессы
p1.data="что-то";
p2.data="ещё что-то";
.................
// запускаем вычисления
e.run();
// выводим результаты
cout << p1.data;
cout << p2.data;
}
Упрощение следующее. Выделяем явно секции построения графа программы и инициализации данных. Предполагаем, что граф программы никак не зависит от входных данных программы. Например, так:
int main(int argc, char*argv[])
{
engine e(argc,argv);
// конструируем процессы
prc1 p1=e.prc1();
prc2 p2=e.prc2();
.................
// связываем их
p1.port1(p2.port2());
.................
// даём команду отображения графа алгоритма на ВС
// дочерние процессы выполняют код только до этой команды
e.map();
// а теперь инициализируем процессы
p1.data="что-то";
p2.data="ещё что-то";
.................
// запускаем вычисления
e.run();
// выводим результаты
cout << p1.data;
cout << p2.data;
}
В данном случае не требуется размножать информацию о графе программы и управлять сборкой графа на удалённых узлах. Для примера Sin2(x)+Cos2(x) код может выглядеть так:
int main(int argc, char*argv[])
{
engine e(argc,argv);
// конструируем процессы
Parent p(e);
Child ch1(e),ch2(e);
// связываем их
ch1.p(p.p1());
ch2.p(p.p2());
// назначаем процессы на узлы MPI
p.at(0); ch1.at(1); ch2.at(2);
// на этом часть, выполняющаяся на всех узлах закончена
// даём команду отображения графа алгоритма на ВС
// дочерние процессы выполняют код только до этой команды
e.map();
// а теперь инициализируем процессы
cin >> x;
// запускаем вычисления
p.init();
e.run();
// выводим результат
cout << "Sin2(x)+Cos2(x)=" << one;
}
Примерный алгоритм работы вызова e.map();
if(rank текущего процесса == 0){
for(актор : все акторы программы){
if(актор назначен на процесс с rank!=0) отправить актор на его процесс;
}
}
else{
for(актор : акторы, назначенные на текущий процесс) принять актор;
for(){
обрабатывать сообщения;
if(сообщений больше нет) break;
}
for(актор : акторы, назначенные на текущий процесс)
выслать актор мастер-процессу;
закрыть процесс MPI, вызвав MPI_Finalize();
return 0;
}
Примерный алгоритм работы вызова e.run();
for(){
обрабатывать сообщения;
if(сообщений больше нет) break;
}
разослать всем процессам команду "переслать свои акторы мастер-процессу";
for(актор : все акторы программы){
if(актор назначен на процесс rank!=0) принять актор с данного процесса;
}
закрыть процесс MPI, вызвав MPI_Finalize();