2016-06-13 44 views
1

這是我正在嘗試做的「最小」非工作示例。在OpenMP減少中使用多態類型

此代碼是用-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(基類),且BC(從A派生)
  • 計算機Bar該實現並行使用OpenMP計算(通過compute()函數)並執行一些操作(從BC課程),致電operator()
  • 管理器:管理啓動計算並設置不同的動作。

現在我有告訴我這infortunate錯誤,我cannot declare variable 'omp_priv' to be of abstract type 'A'。這很好理解。我的A類實際上是抽象的,但我希望OpenMP能夠理解,我的A * action_屬性來自Manager類是BC類型。但我怎麼能這樣做?


奇怪的是,這個代碼的工作,如果:

  • 我繞過Manager類(在main()取消註釋作業部)

,或者:

  • 我放棄平行主義和評論線34/35(那些以#pragma

但是,這些都是不可想象的選項。

感謝您的回答。

回答

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)) 

但它沒有。該標準似乎對我來說有點模糊,至於型號名稱 s是否允許在typename-list中。在我看來,引用只是不正確的支持。