Intel, AMD及VIA CPU的微架构(32)

13. Intel Silvermont流水线

在中仅有小打小闹的几年后,低功耗的Atom设计最终迈出了一大步。现在Silvermont处理器是ARM处理器的一个有力竞争者。对整数指令,它有有限的乱序执行能力,但对浮点与向量指令没有。它支持SSE4.2指令,但不支持AVX。

流水线有14级,而之前的Atom设计有16级。3级用于指令获取,3级用于指令解码,2级用于寄存器分配与重命名,1级用于调度,1及用于执行,4级用于回收与提交。更短的流水线据说将分支误预测惩罚降低到了10时钟周期,不过我的测试显示大约12个时钟周期,几乎与Atom相同。

芯片有1到4个带有2个执行核的单元,总共最多8线程。一个单元里的2个核共享2级缓存,但不共享流水线或执行资源。

13.1. 流水线

Slivermont有5条流水线:一个用于内存读写操作,两个用于整数操作,两个用于浮点与向量操作。最大平均吞吐率是每时钟周期两条指令,在两条指令去往不同的流水线时实现。

两个整数流水线可以乱序执行。每个整数流水线有可以在队列中保存8条指令的保留站。通过一个6项的保留站,内存操作也可以乱序进行,而浮点与向量操作在自己的流水线内不能重排。

13.2. ​​​​​​​指令获取与解码

指令边界在代码缓存中标记。这是消除自Pentium MMX以来Intel没有使用的指令长度解码瓶颈的一个简单技术,而AMD始终使用指令长度解码。

Silvermont有两个解码器,每时钟周期可以获取及解码两条简单指令。超过8字节的指令有每时钟周期一条指令的吞吐率。大多数指令仅从解码器产生一个μop。读-修改及读-修改-写指令从解码器产生送往内存单元与执行单元的单个μop。产生多个μop的指令使用微代码ROM,除了POP寄存器与FXCH指令。所有使用微代码ROM的指令,如果去往解码器0,需要4时钟周期解码。如果这样一条指令首先去往解码器1,那么在2时钟周期的时延后,它被重定向到解码器0。这意味着,对产生2个μop且恰好首先去往解码器0的指令,解码过程需要6时钟周期。

带有超过3个前缀及转义字节的指令在解码器中导致严重的时延。不像Intel与AMD的大多数其他处理器,Silvermont不仅包括这个限制里的标准前缀,还包括像0F这样的转义字节。因此,这个限制很容易超出。所有属于SSSE3与更新指令集的xmm指令,在指令代码中,有一个前缀字节(66)页两个转义字节(0F 38或0F 3A)。如果任意r8 ~ r15或xmm8 ~ xmm15寄存器用在这样一条指令里,那么需要一个额外的REX前缀,这样就可以超过3个前缀与转义字节的限制。例如:

; Example 13.1. Prefix limitation in Silvermont

pblendw xmm1, xmm2, 2 ; 1 prefix + 2 escape bytes

pblendw xmm1, xmm8, 2 ; 2 prefixes + 2 escape bytes

在这个例子中的第一条指令通常在一个时钟周期里解码,而第二条指令,如果首先去往第一个解码器,需要4时钟周期解码,否则如果去往第二个解码器,需要6时钟周期。对长度改变前缀没有惩罚。

这两个解码器不能同时处理两条分支指令。为此,应该避免连续的分支指令。

13.3. ​​​​​​​循环缓冲

Silvermont有一个回收已解码μop的循环缓冲。通过消除解码瓶颈,它可以提升最多29条指令循环的性能。

13.4. ​​​​​​​宏操作融合

Silvermont不能将多条指令融合为单个μop。

​​​​​​​13.5. 寄存器分配与乱序执行

在通用寄存器上的指令可以有效程度地乱序执行。显然,同时不能挂起超过8条指令。在浮点与向量寄存器上的指令,与去往相同执行端口及流水线的其他指令,不能一起乱序执行。但在一个流水线里的浮点指令可以绕过另一个流水线里的浮点指令。例如,一条浮点乘法指令(在FP0)可以在之前一条浮点加法指令(在FP1)前面执行。

相同的逻辑寄存器可以分配到不同的物理寄存器,以消除假的依赖。这也适用于浮点与向量寄存器,即使在相同的流水线中它们不能乱序执行。

13.6. ​​​​​​​无关的特殊情形

将一个寄存器置零的常用方式是与自己XOR或减去自身,比如XOR EAX, EAX。Silvermont处理器知道,如果两个输入操作数是同一个寄存器,某些指令与寄存器之前的值无关。这仅工作在几个情形里。一个32位寄存器与自己的XOR被认为与之前值无关,但这不能作用于8,16或64位寄存器。因此,清理一个通用寄存器的最好方式是将该寄存器的32位版本与自身XOR。这将清除所有64位。SUB,SBB与CMP指令不能以这个方式察觉。一个向量寄存器可以通过PXOR,XORPS或XORPD指令,与自身XOR,清除对之前值的依赖,但不能通过减法、比较或其他指令。

13.7. ​​​​​​​执行单元

Silvermont有5个带有自己调度器的执行端口:

端口

操作

内存

内存读写

整数端口0

ALU,乘法,偏移

整数端口1

ALU,跳转

F.P. 端口0

乘法、除法、偏移、封装、转换

F.P. 端口1

加法

表13.1. Silvermont中的执行单元

执行单元是部分流水线化的。整数乘法器连同浮点加法器与乘法器,对较小的数据,有每时钟周期一条指令的吞吐率,对较大数据,有每两时钟周期一条指令的吞吐率:

端口与单元

数据大小

时延

吞吐率倒数

IP0乘法

32位整数

3

1

IP0乘法

64位整数

5

2

FP0乘法

416位整数组成的64位向量

4

1

FP0乘法

816位整数组成的128位向量

5

2

FP0乘法

单精度浮点

4

1

FP0乘法

4个单精度组成的128位向量

5

2

FP0乘法

双精度

5

2

FP0乘法

2个双精度组成的128位向量

7

4

FP0/1加法

81632位整数组成的向量

1

0.5

FP0/1加法

64位整数组成的向量

4

?

FP1加法

单精度浮点

3

1

FP1加法

4个单精度浮点组成的128位向量

3

1

FP1加法

双精度

3

1

FP1加法

2个双精度组成的128位向量

4

2

表13.2. Silvermont中部分流水线化的执行单元

在整数端口0与浮点端口0之间共享一个除法单元。它有19到69个时钟周期的时延,没有流水线化。浮点除法有固定的时延。

读写带宽

内存带宽是每时钟周期一条128位读或写指令。每时钟周期进行一次读操作与一次写操作是可能的,但仅在这两个操作是同一条指令的部分时,如一条读-修改-写指令。在所有其他情形中,最大带宽是每时钟周期一次内存操作。

数据旁路时延

在整数单元与浮点/向量单元间移动数据的指令有3 ~ 4个时钟周期的时延。否则,在不同执行单元间移动数据没有额外的时延。另外,在浮点数据上使用整数向量指令没有惩罚,反之亦然。

下溢与次正规值

以次正规值作为输入或输出,或者产生下溢的操作,需要大约160个时钟周期,除非同时使用flush-to-zero模式以及denormals-are-zero模式。

13.8. ​​​​​​​部分寄存器访问

写部分寄存器对该寄存器余下部分有一个假的依赖。一个通用寄存器或向量寄存器的不同部分不视为彼此独立。

标记寄存器可处理为不同的部分。在写部分标记寄存器后,读任意标记,有1时钟周期的额外时延。

13.9. ​​​​​​​缓存与内存访问

缓存

Silvermont

1级代码

每核32 kB8路,64组,每行64 B

1级数据

每核24 kB6路,64组,每行64 B,时延3

2

1 MB16路,1024组,每行64,时延19。线程间共享

表13.3. Silvermont上的缓存大小

没有观察到缓存库冲突。在4kB倍数隔开的内存间有假的依赖。

13.10. ​​​​​​​写转发

一个内存写可以转发给后续一个在相同起始地址、相同大小或更小的读。写+后续读的时延是7时钟周期。如果一个非对齐写转发跨过缓存行边界,有一个额外的3时钟周期时延。

当读比写更大或者不在相同的地址开始时,写转发失败。将一个写转发给两个半部的读是不可能的。一个失败的写转发有额外的5时钟周期时延。

13.11. ​​​​​​​多线程

Silvermont有一个或多个单元带有2个核。一个单元里的这两个核共享2级缓存。运行在同一个单元里的两个线程不会竞争除了2级缓存以外的资源。

13.12. ​​​​​​​Silvermont里的瓶颈

指令获取与解码

解码绝对是Silvermont设计中最弱的一环。产生多个μop的指令需要至少4时钟周期解码,很多时候需要更多时间(有少数例外)。这同样适用于需要一个额外前缀的指令。所有属于SSSE3及更新指令集的xmm指令需要4或6个时钟周期解码,如果它们使用了任意r8 ~ r15或xmm8 ~ xmm15寄存器。在对Silvermont的代码设计里,应该不惜一切代价避免在解码器中需要额外时间的指令。

执行端口与执行单元

大多数执行单元有完全的128位能力,但某些执行单元仅部分流水线化,对完整的向量或双精度数据,需要额外的时钟周期。

对小的低功耗处理器,执行单元的能力看起来令人满意。

Atom在遗留x87代码上令人崩溃的性能,最终被修复。

乱序执行

Silvermont有寄存器重命名,但对乱序执行有非常有限的能力。对获得最好性能,编译器的调度可能是必要的。

分支预测

分支目标缓冲的大小未知。预测率一般。误预测惩罚相对低。根据我的测试,间接分支没有模式预测。

内存访问

吞吐率是每时钟周期一个读/写指令。缓存性能良好。

多线程

除了2级缓存,线程间不共享关键资源。这使得多线程高效。

文献

Intel: "Intel 64 and IA-32 Architectures Optimization Reference Manual”. July 2013.

Sebastian Anthony: “Intel’s Silvermont revealed: After a five-year snooze, Intel is finally ready to crush ARM”. http://www.extremetech.com/computing/155082-intels-silvermont-revealed-after-a-five-year-snooze-intel-is-finally-ready-to-crush-arm. 2013.

Anand Lal Shimpi: “Intel’s Silvermont Architecture Revealed: Getting Serious about Mobile”. http://www.anandtech.com/show/6936/intels-silvermont-architecture-revealed-getting-serious-about-mobile. 2013.

David Kanter: ”Silvermont, Intel’s Low Power Architecture”. http://www.realworldtech.com/silvermont/. 2013.

你可能感兴趣的:(Agner,Fog编写的优化手册)