在 OpenMP 中访问线程的专用内存

Accessing a thread's private memory in OpenMP

本文关键字:专用 内存 线程 访问 OpenMP      更新时间:2023-10-16

根据OpenMP内存模型,以下是不正确的:

int *p0 = NULL, *p1 = NULL;
#pragma omp parallel shared(p0,p1)
{
  int x;
  // THREAD 0              // THREAD 1
  p0 = &x;                 p1 = &x;
  *p1 ...                  *p0 ...
}

我的例子看起来像这样:

int *p0 = NULL, *p1 = NULL;
#pragma omp parallel shared(p0,p1)
{
  int x;
  // THREAD 0              // THREAD 1
  p0 = &x;                 p1 = &x;
  #pragma omp flush
  #pragma omp barrier
  *p1 ...                  *p0 ...
  #pragma omp barrier
}

这是错误的吗?我无法在内存模型中找到不允许此操作的内容。

我假设我的玩具示例是正确的,因为在3.1中的内存模型中,它们允许任务访问私有变量,只要程序员确保它仍然存活。鉴于任务可以被解耦,理论上它们可以在不同的工作线程中执行,因此允许OpenMP线程访问另一个线程的私有内存。

应该可以。Flush同步所有共享变量,barrier保证具有所有线程的mp环境仍处于活动状态。只要你不在p1赋值中使用p0,反之亦然,应该没问题。虽然我无法想象为什么有人会做那样的事。也许你能告诉我更多关于这个构造背后的原因。

由于p0和p1在平行区域之后仍然存在,因此您可以在那里进行所有赋值,而不存在障碍等

作为一个侧面的想法,这类似于试图通过将局部变量赋值给全局变量来读取某个函数中的局部变量,然后读取全局变量。

这里的类比是,全局变量的作用类似于多线程中的共享变量,本质上允许访问应该是线程私有的东西(就像局部变量一样,应该只在函数中可见)。

所以回答这个问题,对线程私有内存进行解引用是完全有效的。这是允许的,因为指针别名是允许的(这是两个或多个变量提供访问内存中相同的位置,在你的情况下,一个是线程私有整数,另一个是共享指针)。

虽然完全有效,但要注意这可能会导致一些难以检测的竞争条件,因为通常不会使用锁来保护对线程私有变量的访问。