当一个pragma内部有一个pragma时,OpenMP会发生什么?

时间:2011-12-22 20:19:47

标签: c++ c openmp

#pragma omp parallel开始时创建了一堆线程,然后当我们到达#pragma omp for时,工作负载就会被分发。如果for循环中有for循环,我会在它前面放置一个#pragma omp for会发生什么?每个线程都会创建新线程吗?如果没有,哪个线程被分配了这个任务?在这种情况下到底发生了什么?

2 个答案:

答案 0 :(得分:3)

默认情况下,不会为内部循环生成任何线程。它是使用到达它的线程顺序完成的。

这是因为默认情况下禁用嵌套。但是,如果通过omp_set_nested()启用嵌套,则会生成一组新线程。

但是,如果您不小心,这将导致p^2个线程数(因为每个原始p线程将产生另一个p个线程。)因此默认情况下禁用嵌套。

答案 1 :(得分:1)

在以下情况中:

#pragma omp parallel
{
#pragma omp for
  for(int ii = 0; ii < n; ii++) {
    /* ... */
#pragma omp for 
    for(int jj = 0; jj < m; jj++) {
      /* ... */
    }
  }
}

当您违反OpenMP标准时,会触发未定义的行为。更准确地说,您违反了第2.5节(工作共享结构)中出现的限制:

  

以下限制适用于工作共享结构:

     
      
  • 团队中的所有线程都必须遇到每个工作共享区域,或者根本不会遇到任何工作共享区域。
  •   
  • 对于团队中的每个线程,遇到的工作共享区域和障碍区域的顺序必须相同。
  •   

示例A.39.1c and A.40.1c中清楚地显示了这一点:

示例A.39.1c :以下循环构造嵌套的示例符合,因为内部和外部循环区域绑定到不同的并行 区域:

void work(int i, int j) {}
void good_nesting(int n)
{
  int i, j;
#pragma omp parallel default(shared)
  {
#pragma omp for
    for (i=0; i<n; i++) {
#pragma omp parallel shared(i, n)
    {
#pragma omp for
      for (j=0; j < n; j++)
        work(i, j);
    }
    }
  }
}

示例A.40.1c :以下示例不符合,因为内部和外部循环区域紧密嵌套

void work(int i, int j) {}
void wrong1(int n)
{
#pragma omp parallel default(shared)
  {
    int i, j;
#pragma omp for
    for (i=0; i<n; i++) {
    /* incorrect nesting of loop regions */
#pragma omp for
      for (j=0; j<n; j++)
        work(i, j);
    }
  }    
}

请注意,这与:

不同
#pragma omp parallel for
  for(int ii = 0; ii < n; ii++) {
    /* ... */
#pragma omp parallel for 
    for(int jj = 0; jj < m; jj++) {
      /* ... */
    }
  }

您尝试生成嵌套的并行区域。只有在这种情况下才会讨论Mysticial的答案。