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

парал прогр / 2020-2021_311_ParalRasprProgram_Gnosheva_work12_1

.pdf
Скачиваний:
9
Добавлен:
18.08.2022
Размер:
261.88 Кб
Скачать

Work12

Архитектура компьютера

8 гб ОП, 4 ядра

Задание:

Аналогично работе с OMP было выполнено следующее задание через MPI.

В качестве методов приближенного вычисления двойных интегралов рассмотрены параллельные реализации метода статистических испытаний.

Предположим, необходимо взять интеграл от некоторой функции. Воспользуемся , геометрическим образом интеграла как площади под графиком этой функции.

Выберем n псевдо-случайных точек (xi, yi).

Запуск последовательной версии

Реализация параллельной версии программы с помощью OMP:

Результат работы параллельной версии OMP

Параллельная версия функции с помощью MPI:

Результат работы

Вычислим ускорение:

Последовательная версия

Параллельная версия OMP

Параллельная версия MPI

0.349

0.1233

0.02559

Ускорение параллельной версии OMP : 2.83

Ускорение параллельной версии MPI : 13.638

Ускорение параллельной версии MPI по сравнению с OMP : 4.818

Листинг программы MPI

#include "pch.h"

#include <iostream>

#include <ctime>

#include "mpi.h"

using namespace std;

// Число pi

#define PI 3.1415926535897932384626433832795 int my_rank; /* ранг текущего процесса */

int numprocs; /* общее число процессов */

double f(double x, double y)

{

double a1 = 0.0; // левая граница интегрирования double b1 = 16.0; // правая граница интегрирования

return (exp(sin(PI * x) * cos(PI * y)) + 1.0) / ((b1 - a1) * (b1 - a1));

}

double random(double a, double b) {

srand(time(NULL));

return (double)rand() / (double)RAND_MAX;

}

// Функция для вычисления приближенного значения интеграла

void integral(const double a, const double b, const double h, double* res) {

double sum, sum2;

double x, y;

int n = (int)((b - a) / h);

sum2 = 0.0; sum = 0.0;

for (int i = my_rank; i < n; i += numprocs) {

x = a + random(a, b) * (b - a);

y = a + random(a, b) * (b - a);

sum += f(x, y) * (b - a) * (b - a) / n;

}

MPI_Reduce(&sum, res, 1, MPI_LONG_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); //*res = sum2 * (b - a) * (b - a) / n;

}

// Функция должна задать границы интегрирования и вызвать функцию вычисления интеграла

double experiment(double *res)

{

double stime, ftime; // время начала и конца расчета double a = 0.0; // левая граница интегрирования double b = 16.0; // правая граница интегрирования double h = 0.00001; // шаг интегрирования

if (my_rank == 0) { stime = MPI_Wtime();

}

integral(a, b, h, res); // вызов функции интегрирования if (my_rank == 0) {

return MPI_Wtime() - stime;

}

}

int main()

{

MPI_Init(NULL, NULL); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); int i; // переменная цикла

double time; // время проведенного эксперимента double res; // значение вычисленного интеграла double min_time; // минимальное время работы

// реализации алгоритма

double max_time; // максимальное время работы

// реализации алгоритма

double avg_time; // среднее время работы

// реализации алгоритма

int numbExp = 10; // количество запусков программы

// первый запуск min_time = max_time = -1; avg_time = 0;

// оставшиеся запуски

for (i = 0; i < numbExp - 1; i++)

{

time = experiment(&res); if (my_rank == 0) { avg_time += time;

if (max_time < time) max_time = time;

if (min_time == -1 || min_time > time) min_time = time;

}

}

// вывод результатов эксперимента if (my_rank == 0)

{

cout << "execution time : " << avg_time / numbExp << "; " << min_time << "; " << max_time << endl;

cout.precision(8);

cout << "integral value : " << res << endl;

}

MPI_Finalize(); return 0;

}