MPC7450指令延迟深度解析:从流水线原理到性能调优实战

MPC7450指令延迟深度解析:从流水线原理到性能调优实战 1. 项目概述从延迟表到性能调优的实战指南如果你正在为基于PowerPC架构的嵌入式系统或高性能计算设备编写底层代码尤其是那些搭载了MPC7450这类处理器的老牌工控机、网络设备或游戏主机那么你很可能已经翻遍了官方手册找到了一堆像天书一样的指令延迟表格。这些表格罗列着add需要1个周期fdiv需要35个周期vperm需要2个周期……但然后呢面对这上百条指令和一堆缩写很多开发者会感到无从下手这些数字到底意味着什么我该怎么用它们来让我的程序跑得更快这正是我写这篇指南的初衷。我手头这份《MPC7450 RISC微处理器家族软件优化指南》的附录详细列出了从MPC750、MPC7400到MPC7450几乎所有指令的执行延迟。但手册是死的经验是活的。仅仅知道lwz加载字在MPC7450上是3周期延迟而在前代是2周期这只是一个现象。关键在于理解为什么会有这个变化以及这个变化会如何实际影响你的流水线调度、循环展开和指令排序策略。MPC7450作为一款旨在冲击更高主频的改进型处理器其内部执行单元如IU1, IU2, FPU, VPU等的分配和流水线深度都进行了调整这直接导致了延迟特性的改变。例如浮点单元FPU的许多指令延迟从3周期增加到了5周期而向量排列单元VPU的指令则从1周期变成了2周期。这背后是更深时钟频率与流水线级数之间的经典权衡。本文将带你穿透这些枯燥的数字表格直抵性能优化的核心。我不会仅仅复述手册内容而是结合我多年在相关平台进行内核驱动和数学库优化的实战经验为你解读这些延迟数据的深层含义并给出可直接落地的优化策略。无论你是在优化一个实时信号处理循环还是试图榨干一个老旧游戏主机的每一分图形性能理解MPC7450的指令执行延迟都是你从“能运行”走向“高效运行”的必经之路。2. 核心概念解析延迟、吞吐量与流水线在深入MPC7450的具体数据之前我们必须先统一语言搞清楚几个最核心的概念。这些概念是理解所有后续优化技巧的基石。2.1 指令执行延迟指令执行延迟通常简称为延迟指的是从一条指令的操作数准备就绪、开始执行算起到其执行结果可以被后续指令使用为止所经过的处理器时钟周期数。这是一个非常关键的定义。举个例子假设我们有两条连续的整数加法指令add r3, r4, r5 ; 指令A: r3 r4 r5 add r6, r3, r7 ; 指令B: r6 r3 r7对于指令B来说它的一个操作数r3依赖于指令A的结果。在MPC7450上add指令在IU1单元执行延迟为1个周期。这意味着指令A在周期N开始执行其结果r3要到周期N1才会写入寄存器堆并变得可用。因此指令B最早只能在周期N1开始执行。如果编译器或程序员试图让指令B在周期N就启动即与指令A背靠背发射处理器会通过硬件互锁机制自动插入一个气泡Stall让指令B等待直到r3就绪。这个等待的周期就是由延迟导致的性能损失。手册中表格的“Cycles”列大部分描述的就是这个“延迟”。对于非流水线化的指令如fdiv除法这个数字就是它独占功能单元的总时间。2.2 吞吐量与流水线吞吐量衡量的是处理器持续执行同类指令的速率即每个时钟周期能完成多少条指令。它和延迟密切相关但角度不同。许多功能单元是流水线化的。手册中常用“3:1”这样的格式表示其中冒号前的数字是延迟冒号后的数字是吞吐量倒数。3:1表示延迟为3周期但吞吐量是每1个周期可以开始一条新指令前提是操作数不相关。这意味着该单元有3级流水线可以同时处理最多3条处于不同执行阶段的指令。例如MPC7450的FPU浮点加法指令fadd的延迟是5周期5:1。虽然从输入到输出要等5个周期但你可以每个周期都发射一条新的fadd指令操作数独立FPU的流水线会被填满从而实现每个周期完成一条fadd的峰值吞吐量。这就是指令级并行的基础。相反fdiv双精度浮点除在MPC7450上延迟为35周期且没有冒号后的吞吐量数字说明它是非流水线化的。在这35个周期内整个FPU都被这条除法指令占用无法开始执行任何其他浮点运算指令。此时延迟就等于吞吐量的倒数性能瓶颈非常严重。2.3 串行化操作手册表格中在周期数后面有时会跟着诸如{e},{s},{c},{r},{y}的标记。这些是串行化标记是性能的“隐形杀手”。{e}(执行串行化): 指令必须独占执行单元直到完全完成期间不能发射其他指令到该单元。mtspr写特殊寄存器通常带有此标记。{s}(存储串行化): 对于存储指令要求所有之前的存储操作必须完成才能开始本条存储。这保证了存储顺序但限制了存储指令的并发。MPC7450的许多存储指令都有此标记。{c}(完成串行化): 指令必须按顺序完成不能乱序退休。lmw加载多字指令就有此标记。{r}(重取串行化): 指令完成后需要清空流水线并重新取指。isync指令同步和rfi从中断返回是典型例子它们会导致巨大的流水线气泡。{y}(同步串行化): 与sync内存同步指令相关涉及复杂的系统总线广播操作延迟很长且与总线时钟比b相关。 注意在编写对性能极其敏感的代码时应尽量避免或减少使用带有串行化标记的指令。例如频繁调用sync来保证内存一致性会带来灾难性的性能下降MPC7450上sync延迟高达35周期。必须评估是否真的需要这么强的内存序。2.4 功能单元分配的变化MPC7450相比MPC7400一个重要的架构变化是功能单元的重组。手册提到“SRU/IU1/IU2 in the MPC750/MPC7400 to IU1/IU2 in the MPC7450”。MPC7400: 有独立的系统寄存器单元SRU来处理mfcr、mtcrf等CR操作和系统指令还有两个整数单元IU1和IU2。MPC7450: 取消了独立的SRU其功能被合并或重新分配。现在大部分CR逻辑指令如crand,crxor和许多系统指令如mfspr,mtspr改由IU2单元执行并且延迟普遍从1周期增加到了2周期。而像单字段mtcrf这样的指令则被分配给了IU1并且取消了串行化延迟仅为1周期这反而是一个性能提升。 实操心得这个变化告诉我们在MPC7450上操作条件寄存器CR的代价变高了从1周期到2周期。因此应更谨慎地使用条件码避免在紧凑循环中频繁测试或设置CR字段。相反利用好非串行化的单字段mtcrf来快速设置CR可能成为新的优化点。3. MPC7450指令延迟详解与横向对比理解了基本概念后我们深入手册中的表格进行一场“大家来找茬”式的对比分析。通过对比MPC7450与前代MPC750/MPC7400的差异我们能更清晰地把握其性能特性。3.1 整数与逻辑指令整数指令是程序的基石。MPC7450的整数单元IU1和IU2设计旨在维持高频率。指令类型MPC750/7400 延迟MPC7450 延迟变化与分析简单整数运算add,subf,and,or,xor等1 周期 (IU1/IU2)1 周期 (IU1)无变化。基础ALU操作保持1周期延迟这是维持IPC每周期指令数的关键。整数乘除法mulli(立即数乘法)2-3 周期 (IU1)3周期吞吐量1/1 (IU2)延迟略有增加。从可变延迟取决于操作数固定为3周期但吞吐量是每周期1条说明乘法器是流水线化的。mullw,mulhw(32x32乘法)2-5 周期 (IU1)4周期吞吐量1/2 (IU2)延迟和吞吐均有变化。手册脚注提到如果乘数B的高15位全0或全1可提前结束3周期。但通常需要4周期延迟且每2周期才能开始一条新乘法指令说明乘法器资源可能更紧张或流水线更深。divw,divwu(32位除法)19 周期 (IU2)23 周期 (IU2)延迟显著增加。整数除法是非流水线化的延迟增加4周期约21%这是追求高主频架构的常见牺牲。移位与循环slw,srw,rlwinm等1 周期 (IU1/IU2)1 周期 (IU1)无变化。sraw,srawi(算术右移)1 周期 (IU1/IU2)2 周期 (IU1)延迟增加。手册脚注解释GPR结果1周期可用但包含CA进位和OV溢出标志的完整结果需要2周期。如果你只关心移位结果而不关心标志编译器可能无法优化掉这额外的等待。条件寄存器逻辑crand,crxor,mfcr,mtcrf(多字段)1 周期 (SRU)2 周期 (IU2)延迟增加单元改变。如前所述CR操作从专用SRU移到了共享的IU2且延迟加倍。这是重要的性能回退。mtcrf(单字段)1 周期串行化{e} (SRU)1 周期无串行化(IU1)重大优化单字段写CR现在更快且不阻塞IU2。手册甚至建议如果需要设置2-3个CR字段分别用单字段mtcrf可能比一条多字段mtcrf更快。 优化策略警惕整数除法divw的23周期延迟是巨大的。在性能热点循环中尽可能用乘法、移位等操作替代除法或者预先计算倒数进行乘法运算。乘法流水线利用虽然mullw延迟是4但吞吐是每2周期1条。要发挥性能需要安排足够的独立乘法指令来填充它的流水线避免后一条乘法因数据依赖而等待。CR操作优化减少在循环内的CR逻辑操作。如果必须设置多个CR位评估使用多个单字段mtcrf指令的可能性。3.2 加载/存储指令内存访问的延迟是性能的主要瓶颈。MPC7450的加载存储单元LSU变化值得关注。指令类型MPC750/7400 延迟MPC7450 延迟变化与分析整数加载lwz,lbz,lhz2 周期3 周期延迟普遍增加1周期。这是MPC7450的一个主要变化意味着从数据缓存D-Cache命中到数据可用需要多等1个时钟周期。浮点加载lfs,lfd2 周期4 周期延迟增加2周期。浮点加载路径可能更长延迟翻倍。这对浮点密集型代码影响较大。向量加载lvx,lvewx2 周期 (仅MPC7400)3 周期延迟增加1周期。存储指令stw,stfd,stvx2 周期3 周期 通常带{s}标记延迟增加且普遍串行化。存储操作在MPC7450上需要按顺序完成{s}这限制了存储指令的并发提交可能成为瓶颈。多字/字符串操作lmw,stmw2n 周期3n 周期基础开销增加1周期。n是传输的字数。这类指令本身效率不高延迟增加使其更不具吸引力。缓存控制dcbf,dcbst2-3周期吞吐差3周期吞吐1/1 (但带{s})延迟变化吞吐改善但串行化。虽然单条指令延迟变化不大但MPC7450的吞吐量描述更清晰。然而{s}串行化意味着不能背靠背快速执行多个缓存操作。 优化策略加载延迟隐藏由于加载延迟增加指令调度变得更为关键。编译器应尽可能早地发出加载指令并在使用该数据之前插入其他不相关的指令来“填充”这3个甚至4个周期的等待时间。手动编写汇编时需要有意识地进行这种调度。避免存储转发阻塞存储指令的{s}串行化要求它们按程序顺序退休。频繁的、连续的存储操作可能会在存储队列中堆积导致后续存储指令被阻塞。适当分散存储操作或合并存储如使用stmw但需权衡其本身开销可能有益。浮点/向量加载预警lfd的4周期延迟非常可观。在浮点计算循环中必须提前很多拍发起数据加载否则计算单元会长时间空闲。考虑使用软件预取dcbt或更激进地展开循环来掩盖延迟。3.3 浮点指令浮点单元FPU是MPC7450延迟增加最显著的领域之一这与其追求更高时钟频率而加深流水线有关。指令类型MPC750/7400 延迟MPC7450 延迟变化与分析浮点加/减/乘fadd,fsub,fmul3 周期 (单/双精度加) 4周期(双精度乘 MPC750)5 周期(所有)延迟大幅增加。所有基本浮点运算延迟统一增加到5周期但吞吐量保持每周期1条 (5:1)。说明FPU采用了更深的、统一的5级流水线。浮点乘加fmadd,fmsub3-4 周期5 周期延迟增加。乘加指令非常强大一次完成乘法和加法但延迟同样增加到5周期。浮点除法fdiv,fdivs17/31 周期 (单/双)21/35 周期延迟增加。非流水线化的除法单元延迟也增加了约4周期与整数除法趋势一致。浮点比较fcmpu3 周期5 周期延迟增加。甚至比较操作也走FPU流水线延迟同步增加。 优化策略深流水线调度5级流水线意味着需要更多的独立指令来填充。对于浮点循环循环展开变得比在MPC7400上更加重要。你需要展开足够多次以产生大量相互独立的浮点操作才能有效隐藏这5周期的长延迟。善用乘加指令尽管延迟增加fmadd等乘加指令依然是将两个操作合并为一个5周期延迟指令的最佳选择应优先使用而不是分开的fmul和fadd。极度警惕除法fdiv的35周期延迟是性能黑洞。任何可能的地方都应使用近似倒数结合牛顿迭代法来用乘法和加法替代除法。这在图形处理如透视除法或物理模拟中非常常见。3.4 向量指令MPC7450继承了MPC7400强大的AltiVec向量单元但部分单元的延迟也有调整。指令类型MPC7400 延迟MPC7450 延迟变化与分析向量简单整数vaddubm,vmaxsb等1 周期 (VSIU)1 周期 (VIU1)无变化。简单的向量ALU操作保持1周期延迟吞吐量高这是向量化的优势所在。向量复杂整数vmuleub,vmladduhm等3 周期吞吐1/1 (VCIU)4 周期吞吐1/1 (VIU2)延迟增加1周期。乘法、点积等复杂操作流水线加深。向量浮点vaddfp,vmaddfp等4 周期吞吐1/1 (VFPU)4 周期吞吐1/1 (VFPU)无变化。向量浮点单元延迟与MPC7400一致是一个好消息。向量排列vperm,vspltw,vsl等1 周期 (VPU)2 周期吞吐1/1 (VPU)延迟翻倍。这是一个重要变化。向量排列/移位/打包/解包指令的延迟从1周期变为2周期。vsl和vsr甚至从VSIU移到了VPU执行。向量比较vcmpgtfp,vmaxfp1 周期 (VSIU)2 周期吞吐1/1 (VFPU)延迟增加单元改变。这些浮点比较和极值指令移到了VFPU执行延迟增加。 优化策略排列操作的成本VPU延迟翻倍需要警惕。在向量化代码中像vperm任意排列和vspltw广播这样的指令非常有用但现在它们有2周期延迟。需要合理安排指令流避免在紧接其后的指令尤其是依赖其结果的VIU1/VFPU操作前产生气泡。可以考虑将排列指令提前执行。混合单元调度AltiVec代码通常混合使用VIU1、VIU2、VFPU和VPU。由于这些单元在MPC7450上某种程度上是独立的编译器或程序员可以尝试交错安排不同单元的指令以实现更好的流水线填充。例如在等待一个VIU2的复杂整数结果4周期时可以插入VIU1的简单操作或VPU的排列操作。保持向量浮点优势VFPU延迟未变因此向量化浮点代码在MPC7450上依然能获得极高的收益。重点优化内存访问以喂饱VFPU。3.5 系统与控制指令这类指令虽然不常用但用错地方代价巨大。指令MPC750/7400 延迟MPC7450 延迟变化与分析sync3 周期 (MPC750) / 8broadcast (MPC7400)35 周期(假设5:1时钟比)延迟极高。sync确保所有内存操作完成涉及系统总线广播。其延迟与处理器/总线时钟比b相关在典型配置下非常昂贵。绝对避免在频繁执行的路径中使用。isync2 周期带{c,r}0 周期带{r}执行时间变短但仍有重取串行化。isync本身不占执行时间但会导致流水线清空和重取指实际开销取决于流水线深度。mtmsr,mfspr1-3 周期 带{e} (SRU)2-5 周期 带{e} (IU2)延迟增加仍在IU2串行化。操作MSR、SPR等系统寄存器代价高昂会阻塞IU2。 核心建议系统指令是必要的如上下文切换、内存屏障但它们不是为性能路径设计的。在关键的循环或函数中必须不惜一切代价避免使用sync、isync以及频繁的mtspr/mfspr。如果需要内存序首先评估是否可以使用更轻量级的eieio在MPC7450上为3周期带{s}或者依赖硬件本身的内存一致性模型。4. 基于延迟数据的实战优化技巧掌握了具体的延迟数据我们就可以将其转化为实实在在的优化手段。以下是一些经过验证的策略。4.1 指令调度与循环展开这是应对长延迟最经典、最有效的方法。目标是让后续指令不依赖于前一条指令的结果从而让处理器可以持续工作。示例优化一个简单的浮点点积循环单精度原始C代码可能编译成如下核心循环Loop: lfsx fp0, r4, r5 ; 加载A[i] 延迟4周期 lfsx fp1, r6, r5 ; 加载B[i] 延迟4周期 fmadds fp2, fp0, fp1, fp2 ; fp2 A[i]*B[i] 延迟5周期依赖fp0,fp1 addi r5, r5, 4 ; 更新索引 bdnz Loop ; 循环控制这里存在严重的依赖链fmadds必须等待两个lfsx的结果各4周期而下次循环的lfsx又可能依赖地址更新实际上地址计算addi是整数操作与浮点加载无关但加载本身依赖地址寄存器r5。更严重的是fmadds的结果fp2在下一次迭代中又被使用形成了跨迭代的依赖fp2的写后读相关这使得每次fmadds都必须等待上一次的5周期延迟完成才能开始无法利用流水线。优化方案循环展开与寄存器重命名我们展开4次循环并使用多个累加器寄存器来打破依赖链li r7, 0 ; 初始化偏移 li r8, 16 ; 展开后步长4*4字节 vspltisw vAcc0, 0 ; 用4个向量累加器 (每个向量含4个单精度浮点数) vspltisw vAcc1, 0 ; 相当于16个独立的标量累加器 vspltisw vAcc2, 0 vspltisw vAcc3, 0 Loop: lvx vA0, r4, r7 ; 加载A[i:i3] 延迟3周期 lvx vB0, r6, r7 ; 加载B[i:i3] 延迟3周期 vmaddfp vAcc0, vA0, vB0, vAcc0 ; 向量乘加延迟4周期 addi r7, r7, 16 lvx vA1, r4, r7 lvx vB1, r6, r7 vmaddfp vAcc1, vA1, vB1, vAcc1 addi r7, r7, 16 ... (重复加载和乘加共4组) ... bdnz Loop ; 循环后将4个向量累加器vAcc0-vAcc3相加得到最终结果优化点分析向量化使用lvx和vmaddfp一次处理4个单精度浮点数将计算密度提高4倍。展开与多累加器展开4次并使用4个独立的向量累加器vAcc0-3完全打破了vmaddfp指令之间的数据依赖。现在连续的vmaddfp指令可以每个周期发射一条因为VFPU吞吐量是1/1尽管单条指令仍有4周期延迟但流水线可以被填满。隐藏加载延迟lvx延迟为3周期vmaddfp依赖加载结果。通过展开我们在第一条vmaddfp之后立即开始为第二次迭代加载数据addi和下一组lvx。只要循环体足够大加载操作可以提前很多拍开始从而将其延迟隐藏在大量的计算指令之后。地址计算分离整数地址计算addi与浮点运算并行进行不占用浮点/向量单元资源。4.2 数据预取与缓存友好访问MPC7450的加载延迟增加使得数据预取更为重要。除了硬件预取软件可以主动使用dcbt数据缓存块预取指令。策略在计算当前数据块时提前预取下一个或多个数据块到缓存中。; 假设 r3 指向当前数据块 r4 指向下一个数据块 ; 循环开始前或上一次迭代末尾 dcbt r4, r0 ; 预取 r4 地址的数据到缓存 ; ... 处理 r3 指向的当前数据块 ... addi r3, r3, BLOCK_SIZE addi r4, r4, BLOCK_SIZEdcbt指令在MPC7450上延迟为3周期吞吐量为每周期1条且没有串行化标记开销相对较低。关键是找到合适的预取距离提前多少条指令发起预取这需要根据循环体大小和内存延迟来调整。 注意事项预取并非总是有益。预取错误预取了不需要的数据会污染缓存反而降低性能。对于步长不规则或难以预测的访问模式应谨慎使用。4.3 针对功能单元特性的优化利用IU1的非串行化mtcrf如果你需要设置多个CR位并且这些位来自不同的计算结果可以考虑分别用单字段mtcrf设置而不是用一条多字段mtcrf在IU2执行2周期且串行化。但需要权衡指令数量增加带来的解码和发射压力。整数乘法的吞吐量限制记住mullw的吞吐量是每2周期1条。如果你有一段代码密集使用32位乘法尝试将部分乘法转换为移位-加法的组合如果乘数是常数2的幂次或者尝试使用向量整数乘法如果数据可向量化因为向量简单整数乘法的吞吐量更高每周期1条。避免VPU瓶颈在新的算法设计中如果大量使用vperm等排列指令要有意识地将它们“提前”执行或者尝试用不同的数据布局来减少排列操作。例如如果数据需要频繁转置考虑是否可以在数据生成阶段就按列存储而不是在计算时通过vperm来模拟。4.4 编译器提示与内联汇编现代编译器如GCC的-mcpu7450通常已经知晓目标处理器的基本延迟和流水线信息并会进行指令调度。但你可以通过以下方式给予更多帮助循环展开提示使用GCC的#pragma GCC unroll n或__attribute__((optimize(unroll-loops)))。内联汇编对于最核心的热点循环手动编写精心调度的汇编代码仍然是终极手段。你可以精确控制每条指令的顺序以最大化功能单元的利用率并隐藏延迟。函数属性使用__attribute__((hot))标记热点函数引导编译器进行更激进的优化。数据对齐确保数组和关键数据结构的地址是16字节对齐的对于AltiVec或至少8字节对齐对于双精度浮点。未对齐的访问会导致性能损失。使用__attribute__((aligned(16)))。5. 性能分析与调试实战理论再好也需要实践验证。当你对代码进行优化后如何确认优化是否有效5.1 使用性能监控单元MPC7450拥有强大的性能监控单元PMU可以统计各种硬件事件例如周期数Cycle指令完成数Instructions Completed缓存命中/失效次数L1/L2 Cache Miss分支预测失败次数Branch Mispredicts各种停顿周期数如GPR停顿、FPR停顿、LSU停顿在嵌入式Linux或VxWorks等系统中通常有工具或驱动可以访问这些计数器。通过比较优化前后的PMU数据你可以精确量化改进效果并定位剩余的瓶颈。例如如果发现L1 D-Cache失效次数很高说明你的数据访问模式不友好需要调整如果发现GPR停顿很多可能是整数指令依赖太强或寄存器压力过大。5.2 模拟器与静态分析对于没有实体硬件或需要前期评估的情况指令集模拟器如IBM的PowerPC Simulator或QEMU的PPMU模式非常有用。一些模拟器可以生成详细的流水线活动报告显示每个周期哪个功能单元在忙碌哪里产生了气泡Stall。这比单纯看周期数更能洞察问题本质。静态分析工具如一些高级编译器的反馈信息可以指出循环中可能存在的主要依赖链帮助你确定需要展开的倍数。5.3 常见性能陷阱与排查“为什么我的向量代码没提速”检查数据对齐未对齐的lvx/stvx会导致异常或极慢的微码处理。检查依赖链使用vmaddfp等指令时结果向量是否立即被下一条指令使用确保使用了多个累加器。检查内存带宽你的循环是否只是简单地从内存加载、运算、再存回这可能受限于内存带宽而非CPU计算。尝试提高缓存命中率。“浮点循环展开后性能提升不明显”检查展开因子FPU延迟5周期理论上需要至少5-6次独立的浮点操作才能隐藏延迟。你的展开次数够吗检查寄存器压力展开过多可能导致寄存器不够用引发寄存器溢出spill即编译器被迫将中间结果存到内存这反而更慢。需要平衡。“插入了dcbt预取性能反而下降”预取距离错误预取太早数据在被使用前可能被缓存淘汰预取太晚数据没来得及加载。预取无用数据确认你预取的地址确实是接下来要访问的。缓存污染在缓存容量很小的系统中过度预取可能挤掉了更有用的数据。“系统调用或异常处理后性能骤降”检查上下文异常处理可能会使用大量系统指令如mtmsr,rfi并清空流水线。确保性能关键路径不会频繁触发异常如浮点不可用异常、对齐异常。确保中断处理程序是高效的。对MPC7450这类处理器的性能优化是一场与流水线延迟和功能单元吞吐量的精细博弈。手册中的延迟表是你的地图而理解数据依赖、掌握指令调度和循环展开技巧则是你的导航术。记住没有一劳永逸的优化最好的策略总是依赖于具体的代码和场景。从分析最关键的热点循环开始运用本文提到的对比数据、优化策略和排查方法大胆尝试并用性能监控工具验证结果。最终你会对如何驾驭这颗经典的PowerPC核心产生深刻的直觉让它在你的应用中发挥出超越其纸面规格的效能。