任务是错误的抽象概念

这篇博客讨论了在 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 中并发和并行的愿景:提出引入parco关键字,实现更方便的并发和并行异步执行,如for par..in循环、co awaitpar await等,将并发和并行执行直接融入语言,解决可扩展并行异步执行问题,且与#[maybe(async)]函数体配合良好。
  • 结论:任务在非并行和并行并发执行中都存在问题,Monoio 和 Glommio 的成功对工作窃取执行器提出了质疑,需要更多数据来决定,同时标准化异步 API 需先稳定异步析构函数,应将并发和并行原语提升到语言层面,以实现更好的异步 Rust。
阅读 28
0 条评论