Shared или private, три простых правила

В Openmp параллелизация подкупает своей простотой. Добавил прагму к циклу и хоп — я знаю кунг-фу. Тем не менее такое отношение частенько приводит к разнообразным ошибкам обращения к одной и той же переменной.
В OpenMP есть два основных класса переменных — shared и private. Shared переменная общая между потоками, хранится в обычной памяти процесса (стек или хип) и ничего не стоит. Private переменная для каждого OpenMP потока своя и хранится в TLS — специальном месте, уникальном для каждого потока (thread), есть дополнительные расходы на копирование.
Как их отличать между собой.
1. По умолчанию все переменные внутри parallel секции считаются shared за исключением п.2.
2. Все локальные переменные (объявленные внутри parallel секции) и итераторы будут private.
3. Все нелокальные переменные (объявленные ранее parallel) в которые что-то пишется (lvalue) должны быть явно указаны как private.

Собственно все. Теперь примеры.
Пример 1.

double* a;
double* b;
double z = 1.0;
...
#pragma omp parallel for
for(int i=0; i<len; i++){
a[i] = b[i]*z;
}

Тут все хорошо — внутри цикла копирование. Доступ массива у каждого потока свой — итератор разный, он private. Константа общая, но в нее не пишут.
Теперь типичный «проблемный» пример, когда вводятся временные переменные.
Пример 2.

double* a;
double* b;
double z = 1.0;
double tmp;
...
#pragma omp parallel for private(tmp)
for(int i=0; i<len; i++){
tmp = b[i]*z;
a[i] = tmp;
}

dmitry

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