
Лаб. 12 ТПП
.docxЛабораторная работа №12
Виртуальные топологии
Цель: изучить основные принципы использования виртуальных топологий в технологии MPI на примере использования в рамках языка С++.
Задание:
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <cwchar>
#include <iostream>
#define GROUP1_SIZE 5 // Размер первой группы для кольцевого обмена
// chcp 65001
// mpiexec -n 9 .\TPP_LAB_7.exe
int main(int argc, char* argv[]) {
setlocale(LC_ALL, "ru_RU.UTF-8");
MPI_Init(&argc, &argv);
int rank, size, separator;
MPI_Comm group_comm;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < GROUP1_SIZE + 2) {
if (rank == 0) {
wprintf(L"Требуется минимум %d процессов.\n", GROUP1_SIZE + 2);
}
MPI_Finalize();
return 0;
}
// Разделение процессов на две группы
if (rank < GROUP1_SIZE) {
separator = 0;
}
else {
separator = 1;
}
MPI_Comm_split(MPI_COMM_WORLD, separator, rank, &group_comm);
if (separator == 0) {
// Группа 1: Декартовая топология (кольцевой обмен)
MPI_Comm cart_comm;
int dims[1] = { GROUP1_SIZE };
int periods[1] = { 1 }; // Замкнутое кольцо
int reorder = 0;
MPI_Cart_create(group_comm, 1, dims, periods, reorder, &cart_comm);
int cart_rank, left, right;
MPI_Comm_rank(cart_comm, &cart_rank);
MPI_Cart_shift(cart_comm, 0, 1, &left, &right);
int send_data = cart_rank + 100;
int recv_data;
MPI_Sendrecv(&send_data, 1, MPI_INT, right, 0,
&recv_data, 1, MPI_INT, left, 0,
cart_comm, MPI_STATUS_IGNORE);
wprintf(L"Процесс ранга %d (Группа 1, ранг в группе: %d): послал %d процессу %d, получил %d от процесса %d\n",
rank, cart_rank, send_data, right, recv_data, left);
fflush(stdin);
MPI_Comm_free(&cart_comm);
}
else {
// Группа 2: Топология графа (звезда: master-slave)
int group2_rank, group2_size;
MPI_Comm_rank(group_comm, &group2_rank);
MPI_Comm_size(group_comm, &group2_size);
int* index = new int[group2_size];
int* edges = new int[2 * (group2_size - 1)];
// Настройка топологии звезды
for (int i = 0; i < group2_size - 1; i++) {
edges[i] = i + 1;
}
for (int i = group2_size - 1; i < 2 * (group2_size - 1); i++) {
edges[i] = 0;
}
for (int i = 0; i < group2_size; i++) {
if (i == 0) {
index[i] = group2_size - 1;
}
else {
index[i] = index[i - 1] + 1;
}
}
MPI_Comm graph_comm;
MPI_Graph_create(group_comm, group2_size, index, edges, 0, &graph_comm);
if (group2_rank == 0) {
for (int i = 1; i < group2_size; i++) {
int data_to_send = i + 100;
MPI_Send(&data_to_send, 1, MPI_INT, i, 0, graph_comm);
wprintf(L"Основной процесс (Группа 2): отправил %d процессу-исполнителю %d\n", data_to_send, i);
fflush(stdin);
}
for (int i = 1; i < group2_size; i++) {
int data_received;
MPI_Recv(&data_received, 1, MPI_INT, i, 0, graph_comm, MPI_STATUS_IGNORE);
wprintf(L"Основной процесс (Группа 2): получил %d от процесса-исполнителя %d\n", data_received, i);
fflush(stdin);
}
}
else {
int data_received;
MPI_Recv(&data_received, 1, MPI_INT, 0, 0, graph_comm, MPI_STATUS_IGNORE);
wprintf(L"Процесс-исполнитель (Группа 2, ранг в группе %d): получил %d от основного процесса\n", group2_rank, data_received);
fflush(stdin);
int data_to_send = data_received * 2;
MPI_Send(&data_to_send, 1, MPI_INT, 0, 0, graph_comm);
}
delete[] index;
delete[] edges;
MPI_Comm_free(&graph_comm);
}
MPI_Comm_free(&group_comm);
MPI_Finalize();
return 0;
}