接上文

  权衡缓存设计

  考虑设计一种TLP优化的内核。这种内核有4个SMT线程,每个线程在每个运行周期能够发出4个指令。一般来说,大约20%的指令都将装载到内存中,因此,一级缓存在正常设计中的需求是特别高的。能够在每个运行周期装载二次可能会提高性能。然而,做一次全面的双端口缓存(每个周期在任何地方都可做两次读写操作)可能会使缓存的物理尺寸增加一倍,或者使同样物理尺寸的缓存容量减少一半。替代的方法是使用“伪双端口”缓存,并行提出对单独的存储(相关的构件)的要求,以便利用较小的芯片面积成本提供大多数性能。

  一级缓存的尺寸还必须与二级缓存的设计进行权衡,一级缓存的命中率越好,二级缓存的设计就越容易。然而,更好的一级缓存命中率一般意味着缓存的尺寸更大(价格更昂贵)。而且,一级缓存越大,二级缓存就越小,整个缓存的共享也就越少。这将损害效率并且使内存设计(和任何三级缓存设计)更困难。

  不过,有一种提高一级缓存命中率的简单的、低成本的方法。这个方法就是使用密度更大的SRAM内存。特殊生产工艺中密度最大的SRAM内存设计大约比一级缓存SRAM内存使用存储密度大二至三倍。最简单的理由是,当前的一级缓存设计需要非常低的延迟,这就意味着必须使用速度快的SRAM内存。一般来说,使用特殊设计和工艺技术提高SRAM内存速度的惟一方法就是增加芯片的尺寸。这种做法将增加信号的强度。TLP优化的设计对延迟不太敏感,因此,可以使用速度较慢、但是密度更大的SRAM内存。不过,带宽的问题仍需要解决。

  是采用“0级”缓存的时候吗?

  我认为,缓解这些取舍问题的一个好方法就是推出一个稍微与众不同的缓存。为了争论方便,我们姑且把它称作“0级缓存”或者“L0”吧。(不过有些旧的参考资料确实把0级缓存当作是一级缓存)这个思路是仅仅缓存每个硬件线程的几个内存构件,例如16个字节的8至32个构件。这些缓存过程当然需要一个运行周期的访问时间。由于这是以每个线程为基础的,每个线程在同一时间都可以访问0级缓存。这意味着CPU内核每个周期可以装载与它拥有的线程同样多的次数。

  但是,缓存的命中率如何呢?如果0级缓存的命中率很糟糕,那么,整个实践就没有意义了。我认为,在很多服务器程序中,0级缓存的命中率大约是70%,但是,我还没有发现任何像这样分析这件事情的论文,因此,这只是一个猜测。这个比例也许高的离谱,甚至使用很长的服务器代码也是如此。许多内存访问只是读一个队列或者一个特定目标域的几个要素。即使这个队列很短,仍有很多按照顺序的访问,它们的0级缓存命中率都很高。

  如果0级缓存的平均命中率是70%,那就会减少70%的进入一级缓存的请求。同整个芯片相比,一级缓存虽然很小,但是比0级缓存要复杂得多,因此,较少地使用一级缓存实际上还会省一些电。平均内存延迟也会下降,从而改善性能。此外,通过减少对一级缓存的依赖,一级缓存的设计能够以更灵活的方式进行。换句话说,使用高密度SRAM内存或者与另一个CPU内核共享一级缓存将变得更可行。

  0级缓存执行指令应该做得非常好,并且命中率要达到大约80%以上。足够缓存典型的内部循环。正如以前提到的那样,这种指令缓存更适合多个内核之间的共享。0级指令缓存还可以用来缓存部分解码版本的指令,因此可以取消0级指令缓存和执行级之间的管线中的一些级。

  因为0级缓存可以减少对一级缓存的需求,共享一级缓存和使用速度较慢、但是密度较大的SRAM内存将变得更加可行。然而,4个CPU内核共享较大的一级指令缓存的方便性和可行性取决于它要提供多大的性能。每个内核每个周期能够执行的指令数量越多,0级缓存的命中率就越低,对共享的一级指令缓存的需求就越大。4个小的单线程Niagara式的CPU内核肯定比4个具有4个线程的内核更容易共享一级指令缓存。

  有一个很有趣的想法。如果使用0级小缓存意味着一级缓存能够更大和共享,那么,在那个指令中让0级缓存像二级缓存一样也许会有一些好处,并且数据输入是统一的而不是分裂的。例如,二个内核在拥有单独的0级指令和每个硬件线程的数据缓存的同时也许还能够共享一个容量为256KB的统一的一级缓存。