Uploaded by Denis Severin (Denis0011)

PP lab 9

advertisement
МИНОБРНАУКИ РФ
Федеральное государственное бюджетное
образовательное учреждение высшего образования
«Тульский государственный университет»
Институт прикладной математики и компьютерных наук
Кафедра вычислительной техники
Отчёт по лабораторной работе №9
«Коллективные обмены в MPI»
по дисциплине «Параллельное программирование»
Вариант 2
Выполнил
Ст. гр. 220682
Проверил
Асс.
Шмелев Г. С._____
Думчев Е. В.____
Тула 2021
ЗАДАНИЕ НА РАБОТУ
Написать параллельную программу для вычисления максимального и
минимального значений среди элементов матрицы A – 400 x 300, заполненной
случайными числами. Определите зависимость коэффициента ускорения от числа
процессоров.
ПРОГРАММНАЯ РЕАЛИЗАЦИЯ
#include "matrix.hpp"
#include <mpi.h>
#include <iostream>
#include <random>
#include <chrono>
#define rows 400
#define cols 300
class Timer
{
private:
using clock_t = std::chrono::high_resolution_clock;
using second_t = std::chrono::duration<double, std::ratio<1> >;
std::chrono::time_point<clock_t> m_beg;
public:
Timer() {}
void start() {
m_beg = clock_t::now();
}
void reset()
{
m_beg = clock_t::now();
}
double elapsed() const
{
return std::chrono::duration_cast<second_t>(clock_t::now() - m_beg).count();
}
};
class Random
{
public:
Random()
{
std::random_device device;
random_generator_.seed(device());
}
double returnRandom(double max)
{
std::uniform_real_distribution<double> range(0.0, max);
return range(random_generator_);
}
2
private:
std::mt19937 random_generator_;
};
int main(int argc, char** argv)
{
Random rnd;
simple_matrix::matrix matrix{ rows, cols };
int rank, size;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank); // определение ранга процесса
MPI_Comm_size(MPI_COMM_WORLD, &size); // определение размера области взаимодействия
if (rank == 0)
{
for (auto i = 0; i < rows; ++i)
for (auto j = 0; j < cols; ++j)
matrix.set(i, j, rnd.returnRandom(100));
}
if (rank == 0)
{
Timer t;
t.start();
auto minmax = std::minmax_element(matrix.begin(), matrix.end());
std::cout << "min = " << *minmax.first << "; max = " << *minmax.second << "; time = " << t.elapsed() << std::endl;
}
int numberInThread = ((rows * cols) % size == 0 ? rows * cols / size : rows * cols / size + 1);
double* partOfMatrix = new double[numberInThread];
Timer t;
if (rank == 0)
t.start();
MPI_Scatter(matrix.inner_matrix(), numberInThread, MPI_DOUBLE, partOfMatrix, numberInThread, MPI_DOUBLE, 0,
MPI_COMM_WORLD);
double res[2];
res[0] = *(std::min_element(partOfMatrix, partOfMatrix + numberInThread));
res[1] = *(std::max_element(partOfMatrix, partOfMatrix + numberInThread));
delete[] partOfMatrix;
double* sub_res = nullptr;
if (rank == 0)
sub_res = new double[size * 2];
MPI_Gather(res, 2, MPI_DOUBLE, sub_res, 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
if (rank == 0)
{
auto minmax = std::minmax_element(sub_res, sub_res + size * 2);
std::cout << "min = " << *minmax.first << "; max = " << *minmax.second << "; time = " << t.elapsed() << "; size = " << size
<< std::endl;
delete[] sub_res;
}
MPI_Finalize();
return 0;
}
3
ТЕСТИРОВАНИЕ
В верхней строке вывода представлено время нахождения минимальных и
максимальных элементов в однопоточном режиме.
В нижней строке – в многопоточном.
На рисунках 1-4 представлены рельтаты выполнения программы для 1, 2, 4 и 6
потоков соответственно.
Рисунок 1 – Результат работы для 1 потока
Рисунок 2 – Результат работы для 2 потоков
Рисунок 3 – Результат работы для 4 потоков
Рисунок 4 – Результат работы для 4 потоков
В результате получим следующий график зависимости времени выполнения от
количества потоков (рисунок 5). На него также были добавлены параметры времени
выполнения для 12 и 36 потоков.
Проще всего данную зависимость можно описать при помощи гиперболической
регресии при аппроксимации функции.
𝑦 = 0.0007 +
4
0.0009
𝑥
Рисунок 5 – Зависимость времени выполнения от количества потоков
5
Download