OpenMP 有序子句

OpenMP ordered clause

OpenMP中的ordered子句应该如何正确使用?有这个测试代码来检查循环是否会通过增加 n 的值来执行,但情况并非总是如此。

我是否误解了有序子句的定义?

The ordered construct specifies a structured block in a loop region that will be executed in the order of the loop iterations. This sequentializes and orders the code within an ordered region while allowing code outside the region to run in parallel.

    #include <stdio.h>
    #include <stdlib.h>
    #include <omp.h>

    int main(){

        int n;
    omp_set_num_threads(4);
    #pragma omp parallel
        {
    #pragma omp for ordered
            for (n=0;n<10;n++)
                printf("n = %d\n",n);
        }
        return 0;
    }

编译时使用

   gcc -Wall -Wextra -fopenmp test_par.c

输出为

    ./a.out 
    n = 0 
    n = 1 
    n = 2 
    n = 9 
    n = 3 
    n = 4 
    n = 5 
    n = 6 
    n = 7 
    n = 8 

OpenMP ordered 子句应该在两个不同的阶段使用:

  1. 作为 for 指令的一个子句,指示一些可能的迭代顺序;然后
  2. 作为一个独立的指令,指示循环内语句的哪些部分要保持有序。

所以本质上,你的例子应该是:

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>

int main(){

    int n;
    omp_set_num_threads(4);
    #pragma omp parallel
    {
        #pragma omp for ordered
        for (n=0;n<10;n++)
            #pragma omp ordered
            printf("n = %d\n",n);
    }
    return 0;
}

给出:

$ g++ -fopenmp order.cc
$ ./a.out 
n = 0
n = 1
n = 2
n = 3
n = 4
n = 5
n = 6
n = 7
n = 8
n = 9

不过,这里要注意两点:

  1. 这个并行循环实际上是完全顺序化的,因为 ordered 指令之外没有任何东西
  2. 此外,如果您想减轻 ordered 指令引起的序列化影响,您应该使用 schedule 指令。例如,在有序循环的情况下,"effective" 调度的一个很好的候选者是 schedule( static, 1 )

最后,Hristo Iliev 对这一切的解释比我所能解释的还要好 here