花儿为什么这样红?——K6-3的奥秘
只有K6-3才最后把K6核心的潜力真正发挥出来。Anand的测试告诉我们一些非常有趣的结果(部分测试结果见上期本版),那些高分值的结果看起来好像是K6-3全速二级缓存(Cache)带来的,但这里面有更多的原因。让笔者带你进入K6-3的核心里去看看,你一定会有有趣的发现。
#1 一、隐藏在高分值后的神秘事实
首先,让我们看看Winstone′99(一种测试软件)的得分值,对比一下从K6-2 300到K6-3 450,从赛扬300(无Cache)到赛扬450A的性能提升情况(见^061701a^1)。
你是不是很惊讶?K6-3 450同K6-2 300的差别比赛扬450A同赛扬300的差别大。不要忘记,赛扬300没有二级Cache,而K6-2却有工作在100MHz下的2MB二级Cache,为什么K6-3性能提升的幅度有这么大呢?
为了看得更清楚,让我们把主板上的三级Cache(K6-3)和二级Cache(K6-2)关掉(Disable)。正如有人指出:在Winstone '99测试中,带有2MB三级Cache的K6-3比没有三级Cache的快11%。因此,笔者做了快速测试,把K6-2 300的二级Cache关掉。现在来看结果(见^061701b^2)。
看到了吗?K6-3的提升幅度比赛扬A450的提升幅度高42%!我并不认为这个结果只是由K6-3的两倍二级Cache带来的。AMD的工程师BOB说:“我们很惊奇地发现在板三级Cache竟然仍有效。”
#1 二、为什么K6核心对Cache如此渴求
我想我们有足够的证据说,K6核心(当然包括K6-3)处于极端Cache饥饿状态。为什么?请继续往下读。K6具有一条短且一流的6工位流水线(见^061701c^3),下面我只对流水线上最重要的三个工位进行解释:解码(Decode)、流出(Issue)和执行(Execute)阶段。
#1 1.Post-RISC CPU
PⅡ和K6都是Post-RISC CPU,它们需将CISC(复杂指令集)X86指令集解码成类RISC(精简指令集)指令,这个工作在解码工位完成。X86指令可以很小(小于8字节),也可以很大(大于16字节),并且这套指令集包含许多程序员从不使用的指令。而RISC指令的大小都是一样的,并且它的指令集小得多。因此,RISC指令更有效且CPU内核(Die)可以做得很小,省下来的空间就可用来做其他事情,如集成二级Cache。
在流出(Issue)工位,你把类RISC指令放到缓冲器中。当操作数(数据)和执行工位都有空的时候,一个调度器将把缓冲器中的指令移到合适的执行单元中,如整数指令将被移到整数单元,浮点指令被送到浮点单元。这样的缓冲器和调度器是必须具备的,因为现在的CPU能够“乱序”执行指令(即不按程序顺序执行),在Retire(引出)工位时,所有的结果将按原程序的顺序排列。
在执行工位,所有的指令被执行单元执行。(嗯,就这么简单)
#1 2.两种CPU核心的比较
让我们先来比较K6和PⅡ核心的性能。(见^061701d^4)
PⅡ最多能够对3个X86指令进行解码,比K6核心快50%。但是,K6核心在向执行单元注入的指令比PⅡ快33%,执行单元的指令执行比PⅡ快100%。换句话说,PⅡ核心具有快速的解码器,但执行器相对较慢。这意味着有大量的等待指令和充满内容的缓冲器;而K6有一个较慢的解码器,但它的执行器却很快。因此,同PⅡ相反,等待指令较少且缓冲器很空。也就是说,它的后端(执行)性能优于前端(解码)性能。
由于K6缓冲器在大部分时间里总是空着,解码器需要总是很忙才能发挥K6的最大性能,如果没有指令或数据供给解码器,CPU只好在一旁“玩弄手指”。想象一下,你碰到这种事该怎样处理呢?答案是只有给解码器不停地输送新指令。而这些指令来自快速的一级Cache或二级Cache,考虑到经常发生Cache未命中的情况(即Cache中没有需要的指令或数据,此时CPU只好到较慢的主内存中查找),只有非常大的而且快速的一级或二级Cache才能让解码器不停地工作。
这就是为什么K6核心对Cache如此渴求的原因!它执行得如此之快以至于它总是得等待新指令的到来。如果解码器也被迫等待,那整个系统都会停顿下来。
现在来看PⅡ核心,如果在Cache中没有所需的指令或数据(Cache未命中),并且解码器也有空,这并不意味着有什么太大的损失,因为执行单元正在忙着处理那些在缓冲器中的指令呢。当然,缓冲器里的指令会消耗殆尽,但解码器也会很快恢复工作,重新充满缓冲器。在这里,PⅡ核心对Cache性能的要求不像K6核心那样迫切。
#1 三、三级Cache的效能
为什么三级Cache对运行商业应用程序的影响如此突出呢?下面是BOB的回答:“我们还不能完全描述它的效果,但我个人认为,由于二级Cache是4路相关,三级Cache是直接映射,因而它们会趋向覆盖不同的内存区域,结果组合为一个更大的Cache而不是重叠的Cache。”
不知道什么是“4路相关”和“直接映射”?好的,下面我会解释。
#1 1.关于Cache
如果你的系统有1MB三级Cache,但你有64MB或更多内存,你会把哪些内容放到Cache中呢?幸运的是,大部分程序在大部分时间内都经常执行小部分代码。请看下面这个例子:
for(i=0;i<100;i++)
{
指令A
……
指令E
}
编过程序的人都知道什么是“循环”或重复,如果你在第一次循环后把指令A到指令E放到Cache中,Cache命中率就可以达到99%,因为在100次程序循环中,你可以在Cache中99次找到所需指令。这也是为什么需要Cache的原因之一。
运行商业程序时,你会按下许多按扭,因此触发许多不同的“事件”。换句话说,你需要把大量的指令或数据放在Cache里。在一个字处理软件如WORD里,当拼写检查器工作时,你可能会向上或向下拉动滚动条,当你整理文档格式时,你又可能会时常拉动滚动条。好了,你可能已看到要害了,在拼写检查或格式化文档时,有关滚动的指令最好留在Cache中。但那些指令对一级Cache来说太大了,因此你最好有快速的二级或三级Cache来保持它们。
Instruction Fetch(指令引入)
X86>RISC 86解码
RISC 86 Issue
Execution Stage1(执行工位1)
Execution Stage 2(执行工位2)
Retire(引出)
#1 2.直接映射Cache和4路相关Cache
二级Cache最好存储比一级Cache有更多不同的信息,三级Cache最好存储比二级Cache有更多不同的信息,否则,CPU也许每次都要为了同样的数据而检查所有的Cache。这就是为什么三级Cache必须比二级Cache大(大多数设计者认为最好是4倍),二级Cache必须比一级Cache大的原因。
你怎样才能确信256KB二级Cache里的内容没有被完全拷进1MB三级Cache内呢?OK,你必须为不同的Cache设置不同的规矩。
首先,Cache被有组织地划分为不同的行和列,就像一个表格。每一行的大小为32字节。这时,1MB三级Cache包含32768 行 (1024 K / 32)。那么你如何对64MB或更多的主内存进行缓冲呢?你可以把每一行Cache定位分配给每一大块内存。也就是说,每行Cache要分到64MB/32768=2KB的内存地址。这种方法的优点在于CPU不需要花太长的时间搜索Cache,此时,每行Cache里有无所需信息是很明确的。不过,这种方法的缺点也很明显。如果我们不停地重复使用同一批指令,而这些指令又占用同一行Cache,那我们就不能把所有的指令放进Cache,因为这行Cache已经满了。最坏的情况是一个重要的指令不断地被另一个重要指令替换(它们共享同行Cache),同时,另一行的一个不太重要的指令又一直呆在Cache里。
三级Cache的工作方式就是这样,我们称之为“直接映射”。
“全相关”Cache的工作方式同“直接映射”正相反:内存中任一位置的信息可以被存到Cache中的任一行,这招给了你最大的灵活性。因此,最重要的指令和数据总是可以被安排进Cache中,可以达到高命中率。不过这种技术不太实用,因为CPU将不得不搜索每行Cache来确认所需信息在不在Cache中。
K6-3的二级Cache工作方式称为“4路相关”。同直接映射比较,你可以保留4行Cache(1套)给大多数内存地址,64MB内存就可以分配给256 KB / 32 / 4 = 2048个4行Cache。也就是说,32KB的内存地址可以共享1套4行Cache。这种方法有一个主要的优点:你能存放最常用指令和数据的可能性比存放在1行Cache中的可能性大大增加了。缺点是,当每次搜索Cache时,你得校验4行Cache,以确认所需信息是否在Cache中。不过,这个缺点影响很小。不管怎样,4路相关Cache的命中率(一般为90%)比直接映射Cache大得多。
#1 3.二级Cache和三级Cache的组合作用
为什么通过“直接映射”三级Cache和“4路相关”二级Cache的组合,能够提高K6-3的性能呢?下面举个例子说明:
1)直接映射Cache(1MB三级Cache)可能包含较少用到的指令和数据。例如一行Cache必须在两个重要指令间“挑选”一个,而另一行Cache必须在两个不太重要的指令间选择。
2)4路相关Cache(256 KB二级Cache)由于有4行Cache,就不会有上述问题。它会在32KB内存地址中挑选最重要的指令。它将把最小、最近用到(LRU)的指令或数据替换为更重要(更常用到)的指令(或数据)。它更聪明、更具弹性。
让我们看看32KB内存片共享同行Cache时的情况(见^061701e^5)。
看到了吗?当32KB内存共享4行二级Cache时,2KB内存共享1行三级Cache。还记得开先的那个字处理例子吗?WORD需要12MB系统内存,并且你会重复使用许多功能,也许这些功能会占到1MB或2MB空间。你没有办法把这些“最常使用的功能”放到256KB二级Cache内。但二级Cache能确认把最重要的指令或数据放到4行Cache里(4× 32 bytes=2048bytes),而三级Cache能对那些次常用的指令或数据进行缓冲,它们通过这种方式相互补充。
商业应用程序(如字处理、数据库和图形软件等)通常具有重复使用大量指令或数据的特点,在带有1~2MB三级Cache的K6-3系统上就能运行得非常好。看看Anand的测试结果就明白了:在Winstone'99中,K6-3 350的性能接近于PⅡ 450。
当笔者听到有人说“Pentium MMX 200就能很快地运行所有商业程序”时,就忍不住想笑。当他在那块CPU上(即使有128MB内存)想要进行一些图片编辑或复杂网页编辑操作时,他就知道结果了。试试在WORD中编辑一个充满字符的大文本,并且打开拼写检查和语法检查,我曾在那种PC系统上工作过,让我告诉你结果吧:它很慢。虽然许多人只在他们的PC上做简单的工作,如写写信,但一旦你发现你的PC还要做其他工作如写复杂的文章、编辑视频、为照片添加效果、测试JAVA程序......你会发现,如果你的PC在Winstone '99中有很好的得分,你会很愉快的。
#1 四、总结
K6的执行单元比它的解码单元要强大一些,解码单元是K6架构中的瓶颈。因此,要发挥最大性能,就必须让快且大的一、二、三级Cache不停地把指令或数据供给解码单元。这就是为什么K6-3有如此精彩性能并从全速二级Cache中受益的原因。