【问题标题】:How to do an ordered reduction in OpenMP如何在 OpenMP 中进行有序缩减
【发布时间】:2017-06-14 07:27:19
【问题描述】:

OpenMP 4.5+ 提供了在 C++ 中进行向量/数组缩减的功能 (press release)

使用所述功能允许我们编写,例如:

#include <vector>
#include <iostream>

int main(){
  std::vector<int> vec;

  #pragma omp declare reduction (merge : std::vector<int> : omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end()))

  #pragma omp parallel for default(none) schedule(static) reduction(merge: vec)
  for(int i=0;i<100;i++)
    vec.push_back(i);

  for(const auto x: vec)
    std::cout<<x<<"\n";

  return 0;
}

问题是,在执行此类代码时,各个线程的结果可能以任何方式排序。

有没有办法强制执行顺序,使线程 0 的结果先于线程 1,以此类推?

【问题讨论】:

标签: c++ openmp


【解决方案1】:

没有明确指定缩减的顺序。 (“OpenMP 程序中值组合的位置以及 组合的值未指定。”,OpenMP 4.5 中为 2.15.3.6)。因此您不能使用缩减。

一种方法是按如下方式使用ordered:

std::vector<int> vec;
#pragma omp parallel for default(none) schedule(static) shared(vec)
for(int i=0;i<100;i++) {
    // do some computations here
    #pragma omp ordered
    vec.push_back(i);
}

请注意,vec 现在是共享的,ordered 表示线程之间执行和同步的序列化。这可能对性能非常不利,除非您的每个计算都需要大量且统一的时间。

您可以进行自定义排序减少。从for 循环中拆分parallel 区域,并按顺序手动插入本地结果。

std::vector<int> global_vec;
#pragma omp parallel
{
    std::vector<int> local_vec;
    #pragma omp for schedule(static)
    for (int i=0; i < 100; i++) {
        // some computations
        local_vec.push_back(i);
    }
    for (int t = 0; t < omp_get_num_threads(); t++) {
        #pragma omp barrier
        if (t == omp_get_thread_num()) {
            global_vec.insert(local_vec.begin(), local_vec.end())
        }
    }
}

【讨论】:

  • 很好的答案!在您的后一种方法中,您可以do as in this answer。我不确定哪个更可取,但我猜想barrier 方法还有更多等待时间。
猜你喜欢
  • 1970-01-01
  • 2021-06-17
  • 2023-03-31
  • 1970-01-01
  • 2011-04-16
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多