我有一个函数,想要使用 numba
进行编译,但是需要在该函数内部计算阶乘。不幸的是,numba
不支持 math.factorial
:
import math
import numba as nb
@nb.njit
def factorial1(x):
return math.factorial(x)
factorial1(10)
# UntypedAttributeError: Failed at nopython (nopython frontend)
我发现它支持math.gamma
(可用于计算阶乘),但与实际的math.gamma
函数相反,它不返回表示“整数值”的浮点数:
@nb.njit
def factorial2(x):
return math.gamma(x+1)
factorial2(10)
# 3628799.9999999995 <-- not exact
math.gamma(11)
# 3628800.0 <-- exact
相比于math.factorial
,它的速度较慢:
%timeit factorial2(10)
# 1.12 µs ± 11.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit math.factorial(10)
# 321 ns ± 6.12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
所以我决定定义自己的函数:
@nb.njit
def factorial3(x):
n = 1
for i in range(2, x+1):
n *= i
return n
factorial3(10)
# 3628800
%timeit factorial3(10)
# 821 ns ± 12.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
虽然它的速度比math.factorial
慢,但比基于math.gamma
的numba函数快,并且值是“精确”的。
所以我正在寻找一种最快的方法,在一个nopython numba函数内计算正整数(<=20;为避免溢出)的factorial
。
0..20
的阶乘,那么查找表可能值得检查以提高速度。 - High Performance Mark