Подтвердить что ты не робот

Программирование на основе задач: #pragma omp task против #pragma omp parallel для

Учитывая:

    void saxpy_worksharing(float* x, float* y, float a, int N) {
      #pragma omp parallel for
      for (int i = 0; i < N; i++) {
         y[i] = y[i]+a*x[i];
      }
    }

и

    void saxpy_tasks(float* x, float* y, float a, int N) {
      #pragma omp parallel
      {
         for (int i = 0; i < N; i++) {
         #pragma omp task
         {
           y[i] = y[i]+a*x[i];
         }
      }
   }

В чем разница между задачами и параллельной директивой omp? Почему мы можем писать рекурсивные алгоритмы, такие как сортировка слияния с задачами, но не с общением?

4b9b3361

Ответ 1

Я бы посоветовал вам взглянуть на учебник OpenMP из Национальной лаборатории Лоуренса Ливермора, доступный здесь.

В вашем конкретном примере используется не с использованием задач OpenMP. Второй код создает N раз число задач потоков (потому что в коде отсутствует ошибка }, я вернусь к ней позже), и каждая задача будет выполнять очень простое вычисление. Накладные расходы задач были бы гигантскими, как вы можете видеть в моем ответе на этот вопрос. Кроме того, второй код концептуально неверен. Поскольку нет директивы об обслуживании, все потоки будут выполнять все итерации цикла и вместо N задач, N раз число задач нитей будет создано. Его следует переписать одним из следующих способов:

Отдельная задача производителя - общий шаблон, NUMA недружественный:

void saxpy_tasks(float* x, float* y, float a, int N) {
   #pragma omp parallel
   {
      #pragma omp single
      {
         for (int i = 0; i < N; i++)
            #pragma omp task
            {
               y[i] = y[i]+a*x[i];
            }
      }
   }
}

Директива single заставит цикл работать только внутри одного потока. Все остальные потоки пропустили бы его и попали в неявный барьер в конце конструкции single. Поскольку барьеры содержат неявные точки планирования задачи, потоки ожидания сразу же начнут обрабатывать задачи по мере их появления.

Производитель параллельных задач - больше NUMA:

void saxpy_tasks(float* x, float* y, float a, int N) {
   #pragma omp parallel
   {
      #pragma omp for
      for (int i = 0; i < N; i++)
         #pragma omp task
         {
            y[i] = y[i]+a*x[i];
         }
   }
}

В этом случае цикл создания задачи будет разделяться между потоками.

Если вы не знаете, что такое NUMA, игнорируйте комментарии об удобстве NUMA.