2015-04-12 34 views
4

所有,Python的Numba/JIT條件和遞歸(堆)使用

我使用numba JIT加快我的Python代碼,但是代碼應該是即使沒有安裝numba & LLVM的功能。

我的第一個想法是要做到這一點,如下所示:

use_numba = True 
try: 
    from numba import jit, int32 
except ImportError, e: 
    use_numba = False 

def run_it(parameters): 
    # do something 
    pass 

# define wrapper call function with optimizer 
@jit 
def run_it_with_numba(parameters): 
    return run_it(parameters) 

# [...] 
# main program 
t_start = timeit.default_timer() 

# this is the code I don't like 
if use_numba: 
    res = run_it_with_numba(parameters) 
else: 
    res = run_it(parameters) 

t_stop = timeit.default_timer() 
print "Numba: ", use_numba, " Time: ", t_stop - t_start 

,因爲我曾預計這是不行的,因爲編譯似乎只適用於run_it_with_numba()函數哪位基本上沒有nothing-但而不是從該函數調用的子例程。

結果只會變得更好,當我在包含工作量的功能應用@jit。

是否有機會避免包裝函數並在主程序中,如果從句?

有沒有辦法告訴給Numba還以優化從我進入函數調用子程序?因爲run_it()還包含一些函數調用,我期望@jit來處理這個問題。

立方米, 啤酒

回答

1

我認爲你想以不同的方式做到這一點。而不是包裝該方法,只需選擇別名即可。例如使用僞方法,以允許實際時間:

import numpy as np 
import timeit 

use_numba = False 
try: 
    import numba as nb 
except ImportError, e: 
    use_numba = False 

def _run_it(a, N): 
    s = 0.0 
    for k in xrange(N): 
     s += k/np.sin(a) 

    return s 

# define wrapper call function with optimizer 
if use_numba: 
    print 'Using numba' 
    run_it = nb.jit()(_run_it) 
else: 
    print 'Falling back to python' 
    run_it = _run_it 

if __name__ == '__main__': 
    print timeit.repeat('run_it(50.0, 100000)', setup='from __main__ import run_it', repeat=3, number=100) 

use_numba標誌運行此作爲True

$ python nbtest.py 
Using numba 
[0.18746304512023926, 0.15185213088989258, 0.1636970043182373] 

False

$ python nbtest.py 
Falling back to python 
[9.707707166671753, 9.779848098754883, 9.770231008529663] 

或IPython的筆記本使用nice %timeit法寶:

run_it_numba = nb.jit()(_run_it) 

%timeit _run_it(50.0, 10000) 
100 loops, best of 3: 9.51 ms per loop 

%timeit run_it_numba(50.0, 10000) 
10000 loops, best of 3: 144 µs per loop 

注意,定時numba方法時,定時的方法的單次執行將考慮到所花費的時間numba到JIT的方法。所有後續運行將更快。

+0

太好了,謝謝。 ...花了我一秒鐘找到第3行的錯字:) – Ale

4

可以在沒有安裝Numba的情況下提供的jit一個什麼都不做版本:

use_numba = True 
try: 
    from numba import jit, int32 
except ImportError, e: 
    use_numba = False 
    from _shim import jit, int32 

@jit 
def run_it(parameters): 
    # do something 
    pass 

# [...] 
# main program 
t_start = timeit.default_timer() 

res = run_it(eval(row[0]), workfeed, instrument) 

t_stop = timeit.default_timer() 
print "Numba: ", use_numba, " Time: ", t_stop - t_start 

_shim.py只包含:

def jit(*args, **kwargs): 
    def wrapper(f): 
     return f 
    if len(args) > 0 and (args[0] is marker or not callable(args[0])) \ 
     or len(kwargs) > 0: 
     # @jit(int32(int32, int32)), @jit(signature="void(int32)") 
     return wrapper 
    elif len(args) == 0: 
     # @jit() 
     return wrapper 
    else: 
     # @jit 
     return args[0] 

def marker(*args, **kwargs): return marker 

int32 = marker 
+0

謝謝你,有沒有辦法告訴給Numba還以優化從我進入函數調用子程序?因爲run_it()還包含一些函數調用,所以我想要優化這些函數。 – Ale

+0

@Ale - 看着[文檔](http://numba.pydata.org/numba-doc/0.18.1 /reference/pysupported.html#function-calls)它看起來並不需要做任何事情,numba *應該*遞歸到它們中並優化它們(只要子例程不使用任何不受支持的構造)。但是,從我粗略閱讀的文檔中,聽起來像*首選的*做的事情是明確裝飾你的熱門功能,以便它們單獨編譯,而不是試圖'jit'你的整個運行時。 (我從來沒有用過numba,所以我可能會在這裏離開基地)。 –