【问题标题】:why do people declare iterated values before loop for openmp?为什么人们在openmp循环之前声明迭代值?
【发布时间】:2014-04-01 15:24:32
【问题描述】:

所以据我了解,这两种方法在所有版本的 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);
}

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

【问题讨论】:

  • 我也想知道同样的事情。我想大多数人都不知道更好。它还经常导致错误,因为人们认为内部循环也可以正常工作,但事实并非如此(没有明确声明内部迭代器私有)。 GNU89 方言(ICC 也使用)允许混合声明,所以我真的不明白为什么人们仍然喜欢在循环之外声明迭代器。这很容易出错。
  • 事实证明,尽管 GNU89 确实允许混合声明,但它仍然不允许循环初始声明,因此需要 C99(例如 GNU99)或 C++ 方言。我更新了我的答案来解决这个问题。

标签: c++ openmp


【解决方案1】:

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

【讨论】:

  • 但是任何 C++ 编译器都不应该关心?我的意思是,openmp 可能比 C++ 更多地用于 C,但 99% 的示例都是 C 风格似乎仍然很奇怪......
  • 大多数示例可能同时针对 C 和 C++ 用户。 OpenMP 也落后于 C++ 的开发,例如for 带有随机访问迭代器的构造直到 3.0(2008 年)版本才成为标准的一部分。
  • 另一个原因是迭代器变量在同一个函数内的多个for循环中使用。
  • 另一个原因是迭代器变量在for 循环之后可用。
  • @ThomasMatthews,因为迭代器是私有的,所以在 OpenMP 中效果不佳。 Lastprivate 有时会有所帮助,但实际上我几乎从未见过它使用过。
【解决方案2】:

在循环之外声明循环迭代器很容易出错并且通常是不必要的。也许关于 OpenMP 的 SO 问题中最大的一部分是由于内部循环和在循环外声明迭代器造成的问题。

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 方言 GNU89does not allow loop initial declarations(即使它确实允许混合声明),因此循环初始声明需要 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 %d\n",i, j);  //output 8, 24
}

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-07
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多