Rust 开发系列PyO3:Rust与Python的联动编程(下)

Posted 虾神说D

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust 开发系列PyO3:Rust与Python的联动编程(下)相关的知识,希望对你有一定的参考价值。

第四节:Rust PyO3与Python原生代码的效率对比

今天我们通过一系列代码和算法,来对比一下Rust PyO3编写的扩展与原生Python代码之间的效率。

对比的算法如下:

  1. 大浮点数运算,主要就测试浮点数的乘法和除法,这种计算不涉及算法的复杂性,存储是看编译器运行的效率。

  2. 浮点数累加运行,是一个标准的O(n)复杂度的算法,即:1+2+3+4... + n ,当然,你说我用高斯公式行不行,咱们这里做的测试,所以直接用暴力迭代法即可。主要测试的迭代的能力。

  3. 矩阵运算,这是一个0(n^2)复杂度的算法,我这里没有做二维矩阵运算(因为二维矩阵需要计算行列数量对应,麻烦的),而选用的测试用例是两个一维向量相乘,得到一个二维数组。还是测试的是迭代的能力。

  4. 素数与孪生素数的计算,这也是一个迭代的效率的对比。

素数也叫做质数,是指除1和本身以外,没有其他因数的数,是数论里面的一个非常经典的概念,我们耳熟能详的哥德巴赫猜想就是一道有关素数的题目。

而孪生素数,指的是两个素数之间真好相差为2的两个,例如3和5,5和7,11和13,这样的。 因为素数是随机的出现在数轴上的,几乎无法预测,要判定一个数是否是素数,只有从2开始,逐步排查,直到把所有的可能性都排除掉之后,才能直到是否是素数,这就代表更本没有捷径可循。

最后,随着数值变大,素数的分布会越来越稀松,那么是否存在一种可能性,当数字大到一定程度之后,素数就突然消失了呢?当然这个猜想在古希腊欧几里得时候就被证明了,素数是无穷的,无论大到什么级数,素数都不会消失。

那么就来了第二个猜想:素数的分布变稀松,那么孪生素数是否会消失呢?这个就是著名的“孪生素数猜想”,目前这个距离攻克这个猜想最近的人,是华裔数学家张益唐,他发表的论文,把两对孪生素数之间的距离缩小到了7000万,后来的数学家在他的理论上推导出,这数字可以小于246,即出现了一对孪生素数之后,在其后的246个数值之内,一定会出现第二对孪生素数。

有关素数的问题还是很有意思的,数学人类思维的极限运动之一,而数论则被称为数学皇冠上的明珠,有兴趣的同学可以自己去了解一下。

  1. 斐波拉契数列……这个是计算机算法的入门题,不做解释了。

以下是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的联动编程(下)

rust拓展包是什么内容

[from js to rust 系列][宏-01][官网文档 19.5]高级特性:宏[译文]

C++&Rust对比C++学习和运用Rust语言系列文章

C++&Rust对比C++学习和运用Rust语言系列文章

C++&Rust对比C++学习和运用Rust语言系列文章