如果我使用共享变量,让我们说一个double,来计算程序执行时的某种总和。无论如何,这是否容易受到非稳定运营的影响?我的意思是,是否有可能多个核心以异步方式访问此变量并导致不稳定的结果?
例如: 这是一个全局变量:
double totalTime = 0;
并在每个核心中调用一个命令:
totalTime += elapsedTime;
通过获取totalTime的值,将其作为CPU寄存器,然后执行添加来执行最后一个操作/语句。我可以想象,不止一个核心会在同一时刻获取相同的值,然后添加新的elapsedTime,然后由于延迟,存储在totalTime中的值将被错误的值覆盖。那可能吗?我该如何解决这个问题?
谢谢。
答案 0 :(得分:5)
显然,此操作不是线程安全的,因为正如您自己提到的,它涉及多个汇编程序指令。事实上,openMP甚至对这种操作有一个特殊的指令。
你需要atomic
pragma才能成功,“原子”:
#pragma omp atomic
totalTime += elapsedTime;
请注意,atomic
仅在您对内存位置进行单次更新时才有效,例如添加,增量等。
如果您有一系列需要原子化的指令,则必须使用critical
指令:
#pragma omp critical
{
// atomic sequence of instructions
}
编辑:这是“snemarch”的一个很好的建议:如果你在一个并行循环中反复更新全局变量totalTime
,你可以考虑使用reduction
子句来自动化流程并提高效率:
double totalTime = 0;
#pragma omp parallel for reduction(+:totalTime)
for(...)
{
...
totalTime += elapsedTime;
}
最后totalTime
将正确包含本地elapsedTime
值的总和,而无需显式同步。