我可以澄清 Project Loom 吗?

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

Brian Goetz 让我对 Loom 项目感到兴奋,为了充分理解它,我需要对现状进行一些澄清。

我的理解是这样的:目前,为了拥有真正的并行性,我们需要每个cpu/核心有一个线程。

  1. 那么在 n 核机器上拥有 n+1 个线程还有什么意义呢? Loom 项目将通过依赖 jvm 在 JVM 内部的虚拟线程上执行任务,为我们带来几乎无限的线程/光纤。
  2. 这会是真正的并行吗?
  3. 具体来说,这与前面提到的“n 核机器上的 n+1 个线程”场景有何不同?

感谢您的宝贵时间。

parallel-processing project-loom
2个回答
4
投票

虚拟线程允许并发(IO 限制),而不是并行(CPU 限制)。它们代表因果同时性,但不代表资源使用同时性。

事实上,如果两个虚拟线程处于 IO 绑定* 状态(例如等待 REST 调用返回),则根本不会使用任何线程。然而,普通线程的使用(如果不使用反应式或可完成语义)将被阻塞并且在调用完成之前不可用。

*除了某些条件(例如,使用synchonize与ReentrackLock、本机方法中发生的阻塞,以及可能的其他一些小区域)。


3
投票

那么在 n 核机器上拥有 n+1 个线程有什么意义吗?

首先,大多数现代 n 核机器都有 n*2 个硬件线程,因为每个核心有 2 个硬件线程。

有时,产生比硬件线程更多的操作系统线程确实有意义。当某些操作系统线程处于休眠状态等待某事时就会出现这种情况。例如,在 Linux 上,直到几年前 io_uring 出现之前,还没有好的方法来为本地磁盘上的文件实现异步 I/O。传统上,磁盘密集型应用程序产生的线程多于 CPU 核心,并使用阻塞 I/O。

这会是真正的并行吗?

取决于实施。不仅仅是语言运行时,还有标准库的 I/O 相关部分。例如,在 Windows 上,当使用 async/await(相当于 2012 年左右发布的 loom 项目)在 C# 中执行磁盘或网络 I/O 时,这些任务是真正并行的,操作系统内核和驱动程序确实在同时执行更多工作时间。 AFAIK Linux 上的 async/await 只对套接字真正并行,而不是文件,对于异步文件 I/O,它在后台使用操作系统线程池。

具体来说,这与前面提到的“n 核机器上的 n+1 个线程”场景有何不同?

由于某些原因,操作系统线程更加昂贵。 (1) 它们需要本机堆栈,因此每个操作系统线程都会消耗内存 (2) 内存速度较慢,处理器有缓存来补偿,操作系统线程之间的切换会增加 RAM 带宽,因为线程特定的数据在上下文切换后会失效 (3) 操作系统调度程序正在改进几十年来,但它们仍然不是免费的。原因之一是将线程状态保存到内存或从内存恢复需要时间。

与切换操作系统线程相比,在 C# async/await 或 Java 的 Loom 中实现的更高级别的协作多任务处理在切换上下文时产生的开销要少得多。至少从理论上讲,这应该会提高 I/O 密集型应用程序的吞吐量和延迟。

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