likes
comments
collection
share

Rust(1) - 如何使用 Rust 使 Python 函数速度提高 5000%

作者站长头像
站长
· 阅读数 3

搬运一篇medium的看上去很x的文章:# This Is How You Make Your Python Functions 5000% Faster With Rust (Yes, You Read It Right!)

Rust 被大多数科技巨头广泛采用,甚至白宫现在也建议开发人员使用它来构建关键软件。Rust 对于来自 Python 等动态类型语言的开发人员来说可能具有挑战性。

寻找第 N 个素数:Python 实现

首先用 Python 编写一个函数来查找第 n 个素数(质数)

def is_prime(num):
    # 检查一个数是否是素数
    if num < 2:
        return False
    for i in range(2, num):
        if num % i == 0:
            return False
    return True

def find_nth_prime(n):
    # 找到第n个素数
    count = 0
    num = 1
    while count < n:
        num += 1
        if is_prime(num):
            count += 1
    return num

让我们使用这个函数计算第 50 个素数

#prime_finder.py

from timeit import timeit
import sys

# 上面的素数查找函数定义放在这里
# ...

def main():
    n = int(sys.argv[1]) #使用 CLI 接受数字

    print(f"Using Python => The {n} prime number is: {find_nth_prime(n)}")

    ITERATIONS = 100

    python_time_per_iter = timeit(
        lambda: find_nth_prime(n), number=ITERATIONS) / ITERATIONS

    print(
        f"Time taken using Python Prime finder: {python_time_per_iter* 1000:.2f} milliseconds per iteration.")

if __name__ == "__main__":
    main()

当我在终端中执行命令 python prime_finder.py 50 时,获得的响应如下所示

Rust(1) - 如何使用 Rust 使 Python 函数速度提高 5000% 我们的 Python 函数实现花了 0.64 毫秒来找到第 50 个素数

寻找第 N 个素数:Rust 实现

让我们用 Rust 重写相同的函数

fn is_prime_rust(num: u32) -> bool {
    if num < 2 {
        return false;
    }

    for i in 2..num {
        if num % i == 0 {
            return false;
        }
    }
    
    true
}

fn find_nth_prime_rust(n: u32) -> u32 {
    let mut count: u32 = 0;
    let mut num: u32 = 1;

    while count < n {
        num += 1;

        if is_prime_rust(num) {
            count += 1;
        }
    }

    num
}

在 Python 中集成 Rust 代码

第 1 步:初始化我们的项目

$ mkdir rust_prime_funcs && cd rust_prime_funcs # 创建项目目录

$ python -m venv env # 创建Python虚拟环境

$ source ./env/Scripts/activate # 激活虚拟环境

Step 2: 安装Maturin

接下来,我们使用 Maturin,这是一个工具,可以帮助我们构建和发布带有  pyo3、 rust-cpython 和 CFFI 绑定的 crate,以及 Rust 二进制文件作为 Python 包

$ pip install maturin  # 使用 pip 安装 maturi

$ maturin init # 初始化 maturin 并在出现提示时选择“pyo3”

Step 3: 使用 Rust 创建 Python 模块

// rust_prime_funcs/src/lib.rs

use pyo3::prelude::*;

// Rust 中的辅助函数
#[pyfunction]
fn is_prime_rust(num: u32) -> bool {
    if num < 2 {
        return false;
    }

    for i in 2..num {
        if num % i == 0 {
            return false;
        }
    }

    true
}

// Rust 中的第 N 个素数查找函数
#[pyfunction]
fn find_nth_prime_rust(n: u32) -> u32 {
    let mut count: u32 = 0;
    let mut num: u32 = 1;

    while count < n {
        num += 1;

        if is_prime_rust(num) {
            count += 1;
        }
    }

    num
}

/// 用 Rust 实现的 Python 模块
#[pymodule]
fn rust_prime_funcs(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(find_nth_prime_rust, m)?)?;
    Ok(())
}

Step 4: 构建 Python 模块

使用以下命令通过终端构建 Python 模块

$ maturin develop --release

Step 5: 比较 Python 与 Rust 函数性能

# rust_prime_funcs/test/prime_finder.py

import sys
from timeit import timeit

from rust_prime_funcs import find_nth_prime_rust

def is_prime(num):
    # 检查一个数是否是素数
    if num < 2:
        return False
    for i in range(2, num):
        if num % i == 0:
            return False
    return True

def find_nth_prime(n):
    # 找到第n个质数
    count = 0
    num = 1
    while count < n:
        num += 1
        if is_prime(num):
            count += 1
    return num

def main():
    n = int(sys.argv[1])

    print(f"\nUsing Python => The {n} prime number is: {find_nth_prime(n)}")
    print(f"Using Rust => The {n} prime number is: {find_nth_prime_rust(n)}")

    ITERATIONS = 100

    python_time_per_iter = timeit(
        lambda: find_nth_prime(n), number=ITERATIONS) / ITERATIONS

    rust_time_per_iter = timeit(
        lambda: find_nth_prime_rust(n), number=ITERATIONS) / ITERATIONS

    print(
        f"\nTime taken using Python Prime finder: {python_time_per_iter* 1000:.2f} milliseconds per iteration.")

    print(
        f"Time taken using Rust Prime finder: {rust_time_per_iter * 1000:.2f} milliseconds per iteration.")

    if python_time_per_iter > rust_time_per_iter:
        performance = (
            (python_time_per_iter - rust_time_per_iter) / rust_time_per_iter) * 100
        print(f"\nRust code is faster than Python by {performance:.2f}%\n")
    else:
        performance = (
            (rust_time_per_iter - python_time_per_iter) / python_time_per_iter) * 100
        print(f"\nPython code is faster than Rust by {performance:.2f}%\n")

if __name__ == "__main__":
    main()

执行后比较性能 Rust(1) - 如何使用 Rust 使 Python 函数速度提高 5000%

用于查找第 n 个素数的 Rust 函数比我们的 Python 实现快了 5264.74%,即几乎 53 倍。

上面这个例子是在 Python 代码中使用 Rust 的简单示例,但有一些重要的库要么提供 Python 到 Rust 代码的绑定,要么完全用 Rust 编写

比如:

  • orjson: 一个快速、正确的 Python JSON 库
  • pydantic: 一个流行的数据验证库
  • Polars: 用于高效数据操作和分析的快速 DataFrame 库
  • tokenizers: 由  Hugging Face 构建的快速高效的文本标记化和预处理
  • cryptography: 用于实现密码操作的库
  • PyOxidizer: 现代Python应用程序打包和分发工具
  • retworkx: 专为量子计算和其他科学应用而开发的高性能图形库