如果我的 CPU 额定频率为 2GHz,有 4 个内核支持 8 个线程,那么所有 8 个线程是否都以额定时钟速度运行?或者由于线程数是内核的两倍,因此每个线程都以 1GHz 运行?
答案1
首先,内核不“拥有”线程。线程是进程的属性。进程和线程是操作系统创建的东西,CPU 实际上没有直接的概念。那些声称其产品有“四核八线程”的广告商使用了误导性术语。
你的核心有一个或两个逻辑处理器就操作系统而言,逻辑处理器 (LP) 是指能跑一个线程。如果您在固件设置中禁用了超线程,或者您的 CPU 不支持超线程,则每个核心有一个 LP。如果支持超线程,则每个核心有两个 LP。(未来的 x86/x64 处理器可能会在每个核心上实现两个以上的 LP。)
典型 Windows 系统中的进程可能在任意给定时间总共拥有数百到数千个线程。您可以在任务管理器的“详细信息”选项卡(在 Windows 7 及更早版本中称为“进程”选项卡)中查看每个进程中的线程数 - 只需启用“线程”列即可。
大多数 Windows 系统中的绝大多数线程大部分时间都在“等待”某件事:它们在等待 I/O 完成、等待计时器到期、等待页面错误解决。处于等待状态的线程(Unix 和 Linux 使用术语“阻塞”)不会尝试使用 CPU 时间,也不会使用任何 CPU 时间,直到它们所等待的事情发生。
大多数未等待的线程要么处于“正在运行”状态,这意味着它们实际上正在逻辑处理器上执行,要么处于“就绪”状态,这意味着它们正在运行,但所有 LP 此刻都在忙于处理其他线程。(除了就绪、正在运行和等待之外,还有一些其他状态这里不感兴趣。)
接下来的所有内容仅涉及“正在运行”的线程。
如果您未启用 HT,或者启用了 HT,但非等待线程数不高于内核数,则性能应与禁用 HT 时相同。大多数现代操作系统(包括 Windows)都尝试在每个内核上仅使用一个 LP,直到运行线程数多于 LP。将两个线程放入一个内核的 LP 中,而将另一个内核中的两个 LP 都闲置(通常)是没有意义的。操作系统在这方面并不总是 100% 成功,但大多数时候它们都做得很好。
如果一个核心中的两个 LP 都是正在运行的线程,那么这两个线程完成的“计算”工作的总和将大概会稍微大一些……一般是 40% 到 60%……比只有一个内核且操作系统在两个线程之间进行时间分片的情况要好。而且,完成的总工作量几乎肯定会比每个线程单独在一个内核上运行的情况要少一些。
请注意,正在运行的线程(就操作系统所知)可能仍然在其 LP 中停滞。一种常见情况是线程访问了尚未位于 CPU L1 缓存中的 RAM。将所需数据从外层缓存或 RAM 带入 L1 缓存需要时间。在此期间,线程可能在其指令流中没有取得任何进展,但 Windows 并不知道这一点。CPU 固件可能会利用这段时间在核心中的其他 LP 中执行某些工作。或者,它可能会为等待 RAM 内容的线程执行一些无序工作。操作系统对这些事情一无所知,只是将线程报告为“正在运行”,并继续累积其“已用 CPU 时间”,即使它在“停滞”期间可能没有取得任何进展。
因此...我们可以通过超线程一次运行两个线程,一个内核中的每个 LP 上各一个。但这并不意味着每个内核现在拥有两个内核的计算资源(“执行单元”),也不意味着时钟速度在两个 LP 之间分配。
超线程利用了这样一个事实:大多数线程并不总是充分利用核心的所有执行单元。事实上,这种情况非常罕见……这就是 HT 能够如此出色地发挥作用的原因。HT 允许第二个线程在处理器中共存同时与第一个线程一样,理想情况下,第二个线程可以使用第一个线程无法使用的执行单元。这是在 CPU 的微代码中实现的。
实际上,CPU 固件并没有区分“第一”和“第二”线程;它不会选择给予其中一个线程比另一个线程更多的关注。固件只是试图让尽可能多的 CPU 执行单元保持忙碌状态,完成尽可能多的工作。超线程只是让它同时处理两个指令流,从而更多地使用 CPU 的执行单元。
CPU 固件甚至不知道操作系统将什么视为线程,也不知道“线程上下文切换”。它只知道有两个不同的指令流要处理,每个指令流都有自己的一组指令指针、堆栈指针和许多其他架构寄存器的值。有时,由于固件未知的原因,操作系统会出现并更改所有这些东西(线程上下文切换)。
HT 不会做的另一件事是实现操作系统线程优先级概念的任何部分。因此,如果您在单个 HT 核心的 LP 中有两个线程,并且操作系统认为这些线程具有不同的优先级,则 CPU 中的 HT 固件将不知道这一点。特别是,它不会优先将执行单元分配给优先级较高的线程。操作系统确实使用线程优先级来决定选择在哪些 CPU 上运行哪些线程。
有关超线程工作原理的更多信息,请参阅本文在 Ars Technica。遗憾的是,由于他们重新托管了网站,所以插图没有出现 - 也许给他们发一封电子邮件可以解决这个问题。有关 Windows 如何“调度”线程的更多信息,请参阅“调度”一章Windows 内部原理作者:所罗门·鲁西诺维奇等人。
答案2
基本上,您的操作系统会将线程数视为核心数。当一个线程未满负荷时,它会更多地使用另一个线程,从而使您的计算机运行速度更快。(我认为)