- •Лабораторные работы по курсу «Параллельное программирование»
- •Кластер Beowulf
- •Структура кластера кафедры 304
- •Организация взаимодействия между процессами при параллельных вычислениях
- •Основные функции mpi
- •Вычисление числа π методом численного интегрирования
- •Вычисление числа π методом Монте-Карло
- •Введение
- •Коммуникации точка-точка в mpi
- •Содержание отчета
- •Лабораторная работа №2
- •Коллективные коммуникации в mpi
- •Алгоритмы параллельного поиска и сортировки
- •Задание
- •Содержание отчета
- •Лабораторная работа №3
- •Введение
- •Умножение матриц ленточным методом
- •Алгоритм Фокса умножения матриц
- •Пример работы Fox's алгоритма
- •Этап 0 (шаг 1 ( слева ), шаг 2 ( по центру ), шаг 3 ( справа ) ):
- •Этап 1 ( слева ) и этап 2 (справа ):
- •Содержание отчета
- •Список литературы
Вычисление числа π методом численного интегрирования
Известно,
что
Заменяя
вычисление интеграла конечным
суммированием, имеем
,
где
,
n-число
участков суммирования при численном
интегрировании. Площадь каждого участка
вычисляется как произведение ширины
‘полоски’ на значение функции в центре
‘полоски’, далее площади суммируются
главным процессом (используется
равномерная сетка).
Очевидно, что распараллеливание этой задачи легко сделать, если каждый процесс будет считать свою частичную сумму, а затем передаст результат вычислений главному процессу. Как избежать здесь повторяющихся вычислений? Процесс должен знать свой ранг, общее число процессов и число интервалов, на которое будет разбит отрезок (чем больше интервалов, тем выше будет точность). Тогда в цикле от 1 до числа интервалов процесс будет вычислять площадь полоски на i-ом интервале, а затем переходить не на следующий i+1интевал, а на интервал i+m, где m-число процессов. Как мы уже знаем, для получения ранга и общего числа процессов существуют функции MPI_Comm_rank и MPI_Comm_size. Перед началом вычислений главный процесс должен передать всем остальным число интервалов, а после вычислений собрать у них полученные частичные суммы и просуммировать их, в MPI это реализуется передачей сообщений. Для передачи сообщений здесь удобно использовать функцию коллективного взаимодействия MPI_Bcast, которая рассылает одинаковые данные от одного процесса всем остальным. Для сбора частичных сумм есть 2 варианта - можно использовать MPI_Gather, которая собирает данные со всех процессов и отдает их одному (получается массив из m элеменов, где m-число процессов) или MPI_Reduce. MPI_Reduce действует аналогично MPI_Gather – собирает данные от всех процессов и отдает одному, но не в виде массива, а предварительно производит определенную операцию между элементами массива, например, суммирование и после этого отдает один элемент. Для этой задачи более удобным выглядит использование MPI_Reduce. Текст программы приведен ниже
#include "mpi.h"
#include <stdio.h>
#include <math.h>
double f(double a)
{
return (4.0 / (1.0 + a*a));
}
int main(int argc, char *argv[])
{
int n, myid, numprocs, i;
double PI25DT = 3.141592653589793238462643;
double mypi, pi, h, sum, x;
double startwtime, endwtime;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
n = 0;
if (myid == 0)
{
n=100;
startwtime = MPI_Wtime();
}
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
h = 1.0 / (double) n;
sum = 0.0;
for (i = myid + 1; i <= n; i += numprocs)
{
x = h * ((double)i - 0.5);
sum += f(x);
}
mypi = h * sum;
MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if (myid == 0)
{
printf("pi is approximately %.16f, Error is %.16f\n",
pi, fabs(pi - PI25DT));
endwtime = MPI_Wtime();
printf("wall clock time = %f\n",
endwtime-startwtime);
}
MPI_Finalize();
return 0;
}
Рассмотрим подробнее вызовы функий MPI_Bcast и MPI_Reduce:
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD) – содержимое переменной n и одного элемента типа MPI_INT из процесса с рангом 0 посылается всем остальным процессам (MPI_COMM_WORLD – все процессы в коммуникаторе ) в ту же переменную n. После этого вызова каждый процесс будет знать общее число интервалов. По окончании вычислений MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD) суммирует (параметр MPI_SUM) значения из переменных mypi типа MPI_DOUBLE каждого процесса и записывает результат в переменную pi процесса с рангом 0. Для замера времени вычислений главный процесс использует функцию MPI_Wtime.
double MPI_Wtime();
MPI_Wtime возвращает число секунд в формате числа с плавающей точкой, представляющее время, прошедшее с момента старта программы.
