парал прогр / 2020-2021_311_ParalRasprProgram_Gnosheva_work12_1
.pdfWork12
Архитектура компьютера
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;
}