在C语言中利用OpenMP为全局变量创建私有副本的技术问询
如何让每个OpenMP线程拥有全局变量的私有副本(最小化代码修改)
我现在有一段C代码,逻辑是通过OpenMP并行循环调用一个函数,希望每个线程操作全局变量的私有副本,让输出全是1,但实际输出是乱序的0到99。代码如下:
int getal = 0; void incrementAndPrint() { getal = getal + 1; printf("%d\n", getal); } void main() { int times = 100; #pragma omp parallel for for (int n = 0; n < times; n++) { incrementAndPrint(n); // 注:原代码里函数参数n未被使用,应为笔误 } }
期望输出:1 1 1 ...(共100个1)
实际输出:乱序的0到99(多线程同时读写全局变量getal,既存在竞争,也没有私有副本)
请问能不能在不大量修改现有代码的前提下,让每个线程拥有全局变量getal的私有副本?
当然可以!OpenMP专门提供了threadprivate指令来处理这种全局/文件作用域变量的线程私有化需求,几乎不需要改动现有代码结构,只需要加一行声明即可。
具体修改方案
只需要在全局变量getal的声明后面加上#pragma omp threadprivate(getal)——因为全局变量默认初始值为0,threadprivate会让每个线程的私有副本继承这个初始值,刚好符合你的需求。
修改后的代码如下:
#include <stdio.h> #include <omp.h> // 部分编译器需要显式包含OpenMP头文件 int getal = 0; #pragma omp threadprivate(getal) // 关键:为每个线程创建getal的私有副本 void incrementAndPrint() { getal = getal + 1; printf("%d\n", getal); } int main() { // 标准C中main函数应返回int,建议修正 int times = 100; #pragma omp parallel for for (int n = 0; n < times; n++) { incrementAndPrint(); // 原参数n未使用,可移除避免编译警告 } return 0; }
为什么这样可行?
threadprivate会为每个OpenMP线程生成该全局变量的独立私有实例,每个线程只能访问自己的副本,彻底消除了多线程竞争问题。- 每个线程的
getal副本初始值与全局变量一致(这里是0),所以每个线程第一次调用incrementAndPrint时,都会把自己的副本从0加到1,输出结果全是1,完全符合你的期望。
补充说明
如果不想用threadprivate,也可以在parallel for指令里用private子句,但那样需要把getal改成局部变量并传递,反而会改动更多代码。相比之下,threadprivate就是专门为全局变量的线程私有化设计的,更贴合你的需求。
内容的提问来源于stack exchange,提问作者tauros_is_the_best_pokemon
相关产品推荐
相关产品推荐

