Как мне использовать меньше частных переменных для задач OpenMP?

Вопрос или проблема

Я учу 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;
}

Объяснение изменений:

  1. Объявление переменной tid: Теперь переменная tid объявляется в секции #pragma omp parallel с указанием private(tid). Это гарантирует, что каждый поток будет иметь свою собственную копию tid.

  2. Использование локальной переменной в задачах: Вместо использования переменной tid непосредственно в блоках задач, я создал локальную переменную local_tid. Это позволяет избежать путаницы между переменными и гарантирует, что Вы всегда будете работать с корректной версией tid для текущего потока.

Таким образом, Вы уменьшаете количество повторяющихся указаний private(tid) и сохраняете четкость и читаемость кода. Каждый поток по-прежнему будет иметь свою независимую копию переменной, что предотвращает условия гонки и ошибки, связанные с конкурентным обращением к этой переменной.

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

Капча загружается...