计算能力已成为世界各国经济发展的重要资源,中国也不例外。该国在领域投入了大量的资源,处于这一领域的最前沿。我们之前报道了该公司的3A5000 ,这是一款四核处理器,每时钟周期的性能合理,但时钟频率太低,不具备竞争力。
本文引用地址:现在,我们来看看新推出的 。也是四核2.5 GHz的规格,但使用了新设计的LA664核心。与3A5000的LA464核心相比,LA664的进步当刮目相看。虽然LA664延续了与LA464的指令集和微架构设计,但LA664具有更宽的流水线和更多的执行单元。为了让CPU效率更高,LA664增加了SMT(超线程)支持。如果对超线程的的实现得当,SMT可以用最小的芯片面积开销提高多线程性能,但把SMT做好非常困难。
一、评估(Sizing Up 3A6000)
7-Zip是一个文件压缩工具,它能达到很高的压缩效率,但相对其它压缩工具,它可能对CPU性能的要求也更高。它几乎只使用标量整数指令,所以SIMD扩展不起作用。在这里,我们通过压缩一个很大的ETL文件来测试3A6000的性能,评估指标是压缩速度,每秒压缩的数据越多越好。
与前代相比,3A6000在不使用SMT(超线程)时,运行7-Zip的性能就已经获得了38%的巨大提升。如果加上SMT支持,这一提升还会增加。当每个CPU核心只使用一个线程时,四个LA664核心在7-Zip测试中大致相当于四个频率更高的Zen1核心。因此,LA664的每个时钟周期的性能非常高(译者注:在相同的频率下,LA664的性能接近于Intel Raptor Lake核心和AMD Zen 4代核心 )。但因为它只在2.5 GHz下运行,由于频率较低,使它的性能无法与AMD的新款CPU相比。
使用8个线程(4个物理核心)后,SMT(超线程)使3A6000运行7-Zip时的性能再提高了20%,但AMD的Zen 1和Zen 2运行7-Zip时能通过SMT获得40%以上的收益。SMT的作用是为核心提供更明确的并行性,减少平均的运行延迟并使流水线保持更加饱和的工作状态。一方面,较高的SMT增益表明CPU核心的SMT实现经过了很好的调整。另一方面,这意味着CPU核心在运行单个线程时没有很好地降低延迟。
(译者注:7-Zip的性能测试只涵盖了通用CPU性能评估的一小部分,有的CPU运行7-Zip的效率很好,但运行其它程序效率可能极差。比如在相同频率下,10代酷睿一个核心的7-Zip测试成绩不到Pentium4的3倍,但对于通用性能综合测试,10代酷睿的单核同频性能是Pentium4的5倍左右。)
与7-Zip不同,libx264视频编码大量使用SIMD指令。在x86 CPU上,编码器将使用SSE、AVX、AVX2,甚至AVX-512(如果可用)。在龙芯上,libx264将利用LSX(128bit)和LASX(256bit) SIMD扩展。在这里,我转码了一个《守望先锋》的游戏剪辑4K视频,所有CPU都只使用4个物理核心,评估指标是每秒转码的帧数,帧率越高越好。
在视频转码测试中,当启用的核心数量相同时,2.5GHz的3A6000性能可以与最高频率超过4.0GHz的AMD 1800X相提并论。在使用SMT线程以及将任务限制为每个核心一个线程时,它们的转码速度互有胜负。1800X使用Zen 1核心有较的高SMT增益,但可能受到其较弱的AVX2(256bit)实现的限制。3950X的Zen 2核心和3A6000都获得了30%以上的SMT收益。凭借全面改进的架构和稳固的AVX-512(512bit)实现,AMD最新的7950X3D中使用的Zen 4核心脱颖而出。与之前一样,3A6000仅凭借2.5 GHz的频率,性能上的表现就相当出色。
核心对核心,LA664把龙芯CPU从低性能的行列中带了出来,使3A6000能与AMD和Intel以往的高性能产品竞争。Zen 1与Haswell大致相当,即使在今天,这两种微结构的CPU仍然可用。现在,让我们来看看让龙芯能与那些更高级的产品竞争的核心微架构。
(译者注:libx264中的热点代码对龙芯LoongArch架构的汇编优化有所不足,特别是在向量指令的使用方面,通过编译器直接产生的二进制代码很难比得上程序员细致调优的手写汇编代码。)
二、核心架构(Core Architecture)
LA664是一个6发射的支持乱序执行的CPU核心,具有大量的执行资源和深度的指令重排序能力。在这些方面,它具有与最新的英特尔和AMD核心竞争的能力。
LA664是LA464演进的结果。龙芯3A5000中的LA464核心是一个4发射的支持乱序执行的核心,在各个方面的规格都比较适中。LA464是一个全面而实用的核心,几乎没有明显的弱点,为龙的进步奠定了坚实的基础。毫无疑问,LA664继承了LA464的微架构设计。
当然,框图并不能说明全部情况。分支预测、执行延迟和内存访问性能等因素都会产生巨大影响。
三、龙芯3A6000的前端(The Loongson 3A6000’s Frontend)
分支预测(Branch Prediction):
CPU分支预测器负责预判程序最可能执行的分支,并把跳转的方向告诉前端,这一点非常重要。因为如果分支预测的方向错误,CPU的后端在错误的分支上运行会浪费大量的性能、电能和时间,并要再消耗一些时间才能回到正确的分支上。
3A6000的分支预测器具有令人印象深刻的模式识别能力,是迄今为止我们所见过的中国CPU中最好的。它与我们在3A5000中看到的不同,3A5000与最新的Intel和AMD CPU相距甚远。然而,由于AMD一直在分支预测功能上大力投入,它们的Zen 3架构仍然领先一步。
Zen 3通过一个覆盖预测器(overriding predictor)来实现这一点。大多数分支具有简单的行为,并且可以由第一级快速处理,能力更强但速度较慢的第二级只需介入一些跨度较长的分支即可。有了这个方案,Zen 3的分支预测器能够在保持高速的同时跟踪很长的分支。
即使3A6000不能与AMD最新的核心相媲美,龙芯也取得了值得称赞的进步。3A5000的分支预测器看起来更适合从00年代中期到10年代初的高性能内核,而不是最近这十年的东西。龙芯在这一领域的投入无疑是3A6000效率提升的一个重要因素。
分支预测器速度(Branch Predictor Speed):
分支预测器必须既快速又准确,以避免核心空载浪费时间。分支目标缓冲区(Branch Target Buffers,BTB)用来缓存分支目标,使预测器跟随指令流,而无需等待实际的分支指令出现。LA664有一个64条目的L1 BTB,能够快速处理连续预测,在AMD的术语中称为“零气泡(zero bubble)”。BTB未命中的时候,很可能是通过简单地等待指令字节从64KB的指令缓存到达,然后通过分支地址计算器来计算目的地来处理的,这实际上看起来像是绑定到指令缓存的1K-4K条目的L2 BTB。
相比之下,AMD和Intel最新的微架构使用了与指令缓存解耦的大型L2甚至L3 BTB。从另一个BTB级别获取地址可能比等待指令字节到达更快,AMD的Zen 4利用这一点,只要BTB包含了这个分支,就可以实现延迟非常低的分支处理。
此外,将BTB与指令缓存解耦有助于在代码块超出L1i容量时保持高IPC,因为预测器与L1i未命中时产生的延迟隔离。但龙芯不是唯一一种放弃庞大的、解耦的BTB设计的CPU,Tachyum-Prodigy同样认为这种方法过于昂贵,因为他们很难用标准的单元库达到频率目标。与Tachyum的Prodigy一样,3A6000通过使用64KB的大指令缓存来补偿这一点。如果预测器必须处理较少的L1i未命中延迟,那么这一些弱点就无关紧要了。
3A6000似乎还具有更积极的线性指令预取功能。上面的测试只是让分支跳到下一个16字节对齐的块,所以线性指令预取器可以很好地处理。相比之下,AMD的预取似乎完全由分支预测器驱动。一旦我们超过了BTB容量,我们基本上都会看到L2延迟。
间接分支预测(Indirect Branch Prediction):
间接分支比直接分支更难预测。间接分支要跳转到的目标不是直接编码到程序中,而是跳转到寄存器中的地址,3A6000在间接分支预测方面做得很好。
3A6000总共可以跟踪1024个间接目标,是3A5000的两倍。3A5000只能跟踪大约24个独立的间接分支,而3A6000可以跟踪128个以上独立的间接分支。相比之下,Zen 2也可以跟踪1024个间接目标,因此3A6000与最新的x86 CPU非常一致。
“返回”预测(Return Prediction):
“返回(Return)”操作是一种特殊的间接分支,通常与子程序调用(Call)成对出现。对于许多计算机处理器来说,使用堆栈来保存要返回的地址是很常见的。当分支预测器发现调用(Call)指令时,它会将当前地址推入该堆栈。当它遇到返回(Return)指令时,它会从堆栈中弹出一个地址。奇怪的是,3A6000最终将返回堆栈从3A5000中的32个条目减少到只有16个条目。如果两个核心的SMT线程都处于活动状态,则有效容量可能会进一步下降到8个条目。
将返回堆栈容量降至16个条目在一定程度上是合理的,因为即使是较小的返回堆栈也可以捕获大多数调用/返回情况。龙芯CPU可能是用间接分支预测器来处理超出条目数量的情况,因为超过返回堆栈能容纳的数量时,3A6000只会出现适度的性能下降。英特尔也采用了同样的策略,在这种情况下,返回堆栈可以被视为对功率和性能优化,而不是性能的关键。
分支预测精度(Branch Prediction Accuracy):
7-Zip和其它压缩工作负载通常给CPU分支预测带来巨大挑战。3A6000的分支预测器处理能力令人钦佩,对每条指令的预测失误方面与Zen 1不相上下,在准确性方面,3A6000与Zen 2平分秋色,在这种情况下,准确性是一个更好的指标,因为3A6000完成工作执行指令的更少。
因为Loongson的指令流中有更大比例的指令由分支组成,所以每条指令的预测失误率更高。AMD最新的Zen 4架构仍然领先一步,但龙芯在其分支预测器方面取得了值得称赞的进展,3A6000令3A5000望尘莫及。
libx264具有更少的且更容易预测的分支,但我们仍然可以看到测试的CPU之间的差异。在这个测试中,ISA(指令集)差异对龙芯有效。3A6000每条指令很少出现预测失误,但这是因为它执行了更多的指令来完成工作。当有更多的非分支指令需要处理时,预测失误的比例就会降低。
(译者注:libx264的热点代码对龙芯LoongArch指令集的汇编优化有所不足,通过编译器直接产生的二进制代码通常会比优秀程序员手写的汇编代码冗长一些。)
3A6000分支预测器的性能与AMD的Zen 2旗鼓相当。龙芯再次表明,在设计准确的预测器方面,他们可以和巨人一起玩。
指令获取(Instruction Fetch):
一旦分支预测器决定了代码的前进方向,目标代码就会被加载到指令缓存中,并保留数据便于CPU核访问代码。和3A5000差不多,3A6000有一个64KB的4路L1i(一级指令缓存),与只有32KB L1i的英特尔和AMD CPU相比,这是一个不错的L1i。64KB的L1i以及6个解码器,使3A6000的前端比上一代产品加宽了50%。
AMD和英特尔的高性能CPU使用微操作缓存,这可以避免指令解码成本,同时提供更高的吞吐量。自Zen以来,AMD的微操作缓存理论上每个周期可以提供8个微操作,但核心的吞吐量受到下游重命名阶段的限制。
龙芯3A6000在代码块大小超出L1i容量仍时保持了良好的吞吐量。3A5000在从L2运行代码时会莫名其妙地遭遇指令带宽降低的问题,龙芯在3A6000中解决了这一问题。当代码在L2中时,3A6000可以轻松地每周期执行3条指令。
不幸的是,当代码在L3中时的情况并不乐观,看起来3A6000似乎没有改进从L3获取指令的能力。这是一个遗憾,因为Golden Cove和Zen 3每个周期都可以获得3个4字节的指令,而龙芯CPU每个周期获得4字节指令的数量低于2个。
四、重命名和分配(Rename and Allocate)
一旦指令被解码为微操作,核心就必须分配后端跟踪资源(译者注:一般为指令重排序缓冲区和内存重排序缓冲区)。这些资源将会跟踪指令状态,并让核心在输入的数据准备好后立即执行指令,同时仍然确保正确的程序行为和异常处理。这个阶段还通过寄存器重命名消除了依赖关系,并且是实现动态调度以及使用各种技巧为指令执行增加额外并行性的重要环节。
LA664的重命名器对寄存器清零有一种特殊的方式,x86 CPU总是通过XOR操作把寄存器清零,LA664不使用此类操作,这意味着清零操作不会消耗运算单元的资源。
龙芯的重命名器还对寄存器到寄存器的移动进行了一些优化。每个周期能执行两个move r,r指令,因此LA664有时可以在寄存器别名表中进行指针操作,以打破这种依赖关系。然而,它不能以全速率进行,并且寄存器到寄存器的移动仍然需要ALU(算术逻辑运算器)参与。
英特尔和AMD都开发了更先进的重命名器,能够完全消除寄存器到寄存器的移动,而不考虑依赖性。Intel的Golden Cove还可以在重命名阶段通过较小的即时性添加来消除添加,进一步减少执行单元的负载。
五、乱序执行(Out of Order Execution)
为了实现乱序执行,在重命名和分配阶段必须在必要的队列和缓冲区中找到条目来跟踪指令状态。更大的缓存区可以让核心在指令流中回溯更远,从而更好地发现可以并行的指令。龙芯3A6000有一个规模较大的乱序引擎,比3A5000有了很大的进步。
与3A5000相比,寄存器堆和内存重排序队列等主要结构的大小至少增加了25%。LA464的分支顺序缓冲区过小,LA664对此进行了改进。LA664最终具有与AMD的Zen 3相当的重新排序能力。与英特尔的Golden Cove相比,Zen 3和LA664仍然很小,后者拥有巨大的512个条件的ROB和其它更大的结构。
六、超线程实施(SMT Implementation)
更大的乱序缓冲区对于提高单线程性能至关重要,但增大缓冲区的回报会很快减少。SMT通过向操作系统提供多个逻辑核心并在线程之间划分资源来抵消这些递减的回报。因此,启用SMT的CPU可以保持最大的单线程性能,同时在多个硬件线程空闲时能像几个较小的核心一样工作。AMD、Intel和龙芯都是每个核心暴露两个SMT线程。
虽然SMT的好处显而易见,但实施起来却很困难。当操作系统在多个硬件线程上调度工作时,核心必须实时重新配置自己。工程师必须决定如何在两个线程的模式下管理各种核心资源。也就是说,SMT的结构可以是:
双倍资源:每个线程都拥有资源的一个副本。在一线程模式下,第二个副本只是未使用。这会浪费芯片的面积,但可能更容易调整和验证。不必担心资源会被一个线程耗尽,当第二个线程也处于活动状态时就无法获得可用的资源。
静态分配:每个线程获得一半的资源。当一个线程处于停止状态时,另一个线程可以使用所有条目,因此这种方法能更有效利用芯片面积。但这很难验证,因为当两个线程都工作时,资源将不得不被耗尽并重新配置。但调整仍然不太难,因为将资源分成两半可以确保线程之间的某种程度的公平性。
动态调整:在双线程模式下,一个线程消耗的资源条目可以超过一半。这有更大的灵活性和更潜在的性能,但调优更难。更高的资源分配可以提高一个线程的性能,但对另一个线程会产生不成比例的影响(使其缺乏关键资源)。
竞争性共享:所有线程都是自由使用所有资源。即使一个线程处于活动状态,另一个线程也可以使用所有条目,灵活性和潜在性能最大化。例如,如果一个线程正在运行浮点代码,而另一个线程在运行纯整数代码,那么竞争性地共享调度器将使两个线程都能满足资源需求。但调整和验证变得更加困难,缺少资源是一种更常见的可能性,工程师们必须小心避免这种情况。
龙芯选择了一种保守的SMT实现方式,其中大多数资源都是静态分配的。包括ROB、寄存器文件和加载/存储队列。
3A6000上的部分资源是动态调整,整数运算调度器最高似乎能使用30个条目左右,因此即使SMT同级线程处于活动状态,运行在3A6000上的线程也可以与在3A5000上运行时使用几乎一样多的调度器条目。
AMD的Zen 2静态地划分重排序缓冲区,并对浮点运算调度器和非调度队列使用某种动态分配方案。但除此之外,AMD选择了一种非常激进的SMT实现方式。寄存器文件、加载队列和整数调度器是竞争性共享的。这可以部分解释Zen 2令人印象深刻的SMT提升。
对于龙芯来说,采取一种不那么激进、更容易验证的方法可能是合理的。3A6000是他们的第一款支持SMT的CPU,过于雄心勃勃反而是容易失败的路线。
七、整数运行(Integer Execution)
3A6000的整数执行部件与前代相比变化最小,但增加的50%的调度条目应该会提高ALU(算术逻辑单元)利用率。与3A5000一样,3A6000有四个ALU部件,能够执行最常见的操作。两个端口可以处理分支,两个端口可用于整数乘法,这样的设计与Zen 2大致相当。但与Zen 2相比,龙芯有两个整数乘法部件。Zen 2具有更大的总调度能力,但将Zen 2的分布式调度器与龙芯的统一调度器进行比较并不简单。Zen 2可能会遇到16个入口队列中的其中一个在其他队列之前填满的情况,这将导致重命名器处的资源停滞。
龙芯将整数除法吞吐量从3A5000的0.11指令/周期提高到了0.25指令/周期,把延迟从9周期降低到了4周期。这种改进是一个奇怪的选择,因为大多数代码避免使用除法指令,因为它们从以前到现在都非常慢。也许是因为龙芯必须从头开始构建他们的软件生态系统,所以增加晶体管的数量提高运算单元的速度是值得的。
八、矢量和浮点运行(Vector and Floating Point Execution)
龙芯的3A5000具有LASX扩展的256位矢量功能,但采用了仅两个256位单元的保守实现。3A6000对FPU进行很大的修改,它现在有四个执行单元。所有四个单元都可以处理封装为256位的浮点加法运算,使3A6000具有非常强的浮点性能。竞争对手(译者注:兆芯和海光)的x86 CPU每个周期只能进行两次封装为256位的浮点运算。龙芯对封装为256位的浮点乘法和基本整数运算的性能与Zen 2相似。
奇怪的是,标量浮点运算并没有得到同样的增强,只有两个部件可以处理标量浮点运算。更奇怪的是,标量浮点乘法似乎使用了与矢量乘法不同的单元。
尽管龙芯增加了额外的浮点单元,使整体的浮点性能有所提升,但峰值融合乘加(FMA)吞吐量没有改变。LA464和LA664每个周期都可以执行一次FMA操作,使其FMA吞吐量达到AMD的Zen 2或Intel Skylake的一半。
除了提高吞吐量,龙芯还降低了执行延迟,浮点加法的延迟为3个周期,与Zen 3一样。然而,AMD的Zen 3和英特尔的Golden Cove总体上仍然具有更低的浮点执行延迟。尤其英特尔可以在2个周期延迟的情况下完成浮点加法,并且在更高的时钟频率下也可以做到。
与整数功能一样,浮点调度程序条目也增加了50%,达到48个条目。这本身可能比额外的执行单元提供了更多的浮点性能提升,两者共同使3A6000在矢量和浮点工作负载方面成为一款强大的CPU。
AMD的Zen 2也有四个FPU(浮点计算单元),也可以将所有四个单元用于基本的矢量整数运算。然而,它使用了一个巧妙的非调度队列,即使36个条目的调度器已满,也可以避免重命名器停滞。这使得后端可以动态地保存更多的浮点或矢量操作,即使它不能通过搜索这些操作来找到额外的指令级并行性。
九、地址生成(Address Generation)
与LA464相比,龙芯在LA664上极大提高了地址生成能力。LA464有两个通用装载(读内存)/储存(写内存)部件,LA664将其分成两个装载(读内存)部件和两个储存(写内存)部件。
这意味着LA664每周期可以处理比Zen 3更多的标量内存操作,并且可以处理与Golden Cove相同数量的内存操作。不过Zen 3和Golden Cove更灵活,因为与LA664的每个循环2个装载操作相比,它们在一个循环中最多可以发出3个装载操作,但这是对LA464的每个循环单个操作的重大升级。至于向内存写入数据,LA664、Zen 3和Golden Cove(12代酷睿)在每个周期都是2个标量储存操作,而LA464在每个周期只能处理一个储存操作。LA664每个周期可以处理两个256位矢量访问,这些也可以是加载和存储的任意组合。
十、内存排序(Memory Ordering)
一旦生成了地址,加载/存储单元就必须确保内存访问看起来是按程序顺序执行的(译者注:会根据实际的指令执行顺序调整内存访问顺序)。加载时也可能必须从刚刚进行的存储中获取结果(译者注:执行内存写操作后,数据要数个周期后才能真正地保存到内存中,此时不能从内存中加载刚刚存储的数据),与先前的3A5000一样,3A6000可以处理从大约7个周期内的先前存储中加载的情况。部分重叠的情况会导致14个周期的损失,可能加载操作会被阻塞,直到存储操作完成并写回L1D(一级数据缓存)。
Zen 2具有相同的7周期延迟和14周期部分重叠产生的损失,但Zen 2可以处理64字线缓存上的转发,只需额外的周期损失,而龙芯则很难处理这种情况。由于Zen 2可以运行的频率比LA664高得多,因此7个周期的转发延迟对于龙芯来说损失的时间更长。Goldmont Plus的目标频率在2 GHz以上,具有5个周期的存储转发延迟和10个周期的故障情况。
LA664的存储转发行为看起来很像它的上一代,但LA664消除了因地址未对齐(译者注:通常当内存地址不是4或8的整数倍时就是未对齐)而造成的10个周期的损失,并将其降至仅3个周期。这方面LA664比Zen 2稍微好一点,Zen 2需要2到5个周期来处理地址未对齐的存储。
跨越64字节边界的存储转发处理仍然很差,但损失已经从31个周期下降到了可以容忍的21个周期。
下面分别是3A6000和3A5000存储到加载转发延迟测试,使用Henry Wong的方法测量,代码由Clam基于LoongArch指令集编写:
十一、缓存和内存访问(Cache and Memory Access)
良好的缓存和内存层次结构对于保持现代高性能CPU的数据供应至关重要。3A6000保留了与3A5000类似的缓存层次结构,但总体上略有改进。
由于龙芯CPU无法动态提高时钟速度,因此他们通过缩短流水线访问缓存的路径减少延迟。
延迟(Latency):
3A6000的L1D(一级数据缓存)延迟从3A5000的四个周期下降到了三个周期。我认为低时钟CPU的目标就是3个周期的L1D延迟,很高兴在3A6000上看到这一点。
许多现代CPU将L2(二级缓存)用作中间缓存,以便在L1(一级缓存)未命中时与延迟相对较高的L3(三级缓存)隔离开来。3A6000与以前的Intel CPU一样,继续使用256 KB的二级缓存,较新的AMD和Intel CPU倾向于使用更大的L2。Zen 4使用了1MB的L2,而英特尔的Raptor Lake则选择了2MB的L2。尽管龙芯没有实现更大的L2,但他们确实设法将延迟从14个周期降低到了12个周期。假设L1以相同的速度处理命中和未命中,L1到L2的路径可能只减少了一个流水线级。
Zen 2、3A6000和3A5000都具有一个由四个核心共享的16 MB L3缓存。3A6000将L3延迟减少了几个周期,尽管这可能是因为检查L2的速度快了两个周期。
最后,访问DRAM的延迟从144ns缩短到了104ns。3A5000有一个(延迟)可怕的DDR4控制器,它之所以被使用,是因为它的运行频率较低,意味着虽然延迟时间较高,但时钟周期计数却和主流产品相近,也就是说对IPC的影响很小。
3A6000的内存控制器得到极大的改进,虽然104 ns的延迟仍然不太好,但它的周期计数方面的延迟远低于频率更高的3950X。因此,3A6000至少通过减少DRAM存取延迟的周期弱化了低频率的一些缺点。尽管如此,对于单片芯片上的DDR4-2666设置来说,104 ns并不是很好。
虽然3A6000的周期计数延迟具有竞争力,但我们必须考虑实际延迟时间。因为龙芯的CPU频率无法接近现代AMD和Intel CPU,它在包括L1在内的每个缓存级别都较慢。这就解释了为什么尽管LA664有比Zen 2更强的重新排序能力和更高的IPC,但基于LA664的3A5000在很多方面反而不如基于Zen 2的产品。
带宽(Bandwidth):
内存带宽会影响性能,尤其是对于矢量化的多线程应用程序。3A6000在很大程度上继承了上一代的内存层次结构,但龙芯再次在各个方面进行了改进。
3A5000的每周期L1D带宽就已经与英特尔的Skylake或AMD的Zen 2类似了,3A6000则通过改进,实现了写入带宽翻倍。基本上,3A6000的任何写入和读取组合都可以在每个时钟周期以256bit的位宽访问两次L1D。
因此,尽管3A6000的频率很低,但它具有令人印象深刻的L1D写入带宽。LA664打破了Golden Cove的唯一,和它一起成为了存储带宽达到每个周期512bit(译者注:原文此处误写为byte)的面向消费市场的CPU核心。
下图是三款CPU的单线程读写缓存和内存时的带宽,其中AMD是服务器CPU的数据,因为我手上只有这个数据。访问小尺寸数据时是CPU内部的L1、L2、L3缓存在起作用,随着读写数据的尺寸增加,超过缓存的容量后,会很快降低到访问物理内存时的读写带宽。
(译者注:从本文后面的内容可知,作者测试龙芯CPU时是使用的DDR4-2666内存,但3A5000及3A600都支持DDR4-3200内存,因对内存带宽的测试结果没有完全体现出龙芯CPU访问内存的速度。)
下图是三款CPU多线程读写内存时的带宽:
LA664的256KB L2基本上与上一代相同,每个读取带宽周期有21-22字节,写入带宽相同。因此,3A6000的每周期L2带宽仍然低于AMD或Intel 最新的任何CPU。与Intel CPU相比,这一差距变得特别大,后者到L2的路径每周期能访问64字节。
下图是三款CPU每个时钟周期的内存访问带宽:
在访问L3的阶段,LA664的带宽比前代增加了33%。L3的18.7字节/周期使龙芯的表现好于以前的英特尔CPU,但AMD异常强大的L3实现仍然领先。
为多个核心设计共享的缓存带来了额外的挑战,因为必须扩展缓存带宽以满足多个核心的访问。当所有硬件线程都在载入数据时,3A6000可以在每个时钟周期为每个核心提供16.55个字节。这比在只有一个核心运行而没有其他核心竞争的情况下所能得到的只少一点,总体上表现非常好。较旧的3A5000在所有四个内核都已加载的情况下,每个内核每个周期只能提供略高于10个字节的数据,而在单个内核处于活动状态的情况下每个周期可以提供13.7个字节。这表明3A5000的L3在多核同时访问时存在争抢,3A6000在很大程度上解决了这一问题。AMD的Zen 4再次提供卓越的L3带宽,即使多个内核正在访问缓存,每个内核的每个周期也超过24字节。
龙芯的3A5000有一个糟糕得可怕的DDR4控制器。谢天谢地,3A6000有一个更好的。它在技术上支持DDR4-3200,但在使用两个内存通道时,我们无法以3200的速度稳定启动(译者注:龙芯的CPU和主板对内存的兼容性不如Intel和AMD,但整机配套的以及经销商推荐的型号都是经过测试验证的)。当配备双通道DDR4-2666时,3A6000实现的DRAM读取带宽大致与Core i5-6600K不相上下。该芯片的第一代DDR4控制器只能以完美的稳定性使用DDR4-2133(至少我得到的样品是这样),但与具有更快内存的3A6000相比,它具有更好的DRAM读取带宽。
尽管3A6000的DRAM读取性能平平,但它在写入方面确实有诀窍。当龙芯检测到缓存被覆盖而不依赖于其先前的内容时,它可能会避免读取访问请求。这可能有助于某些访问模式,但好处可能有限,因为程序的读取量往往远远多于写入量。
十二、核心到核心延迟(Core to Core Latency)
这项测试使用原子指令的比较和交换操作,获得每个核心之间信号反弹的时间。
龙芯3A6000的表现没有带来任何惊喜,但这是一件好事。
十三、结束语(Final Words)
龙芯的工程师们有很多值得骄傲的地方。创建一个与Zen 2类似的分支预测器并不容易,考虑到龙芯在3A5000中的表现,这一成就更加令人印象深刻。同样,SMT也很难做好,龙芯成功地做到了这两件事。同时龙芯大幅扩大了乱序执行的规模,并改善了其DDR4控制器的性能。由此带来的巨大性能提升使基于LA664的3A6000与主频4.0GHz左右的Zen 1架构的CPU不相上下,至少当物理核心的数量相同时是这样。
中国在努力减少经济发展依赖外国CPU的情况,3A6000是努力的一部分。在减少对外国依赖这方面,3A6000是向前迈出的一大步。Zen 1在今天仍然很实用,所以中国消费者可能会发现3A6000的性能对于轻量级的日常任务来说是可以接受的。龙芯的软件生态系统对芯片可用性的影响将远远大于其性能。
但龙芯的次要目标是与Intel和AMD等西方公司一起成为世界级的CPU制造商。在这方面,他们还有很长的路要走。Zen 1级单核性能值得称赞,但我们必须记住,Zen 1在与英特尔的竞争中获得了市场份额,是因为它将价格合理的6核和8核产品带入了消费者平台,而不是因为它可以在与Skylake的竞争中赢得核心对核心的胜利。3A6000只是一个四核产品,因此缺乏Zen 1最大的优势。
龙芯还将3A6000与英特尔的酷睿i3-10100进行了比较,后者是一款四核Skylake产品,具有6 MB的缓存和4.3 GHz的睿频。虽然名义上是第10代部件,但i3-10100与2015年的酷睿i7-6700K(译者注:i7-6700K是6代酷睿的最高端型号)更具可比性。英特尔的第10代更广为人知的是,它将10核CPU纳入了公司的消费级产品阵容,其中6核和8核产品构成了中端产品。除了更多的核心之外,i5-10600K和i7-10700K等部件还具有更高的睿频。3A6000将无法与这些产品竞争。龙芯还将与Zen 2作斗争,我们已经看到3950X在核心对核心的测试中战胜了3A6000,但只有当超过四个Zen 2核心发挥作用时,这种差距才会扩大。
如今,英特尔的Golden Cove衍生产品和AMD的Zen 4比3A6000的优势更大。AMD和英特尔的消费级产品阵容中基本上都没有四核产品。龙芯的3A6000可能是我们在中国看到的最有前途的CPU,它比迭代ARM A72的拙劣尝试更令人兴奋。但龙芯的工程师们仍有工作要做,我们期待着看到他们下一步的表现。