在作用域设置中重用静态生命周期线程以避免生成开销

问题描述 投票:0回答:1

我正在编写一个 Rust 组件,它可以执行多线程操作以提高性能。为了实现这一点,我使用作用域线程和通道来传递带有生命周期注释的引用。我的方法有效,但由于生成了许多线程,因此性能较差。

我正在寻找一种解决方案,允许重复使用一个线程而不违反生命周期。

我当前的解决方案将 crossbeam 范围的生命周期绑定到 crossbeam 通道,以允许在线程之间安全地传递引用。这是一个简单的例子:

use crossbeam::thread;
use crossbeam::thread::Scope;
use crossbeam_channel::unbounded;
use crossbeam_channel::Receiver;
use crossbeam_channel::Sender;

fn slice_processor_worker<'a>(rx: Receiver<&'a mut [u8]>, tx: Sender<&'a mut [u8]>) {
    // Process the first slice.
    let data = rx.recv().unwrap();
    println!("received {:?} inside worker", data);
    data[0] = 15;
    let _ = tx.send(data);

    // Process the second slice.
    let data = rx.recv().unwrap();
    println!("received {:?} inside worker", data);
    let _ = tx.send(data);
}

fn slice_processor<'scope>(
    scope: &Scope<'scope>,
) -> (Sender<&'scope mut [u8]>, Receiver<&'scope mut [u8]>) {
    let (main_tx, processor_rx) = unbounded();
    let (processor_tx, main_rx) = unbounded();

    scope.spawn(|_| slice_processor_worker(processor_rx, processor_tx));

    (main_tx, main_rx)
}

fn main() {
    let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    thread::scope(|scope| {
        let (tx, rx) = slice_processor(scope);
        let (first_half, second_half) = data.split_at_mut(5);

        scope.spawn(move |_| {
            let _ = tx.send(first_half);
            println!("received {:?} in main", rx.recv().unwrap());
            let _ = tx.send(second_half);
            println!("received {:?} in main", rx.recv().unwrap());
        });
    })
    .unwrap();
}

此代码可以工作,但会导致性能问题。我的用例需要在执行期间跨多个代码路径多次执行此多线程操作,并且我遇到了生成线程的开销。

理想情况下,我会创建一个具有静态生命周期的线程,并将作用域通道绑定到该线程。这样我只需要支付一次线程生成开销。我一直无法找到实现此目标的解决方案。也许对 Rust 的生命周期和并发性有更多了解的人可以找到解决方案?

multithreading performance rust lifetime borrow-checker
1个回答
0
投票

我认为这里最好的解决方案是将操作数据的所有权移至线程,而不是将其保留在外部作用域中。在移动到线程之前,可以将数据放入

Arc
中。这有效地为数据提供了
'static
生命周期(实际上该类型具有
'static
生命周期),因此可以在线程之间移动/发送。

如果您正在流式传输数据而不是示例中的单个数据集,那么您应该将线程池系统(如异步

tokio
或阻塞线程池库)与多个缓冲区结合使用。如果您的中继性能受到限制(以至于每个缓冲区的分配太多,这是一个疯狂的要求),您也可以将缓冲区轮换回缓冲池。

您的示例与您的要求描述并不完全匹配,因此如果可以的话,请添加更多有关您要解决的问题的信息,以便我可以发布更准确和详细的答案。

© www.soinside.com 2019 - 2024. All rights reserved.