捕获通过取消引用指针获得的变量可以是原子的吗?
Can capturing a variable obtained by dereferencing a pointer be atomic?
我有以下用 OpenMP 编译的 C 代码:
(int a[100]
是一个全局数组)
int update (int * x, const int c)
{
int v;
#pragma omp atomic capture
{
v = a[*x];
a[*x] = c;
}
return v;
}
GCC 和 Clang 都没有给出编译器错误。但我怀疑该部分中的所有操作是否真的适合一个原子操作。我的代码是否等同于以下代码?
int update (int * x, const int c)
{
int v;
int X = *x;
#pragma omp atomic capture
{
v = a[X];
a[X] = c;
}
return v;
}
我回答时考虑的是规范,而不是特定的体系结构或编译器。
如果 *x
的值在 update
的执行期间可能会改变,那么您的代码 不安全 。
The OpenMP standard 描述了 atomic
结构。您 atomic capture
的特定结构化块是
{ v = x; x = expr; }
x
and v
(as applicable) are both l-value expressions with scalar type.
- During the execution of an atomic region, multiple syntactic occurrences of x must designate the same storage location.
如果修改*x
,则违反最后一点。
我会说,update
的代码本身在假设下是有效的,所以编译器不会抱怨。但是这个假设是由你来执行的。
请注意,根据标准,您的第二个版本不安全。但是,您可以使用另一个 atomic read
:
来保护读取指针值
int update(int * x, const int c)
{
int v;
int X;
#pragma omp atomic read
X = *x;
#pragma omp atomic capture
{
v = a[X];
a[X] = c;
}
return v;
}
这还要求您保护对 *x
内存的所有写入。在 x86-64
上,无论 atomic read
,clang 和 GCC 都生成相同的代码,但它确保您的代码在所有架构上都是安全的。
我有以下用 OpenMP 编译的 C 代码:
(int a[100]
是一个全局数组)
int update (int * x, const int c)
{
int v;
#pragma omp atomic capture
{
v = a[*x];
a[*x] = c;
}
return v;
}
GCC 和 Clang 都没有给出编译器错误。但我怀疑该部分中的所有操作是否真的适合一个原子操作。我的代码是否等同于以下代码?
int update (int * x, const int c)
{
int v;
int X = *x;
#pragma omp atomic capture
{
v = a[X];
a[X] = c;
}
return v;
}
我回答时考虑的是规范,而不是特定的体系结构或编译器。
如果 *x
的值在 update
的执行期间可能会改变,那么您的代码 不安全 。
The OpenMP standard 描述了 atomic
结构。您 atomic capture
的特定结构化块是
{ v = x; x = expr; }
x
andv
(as applicable) are both l-value expressions with scalar type.- During the execution of an atomic region, multiple syntactic occurrences of x must designate the same storage location.
如果修改*x
,则违反最后一点。
我会说,update
的代码本身在假设下是有效的,所以编译器不会抱怨。但是这个假设是由你来执行的。
请注意,根据标准,您的第二个版本不安全。但是,您可以使用另一个 atomic read
:
int update(int * x, const int c)
{
int v;
int X;
#pragma omp atomic read
X = *x;
#pragma omp atomic capture
{
v = a[X];
a[X] = c;
}
return v;
}
这还要求您保护对 *x
内存的所有写入。在 x86-64
上,无论 atomic read
,clang 和 GCC 都生成相同的代码,但它确保您的代码在所有架构上都是安全的。