提问人:Zannick 提问时间:6/18/2023 最后编辑:Zannick 更新时间:6/18/2023 访问量:74
我可以从人造丝中获得类似纤维的行为吗?
Can I get fiber-like behavior from Rayon?
问:
Rayon 的工作原理是创建一个工作线程池,为每个工作线程分配一个工作队列,并允许具有空队列的工作线程来窃取工作。但是,如果闭包阻塞(例如,工作涉及在互斥锁下编辑共享资源),则工作人员是否能够在另一个工作项上取得进展,就像协作多任务光纤一样?
上下文:我有一个自定义的全局优先级工作队列,我的 rayon 线程从中弹出并推送到,但我没有为实际的 cpu 绑定工作项获得很好的并行化,我想也许我应该切换到 fibers(库)或 tokio。我的另一个选择是让线程池中的人造丝线程比弹出任务的“工作线程”多,并让它们创建子任务。
答:
1赞
Kevin Reid
6/18/2023
#1
如果某个工作单元当前无法取得进展,则可以调用 rayon::yield_now()
以允许其他工作继续进行。因此,原则上,您可以:
let guard = loop {
match mutex.try_lock() {
Ok(guard) => break guard,
Err(TryLockError::WouldBlock) => rayon::yield_now(),
Err(TryLockError::Poisoned(e)) => panic!("{e}"),
}
};
但是,这将浪费一些 CPU 时间——锁被其他线程持有的时间越长——因为它不可能只在锁可用时才能“唤醒”。因此,如果您真的必须这样做,请谨慎行事并衡量性能。
一般来说,Rayon 最擅长计算任务,除了其他 Rayon 任务外,不涉及任何阻塞,具有严格的树形依赖关系。
如果您的任务具有更复杂的依赖项,请考虑改用,也许可以与以计算为中心的异步执行器(如 switchyard
)一起使用。async
评论
0赞
Filipe Rodrigues
6/18/2023
如果返回,我建议实际阻止锁定互斥锁(这意味着没有其他任务可用)。您还可以在锁上使用超时,以允许在此期间创建新锁时执行新锁。rayon::yield_now
Some(Yield::Idle)
rayon
0赞
Chayim Friedman
6/19/2023
这有一个问题,即锁可能直到最后才被获取,然后任务将忙于等待锁。
评论
tokio
rayon
tokio