2016-07-31 36 views
6

Ich versuche zu verstehen, wie der @ jitclass-Dekorator mit verschachtelten Klassen arbeitet. Ich habe zwei Dummy-Klassen geschrieben: fifi und toto fifi hat ein Toto-Attribut. Beide Klassen haben den @ jitclass-Dekorator, aber die Kompilierung schlägt fehl. Hier ist der Code:Wie numba jitclass verschachteln

fifi.py

from numba import jitclass, float64 
from toto import toto 

spec = [('a',float64),('b',float64),('c',toto)] 

@jitclass(spec) 
class fifi(object): 
    def __init__(self, combis): 
    self.a = combis 
    self.b = 2 
    self.c = toto(combis) 

    def mySqrt(self,x): 
    s = x 
    for i in xrange(self.a): 
     s = (s + x/s)/2.0 
    return s 

toto.py:

from numba import jitclass,int32 

spec = [('n',int32)] 

@jitclass(spec) 
class toto(object): 
    def __init__(self,n): 
    self.n = 42 + n 

    def work(self,y): 
    return y + self.n 

Das Skript, das den Code startet:

from datetime import datetime 
from fifi import fifi 
from numba import jit 

@jit(nopython = True) 
def run(n,results): 
    for i in xrange(n): 
    q = fifi(200) 
    results[i+1] = q.mySqrt(i + 1) 

if __name__ == '__main__': 
    n = int(1e6) 
    results = [0.0] * (n+1) 
    starttime = datetime.now() 
    run(n,results) 
    endtime = datetime.now() 

    print("Script running time: %s"%str(endtime-starttime)) 
    print("Sqrt of 144 is %f"%results[145]) 

Als ich das Skript ausführen, ich get [...]

TypingError: Untyped global name 'toto' File "fifi.py", line 11

Beachten Sie, dass, wenn ich einen Verweis auf "Toto" in "FFi" entfernen, der Code funktioniert und ich eine x16-Geschwindigkeit dank numba erhalten.

Antwort

5

Es ist möglich, eine jitclass als Mitglied einer anderen jitclass zu verwenden, obwohl die Art, dies zu tun, nicht gut dokumentiert ist. Sie müssen eine deferred_type Instanz verwenden. Dies funktioniert in Numba 0.27 und möglicherweise früher. Ändern fifi.py an:

from numba import jitclass, float64, deferred_type 
from toto import toto 

toto_type = deferred_type() 
toto_type.define(toto.class_type.instance_type) 

spec = [('a',float64),('b',float64),('c',toto_type)] 

@jitclass(spec) 
class fifi(object): 
    def __init__(self, combis): 
    self.a = combis 
    self.b = 2 
    self.c = toto(combis) 

    def mySqrt(self,x): 
    s = x 
    for i in xrange(self.a): 
     s = (s + x/s)/2.0 
    return s 

ich dann als Ausgabe erhalten:

$ python test.py 
Script running time: 0:00:01.991600 
Sqrt of 144 is 12.041595 

Diese Funktion ist in einigen der fortgeschritteneren jitclass Beispiele von Datenstrukturen gesehen werden kann, zum Beispiel: