Многопоточное программирование в OpenMP


Чтобы посмотреть презентацию с картинками, оформлением и слайдами, скачайте ее файл и откройте в PowerPoint на своем компьютере.
Текстовое содержимое слайдов презентации:

Многопоточное программирование в 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){ . . .} #pragma omp single { // code } #pragma omp sections { #pragma omp section // code 1 #pragma omp section // code 2 } #pragma omp for for (i=0;i#include int main(){ int i; #pragma omp parallel { #pragma omp for for (i=0;i<1000;i++) printf(“%d ”,i); } return 0;} Пример:Директива omp for #include #include int main(){ int i; #pragma omp parallel for for (i=0;i<1000;i++) printf(“%d ”,i); return 0;} Пример:Директива 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<500;i++) printf(“%d ”); #pragma omp section printf(“2nd half\n”); for (i=501;i<1000;i++) printf(“%d ”); } return 0;} Пример:Директива omp single #include #include int main(){ int i; #pragma omp parallel private(i) { #pragma omp for for (i=0;i<1000;i++) printf(“%d ”); #pragma omp single printf(“I’m thread %d!\n”,get_thread_num()); #pragma omp for for (i=0;i<1000;i++) printf(“%d ”); } return 0;} Пример:Директива omp master #include #include int main(){ int i; #pragma omp parallel private(i) { #pragma omp for for (i=0;i<1000;i++) printf(“%d ”); #pragma omp master printf(“I’m Master!\n”) #pragma omp for for (i=0;i<1000;i++) printf(“%d ”); } return 0;} Способы разделения работы между потоками Параллельное исполнение цикла for#pragma omp for параметры:schedule - распределения итераций цикла между потокамиschedule(static,n) – статическое распределениеschedule(dynamic,n) – динамическое распределениеschedule(guided,n) – управляемое распределениеschedule(runtime) – определяется OMP_SCHEDULEnowait – отключение синхронизации в конце цикла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<1000;i++) printf(“%d ”,i); #pragma omp for schedule(dynamic,1) for (i=‘a’;i<=‘z’;i++) printf(“%c ”,i); } return 0;} Области видимости переменных Переменные, объявленные внутри параллельного блока, являются локальными для потока:#pragma omp parallel{ int num; num = omp_get_thread_num() printf(“Поток %d\n”,num);} Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Своя локальная переменная в каждом потокеint num;#pragma omp parallel private(num){ num=omp_get_thread_num() printf(“%d\n”,num);} Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Локальная переменная с инициализациейint num=5;#pragma omp parallel \ firstprivate(num){ printf(“%d\n”,num);} Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Локальная переменная с сохранением последнего значения(в последовательном исполнении)int i,j;#pragma omp parallel for \ lastprivate(j) for (i=0;i<100;i++) j=i;printf(“Последний j = %d\n”,j); Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Разделяемая (общая) переменнаяint i,j;#pragma omp parallel for \ shared(j)for (i=0;i<100;i++) j=i;printf(“j = %d\n”,j); Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Задание области видимости не указанных явно переменных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:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Переменная для выполнения редукционной операцииint i,s=0;#pragma omp parallel for \ reduction(+:s) for (i=0;i<100;i++) s += i;printf(“Sum: %d\n”,s); Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Объявление глобальных переменных локальными для потоковint x;#pragma omp threadprivate(x)int main(){ . . .} Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Объявление глобальных переменных локальными для потоков c инициализациейint x;#pragma omp threadprivate(x)#pragma omp copyin(x)int main(){ . . .} Области видимости переменных Переменные, объявленные вне параллельного блока, определяются параметрами директив OpenMP:privatefirstprivatelastprivateshareddefaultreductionthreadprivatecopying Синхронизация потоков Директивы синхронизации потоков:mastercriticalbarrieratomicflushorderedБлокировкиomp_lock_t Выполнение кода только главным потоком#pragma omp parallel{ //code #pragma omp master { // critical code } // code} Синхронизация потоков Директивы синхронизации потоков:mastercriticalbarrieratomicflushordered Критическая секцияint x;x = 0;#pragma omp parallel{ #pragma omp critical x = x + 1;} Синхронизация потоков Директивы синхронизации потоков:mastercriticalbarrieratomicflushordered Барьерint i;#pragma omp parallel for for (i=0;i<1000;i++) { printf(“%d ”,i); #pragma omp barrier } Синхронизация потоков Директивы синхронизации потоков:mastercriticalbarrieratomicflushordered Атомарная операцияint i,index[N],x[M];#pragma omp parallel for \ shared(index,x) for (i=0;i #include #include int x[1000]; int main() { int i,max; omp_lock_t lock; omp_init_lock(&lock); for (i=0;i<1000;i++) x[i]=rand(); max = x[0]; #pragma omp parallel for shared(x,lock) for(i=0;i<1000;i++) { omp_set_lock(&lock); if (x[i]>max) 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 1000double x[N],y[N],z[N];int main(){ int i; for (i=0;i#define N 1000double x[N],y[N],z[N];int main(){ int i; int num; for (i=0;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/

Приложенные файлы


Добавить комментарий