Содержание
-
Многопоточное программирование в OpenMP
Киреев Сергей ИВМиМГ
-
Процессы и потоки
Процесс – это среда выполнения задачи (программы). Процесс создаётся ОС и содержит информацию о программных ресурсах и текущем состоянии выполнения программы.
-
Поток – это «облегченный процесс». Создается в рамках процесса, Имеет свой поток управления, Разделяет ресурсы процесса-родителя с другими потоками, Погибает, если погибает родительский процесс.
-
Многопоточное программирование
Используется для создания параллельных программ для систем с общей памятью И для других целей… Процессор Ядро Ядро Процессор Ядро Ядро Процессор Ядро Ядро Процессор Ядро Ядро Оперативная память
-
OpenMP – это…
Стандарт интерфейса для многопоточного программирования над общей памятью Набор средств для языков C/C++ и Fortran: Директивы компилятора #pragma omp … Библиотечные подпрограммы get_num_threads() Переменные окружения OMP_NUM_THREADS
-
Модель программирования
Fork-join параллелизм Явное указание параллельных секций Поддержка вложенного параллелизма Поддержка динамических потоков
-
Пример:Объявление параллельной секции
#include int main() { // последовательный код #pragma omp parallel { // параллельный код } // последовательный код return 0; }
-
Пример: Hello, World!
#include #include int main() { printf(“Hello, World!\n”); #pragma omp parallel { int i,n; i = omp_get_thread_num(); n = omp_get_num_threads(); printf(“I’m thread %d of %d\n”,i,n); } return 0; }
-
Задание числа потоков
Переменная окружения OMP_NUM_THREADS >env OMP_NUM_THREADS=4 ./a.out Функция omp_set_num_threads(int) omp_set_num_threads(4); #pragma omp parallel { . . . } Параметр num_threads #pragma omp parallel num_threads(4) { . . . }
-
Способы разделения работы между потоками
-
Пример: Директива omp for
#include #include int main() { int i; #pragma omp parallel { #pragma omp for for (i=0;i
-
#include #include int main() { int i; #pragma omp parallel for for (i=0;i
-
Пример: Директива omp sections
#include #include int main() { int i; #pragma omp parallel sections private(i) { #pragma omp section printf(“1st half\n”); for (i=0;i
-
Пример: Директива omp single
#include #include int main() { int i; #pragma omp parallel private(i) { #pragma omp for for (i=0;i
-
Пример: Директива omp master
#include #include int main() { int i; #pragma omp parallel private(i) { #pragma omp for for (i=0;i
-
Способы разделения работы между потоками
Параллельное исполнение цикла for #pragma omp for параметры: schedule - распределения итераций цикла между потоками schedule(static,n) – статическое распределение schedule(dynamic,n) – динамическое распределение schedule(guided,n) – управляемое распределение schedule(runtime) – определяется OMP_SCHEDULE nowait – отключение синхронизации в концецикла ordered – выполнение итераций в последовательном порядке Параметры области видимости переменных…
-
Пример: Директива omp for
#include #include int main() { int i; #pragma omp parallel private(i) { #pragma omp for schedule(static,10) nowait for (i=0;i
-
Области видимости переменных
Переменные, объявленные внутри параллельного блока, являются локальными для потока: #pragma omp parallel { int num; num = omp_get_thread_num() printf(“Поток %d\n”,num); }
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Своя локальная переменная в каждом потоке int num; #pragma omp parallel private(num) { num=omp_get_thread_num() printf(“%d\n”,num); }
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Локальная переменная с инициализацией int num=5; #pragma omp parallel \ firstprivate(num) { printf(“%d\n”,num); }
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Локальная переменная с сохранением последнего значения (в последовательном исполнении) int i,j; #pragma omp parallel for \ lastprivate(j) for (i=0;i
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Разделяемая (общая) переменная int i,j; #pragma omp parallel for \ shared(j) for (i=0;i
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Задание области видимости не указанных явно переменных int i,k,n=2; #pragma omp parallel shared(n) \ default(private) { i = omp_get_thread_num() / n; k = omp_get_thread_num() % n; printf(“%d %d %d\n”,i,k,n); }
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Переменная для выполнения редукционной операции int i,s=0; #pragma omp parallel for \ reduction(+:s) for (i=0;i
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Объявление глобальных переменных локальными для потоков int x; #pragma omp threadprivate(x) int main() { . . . }
-
Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP: private firstprivate lastprivate shared default reduction threadprivate copying Объявление глобальных переменных локальными для потоков c инициализацией int x; #pragma omp threadprivate(x) #pragma omp copyin(x) int main() { . . . }
-
Синхронизация потоков
Директивы синхронизации потоков: master critical barrier atomic flush ordered Блокировки omp_lock_t
-
Директивы синхронизации потоков: master critical barrier atomic flush ordered Выполнение кода только главным потоком #pragma omp parallel { //code #pragma omp master { // critical code } // code }
-
Директивы синхронизации потоков: master critical barrier atomic flush ordered Критическая секция int x; x = 0; #pragma omp parallel { #pragma omp critical x = x + 1; }
-
Директивы синхронизации потоков: master critical barrier atomic flush ordered Барьер int i; #pragma omp parallelfor for (i=0;i
-
Директивы синхронизации потоков: master critical barrier atomic flush ordered Атомарная операция int i,index[N],x[M]; #pragma omp parallelfor \ shared(index,x) for (i=0;i
-
Директивы синхронизации потоков: master critical barrier atomic flush ordered Согласование значения переменных между потоками int x = 0; #pragma omp parallelsections \ shared(x) { #pragma omp section { x=1; #pragma omp flush } #pragma omp section while (!x); }
-
Директивы синхронизации потоков: master critical barrier atomic flush ordered Выделение упорядоченного блока в цикле int i,j,k; double x; #pragma omp parallelfor ordered for (i=0;i
-
Блокировки omp_lock_t void omp_init_lock(omp_lock_t *lock) void omp_destroy_lock(omp_lock_t *lock) void omp_set_lock(omp_lock_t *lock) void omp_unset_lock(omp_lock_t *lock) int omp_test_lock(omp_lock_t *lock) omp_nest_lock_t void omp_init_nest_lock(omp_nest_lock_t *lock) void omp_destroy_nest__lock(omp_nest_lock_t *lock) void omp_set_nest__lock(omp_nest_lock_t *lock) void omp_unset_nest__lock(omp_nest_lock_t *lock) int omp_test_nest__lock(omp_nest_lock_t *lock)
-
Пример:Использование блокировок
#include #include #include int x[1000]; int main() { int i,max; omp_lock_t lock; omp_init_lock(&lock); for (i=0;imax) max=x[i]; omp_set_unlock(&lock); } omp_destroy_lock(&lock); return 0; }
-
Функции OpenMP
void omp_set_num_threads(int num_threads) int omp_get_num_threads(void) int omp_get_max_threads(void) int omp_get_thread_num(void) int omp_get_num_procs(void) int omp_in_parallel(void) void omp_set_dynamic(int dynamic_threads) int omp_get_dynamic(void) void omp_set_nested(int nested) int omp_get_nested (void) double omp_get_wtick(void) Функции работы с блокировками
-
Порядок создания параллельных программ
Написать и отладить последовательную программу Дополнить программу директивами OpenMP Скомпилировать программу компилятором с поддержкой OpenMP Задать переменные окружения Запустить программу
-
Примерпрограммы:сложение двух векторов
Последовательная программа #define N 1000 double x[N],y[N],z[N]; int main() { int i; for (i=0;i
-
Пример программы:сложение двух векторов
Параллельная программа #include #define N 1000 double x[N],y[N],z[N]; int main() { int i; int num; for (i=0;i
-
Пример программы:решение краевой задачи
Метод Зейделя do { dmax = 0; // максимальное изменение значений u for ( i=1; i eps );
-
omp_lock_t dmax_lock; omp_init_lock (&dmax_lock); do { dmax = 0; // максимальное изменение значений u #pragma omp parallel for shared(u,n,dmax) private(i,temp,d) for ( i=1; i eps );
-
omp_lock_t dmax_lock; omp_init_lock (&dmax_lock); do { dmax = 0; // максимальное изменение значений u #pragma omp parallel for shared(u,n,dmax) private(i,temp,d) for ( i=1; i eps ); Синхронизация – узкое место
-
omp_lock_t dmax_lock; omp_init_lock(&dmax_lock); do { dmax = 0; // максимальное изменение значений u #pragma omp parallel for shared(u,n,dmax) private(i,temp,d,dm) for ( i=1; i eps );
-
omp_lock_t dmax_lock; omp_init_lock(&dmax_lock); do { dmax = 0; // максимальное изменение значений u #pragma omp parallel for shared(u,n,dmax) private(i,temp,d,dm) for ( i=1; i eps ); Неоднозначность вычислений
-
omp_lock_t dmax_lock; omp_init_lock(&dmax_lock); do { dmax = 0; // максимальное изменение значений u #pragma omp parallel for shared(u,n,dmax) private(i,temp,d,dm) for ( i=1; i eps );
-
omp_lock_t dmax_lock; omp_init_lock(&dmax_lock); do { dmax = 0; // максимальное изменение значений u #pragma omp parallel for shared(u,n,dmax) private(i,temp,d,dm) for ( i=1; i eps ); Получили метод Якоби
-
Другие способы устранения зависимостей Четно-нечетное упорядочивание Волновые схемы
-
omp_lock_t dmax_lock; omp_init_lock(&dmax_lock); do { // максимальное изменение значенийu dmax = 0; // нарастание волны (nx – размер волны) for ( nx=1; nx0; nx-- ) { #pragma omp parallel for \ shared(u,nx,dm) private(i,j,temp,d) for ( i=N-nx+1; i eps ); Метод Зейделя: волновая схема
-
Волновая схема с разбиением на блоки
-
Рекомендуемая литературапо OpenMP
http://openmp.org http://www.parallel.ru/tech/tech_dev/openmp.html https://computing.llnl.gov/tutorials/openMP/
Нет комментариев для данной презентации
Помогите другим пользователям — будьте первым, кто поделится своим мнением об этой презентации.