欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Rust實(shí)現(xiàn)Python加速的技巧分享

 更新時(shí)間:2023年09月12日 11:22:05   作者:shelgi  
這篇文章主要想來(lái)和大家一起探討一下關(guān)于使用Rust對(duì)Python計(jì)算進(jìn)行加速的問(wèn)題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

背景

長(zhǎng)期以來(lái),Python由于易上手,有GC且生態(tài)強(qiáng)大等特點(diǎn)被廣泛使用,可是漸漸的人們也發(fā)現(xiàn)了它的不足,解釋型語(yǔ)言的運(yùn)行速度終究比不過(guò)編譯型,況且由于Python設(shè)計(jì)時(shí)的動(dòng)態(tài)數(shù)據(jù)類型一切皆對(duì)象(內(nèi)存都分配在堆上)等思想,也導(dǎo)致了運(yùn)行速度緩慢.

隨著實(shí)時(shí)性要求的不斷提升,在一些計(jì)算量大要求快速響應(yīng)的場(chǎng)景傳統(tǒng)的Python就很難滿足要求,所以隨之慢慢有了各種解決辦法:

  • 用更高效的解釋器
  • 用jit即時(shí)編譯加速
  • 改寫(xiě)成Cython加速
  • 對(duì)GIL動(dòng)手,提高多線程性能

其中目前使用最廣泛,最有效的應(yīng)該是jit與Cython這兩種方案,jit即時(shí)編譯可以將部分需要解釋的代碼直接轉(zhuǎn)為機(jī)器碼從而實(shí)現(xiàn)加速(減少解釋時(shí)開(kāi)銷);而Cython更絕直接將Python原地升級(jí),得到一個(gè)Cython這個(gè)Python與C的混血,可以通過(guò)Cython將代碼翻譯成C/C++的代碼再編譯成動(dòng)態(tài)庫(kù)文件供使用.可是這樣就會(huì)造成Python原本的語(yǔ)法被改的“四不像”,這些后面慢慢再談.

既然都用上動(dòng)態(tài)庫(kù)了,為什么不直接使用C++或者其他高效語(yǔ)言實(shí)現(xiàn),然后供Python調(diào)用呢?說(shuō)到底,Cython不也是翻譯成C/C++的代碼編譯使用,只是為了方便Python開(kāi)發(fā)人員才設(shè)計(jì)了這種類似于Python的語(yǔ)法.如果熟悉其他語(yǔ)言的話完全可以直接使用其他語(yǔ)言實(shí)現(xiàn)而不影響Python的基本語(yǔ)法.所以今天就來(lái)討論一下關(guān)于使用Rust對(duì)Python計(jì)算進(jìn)行加速的問(wèn)題.

Rust加速Python計(jì)算

首先,來(lái)看看Rust實(shí)現(xiàn)和Python實(shí)現(xiàn)基本的速度對(duì)比,目標(biāo)是求斐波那契數(shù)列第n項(xiàng)的值.其中實(shí)現(xiàn)均采用遞歸調(diào)用,為了突出時(shí)間差異這里求第30項(xiàng)的值并重復(fù)50次

Python的實(shí)現(xiàn)與耗時(shí)如下:

import time
?
def fib(n:int) ->int:
 ? ?assert n>=0
 ? ?if n <= 1:
 ? ? ? ?return n
 ? ?return fib(n-1)+fib(n-2)
?
def main(test_times=50):
 ? ?start = time.time()
 ? ?for _ in range(test_times):
 ? ? ? ?fib(30)
 ? ?print(f"time cost {time.time()-start} s")
?
if __name__ == '__main__':
 ? ?main()

Rust的實(shí)現(xiàn)與耗時(shí)如下:

use std::time;
?
fn fib(n:i32)->u64{
 ? ?if n<=0{
 ? ? ? ?panic!("{} must be a postive number!",n);
 ?  }
 ? ?match n{
 ? ? ? ?1|2 => 1,
 ? ? ? ?_ => fib(n-1) + fib(n-2)
 ?  }
}
?
fn main() {
 ? ?let test_times = 50;
 ? ?let start = time::Instant::now();
 ? ?for i in 0..test_times{
 ? ? ? ?fib(30);
 ?  }
 ? ?println!("time cost {:?}",start.elapsed())
}
?

這差異,足足一百多倍.那看來(lái)使用Rust提速是完全可行的,那怎么將Rust與Python相結(jié)合呢?或者如何把Rust的代碼編譯供Python調(diào)用,這個(gè)時(shí)候可以使用pyo3,首先安裝一下maturin工具pip install maturin,然后配置一下項(xiàng)目的Cargo.toml

[package]
name = "speedup_python"
version = "0.1.0"
edition = "2021"
?
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
?
[lib]
name = "speed_python"
crate-type = ["cdylib"]
?
[dependencies]
pyo3 = { version = "0.19.2", features = ["extension-module"] }

這里編譯類型就設(shè)置為lib,關(guān)于多種不同lib類型的區(qū)別可以去看看Rust專欄之前的內(nèi)容.這里的name就是未來(lái)Python中調(diào)用的名字,下面再編寫(xiě)lib.rs

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
?
#[pyfunction]
pub fn fib(n:i32)->u64{
 ? ?if n<=0{
 ? ? ? ?panic!("{} must be a postive number!",n);
 ?  }
 ? ?match n{
 ? ? ? ?1|2 => 1,
 ? ? ? ?_ => fib(n-1) + fib(n-2)
 ?  }
}
?
#[pymodule]
fn speed_python(_py:Python,m:&PyModule)->PyResult<()>{
 ? ?m.add_wrapped(wrap_pyfunction!(fib))?;
 ? ?Ok(())
}

邏輯代碼基本沒(méi)有更改,只是添加了Rust實(shí)現(xiàn)Python module的代碼,這里的module name必須和toml中設(shè)置的name保持一致,否則也會(huì)無(wú)法導(dǎo)入.

最后運(yùn)行maturin develop就可以實(shí)現(xiàn)編譯,給Python調(diào)用了.

加速對(duì)比

現(xiàn)在,我們已經(jīng)實(shí)現(xiàn)了Rust的加速,是不是非常簡(jiǎn)單而且調(diào)用的時(shí)候可以使用原本的Python語(yǔ)法而不用進(jìn)行任何更改.下面就來(lái)對(duì)比一下原始,numba,Cython,Rust四種方式的速度對(duì)比.

其中Cython實(shí)現(xiàn)cpy_fib.pyx如下

cpdef int c_fib(n:int):
 ? ?assert n>0
 ? ?if n in [1, 2]:
 ? ? ? ?return 1
 ? ?else:
 ? ? ? ?return c_fib(n - 1) + c_fib(n - 2)

然后寫(xiě)setup進(jìn)行編譯

from distutils.core import setup,Extension
from Cython.Build import cythonize
?
setup(
 ? ?ext_modules=cythonize(Extension(
 ? ? ? ?'cpy_fib',
 ? ? ? ?sources=['./cpy_fib.pyx'],
 ? ? ? ?language='c'
 ?  )),
)

運(yùn)行python setup.py build_ext --inplace編譯,最后整體對(duì)比

import speed_python
import time
from cpy_fib import c_fib
from numba import jit
?
?
@jit(nopython=True)
def fib_jit(n: int) -> int:
 ? ?assert n > 0
 ? ?if n in [1, 2]:
 ? ? ? ?return 1
 ? ?else:
 ? ? ? ?return fib_jit(n - 1) + fib_jit(n - 2)
?
def fib(n: int) -> int:
 ? ?assert n > 0
 ? ?if n in [1, 2]:
 ? ? ? ?return 1
 ? ?else:
 ? ? ? ?return fib(n - 1) + fib(n - 2)
?
?
def test_speed(func,func_name:str,test_times=50):
 ? ?start = time.time()
 ? ?for _ in range(test_times):
 ? ? ? ?func(30)
 ? ?print(f"{func_name} speed up time cost {time.time() - start} s")
?
?
def main(test_times=50):
 ? ?test_speed(fib,"origin python")
 ? ?test_speed(fib_jit,"numba python")
 ? ?test_speed(speed_python.fib,"rust")
 ? ?test_speed(c_fib,"Cython")
?
?
if __name__ == '__main__':
 ? ?main()

當(dāng)然如果希望進(jìn)一步加速,我們還是有辦法的.使用maturin develop --release生成Rust的調(diào)用,再來(lái)比較一下計(jì)算耗時(shí),速度又提升了一倍多

加速方法耗時(shí)(ms)
原始4144
Numba441
Cython804
Rust178 / 61

這加速對(duì)比也證明了在一些計(jì)算任務(wù)中Rust能更高效的實(shí)現(xiàn),并且不影響原始Python的代碼語(yǔ)法或者結(jié)構(gòu),只需要編譯調(diào)用.完全可以分配不同開(kāi)發(fā)人員同時(shí)開(kāi)發(fā),最后整合測(cè)試調(diào)用即可.

到此這篇關(guān)于利用Rust實(shí)現(xiàn)Python加速的技巧分享的文章就介紹到這了,更多相關(guān)Python加速內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python學(xué)習(xí)之路安裝pycharm的教程詳解

    Python學(xué)習(xí)之路安裝pycharm的教程詳解

    pycharm 是一款功能強(qiáng)大的 Python 編輯器,具有跨平臺(tái)性。這篇文章主要介紹了Python學(xué)習(xí)之路安裝pycharm的教程,本文分步驟通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Python 限定函數(shù)參數(shù)的類型及默認(rèn)值方式

    Python 限定函數(shù)參數(shù)的類型及默認(rèn)值方式

    今天小編就為大家分享一篇Python 限定函數(shù)參數(shù)的類型及默認(rèn)值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • Python編程實(shí)現(xiàn)正則刪除命令功能

    Python編程實(shí)現(xiàn)正則刪除命令功能

    這篇文章主要介紹了Python編程實(shí)現(xiàn)正則刪除命令功能,涉及Python針對(duì)文件與目錄的正則匹配、刪除等相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • python網(wǎng)絡(luò)編程 使用UDP、TCP協(xié)議收發(fā)信息詳解

    python網(wǎng)絡(luò)編程 使用UDP、TCP協(xié)議收發(fā)信息詳解

    這篇文章主要介紹了python網(wǎng)絡(luò)編程 使用UDP、TCP協(xié)議收發(fā)信息詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • pandas 按照特定順序輸出的實(shí)現(xiàn)代碼

    pandas 按照特定順序輸出的實(shí)現(xiàn)代碼

    這篇文章主要介紹了pandas 按照特定順序輸出的實(shí)現(xiàn)代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07
  • 利用Python開(kāi)發(fā)微信支付的注意事項(xiàng)

    利用Python開(kāi)發(fā)微信支付的注意事項(xiàng)

    如今支付的引入是很多互聯(lián)網(wǎng)產(chǎn)品都需要的。為了讓用戶用著更方便快捷,集成像支付寶、微信支付這樣的第三方支付也就成了常有的事。今天跟著小編就來(lái)看看微信支付開(kāi)發(fā)中幾個(gè)值得注意的地方,涉及代碼之處均用 Python 編寫(xiě)。
    2016-08-08
  • Python 過(guò)濾字符串的技巧,map與itertools.imap

    Python 過(guò)濾字符串的技巧,map與itertools.imap

    Python中的map函數(shù)非常有用,在字符轉(zhuǎn)換和字符遍歷兩節(jié)都出現(xiàn)過(guò),現(xiàn)在,它又出現(xiàn)了,會(huì)給我們帶來(lái)什么樣的驚喜呢?是不是要告訴我們,map是非常棒的,以后要多找它玩呢?
    2008-09-09
  • Python合并字符串的3種方法

    Python合并字符串的3種方法

    這篇文章主要介紹了Python合并字符串的3種方法,本文講解了使用+=操作符、使用%操作符、使用String的' '.join()方法3種方法,需要的朋友可以參考下
    2015-05-05
  • python利用lxml讀寫(xiě)xml格式的文件

    python利用lxml讀寫(xiě)xml格式的文件

    這篇文章主要為大家詳細(xì)介紹了python利用lxml讀寫(xiě)xml格式的文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • python 生成器協(xié)程運(yùn)算實(shí)例

    python 生成器協(xié)程運(yùn)算實(shí)例

    下面小編就為大家?guī)?lái)一篇python 生成器協(xié)程運(yùn)算實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09

最新評(píng)論