Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лаб. 11 ТПП

.docx
Скачиваний:
2
Добавлен:
29.12.2024
Размер:
159.74 Кб
Скачать

Лабораторная работа №11

Управление группами процессов и коммуникаторами

Цель: изучить основные принципы управления группами процессов и коммуникаторами в технологии MPI на примере использования в рамках языка С++.

Задание:

#include <iostream>

#include <cstdlib>

#include <ctime>

#include <cstdio>

#include <mpi.h>

#include <cwchar>

// mpiexec -n 2 .\TPP_LAB_7.exe

using namespace std;

#define A 6 // Размер матрицы

void generateMatrix(int matrix[A][A]) {

srand(static_cast<unsigned>(time(nullptr)));

for (int i = 0; i < A; i++) {

for (int j = 0; j < A; j++) {

matrix[i][j] = rand() % 10;

}

}

}

void generateArray(int array[A]) {

srand(static_cast<unsigned>(time(nullptr)) + A);

for (int i = 0; i < A; i++) {

array[i] = rand() % 10;

}

}

int determinant(int matrix[A][A], int n) {

if (n == 1) {

return matrix[0][0];

}

if (n == 2) {

return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];

}

int det = 0;

int temp[A][A];

for (int p = 0; p < n; p++) {

int h = 0;

for (int i = 1; i < n; i++) {

int k = 0;

for (int j = 0; j < n; j++) {

if (j != p) {

temp[h][k] = matrix[i][j];

k++;

}

}

h++;

}

det += (p % 2 == 0 ? 1 : -1) * matrix[0][p] * determinant(temp, n - 1);

}

return det;

}

void printMatrix(int matrix[A][A]) {

for (int i = 0; i < A; i++) {

for (int j = 0; j < A; j++) {

wprintf(L"%d ", matrix[i][j]);

fflush(stdin);

}

wprintf(L"\n");

fflush(stdin);

}

}

void printArray(const int array[A]) {

for (int i = 0; i < A; i++) {

wprintf(L"%d ", array[i]);

fflush(stdin);

}

wprintf(L"\n");

fflush(stdin);

}

int main(int argc, char* argv[]) {

setlocale(LC_ALL, "ru_RU.UTF-8");

MPI_Init(&argc, &argv);

int rank, size;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Datatype MPI_Matrix;

MPI_Type_contiguous(A * A, MPI_INT, &MPI_Matrix);

MPI_Type_commit(&MPI_Matrix);

int count_of_processes_used = size - 1;

if (count_of_processes_used > A) {

count_of_processes_used = A;

}

int count_of_transmitted_matrix = A / count_of_processes_used;

int remains = A % count_of_processes_used;

MPI_Group world_group;

MPI_Comm_group(MPI_COMM_WORLD, &world_group);

// Массивы для хранения групп и коммуникаторов

MPI_Group* sub_groups = new MPI_Group[count_of_processes_used];

MPI_Comm* group_comm = new MPI_Comm[count_of_processes_used];

// Создание групп и коммуникаторов

for (int i = 0; i < count_of_processes_used; i++) {

int members[] = { 0, i + 1 };

MPI_Group_incl(world_group, 2, members, &sub_groups[i]);

MPI_Comm_create(MPI_COMM_WORLD, sub_groups[i], &group_comm[i]);

}

if (rank == 0) {

int matrix[A][A];

int matrix_2[A][A];

generateMatrix(matrix);

wprintf(L"Сгенерированная матрица размером %dx%d:\n", A, A);

fflush(stdin);

printMatrix(matrix);

int det = determinant(matrix, A);

wprintf(L"Определитель матрицы: %d\n", det);

fflush(stdin);

int array[A];

generateArray(array);

wprintf(L"Сгенерированный массив размером %d:\n", A);

fflush(stdin);

printArray(array);

if (det == 0) {

for (int i = 1; i <= count_of_processes_used; i++) {

MPI_Send(&det, 1, MPI_INT, 1, 1, group_comm[i - 1]);

}

}

else {

int count = 0;

for (int i = 1; i <= count_of_processes_used; i++) {

MPI_Send(&det, 1, MPI_INT, 1, 1, group_comm[i - 1]);

if (i == count_of_processes_used) {

for (int k = 0; k < count_of_transmitted_matrix + remains; k++) {

memcpy(matrix_2, matrix, sizeof(matrix));

for (int j = 0; j < A; j++) {

matrix_2[j][count] = array[j];

}

MPI_Send(matrix_2, 1, MPI_Matrix, 1, 0, group_comm[i - 1]);

count++;

}

}

else {

for (int k = 0; k < count_of_transmitted_matrix; k++) {

memcpy(matrix_2, matrix, sizeof(matrix));

for (int j = 0; j < A; j++) {

matrix_2[j][count] = array[j];

}

MPI_Send(matrix_2, 1, MPI_Matrix, 1, 0, group_comm[i - 1]);

count++;

}

}

}

}

//MPI_Send(matrix, 1, MPI_Matrix, 1, 0, MPI_COMM_WORLD);

}

else if (rank > 0 and rank < count_of_processes_used) {

int det = 0;

MPI_Recv(&det, 1, MPI_INT, 0, 1, group_comm[rank - 1], MPI_STATUS_IGNORE);

if (det == 0) {

//wprintf(L"Метод Крамера не применим\n");

//fflush(stdin);

}

else {

int matrix[A][A];

for (int i = 0; i < count_of_transmitted_matrix; i++) {

MPI_Recv(matrix, 1, MPI_Matrix, 0, 0, group_comm[rank - 1], MPI_STATUS_IGNORE);

//wprintf(L"Полученная матрица рангом: %d:\n", rank);

//fflush(stdin);

//printMatrix(matrix);

// Вычисление определителя

int det_kramer = determinant(matrix, A);

int number = rank + i;

double x = (double)det_kramer / (double)det;

wprintf(L"x%d = %lf\n", number, x);

fflush(stdin);

//wprintf(L"Определитель матрицы: %d\n", det);

//fflush(stdin);

}

}

}

else if (rank == count_of_processes_used) {

int det = 0;

MPI_Recv(&det, 1, MPI_INT, 0, 1, group_comm[rank - 1], MPI_STATUS_IGNORE);

if (det == 0) {

wprintf(L"Метод Крамера не применим\n");

fflush(stdin);

}

else {

int matrix[A][A];

for (int i = 0; i < count_of_transmitted_matrix + remains; i++) {

MPI_Recv(matrix, 1, MPI_Matrix, 0, 0, group_comm[rank - 1], MPI_STATUS_IGNORE);

//wprintf(L"Полученная матрица рангом: %d:\n", rank);

//fflush(stdin);

//printMatrix(matrix);

// Вычисление определителя

int det_kramer = determinant(matrix, A);

int number = rank + i;

double x = (double)det_kramer / (double)det;

wprintf(L"x%d = %lf\n", number, x);

fflush(stdin);

//wprintf(L"Определитель матрицы: %d\n", det);

//fflush(stdin);

}

}

}

for (int i = 0; i < count_of_processes_used; i++) {

if (group_comm[i] != MPI_COMM_NULL) {

MPI_Comm_free(&group_comm[i]);

}

MPI_Group_free(&sub_groups[i]);

}

delete[] group_comm;

delete[] sub_groups;

MPI_Finalize();

return 0;

}

Соседние файлы в предмете Технологии параллельного программирования