|
% M+ e; ?# i% [, B& F X! j+ |
再来看图3.25,它来自同一颗处理器,只是运行双线程,每个线程分别运行在处理器的一个超线程上。9 p6 _4 D3 q! v
' O4 E( J8 f6 _3 H图3.25: P4开启两个超线程时的带宽表现
: H5 |6 O R3 t g图3.25采用了与图3.24相同的刻度,以方便比较两者的差异。图3.25中的曲线抖动更多,是由于采用双线程的缘故。结果正如我们预期,由于超线程共享着几乎所有资源(仅除寄存器外),所以每个超线程只能得到一半的缓存和带宽。所以,即使每个线程都要花上许多时间等待内存,从而把执行时间让给另一个线程,也是无济于事——因为另一个线程也同样需要等待。这里恰恰展示了使用超线程时可能出现的最坏情况。
; K# L7 q; p$ ^! ?! }' W
* b( O- G7 v# d; d* T/ O图3.26: Core 2的带宽表现) x X0 Q. \7 R9 D6 s/ C0 P
再来看Core 2处理器的情况。看看图3.26和图3.27,再对比下P4的图3.24和3.25,可以看出不小的差异。Core 2是一颗双核处理器,有着共享的L2,容量是P4 L2的4倍。但更大的L2只能解释写操作的性能下降出现较晚的现象。 9 e8 o( s" a. D* Q
当然还有更大的不同。可以看到,读操作的性能在整个工作集范围内一直稳定在16字节/周期左右,在220处的下降同样是由于DTLB的耗尽引起。能够达到这么高的数字,不但表明处理器能够预取数据,并且按时完成传输,而且还意味着,预取的数据是被装入L1d的。
7 H$ I/ \1 ~# e! F: }7 a; c: d) @+ _: ?5 R, F; ^
写/复制操作的性能与P4相比,也有很大差异。处理器没有采用写通策略,写入的数据留在L1d中,只在必要时才逐出。这使得写操作的速度可以逼近16字节/周期。一旦工作集超过L1d,性能即飞速下降。由于Core 2读操作的性能非常好,所以两者的差值显得特别大。当工作集超过L2时,两者的差值甚至超过20倍!但这并不表示Core 2的性能不好,相反,Core 2永远都比Netburst强。 . E6 k3 l" ~0 L; M, K% i, p
* E& I5 C5 W% p+ y4 ] + v4 K7 E5 s2 J: O+ w
图3.27: Core 2运行双线程时的带宽表现( o& Q. q% ?9 f
2 G0 r( P \$ r+ n* S在图3.27中,启动双线程,各自运行在Core 2的一个核心上。它们访问相同的内存,但不需要完美同步。从结果上看,读操作的性能与单线程并无区别,只是多了一些多线程情况下常见的抖动。
5 h; S3 U' ^, D6 ~0 B, ]
0 v) s( Z" w- l3 D* s" \7 t3 Y有趣的地方来了——当工作集小于L1d时,写操作与复制操作的性能很差,就好像数据需要从内存读取一样。两个线程彼此竞争着同一个内存位置,于是不得不频频发送RFO消息。问题的根源在于,虽然两个核心共享着L2,但无法以L2的速度处理RFO请求。而当工作集超过L1d后,性能出现了迅猛提升。这是因为,由于L1d容量不足,于是将被修改的条目刷新到共享的L2。由于L1d的未命中可以由L2满足,只有那些尚未刷新的数据才需要RFO,所以出现了这样的现象。这也是这些工作集情况下速度下降一半的原因。这种渐进式的行为也与我们期待的一致: 由于每个核心共享着同一条FSB,每个核心只能得到一半的FSB带宽,因此对于较大的工作集来说,每个线程的性能大致相当于单线程时的一半。' I9 d& ^3 L& J' A/ A
由于同一个厂商的不同处理器之间都存在着巨大差异,我们没有理由不去研究一下其它厂商处理器的性能。图3.28展示了AMD家族10h Opteron处理器的性能。这颗处理器有64kB的L1d、512kB的L2和2MB的L3,其中L3缓存由所有核心所共享。 $ g4 w7 [; w8 W) G' q0 e- g( O6 S0 @
, W: v. v* G2 T) J- W6 C , H6 n$ Y L& e1 X/ q
图3.28: AMD家族10h Opteron的带宽表现 C6 v' l" y+ }) Q4 ?" l
* H/ C, y1 h6 b! i8 J$ ]大家首先应该会注意到,在L1d缓存足够的情况下,这个处理器每个周期能处理两条指令。读操作的性能超过了32字节/周期,写操作也达到了18.7字节/周期。但是,不久,读操作的曲线就急速下降,跌到2.3字节/周期,非常差。处理器在这个测试中并没有预取数据,或者说,没有有效地预取数据。
" Z3 G, ]' }# \! L3 _5 f
) M5 v1 i- I$ w" F. o另一方面,写操作的曲线随几级缓存的容量而流转。在L1d阶段达到最高性能,随后在L2阶段下降到6字节/周期,在L3阶段进一步下降到2.8字节/周期,最后,在工作集超过L3后,降到0.5字节/周期。它在L1d阶段超过了Core 2,在L2阶段基本相当(Core 2的L2更大一些),在L3及主存阶段比Core 2慢。 . G5 Q* ]- H+ Q* D. z6 z7 y& n9 S
复制的性能既无法超越读操作的性能,也无法超越写操作的性能。因此,它的曲线先是被读性能压制,随后又被写性能压制。
6 Q# X- e$ W1 A0 \, O3 p5 @6 O
0 h+ B- ?2 R7 \# s$ s7 l' S图3.29显示的是Opteron处理器在多线程时的性能表现。
) X+ b1 a" D: `4 ] : {. _6 l# [: s: ~7 i
图3.29: AMD Fam 10h在双线程时的带宽表现: Q5 A' |* H, _9 D
V# P/ \% Q0 z" u3 d
读操作的性能没有受到很大的影响。每个线程的L1d和L2表现与单线程下相仿,L3的预取也依然表现不佳。两个线程并没有过渡争抢L3。问题比较大的是写操作的性能。两个线程共享的所有数据都需要经过L3,而这种共享看起来却效率很差。即使是在L3足够容纳整个工作集的情况下,所需要的开销仍然远高于L3的访问时间。再来看图3.27,可以发现,在一定的工作集范围内,Core 2处理器能以共享的L2缓存的速度进行处理。而Opteron处理器只能在很小的一个范围内实现相似的性能,而且,它仅仅只能达到L3的速度,无法与Core 2的L2相比。 |
) P7 B# C) O5 Y% B5 k" ~% k4 o0 B |
|