rus*_*ner 0 python struct clone rust pyo3
我在 Rust 中有结构体,其中包含以下字段及其类型:
\n我的问题是如何加速这种结构的对象的克隆?\n现在我只使用
\nfn py_make_copy(&self) -> PyResult<Self> {\n Ok(self.clone())\n}\nRun Code Online (Sandbox Code Playgroud)\n它需要 4 到 6 \xc2\xb5s,这对我来说太慢了。我正在用 Python 测量它。\n不幸的是,我必须深度复制这些对象。
\n我不知道这是否相关,但我使用
\n#[pyclass(subclass)]\n#[derive(Clone)]\nRun Code Online (Sandbox Code Playgroud)\n定义此 Struct 和 #[pyo3(get)] 到所有字段时。
\n我尝试使用 par_iter 并行克隆,但它的持续时间比 py_make_copy 长得多。
\n我试图重现你的说法,这就是我得到的:
use std::{collections::HashMap, hint::black_box, time::Instant};
#[derive(Clone)]
pub struct MyStruct {
pub five_i8: [u8; 5],
pub six_f32: [f32; 6],
pub one_bool: bool,
pub vec1: Vec<u8>,
pub vec2: Vec<Vec<Vec<u8>>>,
pub vec3: Vec<Vec<u8>>,
pub hashmap: HashMap<i8, Vec<u8>>,
pub vec4: Vec<(i8, i8)>,
}
fn main() {
let mut s = MyStruct {
five_i8: [42u8; 5],
six_f32: [69.420; 6],
one_bool: true,
vec1: vec![42u8; 4],
vec2: Default::default(),
vec3: Default::default(),
hashmap: Default::default(),
vec4: vec![(1i8, 2i8); 30],
};
for i in 0..4 {
let mut x = vec![];
for _ in 0..20 {
x.push(vec![1u8; 7]);
}
s.vec2.push(x);
s.vec3.push(vec![42u8; 20]);
s.hashmap.insert(i, vec![2u8; 10]);
}
// Blackbox to prevent optimization
let s = black_box(s);
let start = Instant::now();
for _ in 0..10000 {
let s2 = s.clone();
black_box(s2);
}
let elapsed = start.elapsed();
println!("Time: {} us", elapsed.as_micros() / 10000);
}
Run Code Online (Sandbox Code Playgroud)
$ cargo run --release
Time: 17 us
Run Code Online (Sandbox Code Playgroud)
现在为什么这么慢?答案是:堆分配。其他一切都非常快。
结构中唯一执行堆分配的是HashMap和Vec。每个Vec和HashMap都是一个堆分配。
那么让我们看看:
vec1:1分配vec2:1 + 4 * (1 + 20) = 85分配vec3:1 + 4 = 5分配hashmap:1 + 4 = 5分配vec4:1分配这是分配总数97。
最简单的方法是将 更改Vec<Vec<Vec<>>>为单个扁平化Vec. 这将减少vec2并vec3减少到单个分配,以及分配的总数9。
像这样:
$ cargo run --release
Time: 17 us
Run Code Online (Sandbox Code Playgroud)
$ cargo run --release
Time: 1 us
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
208 次 |
| 最近记录: |