Меню Закрыть

VIII Задание по MPI

image_pdfimage_print

В данном раздели приведены задания для закрепления полученных знаний по технологии программирования параллельных компьютеров MPI.

Задание 1. MPI. Hello World.

Скомпилировать и выполнить программу. Подробно объяснить как она работает.

#include <iostream>
#include "mpi.h"
using namespace std;
int main(int argc, char* argv[]){
MPI_Init(&argc, &argv);
int rank, n, i, message;
MPI_Status status;
MPI_Comm_size(MPI_COMM_WORLD, &n);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0)
{
cout << "Hello from process " << rank << "\n";
for (i=1; i<n; i++){
MPI_Recv(&message, 1, MPI_INT, MPI_ANY_SOURCE,MPI_ANY_TAG, MPI_COMM_WORLD, &status);
cout << "Hello from process " << message << endl;
}
}
else MPI_Send(&rank,1,MPI_INT,0,0,MPI_COMM_WORLD);
MPI_Finalize();
return 0;
}

Задание 2. MPI. Получение информации об атрибутах сообщения.

Подробно разобрать пример ниже, запустить и объяснить его.

#include <iostream>
#include <mpi.h>
using namespace std;
int main(int argc, char **argv)
{
int rank, size, ibuf;
MPI_Status status;
float rbuf;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
ibuf = rank;
rbuf = 1.0 * rank;
if(rank==1) MPI_Send(&ibuf, 1, MPI_INT, 0, 5, MPI_COMM_WORLD);
if(rank==2) MPI_Send(&rbuf, 1, MPI_FLOAT, 0, 5, MPI_COMM_WORLD);
if(rank==0){
MPI_Probe(MPI_ANY_SOURCE, 5, MPI_COMM_WORLD, &status);
if(status.MPI_SOURCE == 1){
MPI_Recv(&ibuf, 1, MPI_INT, 1, 5, MPI_COMM_WORLD, &status);
MPI_Recv(&rbuf, 1, MPI_FLOAT, 2, 5, MPI_COMM_WORLD, &status);
cout << "Process 0 recv " << ibuf << " from process 1, " << rbuf << "from process 2\n";
}
else if(status.MPI_SOURCE == 2){
MPI_Recv(&rbuf, 1, MPI_FLOAT, 2, 5, MPI_COMM_WORLD, &status);
MPI_Recv(&ibuf, 1, MPI_INT, 1, 5, MPI_COMM_WORLD, &status);
cout << "Process 0 recv " << rbuf << " from process 2, " << ibuf << "from process 1\n";
}
}
MPI_Finalize();
}

Задание 3. MPI. Передача и прием сообщений без блокировки. Обмен по кольцевой топологии при помощи неблокирующих операций.

Допишите программу. Скомпилируйте и запустите ее. Внимательно изучите код и объясните, как он работает.

#include <iostream>
#include "mpi.h"
int main(int argc, char **argv)
{
int rank, size, prev, next;
int buf[2];
MPI_Init(&argc,&argv);
MPI_Request reqs[4];
MPI_Status stats[4];
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
prev = rank - 1;
next = rank + 1;
if(rank==0) prev = size - 1;
if(rank==size - 1) next = 0;
MPI_Irecv(&buf[0], 1, MPI_INT, prev, 5, MPI_COMM_WORLD, &reqs[0]);
MPI_Irecv(&buf[1], 1, MPI_INT, next, 6, MPI_COMM_WORLD, &reqs[1]);
MPI_Isend(&rank, 1, MPI_INT, prev, 6, MPI_COMM_WORLD, &reqs[2]);
MPI_Isend(&rank, 1, MPI_INT, next, 5, MPI_COMM_WORLD, &reqs[3]);
MPI_Waitall(4, reqs, stats);
Здесь необходимо вывести на экран номер текущего процесса, и что он получает от предыдущего и
следующего процессов
MPI_Finalize();
}

Задание 4. MPI. Отложенные запросы на взаимодействие. Схема итерационного метода с обменом по кольцевой топологии при помощи отложенных запросов.

Найти и исправить ошибки, дописать цикл for. В каких случаях необходимо использовать цикл?

MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
prev = rank - 1;
next = rank + 1;
if(rank == 0) prev = size - 1;
if(rank == size - 1) next = 0;
MPI_Recv_init(rbuf[0], 1, MPI_FLOAT, prev, 5, MPI_COMM_WORLD, reqs[0]);
MPI_Recv_init(rbuf[1], 1, MPI_FLOAT, next, 6, MPI_COMM_WORLD, reqs[1]);
MPI_Send_init(sbuf[0], 1, MPI_FLOAT, prev, 6, MPI_COMM_WORLD, reqs[2]);
MPI_Send_init(sbuf[1], 1, MPI_FLOAT, next, 5, MPI_COMM_WORLD, reqs[3]);
for(i=...){
sbuf[0] =...;
sbuf[1] =...;
MPI_Startall(4, reqs);
//здесь мог быть ваш код
MPI_Waitall(4, reqs, stats);
//здесь мог быть ваш код
}
MPI_Request_free(reqs[0]);
MPI_Request_free(reqs[1]);
MPI_Request_free(reqs[2]);
MPI_Request_free(reqs[3]);

Задание 5. MPI. Коллективные взаимодействия процессов. Барьер. Моделирование барьерной синхронизации.

Программа написана на языке Си. Необходимо переписать на C++. А именно: вывод на экран printf заменить на cout, соблюдая синтаксис, добавить необходимые библиотеки.

Разобраться с новыми функциями, объяснить выполнение программы.

#include <stdio.h>
#include "mpi.h"
#define MAXPROC 128
#define NTIMES 10000
int main(int argc, char **argv)
{
int rank, size, i, it;
MPI_Init(&argc, &argv);
int ibuf[MAXPROC];
double time_start, time_finish;
MPI_Request req[2*MAXPROC];
MPI_Status statuses[MAXPROC];
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if(rank==0){
for(i = 1; i<size; i++){
MPI_Recv_init(&ibuf[i], 0, MPI_INT, i, 5, MPI_COMM_WORLD, &req[i]);
MPI_Send_init(&rank, 0, MPI_INT, i, 6, MPI_COMM_WORLD, &req[size+i]);
}
time_start = MPI_Wtime();
for(it = 0; it<NTIMES; it++){
MPI_Startall(size-1, &req[1]);
MPI_Waitall(size-1, &req[1], statuses);
MPI_Startall(size-1, &req[size+1]);
MPI_Waitall(size-1, &req[size+1], statuses);
}
}
else{
MPI_Recv_init(&ibuf[0], 0, MPI_INT, 0, 6, MPI_COMM_WORLD, &req[0]);
MPI_Send_init(&rank, 0, MPI_INT, 0, 5, MPI_COMM_WORLD, &req[1]);
time_start = MPI_Wtime();
for(it = 0; it<NTIMES; it++){
MPI_Start(&req[1]);
MPI_Wait(&req[1], statuses);
MPI_Start(&req[0]);
MPI_Wait(&req[0], statuses);
}
}
time_finish = MPI_Wtime()-time_start;
printf("rank = %d model time = %lf\n", rank, time_finish/NTIMES);
time_start = MPI_Wtime();
for(it = 0; it<NTIMES; it++) MPI_Barrier(MPI_COMM_WORLD);
time_finish = MPI_Wtime()-time_start;
printf("rank = %d barrier time = %lf\n", rank, time_finish/NTIMES);
MPI_Finalize();
}

Связанные записи