屠龙之技! 使用Rust加速你的Python
前言¶
默认读者已经习得 rust基础相关, 且掌握python基础语法
资料不多, 我也是小试牛刀
测试结果有一点疑问, 在长度越长的时候,使用指针操作数组,速度反而下降
1. 配置编译环境¶
1.1 创建rust模块¶
1.2 添加相应包¶
// Cargo.toml 添加
[lib]
name = "handle" // python中导入的名字,这里注意要和我们打包后的文件名一致
crate-type = ["cdylib"]
[dependencies.cpython] // rust打包python支持的so主要库
version = "0.5.*"
features = ["extension-module"]
2. rust代码实现¶
// lib.rs
use cpython::{PyResult, Python, py_module_initializer, py_fn, PyList, PyObject, PyDict};
// 注意此处名称和文件名统一
py_module_initializer!(handle, |py, m| {
m.add(py, "__doc__", "This module is implemented in Rust.")?;
m.add(py, "sum_as_string", py_fn!(py, sum_as_string_py(a: i64, b:i64)))?; // 注册
m.add(py, "bubble1", py_fn!(py, bubble1(li:Vec<i32>)))?; // 注册
m.add(py, "bubble2", py_fn!(py, bubble2(li:Vec<i32>)))?; // 注册
Ok(())
});
fn sum_as_string(a:i64, b:i64) -> String { //
format!("{}", a + b).to_string()
}
fn sum_as_string_py(_: Python, a:i64, b:i64) -> PyResult<String> {
let out = sum_as_string(a, b);
Ok(out)
}
// 做成泛型, 当在动态运行语言中运行的时候,性能较i32下降 3%(应该是打包so时编译器无法优化), 这里使用了 i32
fn bubble1(py: Python, mut li:Vec<i32>) -> PyResult<Vec<i32>>
{
let n = li.len();
for i in 0..n{
for j in 0..(n-i-1) {
if li[j] > li[j+1]{
let temp = li[j + 1];
li[j + 1] = li[j];
li[j] = temp;
}
}
}
Ok(li)
}
fn bubble2(py: Python, mut li:Vec<i32>) -> PyResult<Vec<i32>>
{
let li = &mut li;
let n = li.len();
for i in 0..n {
for j in 0..(n - i - 1) {
if li[j] > li[j + 1] {
let temp = li[j + 1];
li[j + 1] = li[j];
li[j] = temp;
}
}
};
Ok(li.to_vec())
}
2.1 build¶
cd handle
cargo build --release
cd target/release
mv ./libhandle.dylib ./handle.so // 注意编译之后需要手动重命名(!mac后缀为dylib需要改为so, win上为dll需要改为pyd)
python相关代码¶
条件: 长度1w 其内元素类型为i32类型的数组, 冒泡排序10次
import random
import time
# 此处默认py文件和编译且改名后的handle文件在同一目录
from handle import bubble2,bubble1
def get_li():
li = []
for i in range(10000):
li.append(random.randint(1, 100))
return li
def bubbleSort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
li = get_li()
st = time.perf_counter()
for i in range(10):
bubbleSort(li)
print(time.perf_counter() - st)
li = get_li()
st = time.perf_counter()
for i in range(10):
bubble1(li)
print(time.perf_counter() - st)
li = get_li()
st = time.perf_counter()
for i in range(10):
bubble2(li)
print(time.perf_counter() - st)