6

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

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

double totalTime = 0;

并且在每个核心中调用一个命令:

totalTime += elapsedTime;

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

谢谢你。

4

1 回答 1

5

显然,此操作不是线程安全的,因为正如您自己提到的,它涉及多个汇编指令。事实上,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值的总和,而无需显式同步。

于 2012-06-11T10:05:42.513 回答