- •Оглавление
- •Директивы
- •Примеры
- •Примеры
- •Примеры
- •Примеры
- •Примеры
- •Пример
- •Примеры
- •Примеры
- •Примеры
- •Синхронизация
- •Синхронизация
- •Пример
- •Пример
- •Пример
- •Пример
- •Пример
- •Пример
- •Пирмер
- •Пример условной компиляции
- •Вопросы
- •Пример условной компиляции
- •Терминология
- •Терминология
- •Терминология
- •Терминология
- •Терминология
- •Терминология
- •Терминология
- •Терминология
- •Конец
Синхронизация
Один из типов — неявная барьерная синхронизация, которая выполняется в конце каждого параллельного региона для всех сопоставленных с ним потоков. Механизм барьерной синхронизации таков, что, пока все потоки не достигнут конца параллельного региона, ни один поток не сможет перейти его границу.
Синхронизация
Неявная барьерная синхронизация выполняется также в конце каждого блока #pragma omp for, #pragma omp single и #pragma omp sections. Чтобы отключить неявную барьерную синхронизацию в каком-либо из этих трех блоков разделения работы, нужно указать раздел nowait:
Пример
#pragmaompparallel
{
#pragmaompfornowait for(inti=1;i<size;++i) x[i]=(y[i-1]+y[i+1])/2;
}
этот раздел директивы распараллеливания говорит о том, что синхронизировать потоки в конце цикла for не надо, хотя в конце параллельного региона они все же будут синхронизированы.
162
Конструкциисинхронизации:
директиваatomic
Частым случаем использования критических секций на практике является обновление общих переменных. Например, если переменнаяsum являетсяобщей и оператор вида sum = sum + expr находится в параллельной области программы, то при одновременном выполнении данного оператора несколькими нитями можно получить некорректный результат.
Конструкциисинхронизации:
директиваatomic
Чтобы избежать такой ситуации можно воспользоваться механизмом критических секций или специально предусмотренной для таких случаев директивой atomic.
#pragmaompatomic[read|write|update |capture]
оператор
или
#pragmaompatomiccapture
структурированный блок
Конструкциисинхронизации:
директиваatomic
Данная директиваотносится кидущему непосредственнозанейоператору присваивания(наиспользуемыевкотором конструкции накладываютсядостаточно понятныеограничения),гарантируя корректную работу собщейпеременной, стоящейвеголевойчасти.
Конструкциисинхронизации:
директиваatomic
Навремявыполненияоператора блокируетсядоступ кданнойпеременной всемзапущеннымвданныймоментнитям, кроменити,выполняющейоперацию. Атомарной являетсятолько работас переменнойвлевойчастиоператора присваивания,приэтомвычисленияв правойчастинеобязаныбытьатомарными.
Конструкциисинхронизации:
директиваatomic
Пример.
Производитсяподсчетобщегоколичества порожденныхнитей.Для этого каждая нить увеличиваетнаединицузначение переменнойcount.Для того, чтобы предотвратитьодновременноеизменение несколькиминитямизначенияпеременной, стоящейвлевойчастиоператора присваивания,используетсядиректива atomic
Конструкциисинхронизации:
директиваatomic
#include <stdio.h> #include <omp.h>
int main(int argc, char *argv[])
{
int count = 0; #pragma omp parallel
{
#pragma omp atomic count++;
}
printf("Число нитей: %d\n", count);
}
Директиваordered
Директивыorderedопределяютблок внутрителацикла,который должен выполнятьсявтом порядке,вкотором итерацииидутвпоследовательномцикле.
#pragmaompordered
структурированный блок
Директиваordered
Блокоператоров относится ксамому внутреннемуизобъемлющихциклов,ав параллельном цикледолжнабытьзадана опцияordered.Нить,выполняющаяпервую итерациюцикла,выполняетоперации данногоблока.
Конструкциисинхронизации:
директиваordered
Нить,выполняющаялюбуюследующую итерацию,должнасначаладождаться выполнениявсехоперацийблокавсеми нитями,выполняющимипредыдущие итерации.Можетиспользоваться, например,дляупорядочениявыводаот параллельныхнитей.
Конструкциисинхронизации:
директиваordered
Следующийпримериллюстрирует применениедирективыorderedиопции ordered.Циклforпомеченкакordered.
Внутрителациклаидутдвевыдачи– одна внеблокаordered,авторая– внутринего.В результатеперваявыдачаполучается неупорядоченной,авторая идётвстрогом порядкеповозрастанию номераитерации.
Конструкциисинхронизации:
директиваordered
int i, n;
#pragma omp parallel private (i, n)
{
n = omp_get_thread_num(); #pragma omp for ordered
for (i = 0; i < 5; i++)
{
printf("Нить%d,итерация%d\n", n,i);
#pragma omp ordered
{
printf("ordered: Нить %d, итерация %d\n", n, i);
}
}
}
Директиваtask
Директиваtaskприменяетсядля выделенияотдельнойнезависимойзадачи.
#pragmaomptaskопция[[[,] опция]...]
структурированный блок
Директиваtask
Текущаянитьвыделяетвкачествезадачи ассоциированныйсдирективойблок операторов. Задачаможетвыполняться немедленнопослесозданияилибыть отложенной нанеопределённоевремяи выполнятьсяпочастям.Размертаких частей,атакжепорядоквыполнениячастей разныхотложенныхзадачопределяется реализацией.
Директиваtask
Возможныеопции:
if(условие)– порождениеновой задачи только привыполнениинекоторого условия;еслиусловиеневыполняется,то задачабудетвыполненатекущейнитьюи немедленно;
Директиваtask
Возможныеопции:
untied– опцияозначает, чтовслучае откладывания задачаможетбыть продолженалюбойнитьюизчисла выполняющихданнуюпараллельную область; еслиданнаяопциянеуказана,то задачаможетбытьпродолженатолько породившейеёнитью;
Директиваtask
Возможныеопции:
default(shared|none)– всемпеременнымв задаче,которым явноненазначенкласс, будетназначенклассshared;none означает,чтовсемпеременнымвзадаче классдолженбытьназначенявно;
Конструкциисинхронизации:
директиваtask
Возможныеопции:
private(список) – задаётсписок переменных,для которых порождается локальная копия вкаждой нити; начальноезначениелокальных копий переменныхизсписканеопределено;
Директиваtask
Возможныеопции:
firstprivate(список)– задаётсписок переменных,для которых порождается локальная копия вкаждой нити; локальные копиипеременных инициализируютсязначениямиэтих переменныхвнити-мастере;
shared(список)– задаётсписок переменных,общихдлявсехнитей.
Базовыеконструкции
Вспомогательныефункции
ВOpenMP существуетряд вспомогательныхфункций
Дляихиспользованиянеобходимо подключитьзаголовочный файл:
#include <omp.h>
181
Функцииисполняющейсреды
Эти функциипозволяютзапрашиватьи задаватьразличныепараметрысреды
OpenMP:
omp_get_num_procsвозвращаетчисло вычислительныхузлов(процессоров/ядер) вкомпьютере.
omp_in_parallelпозволяетпотоку узнать, занимаетсялионвданныймомент выполнениемпараллельного региона.
182
Функцииисполняющейсреды
omp_get_num_threadsвозвращаетчисло потоков, входящихвтекущуюгруппу потоков.
omp_get_max_threadsвозвращает максимальнодопустимоечислонитейдля использованиявследующейпараллельной области.
183
Функцииисполняющейсреды
omp_set_num_threadзадаетчисло потоков длявыполненияследующего параллельного региона,который встретитсятекущемувыполняемому потоку.Функцияможетпомочь распределитьресурсы.
Например,еслиодновременно обрабатываетсязвукивидеонапроцессоре счетырьмяядрами,томожно создатьдля звукаодинпоток, адляобработки видеотри. 184
Функцииисполняющейсреды
omp_set_nestedразрешаетилизапрещает вложенныйпараллелизм.Есливложенный параллелизмразрешён,токаждая нить,в которой встретитсяописание параллельной области,породитдля её выполненияновуюгруппунитейистанетв нейглавной.
omp_get_nestedвозвращает,разрешенли вложенныйпараллелизмилинет.
185
Функцииисполняющейсреды
Еслиимяфункцииначинаетсясomp_set_,то ееможновызыватьтолько вне параллельныхрегионов.
Всеостальные функцииможноиспользовать как внутрипараллельныхрегионов,таки внетаковых.
186
Базовыеконструкции
Функциисинхронизации/блокировки
OpenMP позволяетстроить параллельныйкодбезиспользования этихфункций,таккакимеются директивы,позволяющие осуществлятьопределенныевиды синхронизации
Однаковрядеслучаевэти функции удобныидаженеобходимы
187
Базовыеконструкции
Функциисинхронизации/блокировки
ВOpenMP дватипаблокировок:простые ивложенные.
Вложенныеимеютсуффикс «nest»
Функция
omp_init_lock/omp_init_nest_l
ock omp_destroy_lock/omp_destr
oy_nest_lock omp_set_lock/omp_set_nest_
lock omp_unset_lock/omp_unset_
nest_lock omp_test_lock/omp_test_nest
_lock
Аналог
InitializeCriticalSection
DeleteCriticalSection
EnterCriticalSection
LeaveCriticalSection
TryEnterCriticalSection
188
Функциисинхронизации/блокировки
omp_init_lock — инициализация переменнойтипаomp_lock_t.Аналог
InitializeCriticalSection.
omp_destroy_lock — освобождение переменнойтипаomp_lock_t.Аналог
DeleteCriticalSection.
189
Функциисинхронизации/блокировки
omp_set_lock — одинпоток выставляет блокировку,аостальныепотоки ждут, покапоток, вызвавшаяэтуфункцию,не сниметблокировкуспомощьюфункции omp_unset_lock().Аналог EnterCriticalSection.
omp_unset_lock — снятиеблокировки.
Аналог LeaveCriticalSection.
190
Функциисинхронизации/блокировки
omp_test_lock — неблокирующая попытказахватазамка.Данная функция пробуетзахватить указанныйзамок.Если этоудалось,тодляпростого замка функциявозвращает1.Еслизамок захватить неудалось,то возвращается0.
АналогTryEnterCriticalSection.
191