基于任务的编程:#pragma omp task与#pragma omp parallel for

use*_*956 11 task openmp

考虑:

    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];
      }
    }
Run Code Online (Sandbox Code Playgroud)

    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];
         }
      }
   }
Run Code Online (Sandbox Code Playgroud)

使用任务和omp并行指令有什么区别?为什么我们可以编写递归算法,例如与任务合并排序,而不是与工作共享?

Hri*_*iev 23

我建议您查看劳伦斯利弗莫尔国家实验室的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];
            }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

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];
         }
   }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,任务创建循环将在线程之间共享.

如果您不知道NUMA是什么,请忽略有关NUMA友好性的评论.