这篇博客讨论了在 Rust 中关于并发和并行执行的相关问题,主要观点如下:
- 并发与并行的区别:并发是系统的结构机制,并行是资源。并行执行需要利用系统的并行资源进行并发调度,即使使用多个线程也可能是顺序执行,而单线程也可实现并发执行。
- 任务(Tasks)作为抽象在并行异步执行中的问题:过去认为任务应像
async/.await
的线程等价物,但现在认为这是错误的。在异步 Rust 中,并发和并行可解耦,可通过Join
系列 API 实现并发执行,通过组合实现并行执行,如ParallelFuture
,避免了任务的一些限制和性能开销。 - 任务在并发异步执行中的问题:仅使用
spawn
API 进行并发而不利用并行通常不是好的体验,会有性能开销和语法限制,如spawn_local
的'static
生命周期限制,而不依赖任务的futures-concurrency
可以更好地表达。 - 窃取与发送(Stealing and sending):Rust 的异步设计假设工作窃取调度器是性能的巅峰,但 Glommio 和 Monoio 的运行时表明,线程-per-core 设计在网络基准测试中表现更好,不需要额外的同步原语,这对工作窃取的前提提出了质疑。
- 分片发送边界(Sharded send bounds):Tmandry 提出的想法是在
Send
边界内使用Rc
和其他!Send
类型,但需要更多研究来确定其可行性。 - 并行未来与发送边界(parallel futures and send bounds):对于是否在
spawn
API 中要求Send
边界,需要更多数据来决定,目前证据表明线程-per-core 可能是更好的方法,但在某些情况下允许!Send
类型在可并行化的未来中工作可能更简单。 - Rust 中并发和并行的愿景:提出引入
par
和co
关键字,实现更方便的并发和并行异步执行,如for par..in
循环、co await
和par await
等,将并发和并行执行直接融入语言,解决可扩展并行异步执行问题,且与#[maybe(async)]
函数体配合良好。 - 结论:任务在非并行和并行并发执行中都存在问题,Monoio 和 Glommio 的成功对工作窃取执行器提出了质疑,需要更多数据来决定,同时标准化异步 API 需先稳定异步析构函数,应将并发和并行原语提升到语言层面,以实现更好的异步 Rust。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。