Директива threadprivate
Синтаксис директивы: #pragma omp threadprivate(список) Каждая копия переменной с атрибутом доступа threadprivate инициируется в программе один раз до первого обращения к копии этой переменной в каждой нити(т.е., как при последовательном исполнении программы). Если переменная определена как threadprivate, а значение переменной изменяется до первого обращения к копии переменной, то поведение переменной не определено. Аналогично приватными переменными, нити не имеют связи с копиями переменной threadprivate других нитей. На протяжении последовательных областей программы и областей программы, выполняемых основной нитью, значение переменной будет равно значению переменной в основной нити. После выполнения первой параллельной области, значения переменных типа threadprivate гарантировано сохраняются только в том случае, если нет механизма динамического изменения числа нитей, т.е. число нитей остается неизменным для всех параллельных областей. Ограничения, накладываемые на использование директивы threadprivate: 1. Директива threadprivate должна встречаться вне любого определения или объявления и предшествовать всем обращениям (ссылкам) к любым переменным в списке. 2. Если переменная определена в директиве threadprivate в одном модуле трансляции, то она должна быть определена в директиве threadprivate в каждом модуле трансляции. 3. Переменные threadprivate не разрешены в операторах private, firstprivate, lastprivate, shared или reduction. На эти переменные не оказывает влияние оператор default. 4. Переменная threadprivate не может быть ссылкой.
Пример. Программа начинает последовательное выполнение, до начала параллельной области (#pragma omp parallel for). При входе в параллельную область порождается 4 нити, нити нумеруется автоматически, основная нить имеет номер 0. Каждая нить получает свою копию private переменной i. #include<stdio.h> #include<omp.h> Void main() { int i, n; int num_threads=4; // количество нитей int a[10], b[10], c[10]; // целочисленные массивы for(i=0; i<10; i++) // инициализация элементов массивов { a[i]=i+1; b[i]=i+1; printf("a[%d]=%d b[%d]=%d\n",i,a[i],i,b[i]); } printf("\n RESULT \n"); Omp_set_num_threads(num_threads); // функция OpenMP, устанавливает // количество нитей параллельной области // вход в параллельную область, порождение установленного числа нитей, #pragma omp parallel for private(i) for(i=0; i<10; i++) { n=omp_get_thread_num(); // функция OpenMP, возвращает номер нити c[i]=a[i]+b[i]; printf("n=%d c[%d]=%d\n",n,i,c[i]); } }
Лекция 9 Технология программирования OpenMP. Конструкции разделения работ Конструкция разделения работ распределяет выполнение операторов среди группы нитей. Директивы разделения работ не порождают новые нити и не выполняют синхронизацию при входе в конструкцию разделения работ. OpenMP определяет три конструкции разделения работ: Оператор for Оператор sections Оператор single
Оператор for Операторfor определяет итерационную конструкцию для некоторой области данных, в которой итерации соответствующего цикла будут выполняться параллельно. Итерации цикла for распределяются среди уже существующих нитей. Синтаксис конструкции for: #pragma omp for [оператор [ оператор] ... ] Цикл for цикл for должен иметь классическую форму языка Си: for (выражение; логическая_операция; приращение) { Тело цикла } Операторможет иметь один из следующих типов: private(список) firstprivate(список) lastprivate(список) reduction(оператор: список) Ordered schedule(вид [, длина_порции]) Nowait Операторыprivate, firstprivate, lastprivate и reductionрассматривались ранее. Оператор orderedопределяет блок, в котором итерации цикла выполняются в последовательном режиме. Не допускается использование в конструкции forоператораordered более одного раза. Оператор schedule определяет, как итерации цикла делятся между нитями группы. Правильность программы не должна зависеть от того, какая нить выполняет конкретную итерацию. Вид планирования может быть одним из следующих:
Примеры использования циклов: int a[10]; #pragma omp parallel private(i) { #pragma omp for schedule(static, 3) for(i=0; i<10; i++) a[i] = i+1; }
int a[10]; #pragma omp parallel private(i) { #pragma omp for schedule(dynamic, 3) for(i=0; i<10; i++) a[i] = i+1; }
int a[10]; #pragma omp parallel private(i) { #pragma omp for schedule(guided, 3) for(i=0; i<10; i++) a[i] = i+1; }
©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.
|