为什么人们在 OpenMP 循环之前声明迭代值

why do people declare iterated values before loop for openmp?

本文关键字:声明 迭代 循环 OpenMP 为什么      更新时间:2023-10-16

因此,据我所知,在所有版本的openmp中,以下任何一个都是正确的:

//int i declared in loop, explicitly private
#pragma omp parallel for
for (int i = 0; i < NUMEL; i++)
{
  foo(i);
}
//int i declared outsize loop, but is the iterated value, implicitly private
int i;
#pragma omp parallel for
for (i = 0; i < NUMEL; i++)
{
  foo(i);
}

但是,我更常看到第二个而不是第一个。为什么?

因为不是每个人都用C++编写或针对符合 C99 的 C 编译器。有些人更喜欢坚持旧的 C 要求,即在块的开头声明变量,以便代码与较旧的(C99 之前)C 编译器更兼容。

循环之外声明循环迭代器容易出错,通常没有必要。 也许SO上关于OpenMP的问题中,最大的部分是由于内部循环和在循环外声明迭代器引起的问题。

int i,j;
#pragma omp parallel for
for(i=0; i<n; i++) {  //OpenMP makes the parallel index private by default
    for( j=0; j<n; j++) {  //error j should be private but is shared by default

如果使用循环初始声明,则不会发生此类错误

#pragma omp parallel for
for(int i=0; i<n; i++) { //i is private
    for(int j=0; j<n; j++) {// j is private now

不幸的是,GCC 和 ICC 默认使用的 C 方言 GNU89 不允许循环初始声明(即使它确实允许混合声明),因此 C99(例如 GNU99)方言或C++对于循环初始声明是必需的。

但是,有时在需要最后一个迭代器时在循环外部声明迭代器很有用。 在这种情况下,应使用lastprivate。 例如,如果我只想遍历四个元素的多个,然后知道要使用多少个最终元素,我可以这样做:

#include <stdio.h>
int main() {
    int i,j;
    int n,m;
    n = 10;
    m = 25;
    #pragma omp parallel for lastprivate(i,j)
    for(i=0; i<(n & -4); i++) {
        for(j=0; j<(m & -4); j++) {
        }
    }
    printf("%d %dn",i, j);  //output 8, 24
}

一位程序员曾经告诉我,他更喜欢第二个版本,因为你可以在循环退出后在调试器中看到i的值,这对于具有复杂条件或breaks的循环很有用。 但是这些循环不能很好地并行化,所以如果这是 OpenMP 示例的原因,我会感到惊讶。