|
在技术详解中,我们已经讨论了SSE技术在英特尔最近推出的Prescott处理器中的应用,并向软件开发者介绍了它辉煌灿烂的历史,以及其特性与优势。同时,我们将会把新的SSE指令集的优缺点与AMD推出的 x86-64模式的处理器做一个详尽的比较说明。
在最近的英特尔开发者论坛上,英特尔正式向公众推出了新的PC处理器。这是新一代的处理器,采用 0.9微米工艺制程生产。它的时钟频率可以达到4-5GHz。同时,这种新一代处理器的制造过程使它在性价比上有理由将其L1和L2高速缓存的容量增加到1MB:这样的话,其尺寸就增加了一倍。同时 FSB频率达到了800MHz。 总的来说,几乎所有的CPU部件均得到了一定程度的改进。 但是这一polished-of的产品对软件开发者来说又意味着什么呢?拥有较大的高速缓存无疑是很不错的选择: 你毋庸十分关注存储器的读写速度,对存储器而言读写速度经常成为其性能改善的一个限制因素。但是,这并不能解决所有的问题;因为当数据过于庞大时,即使是改进后的高速缓存对此也不会有太大增益。
Intel的这一新款处理器具有更高的前端总线频率,很明显它不受瓶颈效应的限制。与以前的处理器模式不同的是,新处理器的性能改善与频率增长并非成正比变化。
但是,软件开发者对于像七层low-k材料连接模式的CPU设计模型这一类新生事物几乎没有任何兴趣。对他们而言,更重要的是了解当前适用的新款处理器的指令集,以及为了达到最优性能——即使不能作到最好,至少也要比“前辈”出色——应该在编程过程中使用何种优化技术。 Intel推出的最新款的处理器——Pentium 4要求突破性的软件优化以期达到性能上的重大改善。因为Pentium 4的批处理任务模式,它可能会与Pentium III的主频相同,甚至有可能比后者低两倍。关于这一现象,我们梢后再做细致的讨论。迄今为止,我们必须指出其主要原因与对处理器核心的 radical (重要部分)需要进行重新设计休戚相关,只有这样它才能支持更高的主频。
英特尔推出的新款CPU核心并没有什么革命性的改进。奔腾4所“厌恶”的任一部分(尤其是branching)全部移交给了新出生的“小弟弟”。为了提高时钟频率,他们增加了Prescott模式的pipeline length(管道长度),因此当错误的分支预选导致管道清除时,我们不难预见到其性能会有毁灭性的降低。
但是,仍然有正面新闻,新处理器指令系统进行了扩展。 软件开发者对于MMX, SSE 和SSE2的引进非常满意,因为通常开发者为了优化自己的程序不得不对这些指令作一些额外的工作。 否则,程序决不可能快速运行。 但是,Prescott处理器扩展的13条新指令对软件开发者而言,无疑是一道福音,它大大减少了工作量,并且十分容易上手。
MMX, 3DNow!, SSE, SSE2:操作以及优化准则
在讨论新的指令之前,先让我们对以前的处理器指令系统的SIMD扩展指令作一个简单的回顾。首先,我们来估计一下某些指令系统所能提供的性能上的改善。如果你非常熟悉我们将要讨论的主题,你大可跨过这一部分,直接阅读本文的下一章节。
在某些产品评测中,你或许会发现这样一些程序,它们针对SSE进行优化设计,这样当CPU运行时,其评测性能即会表现的超乎寻常的良好。那么什么是SSE呢?在进一步讨论之前,让我们回想一下缩写词所代表的含义: SSE就是流式SIMD扩展指令,SIMD指的是单指令多重数据 (一条命令处理若个干操作数)。
诸如486或者第一代Pentium一类的老式x86处理器模式是如何运行的呢? 这个过程非常之简单。 他们用很少的寄存器存储二进制数字
你可以运算两个寄存器中的数据之和,并把结果与存储在第三个寄存器中的数字相比较,如果结果大于存储在第三个寄存器中的数字,则按照指令表所示转换到另一阶段执行。但是,当工程师试图改善CPU的性能时,棘手的事情也就随之浮出水面。问题在于当前一条指令没有运算完必需的操作数时,处理器就无法执行另一条指令。我们可以设计一款携有数百个 ALU的CPU,但是它决不可能比只携有一个ALU的CPU运行的更快,因为当任意一个ALU运行时,其他的ALU都只能默默等待结果而不能进行任何干预。 因此英特尔决定扩展处理器指令集,使它可以一次处理多于两个的操作数。这里是它在第一种x86的 SIMD扩展指令集中的工作方式。亦即MMX:
|
操作 |
部件3 |
部件2 |
部件1 |
部件0 |
寄存器 |
|
|
70 |
50 |
30 |
10 |
寄存器1 |
|
+ |
|
|
|
|
|
|
|
80 |
60 |
40 |
20 |
积存器2 |
|
= |
|
|
|
|
|
|
|
150 |
110 |
70 |
30 |
结果 |
一条指令不是仅仅只处理一对数据的相加,而是四对。对于减法,乘法以及其他处理操作数——这些操作数存储在不同的寄存器中——的指令,上述原则也是同样适用的。这种技术的引进使得CPU可以通过增加运算单元的个数很容易的提高自身运行速度(主频依然保持不变)。更确切的说法是,我们并不是增加了运算单元,而是增加了一次处理的操作数。然而,对于软件开发者而言,这一点说明显得有些画蛇添足。
当然,为了大幅度的改善性能,程序员编程时必须要使用SIMD指令集。CPU不能将需要进行同一条指令处理的不同数据存储在一个寄存器中。这意味着程序员不得不明确无误地“告诉”CPU,它必须把将要处理的数据装载到MMX寄存器中,并且对这些数据执行SIMD操作。数据应该存储在专门的存储器中,以便载入适宜的寄存器。在某些情况下,特殊的SIMD优化编译器可能会有所帮助——只要能够高效率的使用SIMD指令集来代替若干条简单指令。 但是,通常情况是,你必须根据一定的指导方针来编写程序代码以便有效地进行编译。
即使使用SIMD指令集也不能保证可以优化所有的运算。考虑一下如下的表达式: (a+ b * c ) * d。 你决不可能用少于三条的命令来完成这一运算。另一方面,如同这种四个参数( x,y,z,w )(亦即, x1+x2+x3+x4, y1+y2+y3+y4, z1+z2+z3+z4, w1+w2+w3+w4) 的处理也仅仅只能简化到用三条SIMD 指令来完成。 如果CPU执行一条SIMD指令能够达到与执行一条简单指令一样的快速,那么这意味着SIMD-优化程序的性能将会得到很大程度的改善。
从软件开发者的角度来看,有若干类型的SIMD优化:直接手工操作的代码优化,这是一件十分艰难的事情,虽然最为有效; 或者可以使用SIMD编译器,这可能会产生一些我们始料不及的后果; 最后一种方法就是使用标准的应用软件库——CPU的设计者已经对软件库进行了充分的优化和分类。软件库中包含目前大多数经常要执行的任务的标准函数。最后一种方法看起来似乎最有吸引力。
|