gpt4 book ai didi

rust - 如何在结构中具有可重用的Vec 以避免分配?

转载 作者:行者123 更新时间:2023-12-03 11:43:03 25 4
gpt4 key购买 nike

我的算法使用Vec<RwLockReadGuard<..>>处理数据。该算法被重复调用,并且我不想每次都被分配Vec,如果可以在处理结束时对其进行clear()并将其存储在与数据处理相关的相同结构。但是,RwLockReadGuard的生存期短于保持结构的可能生存期。由于我只在数据处理函数内部使用Vec,而在它外部始终为空,因此我仍可以某种方式将其存储在struct中吗?是否有 crate 或成语可能会对我有所帮助?

显示问题的最小可重现示例位于问题的底部。

如果每次都分配Vec,它将是这样的:

#[derive(Clone)]
pub struct T;

pub fn process_ts(ts: &[T]) {
unimplemented!();
}

struct Process {
locked_ts: Vec<RwLock<Vec<T>>>,
}

impl Process {
pub fn process(&self) {
let mut ts: Vec<T> = Vec::with_capacity(self.locked_ts.len());

let guards: Vec<RwLockReadGuard<Vec<T>>> = self
.locked_ts
.iter()
.map(|locked_t| locked_t.read().unwrap())
.collect();

let n = guards.iter().map(|guard| guard.len()).min().unwrap();

for i in 0..n {
ts.clear();
for t in &guards {
ts.push(t[i].clone());
process_ts(&ts);
}
}
}
}

我对这种解决方案不满意的是,每次调用 Process::process时,都会分配 ts: Vec<T>guards: Vec<RwLockReadGuard<Vec<T>>>。我可以摆脱 ts:

struct ProcessReuseTs {
locked_ts: Vec<RwLock<Vec<T>>>,
reusable_ts: Vec<T>,
}

impl ProcessReuseTs {
pub fn process(&mut self) {
let guards: Vec<RwLockReadGuard<Vec<T>>> = self
.locked_ts
.iter()
.map(|locked_t| locked_t.read().unwrap())
.collect();

let n = guards.iter().map(|guard| guard.len()).min().unwrap();

for i in 0..n {
self.reusable_ts.clear();
for t in &guards {
self.reusable_ts.push(t[i].clone());
process_ts(&self.reusable_ts);
}
}
}
}

但是,如何提取 guards呢?

use std::sync::{RwLock, RwLockReadGuard};

#[derive(Clone)]
pub struct T;

pub fn process_ts(ts: &[T]) {
unimplemented!();
}

struct ProcessReuseBoth {
locked_ts: Vec<RwLock<Vec<T>>>,
reusable_ts: Vec<T>,
reusable_guards: Vec<RwLockReadGuard<Vec<T>>>,
}

impl ProcessReuseBoth {
pub fn process(&mut self) {
self.reusable_guards.clear();
self.reusable_guards.extend(
self.locked_ts
.iter()
.map(|locked_t| locked_t.read().unwrap()),
);

let n = self
.reusable_guards
.iter()
.map(|guard| guard.len())
.min()
.unwrap();

for i in 0..n {
self.reusable_ts.clear();
for t in &self.reusable_guards {
self.reusable_ts.push(t[i].clone());
process_ts(&self.reusable_ts);
}
}

self.reusable_guards.clear();
}
}

pub fn main() {
unimplemented!()
}

不与
error[E0106]: missing lifetime specifier
--> src/main.rs:13:26
|
13 | reusable_guards: Vec<RwLockReadGuard<Vec<T>>>,
|

Playground

最佳答案

归根结底,似乎您想要做的是分配一个Vec。使用它来存储某些生命周期RwLockReadGuard<'a, Vec<T>>'a类型的元素,然后清除向量并将其放入RwLockReadGuard<'b, Vec<T>>类型的元素,其中生命周期'b是与'a不同的生命周期(实际上没有重叠),依此类推。这是行不通的,因为RwLockReadGuard<'a, Vec<T>>是与RwLockReadGuard<'b, Vec<T>>不同的类型,并且我们无法更改Vec所保存的元素的类型。

但是也许真正的目标不是用相同的Vec来保存这些不同类型的元素(这是不可能的),而是只是避免需要重新分配每个新的Vec。我们可能会问,是否可以从旧的Vec中回收已分配的内存,从而跳过不必分配下一个Vec的情况?好吧,对于一些非常丑陋,不安全的代码,可能有可能只分配一个Vec<u8>,然后在每次调用process时都要进行一些指针争夺,以将其就地转换为所需类型的Vec(大小为零,但非零)。零容量);这可能很难正确完成,并且需要根据Vecstd实现的内部细节进行操作。

也许值得退后一步,认识到每次在堆上分配内容时我们都可以问同样的问题-也就是说,是否有一种方法可以重用刚释放的内容中的空间,从而避免执行新操作分配?在某些情况下,答案可能是肯定的,但是我们不得不问一下,是否值得将我们的代码弄乱以进行优化?

这就引出了一个问题-我们是否有任何证据表明这里的分配实际上是一个重要的性能瓶颈?如果没有,也许就不用担心了。如果确实需要提高分配性能,则可以尝试使用jemalloc或某种形式的竞技场。

关于rust - 如何在结构中具有可重用的Vec <RwLockReadGuard>以避免分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62330718/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com