You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyO3从Rust调用Python函数的最优返回类型

关于PyO3中处理numpy数组的高性能方案

1. Array2 vs Vec<Vec>的性能差异

Array2(来自ndarray crate)的性能远优于Vec<Vec<usize>>。原因在于:

  • Vec<Vec<>>是嵌套堆分配,每行内存不连续,遍历时会频繁触发缓存失效,拖慢速度;
  • Array2采用连续内存布局,默认C顺序下整行数据在内存中是连续的,缓存命中率更高,大数量级遍历的速度提升非常明显。

2. 从numpy.ndarray转换为Array2的实现

首先在Cargo.toml中添加依赖:

[dependencies]
pyo3 = { version = "0.21", features = ["numpy"] }
ndarray = "0.15"
pyo3-numpy = "0.21"

然后在Rust代码中完成转换:

use pyo3::prelude::*;
use pyo3::types::PyArray2;
use ndarray::Array2;

#[pyfunction]
fn rust_func(py: Python, my_py_func: &PyAny) -> PyResult<()> {
    // 调用Python函数并提取numpy数组(注意类型匹配原dtype为int64,对应Rust的i64)
    let py_array: &PyArray2<i64> = my_py_func.call0()?.extract()?;
    
    // 零拷贝获取数组视图(性能最优,只读场景推荐)
    let array_view = py_array.as_array();
    // 如果需要修改数组,再拷贝为拥有所有权的Array2
    let mut array2 = array_view.to_owned();
    
    // 遍历行操作示例
    for row in array2.rows() {
        let val1 = row[0];
        let val2 = row[1];
        // 你的业务逻辑
    }

    Ok(())
}

注意:若原numpy数组是Fortran顺序(列优先),可通过.as_standard_layout()转为C顺序,进一步优化行遍历的缓存效率。

3. 适合output_array的高性能数据结构选择

根据后续操作场景选择:

  • 只读遍历行:优先用ArrayView2<i64>(零拷贝,直接复用Python数组内存),其次是Array2<i64>(连续内存,拷贝一次后遍历效率拉满);
  • 需要修改数组:Array2<i64>是最优解,连续内存布局在修改时同样能保证缓存效率;
  • 需与其他数值库交互:如果要对接nalgebra等线性代数库,可转换为nalgebra::Matrix<i64, Dynamic, Const<2>>,但ndarray与PyO3的生态适配性更好;
  • 类型注意事项:原numpy数组是int64,对应Rust的i64,不要随意用usize,避免跨架构的类型不匹配问题,除非你能确保数值范围不会超出usize的限制。

内容的提问来源于stack exchange,提问作者Abdullah Khalid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:02:42