这是一个" minimal"我正在尝试做的非工作示例。
此代码使用-fopenmp
标志进行编译。
#include <omp.h>
#include <iostream>
class A {
public:
virtual void operator() () = 0 ;
void combine(const A & rhs) {
// do reduction stuff
std::cout << "Combine thread : " << omp_get_thread_num() << std::endl;
}
};
class B : public A {
public:
void operator() () {
// do some B specific stuff
std::cout << "B " ;
}
} ;
class C: public A {
public:
void operator() () {
// do some C specific stuff
std::cout << "C " ;
}
} ;
class Computer {
public:
template<typename B_or_C_type>
void compute( B_or_C_type & action ) {
#pragma omp declare reduction (combine_actions : B_or_C_type : omp_out.combine(omp_in) ) initializer ( omp_priv(omp_orig) )
#pragma omp parallel for schedule(dynamic) reduction(combine_actions : action )
for( unsigned i = 0; i < 100; ++i ) {
// do long computation
action() ;
}
std::cout << std::endl;
}
} ;
class Manager {
public:
Manager(Computer * computer) : computer_(computer), action_(NULL)
{}
template<typename B_or_C_type>
void set_action(B_or_C_type * action)
{
action_ = action ;
}
void run()
{
computer_->compute(*action_) ;
}
private:
Computer * computer_ ;
A * action_ ;
} ;
int main() {
Computer computer;
B b ;
C c ;
// Not working
Manager manager(&computer) ;
manager.set_action(&b) ;
manager.run() ;
manager.set_action(&c) ;
manager.run() ;
//Working
// computer.compute(b) ;
// computer.compute(c) ;
return 0;
}
我有3种类型:
A
(基类),B
和C
(源自A
)Bar
使用OpenMP实现并行计算(通过compute()
函数)并执行一些操作(来自B
或C
通过调用operator()
。现在我有这个错误的错误告诉我,我cannot declare variable 'omp_priv' to be of abstract type 'A'
。这是可以理解的。我的A
类实际上是抽象的,但我希望OpenMP能够理解来自A * action_
类的Manager
属性是B
或C
类型。但我怎么能这样做?
奇怪的是,此代码在以下情况下有效:
Manager
课程(main()
)或如果:
#pragma
开头的那些)然而,这些都是不可想象的选择。
感谢您的回答。
答案 0 :(得分:1)
使用A&
不起作用,但使用A*
会:
B_or_C_type * action_ptr = &action;
#pragma omp declare reduction (combine_actions : B_or_C_type* : omp_out->combine(*omp_in) ) initializer ( omp_priv(omp_orig) )
#pragma omp parallel for schedule(dynamic) reduction(combine_actions : action_ptr )
for( unsigned i = 0; i < 100; ++i ) {
// do long computation
(*action_ptr)();
}
这样您就可以跳过整个B_or_C_type
模板,只使用A
。作为一种更粗略的替代方案,您可以利用对A
的所有已知子类进行切换:
void compute( A & action ) {
B * pb = dynamic_cast<B*>( &action );
if ( pb ) compute( *pb );
C * pc = dynamic_cast<C*>( &action );
if ( pc ) compute( *pc );
}
我不太确定为什么这不起作用。顺便说一句,它与英特尔编译器编译,但崩溃与纯虚函数调用。我原以为这应该这样做:
#pragma omp declare reduction (combine_actions : B_or_C_type& : omp_out->combine(*omp_in) ) initializer ( omp_priv(omp_orig) )
但事实并非如此。关于 typename-list 中允许哪种类型名称,标准似乎有点模糊。在我看来,引用只是没有得到正确支持。