捕获通过取消引用指针获得的变量可以是原子的吗?

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 都生成相同的代码,但它确保您的代码在所有架构上都是安全的。