本篇内容介绍了“Python比C++快吗”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

众所周知,Python 是动态语言,有全局解释器锁,比其他静态语言要慢,也正是这个原因,你也许会转向其他语言如 Java、C++,不过先等等,今天分享一个可以让 Python 比 C++ 还要快的技术,看完再决定要不要转吧。
今天的主角就是 Numba,Numba 是一个开源的即时编译器(JIT compiler),可将 Python 和 NumPy 的代码的转换为快速的机器码,从而提升运行速度。可以达到 C 或 FORTRAN 的速度。这么牛逼是不是很难用呢?No,No,No,So easy,你不需要替换 Python 解释器,不需要单独编译,甚至不需要安装 C / C ++ 编译器。只需将 Numba 提供的装饰器放在 Python 函数上面就行,剩下的就交给 Numba 完成。举个简单的例子:

fromnumbaimportjitimportrandom@jit(nopython=True)defmonte_carlo_pi(nsamples):acc=0foriinrange(nsamples):x=random.random()y=random.random()if(x**2+y**2)<1.0:acc+=1return4.0*acc/nsamples

Numba 是专为科学计算而设计的,在与 NumPy 一起使用时,Numba 会为不同的数组数据类型生成专门的代码,以优化性能:

@numba.jit(nopython=True,parallel=True)deflogistic_regression(Y,X,w,iterations):foriinrange(iterations):w-=np.dot(((1.0/(1.0+np.exp(-Y*np.dot(X,w)))-1.0)*Y),X)returnw

现在我们来看看,同样的代码,使用 Numba 前后与 C++ 的性能对比。比如说我们要找出 1000 万以内所有的素数,代码的算法逻辑是相同的:Python 代码:

importmathimporttimedefis_prime(num):ifnum==2:returnTrueifnum<=1ornotnum%2:returnFalsefordivinrange(3,int(math.sqrt(num)+1),2):ifnotnum%div:returnFalsereturnTruedefrun_program(N):total=0foriinrange(N):ifis_prime(i):total+=1returntotalif__name__=="__main__":N=10000000start=time.time()total=run_program(N)end=time.time()print(f"totalprimenumis{total}")print(f"cost{end-start}s")

执行耗时:

totalprimenumis664579cost47.386465072631836s

C++ 代码如下:

#include<iostream>#include<cmath>#include<time.h>usingnamespacestd;boolisPrime(intnum){if(num==2)returntrue;if(num<=1||num%2==0)returnfalse;doublesqrt_num=sqrt(double(num));for(intdiv=3;div<=sqrt_num;div+=2){if(num%div==0)returnfalse;}returntrue;}intrun_program(intN){inttotal=0;for(inti;i<N;i++){if(isPrime(i))total++;}returntotal;}intmain(){intN=10000000;clock_tstart,end;start=clock();inttotal=run_program(N);end=clock();cout<<"totalprimenumis"<<total;cout<<"\ncost"<<(end-start)/((double)CLOCKS_PER_SEC)<<"s\n";return0;}

$g++isPrime.cpp-oisPrime$./isPrimetotalprimenumis664579cost2.36221s


c++ C++ 确实牛逼,才 2.3 秒,不过好戏还在后头,现在我们使用 Numba 来加速一下,操作很简单,不需要改动原有的代码,先导入 Numba 的 njit,再在函数上方放个装饰器 @njit 即可,其他保持不变,代码如下:

importmathimporttimefromnumbaimportnjit#@njit相当于@jit(nopython=True)@njitdefis_prime(num):ifnum==2:returnTrueifnum<=1ornotnum%2:returnFalsefordivinrange(3,int(math.sqrt(num)+1),2):ifnotnum%div:returnFalsereturnTrue@njitdefrun_program(N):total=0foriinrange(N):ifis_prime(i):total+=1returntotalif__name__=="__main__":N=10000000start=time.time()total=run_program(N)end=time.time()print(f"totalprimenumis{total}")print(f"cost{end-start}s")

运行一下,可以看出时间已经从 47.39 秒降低到 3 秒。

totalprimenumis664579cost3.0948808193206787s

相比 C++ 的 2.3 秒还是有一点慢,你可能会说 Python 还是不行啊。等一等,我们还有优化的空间,就是 Python 的 for 循环,那可是 1000 万的循环,对此,Numba 提供了prange 参数来并行计算,从而并发处理循环语句,只需要将 range 修改为 prange,装饰器传个参数:parallel = True,其他不变,代码改动如下:

importmathimporttimefromnumbaimportnjit,prange@njitdefis_prime(num):ifnum==2:returnTrueifnum<=1ornotnum%2:returnFalsefordivinrange(3,int(math.sqrt(num)+1),2):ifnotnum%div:returnFalsereturnTrue@njit(parallel=True)defrun_program(N):total=0foriinprange(N):ifis_prime(i):total+=1returntotalif__name__=="__main__":N=10000000start=time.time()total=run_program(N)end=time.time()print(f"totalprimenumis{total}")print(f"cost{end-start}s")

现在运行一下:

pythonisPrime.pytotalprimenumis664579cost1.4398791790008545s

才 1.43 秒,比 C++ 还快,Numba 真的牛逼!我又运行了两次,确认自己没看错,平均就是 1.4 秒

“Python比C++快吗”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!