C++:OpenMP 共享内存保护

C++: OpenMP shared memory protection

本文关键字:内存保护 共享 OpenMP C++      更新时间:2023-10-16

如果我使用共享变量,比如说双精度,来计算程序执行过程中的某种总和。这是否容易受到不稳定操作的影响?我的意思是,是否有可能多个内核以异步方式访问此变量并导致不稳定的结果?

例如:这是一个全局变量:

double totalTime = 0;

在每个内核中调用一个命令:

totalTime += elapsedTime;

最后一个操作/语句是通过获取 totalTime 的值来执行的,将其放入 CPU 寄存器,然后进行加法。我可以想象,多个内核会在同一时刻采用相同的值,然后添加新的 elapsedTime,然后由于延迟,存储在 totalTime 中的值将被错误的值覆盖。这可能吗?我该如何解决这个问题?

谢谢。

显然,此操作不是线程安全的,因为正如您自己提到的,它涉及多个汇编程序指令。事实上,openMP 甚至对这种操作有特殊的指令。

您将需要atomic编译指示来使其"原子":

#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值的总和,而无需显式同步。