多核,多线程,超标量,SIMD??

如题所述, 这么多的概念指代的是什么? 区别呢?

关于图片

所有图片均取自 Standford CS149 slide . 如有兴趣, 可以直接看这门课.

超标量

指令级并行, IPC 大于 1 . 简单来说, 就是一个 CPU core 中有多个 ALU 可以同时使用, 配套的还需要多个取指、解码单元.

下图中采用两个 ALU 配套两个取指解码单元, 就实现了一次性运行两条指令. 对于两条连续的数据相关指令, 例如连续运行 mul r1, r0, r0, 由于同时采用 ALU 会出现 r1 对应 cache line 访问冲突, 所以无法同时执行. 这里其实解释了为什么是 “independent scalar instructions”, 我们可以构造例如 mul r2, r1, r0mul r1, r0, r0 之后执行, 显然, 这两条指令不能同时运行.

SuperScalar

SIMD

单指令多数据流. 实际上就是一条指令能算好几个数. 思想很简单, 但是对于一些需要大量计算连续数据 (向量, 矩阵) 的程序就是碾压级的加速, 毕竟 AVX512 一个 cycle 算 512 bit, 而普通情况下一个 cycle 的在 pipeline 下的吞吐量可能也只能到一个 cycle 算三数据指令 mul.

从硬件上看, 实际上是增加了 vector ALU . 在一些 Intel Chip 上, 可以看看有几个 FMA, 对应了每个 CPU core 有几个 SIMD 执行单元. 值得注意的是, 实践当中大量使用 SIMD 时, Intel Chip 的频率似乎会比基频更低, 这可能与 FMA 的频率有关? 但是吞吐量的提升依然是巨大的.

SIMD

多线程

线程级并行, 我们以 SMT (Intel Hyper-Threading) 为例. 实际上, 一个 CPU core 内依然只有一个 ALU 和一个取指解码单元, 也就是一次性最多运行一条指令 (IPC=1) . 然而, 基于一个共同的事实, 内存带宽、I/O延迟、中断等等都可能导致当前指令流等待, 可以额外用一组寄存器保存当前的执行上下文 (比如断点位置等), 然后切换上下文运行另一个指令流以达成 pipeline 充分利用等待时间的效果. 这是非常有效的, 因为支持 Hyper-Threading 的 OS 会尽可能将大概率无关的任务往一个核上进行分配, 例如两个进程. 而对于单进程多线程编程来说, 如果本身是计算密集型并且还远不够 memory bound 的情况下, 那么增加 exectuion context 的效果就不大了.

但是, 我们还必须区分两个概念:

  • hardware thread: 硬件支持的线程, 实际上和 CPU core 一致.
  • virtual thread: 虚拟的逻辑线程, 一般是利用 Hyper-Threading 将线程数倍增.

Multi-Threading

多核

处理器级, 在多核的层面上, 往往是多进程并行 (当然也可以多线程). 有多少个 CPU core 就有多少个 hardware thread, 如果从任务的角度来说, 就是至少有 8 个完全不相关的任务可以完全并行执行.

总结

当前的 CPU 架构一般是多个核, 每个核内采用了超标量架构, 集成 SIMD 执行单元, 同时增加 exectuion context 实现 Hyper-Threading.