16

考虑:

    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 并行指令有什么区别?为什么我们可以用任务编写递归算法,例如归并排序,但不能用工作共享?

4

1 回答 1

29

我建议您查看劳伦斯利弗莫尔国家实验室的 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 友好性的评论。

于 2012-10-25T12:23:51.647 回答