gpt4 book ai didi

c - OpenMP - 临界区 + 缩减

转载 作者:行者123 更新时间:2023-12-04 09:33:38 26 4
gpt4 key购买 nike

我目前正在学习使用 C 和 OpenMP 进行并行编程。
我想编写简单的代码,其中两个共享值由多个线程递增。
首先我使用了减少指令,它按预期工作。然后我改用 关键 启动关键部分的指令 - 它也有效。
出于好奇,我尝试合并这两个解决方案并检查行为。我期望有两个有效的、相等的 values.code:

#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;
}

输出:

non critical = 50000
critical = 4246432



当然,当涉及到“关键”(变量 y)时,输出是随机的,另一个则按预期运行,并且始终为 50000。

的行为x 可以理解- 减少使其在单线程范围内成为私有(private)。在对来自线程的增量值求和并传递给非本地 x 之后。

我不明白的是 的行为是 .它是私有(private)的,就像 x 但它也在 内关键 部分,因此其他线程无法访问它“有多个原因”。然而,我认为,发生的是比赛条件。 关键 以某种方式制作 公共(public)(共享)?

我知道这段代码没有意义,因为只使用 之一就足够了减少/ 关键 .我只想知道这种行为背后的原因。

最佳答案

您的代码只是表现出未定义的行为和 critical 的存在。与你得到错误的结果无关。

Did the critical somehow made y public (shared)?



不,它没有。它只会通过阻止线程的并发执行来减慢循环。

您缺少的是归约操作的结果是 结合归约变量的初始值 ,即变量在平行区域之前的值。在您的情况下, xy具有随机初始值,因此您得到随机结果。即初始值 x在你的情况下恰好是 0,这就是为什么你得到正确的结果,因为它只是 UB。初始化 xy使您的代码按预期运行。

OpenMP 规范指出:

The reduction clause specifies a reduction-identifier and one or more list items. For each list item, a private copy is created in each implicit task or SIMD lane, and is initialized with the initializer value of the reduction-identifier. After the end of the region, the original list item is updated with the values of the private copies using the combiner associated with the reduction-identifier.



这是使用 4 个线程执行原始代码:

$ icc -O3 -openmp -std=c99 -o cnc cnc.c
$ OMP_NUM_THREADS=1 ./cnc
non critical = 82765
critical = 50000
$ OMP_NUM_THREADS=4 ./cnc
non critical = 82765
critical = 50000
$ OMP_NUM_THREADS=4 ./cnc
non critical = 50000
critical = 50000
$ OMP_NUM_THREADS=4 ./cnc
non critical = 82765
critical = 50194
$ OMP_NUM_THREADS=4 ./cnc
non critical = 82767
critical = 2112072800

使用一个线程的第一次运行表明它不是由于数据竞争。

int x=0, y=0; :

$ icc -O3 -openmp -std=c99 -o cnc cnc.c
$ OMP_NUM_THREADS=4 ./cnc
non critical = 50000
critical = 50000
$ OMP_NUM_THREADS=4 ./cnc
non critical = 50000
critical = 50000
$ OMP_NUM_THREADS=4 ./cnc
non critical = 50000
critical = 50000
$ OMP_NUM_THREADS=4 ./cnc
non critical = 50000
critical = 50000

关于c - OpenMP - 临界区 + 缩减,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35175957/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com