【发布时间】:2022-01-12 23:19:08
【问题描述】:
我一直在关注和修改 C/C++ 中的 OpenMP 教程,以演示/理解 schedule() 在 #pragma omp parallel for 中的工作原理。
这是我的代码:
#include <unistd.h>
#include <stdlib.h>
#include <omp.h>
#include <stdio.h>
#define THREADS 4
#define N 100
int main ( ) {
int i;
int perThread=0;
printf("Running %d iterations on %d threads.\n", N, THREADS);
#pragma omp parallel for num_threads(THREADS) private(perThread) //schedule(static)
for (i = 0; i < N; i++) {
perThread++;
printf("Thread: %d\t loops: %d\n", omp_get_thread_num(), perThread);
usleep(10000); // to slow the process down a bit
//Uncomment below to simulate one thread taking longer on each loop
// if(omp_get_thread_num()==1)
// sleep(1);
}
// all threads done
printf("All done!\n");
return 0;
}
我将它保存为“schedule_example.cpp”并编译它:
g++ schedule_example.cpp -fopenmp -o SheduleEx
然后我将它与未注释的第 13 行 schedule(static) 进行比较,并再次与 schedule() 的各种选项进行比较,即 schedule(static,25) schedule(static,5) schedule(dynamic) schedule(dynamic,5) schedule(runtime)
调度程序工作,代码演示了差异(特别是当第 20 和 21 行未注释时。)
问题在于,对于schedule() 的某些但不是所有选项,perThread 的起始值对于某些但不是所有线程都发生了更改,这可以在打印输出中看到。
我在几台不同的机器上运行了代码,它们都显示了相似的结果。
我在 Windows 10 笔记本电脑上使用了 WSL,g++ --version 返回:
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0.
以最后 8 行为例。如果schedule() 被注释掉或使用schedule(static) 输出是正确的:
Thread: 2 loops: 24
Thread: 0 loops: 24
Thread: 1 loops: 24
Thread: 3 loops: 24
Thread: 2 loops: 25
Thread: 1 loops: 25
Thread: 0 loops: 25
Thread: 3 loops: 25
All done!
但是,如果我对 shedule() 甚至 schedule(static,25) 使用其他应该给出相同结果的东西,它会编译并运行,但最后几行输出是:
Thread: 1 loops: 24
Thread: 3 loops: 24
Thread: 0 loops: 22010
Thread: 2 loops: 24
Thread: 1 loops: 25
Thread: 3 loops: 25
Thread: 0 loops: 22011
Thread: 2 loops: 25
All done!
问题是perThread 的起始值已设置为 1986 但仅适用于线程 0。
如果我在不重新编译的情况下重新运行它,我会得到类似的结果,总是线程 0 是错误的,大约 22000,但每次的数量不一样。如果我在重新运行之前重新编译它会给出相同的结果。
然后我在 Raspberry Pi 上运行相同的代码,得到了相似但略有不同的结果。
g++ --version 返回:
g++ (Raspbian 10.2.1-6+rpi1) 10.2.1 20210110
如果使用schedule(dynamic) 或schedule(dynamic, X),Raspberry Pi 只会在所有线程上打印出正确的循环值 - 我尝试将 1、5 和 25 作为 X 的值。
如果使用 (static) 或 (static, X),则除线程 0 之外的所有线程的起始值大约为 67321,此数字对于线程 1、2 和 3 始终相同,并且通常但不总是在代码的连续运行之间相同。
(auto) 的行为与 (static) 相同。
然而,(runtime) 与 (static) 相对,只有线程 0 错误,但也关闭了大约 67481 - 但是当连续运行几次时,每次都出现相同数量的错误。
我在另一台装有 Arch Linux 的 PC 上再次运行相同的代码,得到了与 Windows 10 笔记本电脑相似的结果。
就一个实际问题而言,我在编写代码的方式上是否做错了什么?有没有办法确保线程的变量不被改变?
抱歉,这篇文章太长了,但我认为问题的核心是 schedule() 以某种方式影响了 private() 中的变量,因为 parallel for 循环开始时的一些线程,某些时候.
谢谢
【问题讨论】:
标签: c++ multithreading openmp