2013-07-23 4 views
6

Ich portiere etwas Physiksimulationscode von C++ zu CUDA.Wie man Polymorphismus in CUDA verwendet

Der fundamentale Algorithmus kann verstanden werden als: Anwenden eines Operators auf jedes Element eines Vektors. In Pseudo-Code kann eine Simulation die folgenden Kernel-Aufruf enthalten:

apply(Operator o, Vector v){ 
    ... 
} 

Zum Beispiel:

apply(add_three_operator, some_vector) 

würde in dem Vektor zu jedem Element drei hinzuzufügen.

In meinem C++ Code habe ich eine abstrakte Basisklasse Operator, mit vielen verschiedenen konkreten Implementierungen. Die wichtige Methode ist Klasse Operator { virtuelle Doppeloperation (Doppel x) = 0; Operator komponieren (Operator lo, Operator ro); ... }

Die Implementierung für AddOperator könnte wie folgt aussehen:

class AddOperator : public Operator{ 
    private: 
     double to_add; 
    public: 
     AddOperator(double to_add): to_add(to_add){} 
     double operator(double x){ 
      return x + to_add; 
     } 
}; 

Operator-Klasse verfügt über Methoden zur Skalierung und konkrete Implementierungen von Operator zu komponieren. Diese Abstraktion ermöglicht es mir, einfach "Blattoperatoren" zu allgemeineren Transformationen zusammenzufassen.

Zum Beispiel:

apply(compose(add_three_operator, square_operator), some_vector); 

füge hinzu, drei dann jedes Element des Vektors Quadrat.

Das Problem ist, dass CUDA virtuelle Methodenaufrufe im Kernel nicht unterstützt. Mein aktueller Gedanke ist es, Vorlagen zu verwenden. Dann werden Kernelaufrufe ungefähr wie folgt aussehen:

apply<Composition<AddOperator,SquareOperator>> 
    (compose(add_three_operator, square_operator), some_vector); 

Irgendwelche Vorschläge?

+6

Ich glaube 'virtual' Funktionen erfordern Kompilieren mit' -arch = sm_20' oder höher. Ich würde jedoch empfehlen, Ihren Polymorphismus auf den Host-Code zu isolieren, der den Kernel startet. Selbst wenn Sie schließlich Dinge kompilieren würden, würde ich erwarten, dass die Leistung des Versands virtueller Funktionen in SIMD-Code enttäuschend sein wird. –

+5

Ich stimme Jared zu. Selbst wenn in der CPU dieselben Operationen auf jedes Element großer Vektoren angewendet werden, würde ich eine Umgestaltung in Erwägung ziehen, so dass der Polymorphismus auf einer höheren Ebene liegt und die virtuellen Methodenaufrufe sich nicht in Ihren inneren Schleifen befinden. Sobald Sie dies tun, wird die Parallelisierung viel leistungsfähiger sein (in CUDA, OpenMP oder was auch immer). Sie könnten auch Thrust dafür in Erwägung ziehen. – harrism

+0

Danke für die Rückmeldung. Ich benutze eigentlich bereits Thrust. Ich gehe mit Vorlagen voran. – user2611717

Antwort

1

So etwas wie dies vielleicht ...

template <class Op1, class Op2> 
class Composition {...} 

template <class Op1, class Op2> 
Composition<Op1, Op2> compose(Op1& op1, Op2& op2) {...} 

template<class C> 
void apply(C& c, VecType& vec){...}