5.5. 以一半速度运行浮点及MMX单元?
看一下手册4:“指令表”中的表,我们注意到对64位及128位整形及浮点指令,许多时延是偶数,特别是P4。这引起了MMX与浮点执行单元可能以一半时钟速度运行的猜测。我前后提出了4个猜想来调查这个问题:
猜想1
就像在P3中那样,128位指令被分解为两个64位μops。不过,这个猜想与在P4上可以通过性能监控计数器测量的μops数目不符。
猜想2
我们可以假设P4有两个以一半速度工作的64位MMX单元。每个128位μops将使用这两个单元,需要2个时钟周期,如果图5.1所示。一个64位μops可以使用任一单元,使得不依赖的64位μops可以每时钟周期一个μops的吞吐率执行,假设半速单元可以在偶数及奇数时钟周期开始。依赖的64位μops将有一个2时钟周期的时延,如图5.1所示。
测量得到的时延与吞吐率与这个猜想相符。为了测试这个猜想,我进行了一个实验,交替执行128位与64位μops。在猜想2下,一个64位μops与一个28位μops重叠是不可能的,因为128位μops使用两个64位单元。n个128位μops与n个64位μops的交替长串应该需要4n个时钟周期,如果图5.2所示。
图5.2.
不过,我的实验显示这个序列仅需要3n个时钟周期。(我使64位μop相互依赖,因此它们不能彼此重叠)。因此,我们丢掉猜想2。
猜想3
我们可以修改猜想2,假设内部数据总线宽度仅为64位,因此传递128位操作数到执行单元需要2个时钟周期。如果我们仍然假设有两个64位执行单元以一半速度运行,那么当128位操作数的前一半到来时,第一个64位单元可以在时间T=0开始,当操作数后一半在一个时钟周期后到达时,第二个64位单元将开始(参见图5.3)。在第二个64位单元完成128位操作数的后一半之前,第一个64位单元将能够在时间T=2接受一个新的64位操作数。如果我们有128位与64位μop交替序列,第三个μop是128位的,可以在时间T=3开始它的前一半,使用第二个64位执行单元,而后半个操作数在T=4开始,使用第一个64位执行单元。如图5.3所示,这可以解释n个128位μop与n个64位μop交替序列需要3n个时钟周期的现象。
图5.3
简单128位μop的测量时延不是3个时钟周期,而是2。为了解释这,我们必须看一下执行的128位μop的依赖链。图5.4展示了相互依赖的128位μop的执行。
第一个μop从时间T=0到2处理操作数的前半部,而操作数的后半部在时间T=1到3处理。第二个μop可以在时间T=2处理其操作数的前半部,尽管直到时间T=3,操作数的后半部才就绪。这种类型的n个相互依赖128位μop的序列将需要2n+1个时钟周期。末尾多出的额外1个时钟周期作为串中最后一条指令的部分时延,它将结果写入内存。因此,出于实用目的,我们可以2时钟周期的时延计算简单的128位μop。
猜想4
现在假设仅有一个64位算术单元在全速运行。它有一个2时钟周期的时延,且是两阶段流水线,因此每时钟周期它可以接受一个新的64位操作数。在这个假设下,128位与64位μop的交替序列将仍然如图5.3那样执行。
没有实验方法区分猜想3与4,如果在猜想3里假设的两个单元是相同的,因为在这两个猜想里,执行单元所有的输入与输出同时发生。如果有某些64位操作仅能在两个假设的64位单元中的一个执行,就有可能证明猜想3,而拒绝猜想4。通过进行一个实验,其中,在调度这个操作执行时,仅不支持一个特定操作的单元是空闲的,就有可能完成证明。我对可能仅被两个猜想单元之一支持的操作进行了系统的查找。我找到的仅有的候选是64位加法PADDQ。我的实验显示64位PADDQMM在MMX-ALU单元里执行,而128位PADDQXMM在FP-ADD单元里执行。不过,进一步的实验显示,如果存在两个64位MMX-ADD单元,那么它们都能执行PADDQMM。这使得猜想4的可能性高于猜想3。
如果猜想4是对的,那么我们需要解释为什么它需要两个流水线阶段。如果MMX-ALU单元能够在2个时钟周期里执行一个交错的加法,那么它有可能在一个时钟周期里完成一个封装32位加法。难以相信设计者会因为罕见的PADDQMM指令,让所有的MMX指令的时延为2而不是1。一个更为可能的解释是,每个加法器固定在特定的流水线阶段。因此,我认为猜想4是最可能的解释。
不过,下面的句子读起来像是对猜想3的支持:“IntelNetBurst微架构 … 使用深度流水线化设计,使得在高时钟频率下,芯片各部分可以不同的时钟率运行,一些比处理器的名义引用时钟率(nominally-quotedclock frequency)要快,一些则要慢”(Intel Pentium 4 and Intel Xeon ProcessorOptimization Reference Manual, 2001)。让不同的单元以不同的速度运行,相比让最慢的单元确定整体时钟率,确实是一个更好的设计。这个选择的进一步原因可能是降低功耗并优化散热。某些部分,比如浮点单元,以半速运行是可能的,但上面的摘录也可能指追踪缓存以半速运行。
两个64位半部彼此依赖的128位MMX μop都有4个时钟周期的时延。这与猜想3与4都符合。
工作在80位寄存器上的浮点加法与乘法μop的时延,比在128位寄存器中的相似μop,多一个时钟周期。在猜想3下,这个额外的时钟周期可以被解释为在64位数据总线上传输80位操作数需要的额外时间。在猜想4下,这个额外的时钟周期可以被解释为产生额外的80位精度需要的时间。
在80位寄存器中标量浮点操作的吞吐率是每时钟周期1个μop,而在128位寄存器中标量浮点操作吞吐率为一半,即使它们仅使用128位中的32或64位。这可能是因为目标操作数中余下维持不变的96或64位,将通过执行单元去往新的(重命名的)目标寄存器。
除法行为则不同。有使用迭代、非流水线化的独立除法单元。除法可以有奇数及偶数时延,因此很可能除法单元全速运行。除法使用FP-MUL单元,这意味着FP-MUL单元也可能全速运行。