【发布时间】:2016-05-12 14:03:09
【问题描述】:
我目前正在学习使用 C 和 OpenMP 进行并行编程。
我想编写简单的代码,其中两个共享值由多个线程递增。
首先,我使用了 reduction 指令,它按预期工作。然后我切换到使用 critical 指令来启动临界区——它也有效。
出于好奇,我尝试合并这两个解决方案并检查行为。我希望有两个有效、相等的值。
代码:
#include <stdio.h>
#include <stdlib.h>
#include "omp.h"
#define ITER 50000
int main( void )
{
int x, y;
#pragma omp parallel reduction(+:x,y)
{
#pragma omp for
for (int i = 0; i < ITER; i++ )
{
x++;
#pragma omp critical
y++;
}
}
printf("non critical = %d\ncritical = %d\n", x, y);
return 0;
}
输出:
非关键 = 50000
关键 = 4246432
当然,当涉及到“关键”(变量 y)时,输出是随机的,另一个则按预期运行,始终为 50000。
x 的行为是可以理解的 - reduction 使其在单线程范围内是私有的。在对来自线程的增量值求和并传递给非本地 x 之后。
我不明白的是y的行为。它就像 x 一样是私有的,但它也在 critical 部分内,因此它“有多个理由”无法从其他线程访问。然而,我认为,发生的是比赛条件。 critical 是否以某种方式将 y 公开(共享)?
我知道这段代码没有意义,因为只使用 reduction / critical 之一就足够了。我只想知道这种行为背后的原因。
【问题讨论】:
-
谁初始化变量?好像是 UB。
-
OpenMP 在 reduction 指令中自动执行此操作(0 表示 + 和 -,1 表示 * 和 /)
-
用于私有副本,但不适用于可见变量。如果你初始化它会发生什么?
-
我确信减少隐含地私有化了减少的值。
-
@nullPointer 您在技术上是正确的。但是,当您可以冗长并完全说服自己您正在编写的内容完全按照您的预期工作时,为什么还要依赖 OpenMP 隐式行为呢?
标签: c multithreading openmp critical-section reduction