
Лаб. 10 ТПП
.docxЛабораторная работа №10
Производные типы данных в MPI
Цель: изучить основные принципы использования производных типов данных в технологии MPI на примере использования в рамках языка С++.
Задание:
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <mpi.h>
using namespace std;
#define DIGITS 1 // Количество цифр в числе (>=1)
#define A 2 // Количество чисел (>=2)
// mpiexec -n 5 .\TPP_LAB_7.exe
vector<wchar_t> multiply_long_ints(vector<vector<wchar_t>>& numbers) {
const wchar_t* num1 = numbers[0].data();
const wchar_t* num2 = numbers[1].data();
int len1 = wcslen(num1);
int len2 = wcslen(num2);
//wprintf(L"len1: %d\n", len1);
//wprintf(L"len2: %d\n\n", len2);
int temp_res_len = len1 + len2;
int array_rows = len2;
int array_cols = len1 + len2 + 1;
//wprintf(L"array_cols: %d\n\n", array_cols);
int result_size = len1 + len2 + 1;
vector<wchar_t> temp_result(result_size, L'0');
temp_result[result_size - 1] = L'\0';
// Массив для хранения результатов умножения столбиком,
// для дальнейшего суммирования каждого столбца и получения
// итогового результата
vector<vector<wchar_t>> array(array_rows, vector<wchar_t>(array_cols, L'0'));
for (auto& row : array) {
row[array_cols - 1] = L'\0';
}
int a = 0;
int count = 1;
int temp;
int col;
for (int i = len2 - 1; i >= 0; i--) {
temp = 0;
//col = static_cast<int>(wcslen(result)) - count;
col = temp_res_len - count;
for (int j = len1 - 1; j >= 0; j--) {
a = (num1[j] - L'0') * (num2[i] - L'0') + temp;
temp = a / 10;
if (j != 0) {
a = a % 10;
array[i][col] = L'0' + a;
col--;
}
else {
a = a % 10;
array[i][col] = L'0' + a;
array[i][col - 1] = L'0' + temp;
}
}
count++;
}
int sum;
temp = 0;
//col = static_cast<int>(wcslen(result));
col = temp_res_len;
for (int i = col - 1; i >= 0; i--) {
sum = 0;
for (int j = array_rows - 1; j >= 0; j--) {
sum += (array[j][i] - L'0');
}
sum += temp;
temp = sum / 10;
sum = sum % 10;
//result[i] = L'0' + sum;
temp_result[i] = L'0' + sum;
}
//wprintf(L"wcslen_result: %d\n", wcslen(result));
//wprintf(L"wcslen_temp_result: %d\n\n", wcslen(temp_result.data()));
//wprintf(L"result_result: %s\n", result);
//wprintf(L"temp_result: %s\n\n", temp_result.data());
numbers.erase(numbers.begin());
numbers.erase(numbers.begin());
if (!numbers.empty()) {
numbers.push_back(temp_result);
return multiply_long_ints(numbers);
}
/*for (int i = 0; i < 6; i++) {
wprintf(L"NNN: %s\n", numbers[i].data());
}*/
return temp_result;
}
// Функция для генерации длинного целого числа
void generate_long_ints(vector<vector<wchar_t>>& numbers, int max_digits) {
for (auto& num : numbers) {
for (int j = 0; j < max_digits - 1; j++) {
num[j] = L'0' + rand() % 10;
}
num[max_digits - 1] = L'\0';
wprintf(L"Generated num: %ls\n", num.data());
fflush(stdin);
}
}
void create_long_int_type(MPI_Datatype* long_int_type, int size) {
//int result_size = max_digits * 2 + 1;
MPI_Type_contiguous(size, MPI_WCHAR, long_int_type);
MPI_Type_commit(long_int_type);
}
//void create_long_int_result_type(MPI_Datatype* long_int_result_type, int size) {
// //int result_size = max_digits * 2 + 1;
// MPI_Type_contiguous(size, MPI_WCHAR, long_int_result_type);
// MPI_Type_commit(long_int_result_type);
//}
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);
int max_digits = DIGITS; // Максимальное количество цифр
int max_numbers = A; // Количество чисел в массиве
int num_size = max_digits + 1; // Размер числа с учётом завершающего символа
int result_size = max_digits * max_numbers + 1; // Размер результата с учётом завершающего символа
/*if (rank == 0) {
wprintf(L"result_size: %d\n", result_size);
fflush(stdin);
}
if (rank == 0) {
wprintf(L"num_size_1: %d\n", num_size);
fflush(stdin);
}*/
MPI_Datatype long_int_type;
create_long_int_type(&long_int_type, num_size);
// Массив перемножающихся чисел
vector<vector<wchar_t>> array_of_multiplying_numbers(max_numbers,
vector<wchar_t>(result_size, L'0'));
// Массив временного хранения двух перемножающихся чисел
/*vector<vector<wchar_t>> array_for_storing_two_numbers(2,
vector<wchar_t>(result_size, L'0'));*/
// Временный результат перемножения двух чисел
//vector<wchar_t> temporary_result(result_size, L'0');
//temporary_result[result_size - 1] = L'\0';
//Итоговый результат
/*vector<wchar_t> final_result(result_size + 1, L'0');
final_result[result_size - 1 + 1] = L'\0';*/
srand(static_cast<unsigned>(time(nullptr)) + rank);
if (rank == 0) {
generate_long_ints(array_of_multiplying_numbers, num_size);
}
// Количество используемых процессов
int count_of_processes_used = size - 1;
// Количество используемых процессов в прошлом цикле
//int las_count_of_processes_used = size - 1;
// Текущее количество используемых чисел
//int current_size_array_of_multiplying_numbers =
// static_cast<int>(array_of_multiplying_numbers.size());
// Количество используемых чисел
//int size_array_of_multiplying_numbers =
// static_cast<int>(array_of_multiplying_numbers.size());
if (count_of_processes_used > (A / 2)) {
count_of_processes_used = A / 2;
}
/*if (rank == 0) {
wprintf(L"count_of_processes_used: %d\n", count_of_processes_used);
fflush(stdin);
}*/
/*int length =
static_cast<int>(array_of_multiplying_numbers.size());*/
int count_of_transmitted_numbers = A / count_of_processes_used;
/*if (rank == 0) {
wprintf(L"count_of_transmitted_numbers: %d\n", count_of_transmitted_numbers);
fflush(stdin);
}*/
int remains = A % count_of_processes_used;
/*if (rank == 0) {
wprintf(L"remains: %d\n", remains);
fflush(stdin);
}*/
MPI_Datatype long_int_result_type;
num_size = max_digits * count_of_transmitted_numbers + 1;
/*if (rank == 0) {
wprintf(L"num_size_2: %d\n", num_size);
fflush(stdin);
}*/
create_long_int_type(&long_int_result_type, num_size);
if (rank == 0) {
for (int i = 1; i <= count_of_processes_used; i++) {
for (int j = 0; j < count_of_transmitted_numbers; j++) {
MPI_Send(array_of_multiplying_numbers[0].data(), 1, long_int_type,
i, 0, MPI_COMM_WORLD);
array_of_multiplying_numbers.erase(array_of_multiplying_numbers.begin());
}
}
if (count_of_transmitted_numbers < A) {
vector<vector<wchar_t>> results(count_of_processes_used,
vector<wchar_t>(result_size, L'0'));
for (int i = 0; i < count_of_processes_used; i++) {
MPI_Recv(results[i].data(), 1, long_int_result_type,
i + 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
if (!array_of_multiplying_numbers.empty()) {
for (int i = 0; i < remains; i++) {
results.push_back(array_of_multiplying_numbers[i]);
}
//wprintf(L"Q: %s\n", array_of_multiplying_numbers[0].data());
//fflush(stdin);
}
vector<wchar_t> final_result = multiply_long_ints(results);
wprintf(L"\n\nfinal_result: %ls\n", final_result.data());
fflush(stdin);
}
else {
vector<wchar_t> final_result(result_size + 1, L'0');
final_result[result_size - 1 + 1] = L'\0';
MPI_Recv(final_result.data(), 1, long_int_result_type,
1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
wprintf(L"\n\nfinal_result: %ls\n", final_result.data());
fflush(stdin);
}
}
else if (rank > 0 and rank <= count_of_processes_used) {
vector<vector<wchar_t>> array_for_one_process(count_of_transmitted_numbers,
vector<wchar_t>(result_size, L'0'));
for (int j = 0; j < count_of_transmitted_numbers; j++) {
MPI_Recv(array_for_one_process[j].data(), 1, long_int_type,
0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
vector<wchar_t> temp_result = multiply_long_ints(array_for_one_process);
/* wprintf(L"temp_result: %ls\n", temp_result.data());
fflush(stdin);*/
int length =
static_cast<int>(temp_result.size());
/*if (rank == 1) {
wprintf(L"length: %d\n", length);
fflush(stdin);
}*/
MPI_Send(temp_result.data(), 1, long_int_result_type, 0, 0, MPI_COMM_WORLD);
//MPI_Send(temporary_result.data(), 1, long_int_type, 0, 5, MPI_COMM_WORLD);
}
/*else {
}*/
/*if (rank == 0) {
wprintf(L"Result 1: %ls\n", final_result.data());
fflush(stdin);
}*/
MPI_Type_free(&long_int_type);
MPI_Type_free(&long_int_result_type);
MPI_Finalize();
return 0;
}