C++ 是否可以使用openmp对阵列进行缩减?

C++ 是否可以使用openmp对阵列进行缩减?,c++,arrays,openmp,reduction,C++,Arrays,Openmp,Reduction,OpenMP本机是否支持减少表示阵列的变量 这将像下面这样工作 float* a = (float*) calloc(4*sizeof(float)); omp_set_num_threads(13); #pragma omp parallel reduction(+:a) for(i=0;i<4;i++){ a[i] += 1; // Thread-local copy of a incremented by something interesting } // a now co

OpenMP本机是否支持减少表示阵列的变量

这将像下面这样工作

float* a = (float*) calloc(4*sizeof(float));
omp_set_num_threads(13);
#pragma omp parallel reduction(+:a)
for(i=0;i<4;i++){
   a[i] += 1;  // Thread-local copy of a incremented by something interesting
}
// a now contains [13 13 13 13]
float*a=(float*)calloc(4*sizeof(float));
omp_设置_数量_线程(13);
#pragma omp并行归约(+:a)

对于(i=0;iOpenMP无法对数组或结构类型变量执行缩减(请参阅)


您可能还需要阅读and子句。
private
声明一个变量对每个线程都是私有的,其中as
shared
声明一个变量在所有线程之间共享。我还发现这个问题的答案对于OpenMP和数组非常有用。

仅在OpenMP 3.0中的Fortran中使用,可能仅在cer中使用TAN编译器

请参见最后一个示例(示例3):


现在,最新的openMP 4.5规范支持减少C/C++阵列。

最新的GCC6.1也支持此功能。


<>但是我没有尝试过。希望其他人能测试这个特性。现在,用C++和C++的OpenMP 4.5可以实现数组降阶。
#include <iostream>

int main()
{

  int myArray[6] = {};

  #pragma omp parallel for reduction(+:myArray[:6])
  for (int i=0; i<50; ++i)
  {
    double a = 2.0; // Or something non-trivial justifying the parallelism...
    for (int n = 0; n<6; ++n)
    {
      myArray[n] += a;
    }
  }
  // Print the array elements to see them summed   
  for (int n = 0; n<6; ++n)
  {
    std::cout << myArray[n] << " " << std::endl;
  } 
}
我是用GCC 6.2编译的。您可以在这里看到哪些常见的编译器版本支持OpenMP 4.5功能:


从上面的注释中注意到,虽然这是一种方便的语法,但它可能会从为每个线程创建每个阵列节的副本中调用大量开销。

OpenMP可以从OpenMP 4.5开始执行此操作,GCC 6.3(可能更低)支持它。示例程序如下所示:

#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;
}
#包括
#包括
int main(){
std::vec;
#pragma omp declare reduction(merge:std::vector:omp_out.insert(omp_out.end()、omp_in.begin()、omp_in.end())
#pragma omp parallel用于默认(无)计划(静态)缩减(合并:vec)

对于(int i=0;i可能你可以更详细地解释一下你到底想做什么。提供串行代码可能会有所帮助。再深入一点,听起来像是“只在fortran中”答案是。我最终只是在循环外分配了一个大型的本地副本数组,让线程在for循环内累积到它们自己的副本,然后在for循环后累积到一个全局数组中,仍然在并行区域内,在一个关键部分内。进一步挖掘,这里有一篇关于以下内容的研究论文ng类似,但它还不在openmp中。您可能可以使用原子而不是关键来保护单个添加(甚至一组锁)如果您想减少开销,您甚至可以使用共享数组数组而不是私有数组,并尝试进行您自己的二进制缩减。但这会很难看。我最终手动为数组的线程本地副本分配空间。每个线程将1/8的累积量添加到其本地副本中,然后线程将其二进制缩减量进行累积本地复制到#pragma omp关键块内的全局复制。由于内核数(8)远小于n,同步开销可以忽略不计。这并不漂亮,但可以正常工作。现在可以从OpenMP 4.5开始使用;请参见下面陈江的答案。基本上,您必须指定阵列节(请参阅OpenMP 4.5规范第44页第2.4节)。您的“pragma规范”如下所示:
“pragma omp并行缩减(+:a[:4])
但是要小心,您必须意识到每个线程都会分配自己版本的数组部分;如果在具有多个线程的大型数组上执行此操作,可能会导致内存需求激增。
#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;
}