Python Numba/jit条件和递归(堆栈)使用

Python Numba/jit条件和递归(堆栈)使用,python,jit,numba,Python,Jit,Numba,全部, 我使用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 f

全部,

我使用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()函数(基本上什么都不做),而不适用于从该函数调用的子例程

只有在对包含工作负载的函数应用@jit时,结果才会更好

是否有可能避免主程序中的包装函数和if子句

有没有办法告诉Numba优化从我的输入函数调用的子程序?因为run_it()还包含一些函数调用,我希望@jit能够处理这些调用

特写,
Ale

如果未安装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
其中
\u 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

我想你想用另一种方式来做这件事。与其包装该方法,不如选择将其命名为别名。例如,使用虚拟方法允许实际计时:

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
magic:

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该方法所需的时间。所有后续运行都会更快

谢谢,有没有办法告诉Numba优化从我的输入函数调用的子程序?因为run_it()还包含一些函数调用,我希望对这些函数调用也进行优化。@Ale-看它似乎没有什么需要做的,numba也应该递归到它们中并对它们进行优化(只要子例程也不使用任何不支持的构造)。然而,从我对文档的粗略阅读来看,似乎首选的做法是显式地修饰您的热函数,以便它们可以单独编译,而不是尝试
jit
您的整个运行时。(我从来没有用过麻木,所以我可能在这里打偏了)。太好了,谢谢。。。我花了一秒钟才找到第3行的打字错误:)