前言

随着半导体工艺的升级和芯片技术的发展,为了充分提升CPU的性能出现了各种各样的方式,提升工艺能够极大提升CPU性能,但随着摩尔定律的逐渐失效,优化CPU结构成为了提升CPU性能中越来越重要的一部分。

局部性原理

在CPU频率不断提升的情况下,和CPU进行频繁数据交换的内存速度却提升不够。在这种情况下,CPU直接通过内存进行数据交换时,由于需要等待内存的回应,往往会降低CPU的性能。通过在CPU和内存中间插入Cache作为缓存,能够一定程度上弥补这个问题。

Cache的实现原理

Cache利用空间局部性和时间局部性原理,通过在内存和CPU中间插入一块速度更快的存储器,进而CPU可以先尝试和Cache进行交互,减少CPU访问内存的次数,进而提高系统的整体性能。当Cache中不存在相应数据时,我们会将存储器中的数据和相邻的数据“搬运”到Cache中,这样只需一次访问内存我们可以减少n次内存的访问。

多级Cache

如果都用最先进的工艺实现一个Cache,价格和功耗都是我们无法接受的(当Cache过大时,会由于复杂逻辑产生大的功耗)。因此我们采用多级Cache的方案,不同Cache满足不同需求,如Icache和Dcache代表的L1cache独立于每个Core,L2cache可能在由几个Core进行共用,L3cache可能是整个CPU共用一份。

L1cache分解成Icache和Dcache由于流水线的存在。

无Cache

Cache虽好,但并不是所有的处理器都提供了Cache,原因主要有三点:

  1. Cache会增加功耗和成本,占用过大的芯片面积和发热了。
  2. 一些处理器本身工作频率不高,没有需要Cache解决的带宽问题。
  3. Cache无法保证实时性,缓存命中和未命中需要不同的CPU处理时间,无法满足实时控制场景的需要。

流水线

CPU工作的执行单调而乏味,正如流水线上的工人一样,因此我们也可以通过流水线的方式提升CPU的处理速度。

流水线的原理

流水线通过将一个任务分成多个部分,利用类似并行的处理方式提高了模块的利用率,提升了吞吐量。

想象一个拧螺丝的工作需要4步,每一步需要2s中,那我们从开始到最后完成任务需要8s,也就是说这个时候我们8s可以生产一个产品,但无论我们执行那一步,其他的三步(材料+设备)都是空闲的,因此我们可以通过流水线的方式进行全速前进,这样在全速前进下我们2s就可以生产一个产品(虽然第一个产品生产完成其实也需要8s等待)。

流水线并不是越深越好

首先流水线的分级需要插入寄存器;流水线间如果出现依赖可能还需要增加逻辑进行判断;同时一旦发生了跳转,我们需要丢弃掉前面所有的预取指令。

更多情况下,我们的流水线需要在性能和功耗间做一个平衡。

乱序执行

不同指令间的执行在流水线中可能存在冒险,这种情况下我们可能需要停顿流水线或添加更多逻辑,而还有一种方式就是通过乱序执行,让数据相关的指令不在一起执行,从而根本上避免了冒险的产生。

SISD和SIMD

我们学习过的大多数指令都是SISD(Single Instruction Single Data),这种数据操作会通过一个指令完成一次数据的运算。而SIMD(Single Instruction Multiple Data)可以完成单指令多数据的操作,一次性读取所有的操作数并进行运算。

为什么要有SIMD

数据密集型计算的大规模出现:图像、视频、音频等数据的处理需求催生了SIMD类型指令的出现。如果说之前处理一帧数据需要无数条SISD的指令,那么可能只需要一条SIMD指令,极大提升了这类处理需求的指令效率。

单发射与多发射

多发射可以在一个时钟周期执行多条指令,这是由于处理器内部多个执行单元的存在(又增加了处理器核的面积和逻辑复杂性)。让我们的处理器可以达到指令级的并行。

静态多发射

静态多发射依赖于编译阶段对可以并行的指令打包,合并成一个长指令,这种实现实现又叫做VLIW(Very long Instruction Wrod),这种实现简单,所需硬件也简单,但由于指令集的兼容问题,这种实现并不能完全被主流处理器支持。

动态多发射

动态多发射在硬件上完成了指令的并行话操作,实现这种方式的处理器又被叫做超标量处理器(SuperScalar)。需要在处理器硬件上实现增加很多逻辑。

EPIC

EPIC结合了VILW和SuperScaler的优点,通过在指令中显式提供bit位表达两条指令间有没有相关性,简化了硬件处理两条指令相关的逻辑。

多核

提升芯片面积(如多发射或其他类似的设计增加)在提升CPU性能的同时也带来了更高的功耗,更昂贵的成本。因此对单核的提升出现了一个瓶颈:无法在提升性能的同时降低功耗(相同工艺)。针对于此,多核的时代来临了。

多核处理器能够让多个任务级做到真正并行,而单核处理器只能称之为并发,现代计算机一般都是多个任务同时运行,在这种情况下多核的优势开始显现出来。

片上多核互联

正如在单核流水线和多发射中存在的冲突问题,多核处理器也不能每个核心单独存在,需要进行互联通信。CPU的通信经历了星型连接总线连接交叉开关(Crossbar)连接,到达RingBus阶段。RingBus结合总线型和开关型的优点,在成本功耗与通信效率间达到了平衡。但当处理器核心进一步增多时,RingBus的延迟又成为了新的瓶颈。因此面向众核处理器领域又出现了新的片上互联技术:片上网络(Net On Chip, Noc)

大小核

当工作任务均匀分配到每个核心,并且实现大的负载时,多核处理器的性能得到了充分的发挥。但当工作任务不是很多时,往往会造成处理器中某些核心的空转,白白浪费了电费。为了解决这个问题,不同的厂商都提出了他们的大小核架构方案。可以通过操作系统的调度实现处理器的均匀负载,针对不同的人物,可以使用不同的核心处理问题。

不同厂商的实现不同,比如ARM的big.LITTLE架构中小核心的存在就是为了低功耗,而Intel的E-Core则提供了多线程处理能力,提供的更多是“能效”方面的提升。

超线程(Hyper-Threading)

在主流的X86处理器中,主流CPU都提供了超线程技术,通过增加一定的控制逻辑电路将一个物理处理器当作两个逻辑处理器使用,更大限度提升CPU的资源利用率。

实现原理

通过增加控制逻辑电路,保存各个线程的状态,使不同线程共享一个核心的资源,通过进行上下文切换进行线程转移。

在超线程处理器上这种线程切换可能只需要一个时钟周期,而对于一般处理器的线程切换可能需要上万个时钟周期。

超线程的本质时通过让操作系统分配给CPU更多任务,减少CPU的空闲时间:一个线程空闲时就可以切换到另一个线程了。

超线程一定有利吗

超线程更多适用于高并发的任务中,但对于游戏这种比较吃单核性能的任务下,超线程反而会增加系统开销,影响性能。

现今一些游戏也开始尝试对多线程提供优化,操作系统和各种应用也越来越支持多线程技术。