2016-07-31 128 views
6

我想了解@jitclass修饰器如何与嵌套类一起工作。我写了两个虚拟类:fifi和toto fifi有一个toto属性。这两个类都有@jitclass装饰器,但是编译失败。下面的代码:如何嵌套numba jitclass

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 

一个启动代码的脚本:

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

当我运行该脚本,我获得[...]

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

请注意,如果我在'fifi'中删除了对'toto'的任何引用,代码就可以正常工作,并且由于numba我得到了x16的加速。

回答

5

可以使用jitclass作为另一个jitclass的成员,尽管这样做的方式没有很好的记录。您需要使用deferred_type实例。这可以在Numba 0.27以及更早的时候运行。更改fifi.py到:

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 

然后我得到的输出:

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

此功能可以在一些数据结构的更先进的jitclass例子可以看出,例如: