Rust 开发系列PyO3:Rust与Python的联动编程(下)
Posted 虾神说D
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust 开发系列PyO3:Rust与Python的联动编程(下)相关的知识,希望对你有一定的参考价值。
第四节:Rust PyO3与Python原生代码的效率对比
今天我们通过一系列代码和算法,来对比一下Rust PyO3编写的扩展与原生Python代码之间的效率。
对比的算法如下:
-
大浮点数运算,主要就测试浮点数的乘法和除法,这种计算不涉及算法的复杂性,存储是看编译器运行的效率。
-
浮点数累加运行,是一个标准的O(n)复杂度的算法,即:1+2+3+4... + n ,当然,你说我用高斯公式行不行,咱们这里做的测试,所以直接用暴力迭代法即可。主要测试的迭代的能力。
-
矩阵运算,这是一个0(n^2)复杂度的算法,我这里没有做二维矩阵运算(因为二维矩阵需要计算行列数量对应,麻烦的),而选用的测试用例是两个一维向量相乘,得到一个二维数组。还是测试的是迭代的能力。
-
素数与孪生素数的计算,这也是一个迭代的效率的对比。
素数也叫做质数,是指除1和本身以外,没有其他因数的数,是数论里面的一个非常经典的概念,我们耳熟能详的哥德巴赫猜想就是一道有关素数的题目。
而孪生素数,指的是两个素数之间真好相差为2的两个,例如3和5,5和7,11和13,这样的。 因为素数是随机的出现在数轴上的,几乎无法预测,要判定一个数是否是素数,只有从2开始,逐步排查,直到把所有的可能性都排除掉之后,才能直到是否是素数,这就代表更本没有捷径可循。
最后,随着数值变大,素数的分布会越来越稀松,那么是否存在一种可能性,当数字大到一定程度之后,素数就突然消失了呢?当然这个猜想在古希腊欧几里得时候就被证明了,素数是无穷的,无论大到什么级数,素数都不会消失。
那么就来了第二个猜想:素数的分布变稀松,那么孪生素数是否会消失呢?这个就是著名的“孪生素数猜想”,目前这个距离攻克这个猜想最近的人,是华裔数学家张益唐,他发表的论文,把两对孪生素数之间的距离缩小到了7000万,后来的数学家在他的理论上推导出,这数字可以小于246,即出现了一对孪生素数之后,在其后的246个数值之内,一定会出现第二对孪生素数。
有关素数的问题还是很有意思的,数学人类思维的极限运动之一,而数论则被称为数学皇冠上的明珠,有兴趣的同学可以自己去了解一下。
- 斐波拉契数列……这个是计算机算法的入门题,不做解释了。
以下是Rust的编写的代码部分,算法非常老土,因为做的测试,所以直接暴力迭代了,里面很多实现实际上是有优化算法的,这里暂时忽略。
Python的代码部分,基本上就的Rust代码的复刻了,我们可以对比一下,Python的代码量与Rust的代码量几乎差不多,所以Rust号称要让程序员们写起来很舒服,语法简洁程度基本上是在对齐Python的……
(Rust不是号称最难学的语言之一么……我信你个鬼,你这个老头子坏的很……)
下面是对比测试结论:
第一个对比,就狠狠的给Rust来了个下马威,如果仅仅看简单计算,Python原生的速度几乎要比Rust编写的扩展要快2倍……
因为Python原生的底层基础库,可是用C语言编写的,而你要在这个底层上还要在封装在做转换,那肯定是有要额外的开销的。
然后看看有迭代的计算,这下差距就出来了……
我们可以看见Rust PyO3扩展编写的代码,比原生态的Python代码,在同等条件下的运算,速度从几倍到几万倍的提升不等……这个效率着实阔怕。
众所周知,Python有一个优点,也是它的缺点,就是所有代码属于动态编译,即在运行的时候,才去编译,这样有很强的灵活性,但是从编译到执行,会有一个比较大时间开销,这就是Python慢的原因了。
鉴于此,就出现了用于Python的静态编译技术,即Python的即时编译器numba,用这个包,可以对Python的代码进行即时编译,这样就节约了大量的动态编译时间,理论上可以极高效的提高Python的执行效率。
用官方的话说:
Python 程序中由 Numba 编译的数值算法,可以接近使用编译后的 C 语言或 FORTRAN 语言编写的程序的速度;并且与原生 Python 解释器执行的相同程序相比,运行速度最多快 100 倍。这是一项重要进步,推动了高效编程与高性能计算的完美结合。
经过Numba的JIT编译之后,我们发现,在素数判定和孪生素数计算上,它甚至比Rust PyO3的效率更好!
那么有了Numba,我们还需要Rust扩展么?用官方的说法:
Numba仅能支持原生Python函数,以及部分numpy函数,其他高层封装基本上不支持,如pandas、sklearn等
下面我们来试试Python的高层封装包,以Pandas为例:
两边的代码如下:
Python部分:
JIT部分:
Rust部分: 配置:
代码部分:
结果:
测试中,可以看出来,numba.jit对于Pandas包有一定的性能提升,但是并不是很明显,提升能力不到20%……
而用Rust Pyo3编写的groupby功能,则是他们二则的10倍以上。
最后总结:
以上是关于Rust 开发系列PyO3:Rust与Python的联动编程(下)的主要内容,如果未能解决你的问题,请参考以下文章
Rust 开发系列PyO3:Rust与Python的联动编程(下)