我很难理解超线程。如果逻辑核心实际上不存在,那么使用超线程有什么意义呢? wikipedia文章指出:
对于物理上存在的每个处理器核心,操作系统会寻址两个虚拟(逻辑)核心,并在可能的情况下共享它们之间的工作负载。
如果两个逻辑内核共享相同的执行单元,这意味着其中一个线程必须被保持而另一个执行,这就是说,我不明白超线程如何有用,因为你实际上并没有引入新的执行单位。我无法绕过这个
答案 0 :(得分:5)
有关现代CPU如何通过一次运行多条指令来查找和利用my answer on a softwareengineering.SE question的详细信息,请参阅instruction-level parallelism (ILP)。 (包括Intel Haswell管道的框图,以及更多CPU微体系结构细节的链接)。
你有一个拥有大量执行单元的CPU和一个可以让他们主要负责工作的前端,但只有在良好的条件下。像高速缓存未命中或分支错误预测一样失速,或者只是有限的并行性(例如,执行一个长链FP添加的循环,FP延迟在一个(标量或SIMD)上的瓶颈加上每4或5个时钟而不是一个或两个每个时钟)将导致每个周期的吞吐量远低于4个指令,并使执行单元空闲。
HT(和Simultaneous Multithreading (SMT)一般来说)的目的是让那些饥饿的执行单元继续工作,即使运行具有低ILP或大量停顿的代码(缓存)错过/分支错误预测。)
SMT只为管道添加了一些额外的逻辑,因此它可以同时跟踪两个独立的架构上下文。因此,与两倍或4倍的全内核相比,它的芯片面积和功耗要低得多。 (Knight的登陆Xeon Phi每个核心运行4个线程,主流的Intel CPU运行2.一些非x86芯片每个核心运行8个线程,针对数据库服务器类型的工作负载。)
常见误解
超线程不只是优化的上下文切换。可以在缓存未命中时切换到另一个线程的更简单设计,但HT比这更先进。
当两个线程处于活动状态时,前端在每个周期(在获取,解码和发出/重命名阶段)中在线程之间交替,但无序核心实际上可以从两个逻辑核心执行uop在同一个周期。
在通常交替的管道阶段中,每当一个线程停止时,另一个线程将获得该阶段中的所有周期。 HT比固定交替要好得多,因为一个线程可以完成大量工作,而另一个线程从分支错误预测中恢复或等待缓存未命中。
请注意,一次最多可以有10个缓存未命中(来自Intel CPU中的L1D缓存:这是LFB(线路填充缓冲区)的数量,并且内存请求是流水线的。但是如果下一个加载的地址取决于在较早的加载(例如,指针追逐树或链表)中,CPU不知道从哪里加载,并且不能保持多个请求在飞行中。所以它实际上对于两个线程都是有用的等待缓存未命中并行。
当两个线程处于活动状态时,某些资源会被静态分区,其中一些资源是竞争性共享的。有关详细信息,请参阅this pdf of slides。 (有关如何为英特尔和AMD CPU实际优化asm的更多详细信息,请参阅Agner Fog's microarchitecture PDF。)
当一个逻辑核心"睡觉" (即内核运行HLT
指令或任何MWAIT
进入更深的睡眠状态),物理核心转换为单线程模式,并让仍然活跃的逻辑核心拥有所有资源(包括完整的ReOrder缓冲区大小和其他静态分区资源),因此它在仍在运行的单个线程中查找和利用ILP的能力比其他线程在缓存未命中时停止时的增加更多。
在Skylake上,我发现在我的四核i7-6700k上,8个线程而不是4个线程的视频编码(x265 -preset slower
,1080p)快15%。我没有为4线程测试实际禁用HT,但Linux的调度程序擅长于在有足够的空间可以绕过线程并在单独的物理内核上运行线程时擅长。考虑到x265有很多手写的asm并且每个周期运行非常高的指令,即使它有一个完整的核心,15%的加速也是相当不错的。 (像我使用的较慢的预设往往比内存限制更多的CPU限制。)