Python中Numba库装饰器的具体使用
作者:知识在于积累
一、运行速度是Python天生的短板
1.1 编译型语言:C++
对于编译型语言,开发完成以后需要将所有的源代码都转换成可执行程序,比如 Windows 下的.exe文件,可执行程序里面包含的就是机器码。只要我们拥有可执行程序,就可以随时运行,不用再重新编译了,也就是“一次编译,无限次运行”。
在运行的时候,我们只需要编译生成的可执行程序,不再需要源代码和编译器了,所以说编译型语言可以脱离开发环境运行。
编译型语言一般是不能跨平台的,也就是不能在不同的操作系统之间随意切换。
1.2 解释型语言:Python
对于解释型语言,每次执行程序都需要一边转换一边执行,用到哪些源代码就将哪些源代码转换成机器码,用不到的不进行任何处理。每次执行程序时可能使用不同的功能,这个时候需要转换的源代码也不一样。
因为每次执行程序都需要重新转换源代码,所以解释型语言的执行效率天生就低于编译型语言,甚至存在数量级的差距。计算机的一些底层功能,或者关键算法,一般都使用 C/C++ 实现,只有在应用层面(比如网站开发、批处理、小工具等)才会使用解释型语言。
在运行解释型语言的时候,我们始终都需要源代码和解释器,所以说它无法脱离开发环境。
1.3 速度对比:C++比Python快25倍
我不会C++语言、也没有C++语言的运行的环境,借用网友的对比结果:
编译后,运行C++代码,生成全部13-mers共6700万个大约需要2.42秒。这意味着运行相同算法,Python用时是C++的25倍多。
二、Numba使用与否的对比,计算1000万以内的素数
2.1 原生Python,计算1000万以内的素数
def U27_1000W以内的素数(): import math import time def is_prime(num): if num == 2: return True if num <= 1 or num % 2 == 0: return False for div in range(3, int(math.sqrt(num) + 1), 2): if num % div == 0: return False return True def run_program(N): total = 0 for i in range(N): if is_prime(i): total += 1 return total # if __name__ == "__main__": N = 10000000 start = time.time() total = run_program(N) end = time.time() print(f"1000万以内所有的素数有 {total} 个") print(f"纯Python耗时: {end - start} 秒\b") return end - start
2.2 Numba装饰器,计算1000万以内的素数
def U28_1000W以内的素数_Numba装饰器(): import math import time from numba import njit, prange # @njit 相当于 @jit(nopython=True) @njit def is_prime(num): if num == 2: # 2为素数 return True if num <= 1 or num % 2 == 0: # 偶数中除了2都不是素数 return False for div in range(3, int(math.sqrt(num) + 1), 2): if num % div == 0: return False return True #使用Numba的prange来进行并发循环计算 @njit(parallel = True) def run_program(N): total = 0 #使用Numba提供的prange参数来进行并行计算 for i in prange(N): if is_prime(i): total += 1 return total # if __name__ == "__main__": N = 10000000 start = time.time() total = run_program(N) end = time.time() print(f"1000万以内所有的素数有 {total} 个") print(f"Numba装饰器耗时: {end - start} 秒\b") return end - start
2.3 实测速度:使用numba装饰器,速度提升 22.0 倍,逼近C++
t0 = U27_1000W以内的素数() t1 = U28_1000W以内的素数_Numba装饰器() print(f'使用numba装饰器,速度提升 {round(t0/t1, 0)} 倍') 1000万以内所有的素数有 664579 个 纯Python耗时: 86.78110885620117 秒 1000万以内所有的素数有 664579 个 Numba装饰器耗时: 3.9410934448242188 秒 使用numba装饰器,速度提升 22.0 倍
三、素数算法
质数也就是大于1的整数中,除了1和它本身以外不能被其他整数整除的数,也叫素数。
# 算法一:针对输入的数字x,我们可以遍历从2到x-1这个区间中的数,如果x能被这个区间中任意一个数整除,那么它就不是质数。 def is_prime1(x): for i in range(2, x): if x % i == 0: return False return True # 算法二:对算法一的优化,事实上只需要遍历从2到√x即可。 def is_prime2(x): for i in range(2, int(x ** 0.5) + 1): if x % i == 0: return False return True # 算法三:偶数中除了2都不是质数,且奇数的因数也没有偶数,因此可以进一步优化。 def is_prime3(x): if x == 2: return True elif x % 2 == 0: return False for i in range(3, int(x ** 0.5) + 1, 2): if x % i == 0: return False return True # 算法四:任何一个自然数,总可以表示成以下六种形式之一:6n,6n+1,6n+2,6n+3,6n+4,6n+5(n=0,1,2...)我们可以发现,除了2和3,只有形如6n+1和6n+5的数有可能是质数。且形如6n+1和6n+5的数如果不是质数,它们的因数也会含有形如6n+1或者6n+5的数,因此可以得到如下算法: def is_prime4(x): if (x == 2) or (x == 3): return True if (x % 6 != 1) and (x % 6 != 5): return False for i in range(5, int(x ** 0.5) + 1, 6): if (x % i == 0) or (x % (i + 2) == 0): return False return True
四、Numba
4.1 官方文档
numba 是一款可以将 python 函数编译为机器代码的JIT编译器,经过 numba 编译的python 代码(仅限数组运算),其运行速度可以接近 C 或 FORTRAN 语言。
官方文档链接:http://numba.pydata.org/numba-doc/latest/index.html
到此这篇关于Python中Numba库装饰器的具体使用的文章就介绍到这了,更多相关Python Numba库装饰器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!