- •Базовые понятия OpenMp Введение
- •Модель ветвление-слияние
- •Модель памяти
- •Компиляция
- •2 Директивы OpenMp
- •Опция schedule
- •Директива parallel
- •Директива for
- •Директива single
- •Директива sections
- •Директива master
- •Директива critical
- •Директива barrier
- •Директива atomic
- •Директива ordered
- •Директива task
- •Директива taskwait
- •Директива taskyield
- •2.3 Дополнительные возможности OpenMp Переменные среды и вспомогательные функции
- •Измерение времени
- •2.4 Примеры программ
- •2.5 Задания
Измерение времени
Возвращает затраченное время в секундах:
double omp_get_wtime(void);
Возвращает точность таймера, используемого предыдущей описанной функцией:
double omp_get_wtick(void);
2.4 Примеры программ
Для того, чтобы окончательно уяснить для себя принципы работы с OpenMP, далее приведен простой, но достаточно емкий пример параллельного вычисления числа пи с приминением OpenMP:
#include <stdio.h> #include <math.h> #include <omp.h> int main() { const int N = 10000000; const double L = 1.0; const double h = L / N; const double x_0 = 0.0; double pi; double t_1, t_2; //временные интервалы int i; double sum = 0.0; t_1 = omp_get_wtime(); //начальный замер времени
Инициализируем параллельную область для основного блока вычислений, используя директиву parallel for с опциями reduction и schedule:
#pragma omp parallel for reduction(+: sum) schedule(static) for (i = 0; i < N; ++i) { double x = x_0 + i * h + h/2; sum += sqrt(1 - x*x); }
Делаем конечный замер времени и выводим результаты на экран:
t_2 = omp_get_wtime(); pi = sum * h * 4.0; printf("omp_get_max_threads(): %d\n", omp_get_max_threads()); printf("time: %f\n", t_2 - t_1); printf("pi ~ %f\n", pi); return 0; }
Следующий пример реализует простейшую программу, реализующую перемножение двух квадратных матриц. В программе замеряется время на основной вычислительный блок, не включающий начальную инициализацию.
Задаем три матрицы размерностью 4096×4096 элементов каждая, первые две инициализируются, в третью записывается результат полученных вычислений.
#include <stdio.h> #include <omp.h> #define N 4096 double a[N][N], b[N][N], c[N][N]; int main() { int i, j, k; double t1, t2; //временные интервалы
Инициализируем матрицу, замеряем время начала работы основного вычислительного блока:
for (i = 0; i < N; i++) for (j = 0; j < N; j++) a[i][j] = b[i][j] = i * j; t1=omp_get_wtime();
Основной вычислительный блок, массивы a, b и c задаются общими, а переменные i, j и k частными. После окончания вычислений проводится очередной замер времени после которого выводится общее время выполнения программы:
#pragma omp parallel for shared(a, b, c) private(i, j, k) for(i = 0; i < N; i++){ for(j = 0; j < N; j++){ c[i][j] = 0.0; for(k = 0; k < N; k++) c[i][j] += a[i][k] * b[k][j]; } } t2=omp_get_wtime(); printf("Time=%lf\n", t2-t1); }
2.5 Задания
Задание 1.
Напишите параллельную программу, реализующую скалярное произведение двух векторов.
Задание 2.
Напишите параллельную программу, реализующую поиск максимального значения вектора.
Задание 3.
Напишите параллельную программу, реализующую транспонирование матрицы n×n.
Задание 4.
Реализуйте параллельный алгоритм метода Гаусса решения систем линейных алгебраических уравнений.
Задание 5.
На основе программы для решения СЛАУ методом Гаусса напишите параллельную программу для вычисления определителя и постройте зависимость коэффициента ускорения от числа ядер (потоков) на узле.
Задание 6.
На основе программы для решения СЛАУ методом Гаусса напишите параллельную программу для вычисления обратной матрицы и постройте зависимость коэффициента ускорения от числа ядер (потоков) на узле.
Задание 7.
Напишите параллельную программу реализовывающую метод Гаусса (метод элементарных преобразований) для вычисления ранга произвольной матрицы A – m×n .
Задание 8.
Найти численное решение задачи Дирихле для уравнения Пуассона итерационным методом Зейделя.
