编译器错误 C3020

“var”:OpenMP“for”循环的索引变量不能在循环体中修改

OpenMP for 循环可能不会修改 for 循环主体中的索引(循环计数器)。

以下示例生成 C3020:

// C3020.cpp
// compile with: /openmp
int main() {
   int i = 0, n = 3;

   #pragma omp parallel
   {
      #pragma omp for
      for (i = 0; i < 10; i += n)
         i *= 2;   // C3020
         // try the following line instead
         // n++;
   }
}

使用 lastprivate 声明的变量不能用作并行循环内的索引。

以下示例将为第二个 lastprivate 提供 C3020,因为该 lastprivate 将在最外层的 for 循环中触发对 idx_a 的写入。 第一个 lastprivate 没有给出错误,因为 lastprivate 触发了对最外层 for 循环之外的 idx_a 的写入(从技术上讲,在最后一次迭代结束时)。 以下示例生成 C3020。

// C3020b.cpp
// compile with: /openmp /c
float a[100][100];
int idx_a, idx_b;
void test(int first, int last)
{
   #pragma omp parallel for lastprivate(idx_a)
   for (idx_a = first; idx_a <= last; ++idx_a) {
      #pragma omp parallel for lastprivate(idx_a)   // C3020
      for (idx_b = first; idx_b <= last; ++idx_b) {
         a[idx_a][idx_b] += 1.0f;
      }
   }
}

以下示例演示了可能的解决方法:

// C3020c.cpp
// compile with: /openmp /c
float a[100][100];
int idx_a, idx_b;
void test(int first, int last)
{
   #pragma omp parallel for lastprivate(idx_a)
   for (idx_a = first; idx_a <= last; ++idx_a) {
      #pragma omp parallel for lastprivate(idx_b)
      for (idx_b = first; idx_b <= last; ++idx_b) {
         a[idx_a][idx_b] += 1.0f;
      }
   }
}