Pages

Saturday, December 18, 2010

向量处理器(1)

我决定翻译《计算机体系结构--量化研究方法》第四版附录F。原因在于向量处理器现在变得异常重要。可以说向量处理器是 GPU 的先驱。要从体系结构上理解 GPU,没有道理不先理解历史上的向量处理器。很多向量处理器里面用到的技术,在现在最先进的微处理器中又奇迹般地得到了重生。比如 Cray-1 里面的 T Register File B Register File,和 Stream Processor 中的 Stream Register File SRF)如出一辙。而现代面向通用计算的 GPU 中的Shared Memory S Register File 以及 A Register File的设计初衷也有异曲同工之妙。当然另一个原因是我没有看到有关量化附录的翻译。

这个附录的作者是 Krste Asanović。他本人的Ph.D.  Thesis 就是一个向量处理器的设计。据说随着 David Patterson 慢慢地不管事,现在他已经成为了了 ParLab 的实际领袖。我完全是抱着学习这个附录的心态来翻译的,任何质疑都可以在下面留言。

最后要说的一点,体系结构里最让人头疼的事莫过于五花八门的术语了,而如果要在中英文之间切换这些术语则更恶化这个现象。我的策略是两个。第一,如果有非常好非常成熟非常通用的中文翻译,我用中文--毕竟我是在翻译。但是即使这样我也会用括号表明英文术语。第二,有些术语本身有很大争议。比如 issue dispatchX86 MIPS 对他们的使用完全相反。我于是准备采用另一个页面,来解释那些令人困惑到发指的术语,以免读者完全理解错误原文应有之义。另外,原文之中有一些我认为讲得不是特别清楚或者难以理解的地方我都以注释的形式给出我自己的理解。

---------------大家好,我是分割线---------------

我当然没有在发明向量处理器。现如今就我所知就已经有三种向量处理器存在了。他们是 IIIliac-IV (CDC)Star,和 T1(ASC)。这三者都是向量处理器的先驱作为先驱的一个问题是你总是要犯错误,而我绝对,绝对不想成为先驱。所以成为后来者的好处是你总是可以看到前人犯了什么错误。
Seymour Cray


1. 何出向量处理器?

在第23章我们看到了如何通过每个时钟周期发射多条指令和利用更深的执行单元流水线来开发指令级并行(ILP)以显著提高性能。(这个附录假定你已经完整阅读了第23章和附录G。另外,对向量处理器的内存系统的讨论需要你阅读附录C和第5章。)不幸的是,我们看到在挖掘更大程度的 ILP 的时候遇到了各种各样的困难。

随着我们增加指令发射的宽度和流水线的级数,我们同时也需要更多的不相关指令以保持流水线忙碌。这意味着可以同时 in flight 的指令数目的增长。对于一个动态调度的处理器而言,这意味着硬件资源比如指令窗口(instruction window),ROB,重命名寄存器 renaming register file)也要相应增长以保持足够的能力去维护所有 in flight 的指令的信息。更糟的是每一个硬件单元的端口都要随着发射宽度的增长而增长。跟踪所有  in flight 的指令之间依赖性(dependency)的逻辑随着指令的数目以 2 次方的关系增长。即使对于一个把更多的调度工作转移到了编译器上的静态调度的 VLIW 处理器而言,它仍然需要更多的寄存器,更多的寄存器端口,更多的 hazard interlock 逻辑(我们假定由硬件在指令发射的时候检测是否需要 interlock)来支持更多的 in flight 指令。这同样导致了电路规模和复杂度的 2 次方增长[1]。如此快速的电路复杂度的增长使得设计一个能够控制大量 in flight 指令的处理器困难重重,而且这反过来实际上也限制了发射宽度和流水线深度。

向量处理器早在 ILP 处理器之前就已经成功商业化了。它采用了一种不同的策略来控制多个深度流水的功能部件。向量处理器提供了高层的对于向量--线性数组--的操作。一个典型的向量操作是两个 64 个浮点元素的向量相加得到一个新的 64 个元素的向量。这条向量指令等同于一整个循环,每一次迭代计算出一个元素的结果,更新循环变量,然后跳转回循环头部继续执行。

向量处理器有以下几个重要的特性使得它能够解决大多数上面提到的问题: 
  • 一条向量指令能够做很多事情--它等价于一整个循环。每条指令代表了数十上百条的操作,所以为了保持多个深度流水化的功能单元忙碌而需要的 instruction fetch instruction decode 的带宽急剧减少了。 
  • 通过使用一条向量指令,编译器或者程序员显式地指出了在一个向量之中的各个元素之间的计算互相独立,所以硬件不需要检测一个向量内部的 data hazard。可以使用一组并行的功能单元或者一个非常深度流水的功能单元或者任何以上两种方式的组合来计算向量中的各个元素。
  • 硬件只需要检测两条向量指令之间的 data hazard,而不是每个向量之中的元素之间的 hazard。这意味着所需的依赖检测逻辑的规模其实和标量处理器所需的大致相同,但是现在更多的(对于向量元素)操作可以同时 in flight 
  • 向量指令的访存有固定可知的模式。如果一个向量的元素是相邻的,那么从一组高度 interleaved memory bank 中取那个向量会效果非常好。相对于访问 cache 而言更高的访问主存的延迟被均摊了,因为一个向量访存操作是为向量中的所有元素发起的,而不只是一个元素。 
  • 因为一整个循环都被一条向量指令代替了,而这条向量指令的行为是可预期的,所以通常由循环分支而引起的 control hazard 现在不存在了。
    因为这些原因,向量操作对于同样数目的数据进行操作的时候比相应的一系列标量指令要快得多,所以设计者们如果发现他们的应用程序会经常进行向量操作的话会在设计中包含有向量单元。

    向量处理器尤其对于大规模的科学工程计算特别有效,包括汽车碰撞模拟和天气预报。这些应用程序通常需要一台超级计算机跑上几打个小时来处理 Gigabyte 级别的数据。高速的标量处理器依赖于 cache 来减少访问主存的延迟,但是大规模长时间运行的科学计算程序通常有很大规模的工作集,并且通常局部性非常低,这导致 memory hierarchy 的性能非常糟糕。所以标量处理器会提供旁路 cache 的机制如果软件发现访存的局部性很差。但是使得主存饱和需要硬件跟踪数百上千条的 in flight 的标量访存操作,而这在标量处理器 ISA 中已被证实开销是非常大的。相反,向量 ISA 可以只使用一条向量指令就可以发起对于一整个向量中元素的访存操作,所以非常简单的逻辑就可以提供很高的带宽[2]。

    当这个附录上一次在 2001 年写的时候,诡异的向量超级计算机已经慢慢地从超级计算机领域中淡出了,取而代之的是超标量处理器。但是在 2002 年,日本造出了当时世界上最快的超级计算机,the Earth Simulator。它是为创造一个“虚拟星球”来分析和预测世界环境和气候变化而设计的。它比之前最快的超级计算机还要快 5 倍,并且比身后的 12 个超级计算机加起来还要快。这在高性能计算领域引起了一阵骚乱,特别是在美国。美国人被如此之快地就丢失如此具有战略意义的高性能计算阵地而感到震惊。The Earth Simulator 比那些与之竞争的机器有更少的处理器,但是每一个节点都是一个单芯片的向量微处理器。它对于很多具有重要意义的超级计算代码都有非常高的性能--原因就像之前提到的。The Earth Simulator 以及Cray 发布的新一代向量处理器的影响力导致了对于向量处理器的重新关注和重视。
      
    ---------------大家好,我是分割线---------------

    [1] 为什么是 2 次方请看原书第三章第二小节。简单来讲,这就是一个排列组合的问题。
    [2] 这段话的意思简单来讲就是通常高级的标量处理器里面的内存系统是非常复杂的,需要 MSHR 这样的结构以及很复杂的访存调度算法甚至编译器的优化来提高访存效率,充分利用内存接口本就不高的带宽。而对于向量机而言,由于访问模式规则,非常简单的内存系统的设计配搭上一条向量指令就足以使得内存带宽饱和。

    No comments:

    Post a Comment