声明OpenMP中类模板的用户定义缩减。

3
使用OpenMP时,我想为类模板声明一个用户定义的缩减(reduction)。
#include <omp.h>
#include <iostream>

template<typename T>
class Foo
{
  public:
  T Data_;

  template<typename U> friend Foo<U> operator+( const Foo<U>& lhs, const Foo<U>& rhs );
};

template<typename U>
Foo<U> operator+( const Foo<U>& lhs, const Foo<U>& rhs )
{
  Foo<U> Addition;

  Addition.Data_ = lhs.Data_ + rhs.Data_;

  return Addition;
}

#pragma omp declare reduction( + : template<typename U> Foo<U> : omp_out = omp_out + omp_in ) initializer (omp_priv=omp_orig)

int main( int argc, char* argv[] )
{
  Foo<int> Array[100];
  
  for ( int i = 0 ; i < 100 ; ++i )
  {
    Array[i].Data_ = i;
  }
  
  Foo<int> Sum {0};
  
  #pragma omp parallel for num_threads(4) reduction( + : Sum )
  for ( int i = 0 ; i < 100 ; ++i )
  {
    Sum.Data_ += Array[i].Data_;
  }
  
  std::cout << Sum.Data_ << std::endl;
  
  return 0;
}

但我遇到了以下错误:

error: expected type-specifier before 'template'
#pragma omp declare reduction( + : template<typename U> Foo<U> : omp_out = omp_out + omp_in ) initializer (omp_priv=omp_orig)
                                   ^~~~~~~~

我可以通过将template<typename U> Foo<U>替换为Foo<int>来修复错误。

但是我想知道是否有保持使用template的解决方案。

谢谢。

1个回答

3

假设你有一个模板函数

template<typename T>
T f(T x,T y) {};

你可以将减少操作进行模板化:

#pragma omp declare reduction                                   \
  (rwzt:T:omp_out=f<T>(omp_out,omp_in))

并将其用作:

template<typename T>
T generic_reduction( const vector<T>& tdata ) {
  #pragma omp declare reduction                                   \
    (rwzt:T:omp_out=f<T>(omp_out,omp_in))

  T tmin;
  #pragma omp parallel for reduction(rwzt:tmin)
   for ( stuff ) {}
  return tmin;
}

auto tm = generic_reduction<float>( /* some vector<float> */ );

我有点困扰的是需要定义一个命名函数来包含它们的减少,而不是将所有代码内联化。我无法想出一种在调用环境中使用lambda的方法。


3
好的。这似乎得到了主流编译器的很好支持。只有一个小注意点:我认为最好使用const vector<T>&而不是vector<T>来避免不必要的复制。 - Jérôme Richard
1
@JérômeRichard 对于需要并行化的大小向量,您是完全正确的。代码已编辑。 - Victor Eijkhout

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接