2017-05-30 2 views
1

die Klasse DOF Betrachten und sein Kind particleGroup:Numba jitclass: Elternklasse-Typ als Klassenmitglied

class dof(): 
    def getVar(self): 
     return self.var 

spec = [ 
    ('var', float64[:]), 
    ('C_s', float64[:]),   
] 
@jitclass(spec) 
class particleGroup(dof): 
    def __init__(self, partRelease): 
     self.var = np.array([partRelease.Q, partRelease.M[0], partRelease.M[1], partRelease.M[2], partRelease.B, partRelease.x[0], partRelease.x[1], partRelease.x[2], 0]) 
     self.C_s = np.copy(partRelease.C_s) 
    def getC(self): 
     return self.C_s 

Die Einzelheiten partRelease Objekt sind nicht wichtig.

Die Klasse dof ist eine Python-Klasse, da numba die Vererbung einer JIT-Klasse nicht unterstützt. Daher kann ein deferred_type nicht verwendet werden.

dof kann die Eltern verschiedener Unterklassen sein. Ich möchte die dof Klasse in einer anderen Klasse verwendet werden, wo ich in der Lage wäre, die übergeordnete Funktion getVar() aufrufen.

Meine Frage: Wie eine Instanz dieser Klasse (Dof-Typ oder einer der untergeordneten Typen) in einer anderen Klasse gespeichert? Welchen Typ soll ich in der jitclass-Spezifikation angeben?

Dann: Auch wenn ich den Elternklasse-Typ angeben kann, vermute ich, dass der Aufruf an eine Python-Klasse teuer sein wird. Gibt es einen anderen Weg, Polymorphismus effizient zu machen, z.B. Verwenden von Vorlagen anstelle von Vererbung?

Antwort

0

Ich fand eine Antwort (zumindest auf die zweite Frage).

Eine Lösung ist von Vorlagen inspiriert. Es besteht darin, keine Vererbung zu verwenden, sondern verschiedene Klassen mit den erforderlichen gemeinsamen Funktionen in ihrer Schnittstelle (hier getVar). Ich erhält und zum Beispiel unter Verwendung von Instanzen von Userclass verwenden kann

def createUserClass(dofType, dofObject): 
    dof_t = deferred_type() 
    dof_t.define(dofType) 
    spec = [ 
     ('dof', dof_t), 
    ] 
    @jitclass(spec) 
    class UserClass(): 
     def ___init__(self, dof): 
      self.dof = dof 
     def resetVar(self): 
      a = dof.getVar() 
      a[:] = 0 
    return UserClass(dofObject) 

Dann:

spec = [ 
('var', float64[:]), 
('C_s', float64[:]),   
] 
@jitclass(spec) 
class particleGroup(): 
    def __init__(self, val, valCs): 
     self.var = np.array([val, val, val, val]) 
     self.C_s = np.array([valCs, valCs*2, valCs*3, valCs*4]) 
    def getC(self): 
     return self.C_s 
    def getVar(self): 
     return self.var 

spec = [ 
    ('var', float64[:]), 
] 
@jitclass(spec) 
class otherDofType(): 
    def __init__(self): 
     self.var = np.array([1.0, 0.0]) 
    def getVar(self): 
     return self.var 

Wenn eine Klasse will die gemeinsame Funktionen für jede Art von Objekt verwenden, kann seine Definition in einer Funktion eingekapselt wird :

particleGroupInstance = particleGroup(6.0, 2.0) 
userObjectParticleGroup = createUserClass(particleGroup.class_type.instance_type, particleGroupInstance) 
userObjectParticleGroup.resetVar() 

otherDofTypeInstance = otherDofType() 
userObjectOtherDofType = createUserClass(otherDofType.class_type.instance_type, otherDofTypeInstance) 
userObjectOtherDofType.resetVar() 

Es ist ein bisschen schwer, aber funktioniert und sollte als jede auf Vererbung basierte Lösung schneller sein ...