numba fibonacci 函数速度较慢并且不会 return 相同的结果
The numba fibonacci function is slower and does not return the same result
此代码 return 速度慢且输出不同:
from numba import jit
from timeit import default_timer as timer
def fibonacci(n):
a, b = 1, 1
for i in range(n):
a, b = a+b, a
return a
fibonacci_jit = jit(fibonacci)
开始测试
start = timer()
print fibonacci(100)
duration = timer() - start
开始测试
startnext = timer()
print fibonacci_jit(100)
durationnext = timer() - startnext
print(duration, durationnext)
结果:
C:\Python27>python numba_test_003.py
927372692193078999176
1445263496
(0.00038264393810854576, 0.17378674127528523)
#下一个
C:\Python27>python numba_test_003.py
927372692193078999176
1445263496
(0.0004830358514597401, 0.19266426987655644)
因为您只 运行 一次 Numba jitted 函数,您看到的是 jit 编译时间和 运行 时间的总和。下次你 运行 numba 函数时,你只会看到 运行 时间,而且它会更快,因为 numba 缓存了每组唯一输入参数类型的编译代码:
startnext = timer()
print fibonacci_jit(100)
durationnext = timer() - startnext
print(duration, durationnext)
#5035488507601418376
#(0.0003879070281982422, 0.14705300331115723)
startnext = timer()
print fibonacci_jit(100)
durationnext = timer() - startnext
print(duration, durationnext)
#5035488507601418376
#(0.0003879070281982422, 0.0002810955047607422)
答案的差异是由于 Python 本机对象 int
是无限精度的,而 numba 使用的是容量有限的类 C 本机 int
并且可以溢出。如果您 运行 具有较小输入的函数,您应该会看到它一致,直到您溢出 numba int。
速度变慢的原因是编译时间。第一次调用未签名的 numba-jitted 函数时,它将检查类型并为这些参数编译函数。后续运行会更快,因为已经编译好了:
for _ in range(5):
start = timer()
fibonacci_jit(100)
print(timer() - start)
0.18958417814776496 # first run - includes compilation
6.1441049545862825e-06
3.3513299761978033e-06
3.3513299761978033e-06
3.3513299761978033e-06
但是,由于 numba 使用 C 类型,因此您的整数可能会溢出。您可以轻松检查类型:
fibonacci_jit.inspect_types()
fibonacci (int64,)
--------------------------------------------------------------------------------
# File: <ipython-input-19-a73271f1a552>
# --- LINE 3 ---
# label 0
# del $const0.1
# del [=11=].4
# del [=11=].2
# del [=11=].3
def fibonacci(n):
# --- LINE 4 ---
# n = arg(0, name=n) :: int64
# $const0.1 = const(tuple, (1, 1)) :: (int64 x 2)
# [=11=].4 = exhaust_iter(value=$const0.1, count=2) :: (int64 x 2)
# [=11=].2 = static_getitem(value=[=11=].4, index=0, index_var=None) :: int64
# [=11=].3 = static_getitem(value=[=11=].4, index=1, index_var=None) :: int64
# a = [=11=].2 :: int64
# b = [=11=].3 :: int64
# jump 8
# label 8
a, b = 1, 1
# --- LINE 5 ---
# jump 10
# label 10
# .1 = global(range: <class 'range'>) :: Function(<class 'range'>)
# .3 = call .1(n, func=.1, args=[Var(n, <ipython-input-19-a73271f1a552> (4))], kws=(), vararg=None) :: (int64,) -> range_state_int64
# del n
# del .1
# .4 = getiter(value=.3) :: range_iter_int64
# del .3
# $phi18.1 = .4 :: range_iter_int64
# del .4
# jump 18
# label 18
# .2 = iternext(value=$phi18.1) :: pair<int64, bool>
# .3 = pair_first(value=.2) :: int64
# .4 = pair_second(value=.2) :: bool
# del .2
# $phi20.1 = .3 :: int64
# $phi38.1 = .3 :: int64
# del $phi38.1
# del .3
# $phi38.2 = $phi18.1 :: range_iter_int64
# del $phi38.2
# branch .4, 20, 38
# label 20
# del .4
# i = $phi20.1 :: int64
# del i
# del $phi20.1
# del .4
# del $a20.5
for i in range(n):
# --- LINE 6 ---
# .4 = a + b :: int64
# $a20.5 = a :: int64
# a = .4 :: int64
# b = $a20.5 :: int64
# jump 18
# label 38
# del b
# del $phi20.1
# del $phi18.1
# del .4
# jump 40
# label 40
# del a
a, b = a+b, a
# --- LINE 7 ---
# .2 = cast(value=a) :: int64
# return .2
return a
================================================================================
至少在我的电脑上它使用 int64
,所以最大可能值为 9223372036854775807
。你不能用 numba 解决这个问题。如果你需要任意精度的整数,你必须坚持 Python.
此代码 return 速度慢且输出不同:
from numba import jit
from timeit import default_timer as timer
def fibonacci(n):
a, b = 1, 1
for i in range(n):
a, b = a+b, a
return a
fibonacci_jit = jit(fibonacci)
开始测试
start = timer()
print fibonacci(100)
duration = timer() - start
开始测试
startnext = timer()
print fibonacci_jit(100)
durationnext = timer() - startnext
print(duration, durationnext)
结果:
C:\Python27>python numba_test_003.py
927372692193078999176
1445263496
(0.00038264393810854576, 0.17378674127528523)
#下一个
C:\Python27>python numba_test_003.py
927372692193078999176
1445263496
(0.0004830358514597401, 0.19266426987655644)
因为您只 运行 一次 Numba jitted 函数,您看到的是 jit 编译时间和 运行 时间的总和。下次你 运行 numba 函数时,你只会看到 运行 时间,而且它会更快,因为 numba 缓存了每组唯一输入参数类型的编译代码:
startnext = timer()
print fibonacci_jit(100)
durationnext = timer() - startnext
print(duration, durationnext)
#5035488507601418376
#(0.0003879070281982422, 0.14705300331115723)
startnext = timer()
print fibonacci_jit(100)
durationnext = timer() - startnext
print(duration, durationnext)
#5035488507601418376
#(0.0003879070281982422, 0.0002810955047607422)
答案的差异是由于 Python 本机对象 int
是无限精度的,而 numba 使用的是容量有限的类 C 本机 int
并且可以溢出。如果您 运行 具有较小输入的函数,您应该会看到它一致,直到您溢出 numba int。
速度变慢的原因是编译时间。第一次调用未签名的 numba-jitted 函数时,它将检查类型并为这些参数编译函数。后续运行会更快,因为已经编译好了:
for _ in range(5):
start = timer()
fibonacci_jit(100)
print(timer() - start)
0.18958417814776496 # first run - includes compilation
6.1441049545862825e-06
3.3513299761978033e-06
3.3513299761978033e-06
3.3513299761978033e-06
但是,由于 numba 使用 C 类型,因此您的整数可能会溢出。您可以轻松检查类型:
fibonacci_jit.inspect_types()
fibonacci (int64,)
--------------------------------------------------------------------------------
# File: <ipython-input-19-a73271f1a552>
# --- LINE 3 ---
# label 0
# del $const0.1
# del [=11=].4
# del [=11=].2
# del [=11=].3
def fibonacci(n):
# --- LINE 4 ---
# n = arg(0, name=n) :: int64
# $const0.1 = const(tuple, (1, 1)) :: (int64 x 2)
# [=11=].4 = exhaust_iter(value=$const0.1, count=2) :: (int64 x 2)
# [=11=].2 = static_getitem(value=[=11=].4, index=0, index_var=None) :: int64
# [=11=].3 = static_getitem(value=[=11=].4, index=1, index_var=None) :: int64
# a = [=11=].2 :: int64
# b = [=11=].3 :: int64
# jump 8
# label 8
a, b = 1, 1
# --- LINE 5 ---
# jump 10
# label 10
# .1 = global(range: <class 'range'>) :: Function(<class 'range'>)
# .3 = call .1(n, func=.1, args=[Var(n, <ipython-input-19-a73271f1a552> (4))], kws=(), vararg=None) :: (int64,) -> range_state_int64
# del n
# del .1
# .4 = getiter(value=.3) :: range_iter_int64
# del .3
# $phi18.1 = .4 :: range_iter_int64
# del .4
# jump 18
# label 18
# .2 = iternext(value=$phi18.1) :: pair<int64, bool>
# .3 = pair_first(value=.2) :: int64
# .4 = pair_second(value=.2) :: bool
# del .2
# $phi20.1 = .3 :: int64
# $phi38.1 = .3 :: int64
# del $phi38.1
# del .3
# $phi38.2 = $phi18.1 :: range_iter_int64
# del $phi38.2
# branch .4, 20, 38
# label 20
# del .4
# i = $phi20.1 :: int64
# del i
# del $phi20.1
# del .4
# del $a20.5
for i in range(n):
# --- LINE 6 ---
# .4 = a + b :: int64
# $a20.5 = a :: int64
# a = .4 :: int64
# b = $a20.5 :: int64
# jump 18
# label 38
# del b
# del $phi20.1
# del $phi18.1
# del .4
# jump 40
# label 40
# del a
a, b = a+b, a
# --- LINE 7 ---
# .2 = cast(value=a) :: int64
# return .2
return a
================================================================================
至少在我的电脑上它使用 int64
,所以最大可能值为 9223372036854775807
。你不能用 numba 解决这个问题。如果你需要任意精度的整数,你必须坚持 Python.