Вопрос или проблема
Я учу API задач OpenMP прямо сейчас, но я запутался в том, как использовать клаузу private
при создании задач, чтобы потоки имели независимые копии переменной, объявленной вне секций #pragma omp
.
Рассмотрим код ниже:
#include<stdio.h>
#include<omp.h>
int main(){
#pragma omp parallel num_threads(4)
{
int tid;
#pragma omp single private(tid)
{
tid = omp_get_thread_num();
printf("[A от потока %d] ", tid);
#pragma omp task private(tid)
{
tid = omp_get_thread_num();
printf("[гонка от потока %d] ", tid);
}
#pragma omp task private(tid)
{
tid = omp_get_thread_num();
printf("[машина от потока %d] ",tid);
}
}
}
return 0;
}
Весь этот код должен создать параллельную секцию с пулом из 4 потоков, и каждому потоку из пула назначаются одна или несколько задач, объявленных под #pragma omp task
.
Серийная версия этой программы должна просто напечатать Гоночная машина
, но поскольку я хочу знать, какой поток из пула печатает какое слово, я обвожу квадратными скобками каждое слово с номером потока.
Мой вопрос в том, что я объявляю переменную int tid
в начале программы. Я хочу быть уверен, что каждый поток, выполняющий задачу, имеет свою собственную приватную копию tid
, чтобы эти копии не подвергались условиям гонки.
Поэтому, чтобы сделать это, я повторил клаузу private(tid)
во множестве мест. Есть ли способ сократить это повторение кода?
Ответ или решение
Вам не обязательно дублировать указание на private(tid)
в каждой задаче, чтобы обеспечить независимые копии переменной tid
для каждого потока в OpenMP. Вместо этого, вы можете объявить tid
как private
в секции #pragma omp parallel
и не указывать private
для каждой конкретной задачи. Таким образом, каждая задача, выполняемая в рамках параллельного блока, будет иметь собственную, независимую копию tid
.
Вот как может выглядеть ваш код с уменьшенным количеством повторений и более чистой реализацией:
#include <stdio.h>
#include <omp.h>
int main() {
#pragma omp parallel num_threads(4) private(tid)
{
int tid = omp_get_thread_num();
#pragma omp single
{
printf("[A from thread %d] ", tid);
#pragma omp task
{
int local_tid = omp_get_thread_num();
printf("[race from thread %d] ", local_tid);
}
#pragma omp task
{
int local_tid = omp_get_thread_num();
printf("[car from thread %d] ", local_tid);
}
}
}
return 0;
}
Объяснение изменений:
-
Объявление переменной
tid
: Теперь переменнаяtid
объявляется в секции#pragma omp parallel
с указаниемprivate(tid)
. Это гарантирует, что каждый поток будет иметь свою собственную копиюtid
. -
Использование локальной переменной в задачах: Вместо использования переменной
tid
непосредственно в блоках задач, я создал локальную переменнуюlocal_tid
. Это позволяет избежать путаницы между переменными и гарантирует, что Вы всегда будете работать с корректной версиейtid
для текущего потока.
Таким образом, Вы уменьшаете количество повторяющихся указаний private(tid)
и сохраняете четкость и читаемость кода. Каждый поток по-прежнему будет иметь свою независимую копию переменной, что предотвращает условия гонки и ошибки, связанные с конкурентным обращением к этой переменной.