OpenMP 子句共享与关键

Posted

技术标签:

【中文标题】OpenMP 子句共享与关键【英文标题】:OpenMP clause shared vs critical 【发布时间】:2021-08-13 01:40:27 【问题描述】:

我在多个线程上执行了一个循环。每个循环都会将一个值存储到一个全局向量中。所有线程都使用向量索引变量,每个线程在向量更新后递增索引。 必须保护对索引的访问。 OpenMP 中是如何进行保护的?

1/ 如果我指定#pragma omp parallel shared(k) 这会保护(同步访问)跨线程的 k-index 访问吗?

   int k = 0;
   #pragma omp parallel shared(k)
   for (int i = 1; i < d; ++i)
   
      for (int j = 0; j < i; ++j)
      
         my_vec[k++] = some_value; //no need to protect my_vector, if k is unique across trheads
      
   

2/ 我需要使用临界区吗

   int k = 0;
   #pragma omp parallel
   for (int i = 1; i < d; ++i)
   
      for (int j = 0; j < i; ++j)
      
        #pragma omp critical (section_name)
        
           my_vec[k++] = some_value;
        
      
   

3/我需要同时使用共享子句和临界区块吗?

【问题讨论】:

【参考方案1】:

1/ 如果我指定 #pragma omp parallel shared(k) 这会保护 (同步访问)跨线程的 k-index 访问?

如果您使用共享的k,您将有两个竞争条件

    在变量k更新期间,即在操作k++中。 在访问数组期间my_vec在操作期间my_vec[k++] = some_value;

具有相同k 索引的多个线程可以相互重写my_vec[k] 的值。

AFAIK 没有条件使变量共享可以避免 race-condition。通常情况正好相反。如果你让一个变量共享,你可能需要确保它受到保护以防止并发线程更新。

2/ 我需要使用临界区吗

如果您只使用临界区并且变量k 在线程中是私有的,那么在访问数组my_vec 期间(在操作my_vec[k++] = some_value; )。尽管如此,如果没有另外指定(例如, private(k)),默认情况下 OpenMP 假定变量 k 在线程之间共享。因此,使用临界区足以确保mutual exclusion 对两个共享变量(变量k 和数组my_vec)的访问

3/我需要同时使用共享子句和临界区块吗?

您可以明确指出变量 k 是共享的,但默认情况下选项 2) 就足够了。

【讨论】:

以上是关于OpenMP 子句共享与关键的主要内容,如果未能解决你的问题,请参考以下文章

openmp 共享数组

共享内存的 MPI 与 openMP

将静态库链接到共享库(例如openmp)是一个好主意

为啥 OpenMP 减少在共享内存结构上比 MPI 慢?

如果共享堆栈或数据变量,OpenMP 是不是会将它们移动到堆中?

openMP 并行部分中的共享变量有些奇怪