OpenMP 中调度程序处理循环变量

Procession of loop variables by a scheduler in OpenMP

循环变量默认是私有的。假设我们有这个循环头的线程:

#pragma omp parallel num_threads(4)
{
    #pragma omp parallel for schedule(static,1)
    for(i=0; i<40; i+=2) {
    //...
    }
}

在循环开始执行之前,静态调度程序可能会按如下方式分配迭代:

线程 1: 迭代 0、4、8、12、16

线程 2: 迭代 1、5、9、13、17

线程 3: 迭代 2、6、10、14、18

线程 4: 迭代 3、6、12、15、19

我不明白线程 3 如何在其第三次迭代中知道 i 的正确值(如果循环按顺序执行,这将是第 10 次迭代)。 i 是私有的,所以每个线程都有自己的副本和增量 i。同样,i 的值必须以某种方式共享。这是如何工作的?

长话短说,OpenMP 编译器将为该循环生成一个函数,该函数将由多个线程并行调用。

循环迭代器将被规范化,边界将被重写为 thread_idthread_num 上的参数化:

// code generated for #pragma omp for
void openmp_loop_0(int thread_id, int thread_num, ... closure ...) {
   for(i=thread_id; i<40/2; i+=thread_num) {
      ...a[i*2]...
   }
}

// code replaced in the main() function
thread t0(openmp_loop_0(0, 4, ...).start();
thread t1(openmp_loop_0(1, 4, ...).start();
...
openmp_loop_0(3, 4, ...)
t0.join(), t1.join(), t2.join();

例如线程将执行以下迭代:

tid #0: 0, 4, 8...
tid #1: 1, 5, 9...
tid #2: 2, 6, 10...
tid #3: 3, 7, 11...

这是实现 OpenMP 的一种简单直接的方法,它应该让您了解整个机器的工作原理。