马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
简介 2024年AMD发布了变化巨大的一代微架构Zen5,并宣称Zen5微架构是未来几代微架构的基石。相比较Zen4,Zen5的IPC增加了16%,这个增长非常可观,同时还能实现高达5.7GHz的频率,支持AVX512变体以及FP-512,Dispatch宽度为8,6 ALU,取指和解码(Fetch/Decode)均采用双流水线,本代预计采用TSMC 4/3nm工艺,每个核具有2个线程。值得注意的是,本代的Zen5在投入更多逻辑以提升性能,却可以通过工艺的优化实现面积的平衡,于前代Zen4相比面积基本一致。 每8个Zen5核组成一个Die,服务器芯片EYPC9005最多可以配置这样的16个Die,也就是128个核,每个Die共享32MB的L3缓存。相比于前代提供了更好的性能。而Zen5c每个处理器则可以最多12个Die,每个Die有16个Zen5c,同样是每个Die共享32MB的L3缓存,可以配置的核数为96~192。
取指单元(IFU) Zen5的IFU相比较前代变化非常大,比较有特色的是采用双流水线,并且重新设计了预测器,对预测单元投入很大,前端的巨大改变是性能提升的关键因素。
预测器 考虑到后端增加了执行带宽,前端需要给出更多的指令来支持后端的需求,而预测器则是前端核心部件之一,所以本代AMD就对预测器投入巨大,非常多的组件资源投入都在加倍。AMD很多设计都是粗暴的增加组件的参数,本代了解到的是MMU核预测器投入了巨量资源,基本践行“大力出奇迹”的设计理念。 Zen5的分支预测错误惩罚是12-18cycle,这里的预测惩罚相比较ARM以及RISC-V架构的一些旗舰核是非常大的劣势,一般情况下先进的核预测惩罚压缩到11cycle,甚至有些核压缩到10cycle以下,现代处理器的预测器预测精度目前提升缓慢,所以更多的架构师尤其是精简指令的架构师越来越倾向于压缩预测惩罚时间。但X86毕竟是复杂指令集,并且需要实现非常高的频率(5GHz+),流水线深度很难做到和RISC一样的水准,并且它们的定位也不尽相同,各有自己的优劣。 预测地址的基本单位是Block,每个Block是64B,如果按照4B一个指令,那预测的带宽就是每周期16指令,这对X86架构的一些特性看(12一个跳转分支,6指令一个分支)属于相对比较合适的一个值,算是比较保守吧,如果后续能处理取指带宽的问题,估计会增大Blcok的值(实际的取指带宽受限于Cache Line位置和跳转分支位置),即使无法增大取指带宽,适当增加Block也可以获得一些潜在的收益,具体大家可以查阅一些论文。 L1 BTB是16K entry大小,这是巨大的升级,相比前代Zen4的1.5K entry,升级到10倍,有条件/无条件直接/相同目标的间接都是0预测气泡,对于Return和多目标的间接都是2cycle预测气泡,考虑到其它主流厂商旗舰的0预测气泡预测L1 BTB基本都在1K entry左右,AMD的设计可以说非常激进。L2 BTB是8K entry,如果L1 BTB MISS则会有8个预测气泡,这里非常奇怪,居然有如此巨大的气泡,因为L1 BTB巨大,所以考虑功耗的角度也不会同时访问L1 BTB和L2 BTB,再者不同类型的指令可能也是顺序的访问,但8个预测气泡还是远超过我的想象。比较RISC的一些设计,大概在10-11周期已经做分支执行了,即使在CISC的角度,这个气泡还是感觉巨大,可能需要更多信息去评价这个问题。 间接目标预测器有3072 entry,间接指令一般会有多个目标,预测会根据间接指令的历史从中选择一个目标。对于经常是一个目标的间接指令,一般用普通的BTB来预测结果,延迟也很低,这个特性如果普遍,微架构一般会在硬件上优化这个点。所以也说明代码使用间接类型的指令尽量不使用太多的目标,这对硬件来讲不友好,代码运行效率也低下。间接预测器的算法,我没有看到相关信息,但基本也是TAGE的变体。有公开资料显示,间接指令目标地址长期不变(这里的长期需要自己去调整一个合适的值),会存入延迟较低的L1 BTB。 方向预测使用TAGE算法,官方描述是更大,目前比较典型的值是8-table,有论文显示到12-table后预测精度提升就不明显了,所以现在的优化也不是持续增加表长。在TAGE的基础上做一些参数的优化,但现在一些很难预测的分支,它们的特性已经和TAGE算法基本有些背离,也不能说背离,原来就是这样,只是当时TAGE的算法没有到某个瓶颈点,现在需要挖掘不太符合TAGE算法的一些分支规律以提升预测正确率。 有意思的是,Zen5的BTB使用双口的SRAM结构,这在预测器的设计中不常见,AMD采用这个机制来实现每周期预测2-taken的分支。并且实现这个2-taken/cycle预测约束条件更少,而像其它的一些厂商会约束连续block,不能跨cache line等。这种设计思想来自30年前的论文:“Multiple-Block Ahead Branch Predictors” 对AMD架构师的采访:George Cozma: Can the branch predictor do two taken and two ahead branches in a cycle? Or is it 2 branches of total? Mike Clark: I mean it’s complicated, there’s rules around when we can do 2 ahead. But yes, in general I would say yes. George Cozma: So yes, to two branches per cycle, or yes to two ahead and two taken branches? Mike Clark: We can, in certain situations, do both. AMD实现的这个预测机制至少从理论上讲是很先进的,除了BTB是双口,亦安之前写的文章说过ICache也是双口,有3个依据,“Multiple-Block Ahead Branch Predictors”论文中写的双口Cache。AMD架构师Mike Clark: They get fed from the dual ported instruction fetch to feed the decoder。Decode是双流水线恰好对应取指的机制(这里后来证实双流水线和取指双口无关),不然预测带宽可以取两个不连续的block,取指不可以似乎有点奇怪。但C&C文章说,核心在运行单个线程时只能使用一个解码集群,这让我觉得很迷惑,可能是将无序指令重新拼到微操作队列比较困难,但这点还是不太能理解为什么是线程独占的解码集群,有说法是因为Zen5目标频率很高,所以做成共享的很困难,但AMD又偏偏没采用8宽单线程解码。后来我想了想,使用双口和双流水线的解码簇似乎是2个问题,后面也就没纠结这个问题了。顺便说一下,我之前曾说过双口ICache基本没有人这样设计,实际不是,例如高通的核ICache据说是双口 ,但还没查相关资料。 说回预测器,传统的预测流程大致是这样的,下图的i是一个block的有效指令起始位置,大的BTB是SRAM结构,访问需要下一个周期出结果,也就是一个cycle只能拿到1个block。例如Aa分支目标Bi访问获得block B,已知信息是block有效指令的起始位置Bi和block的分支Bb,然后再用Bb的目标地址获得下一个block的位置。并以此重复,每个周期只能拿到一个block的信息。当然对于全相联结构DFF构造的预测器当然可以在1cycle做这些事情,但时序难。 而论文的方案是:使用Aa分支(目标)来预测Ci,而不是传统的Bb来预测Ci,使用Bb来预测Di。需要双口SRAM。
具体的设计思想感兴趣的朋友可以参考论文,此处亦安不再赘述,设计本身比较有意思。其实在上个实际计算机体系结构发展迅速的时候,有非常多先进的体系结构思想被提出,但受限于工艺的发展,有些思想受限当时的应用目标的限制,而最近几年工艺发展迅速,也能支持厂商做一些激进的设计了。 取指窗口跟踪结构是FIFO构造,存储分支预测信息,深度是128entry,每个entry最多存储一个Cache line的信息,如果没有分支的话。但如果遇到分支,则需要另外的entry来存储跳转的信息,也就是每个entry存储的有效信息是不定的,这也很好理解,128entry也是个相对的合适的值。这个指令跟踪FIFO直到retire才会释放,如果FIFO满了,则取指流水线会stall。 ICache ICache也属于前端的核心部件,对其研究非常多,像预取,替换算法,组织结构等等都有大量的论文。Zen5的L1 Cache是8路组相联,具有32KB大小,Cache Line是64B,每个周期可以取64B的指令,需要2个对齐的32B块,这是一个瓶颈点,并且取指的双流水线不能共享,也就是如果只开一个线程,那么也不能吃满带宽,这是目前Zen5的一个问题,但考虑到Zen5要实现5GHz+的频率,看上去又合理很多。L1 Cache采用LRU替换算法,校验使用奇偶校验方式,这两个选择都很常规,各家基本都是这么做的,替换算法如果做的很复杂,面积开销大,对于L1 ICache收益没那么高,但L1 DCache目前有些应用稍微复杂的算法。这里Zen5取指带宽和Zen4相比变为2倍。前文也说过ICache可能是双口的设计,但没那么确定。这里的取指带宽只是理论上的,有测试显示在某些情况下,取指带宽弱于Zen4,考虑到前端变化巨大,有些设计非常激进,而双Decode簇又不能双线程共享,这些可能都会造成Zen5有些情况的性能瓶颈。 有意思AMD和ARM对ICache设计理念的差异也体现双方对性能功耗面积取舍不同,ARM自A76开始ICache都是4路64KB(大小有些是可配的),而AMD自Zen2一直到Zen5 ICache均是32KB/8路的设计,复杂指令集的指令信息密度更高,所以采用更小的Cache也属于正常(尽管现在复杂指令集和精简指令集界限越来越模糊)。采用不同的结构对功耗,延迟以及命中率都有不小的影响。有一些相对通用模型显示,对于32KB或64KB的给定大小下,访问延迟均是8路比4路有明显的增加,而控制路数一定,仅增加Cache大小,不管是4路还是8路,将Cache大小从32KB增加到64KB,延迟仅有小幅度的增加。而当测试读取功耗时,同样的,一定Cache大小,例如32KB或者64KB给定大小,8路的读取功耗是4路读取功耗的2倍以上,当路数不变,将缓存大小从32KB增加到64KB,4路和8路功耗增加幅度均较小。从这个模型来看,似乎使用4路而增加缓存大小对延迟和功耗平衡更好,但考虑到面积,命中率,以及有些厂商有定制工艺的角度,这种权衡不能下绝对的优劣结论,但可以看出,ARM对能效的追求非常极致,而复杂指令集似乎对性能更加关注。亦安自己做了2张图如下,实际数据可能有偏差,仅参考数据趋势即可。注意:考虑到路预测,解耦的TAG和DATA,实际的情况不会如此大差距。
关于回填,每周期可以回填一个Cache Line,也就是64B,为了处理潜在的L1 核L2之间的延迟,一般有两种比较主流的方式,更加复杂的预取算法,更加激进的预测带宽,也就是预测带宽比取指带宽大很多,这样可以提前将指令取到L1 ICache,但是如果预测精度做的不好,性能可能下降。 Op Cache OC用于存储之前解码过的指令,OC命中可以让流水线跳过取指和解码,对于复杂指令集来讲这几乎是必须要实现的特性,可以在命中时降低流水线深度,在预测错误需要恢复时如果命中也可降低惩罚周期。本代OC具有6K entry,低于前代的Zen4,仅从数量上而言似乎是退步?这是因为增加了指令融合的机制,指令密度增大,属于OC的常规优化。Zen5的OC每周期可以出12条指令,如果没有命中OC,每周期只能出4指令/每线程,这大大提高了带宽,所以OC的命中与否直接影响了性能。 OC是64 set/16路结构,每个set-way(一个entry)可以存储最多6条指令或者融合指令,融合指令可以提高OC的存储效率,其实各个SRAM结构,例如BTB/TLB,都有类似的来提升存储密度的微架构。OC使用物理tag,可以让OC被双线程共享。 这个模块对流水线较深的处理器而言是个很常规的优化,不是近几年出的技术,对于RISC而言,ARM也曾出了几代类似的结构,但后来又放弃了,如果处理器的目标频率很高,流水线很深,那么这个结构还是属于必要的设计。 关于指令融合,提高信息密度,Zen5支持的指令融合有reg-reg的MOV指令和ALU指令。有如下要求:MOV必须是reg-reg,Opcode是0x89或者0x8B ALU跟在MOV后面,并且MOV和ALU目标寄存器匹配 ALU指令的源为寄存器或者immediate数据,不能是内存源 ALU指令只能获取 MOV`` 指令的源数据或目标数据 如果 ALU 指令有两个寄存器数据,则它们应该不同 内存管理单元(MMU) L1 TLB也在这里说,ITLB是64 entry全相联的设计,存储4KB,2MB,1GB的页面,DTLB是96 entry全相联设计,存储4KB,16KB,2MB,1GB的页面。并且对4KB的连续页面进行聚合,聚合4个连续的页面。L1 TLB的设计基本是业界常规的设计,也不会有特别花的设计方式。 L2 ITLB是8路组相联,具有2048 entry,存储4KB和2MB页面,这里1GB是不存到L2的,仅存在L1 TLB,对于指令而言,操作系统基本不会分配1GB的页面,放到L2 ITLB里面可能会增加潜在访问次数,从这个角度看,放到L1 ITLB更合理(当然也可以)。 L2 DTLB是16路组相联具有4096 entry,存储4KB和2MB,额外的4路组相连结构的L2 DTLB存储1GB,具有1024entry。这里的选择是PPA的平衡,例如页面混装还是分开装的选择,分开TLB装不同页面有利于降低延迟,同时访问增大了功耗。混合装页面有利于资源利用率,一个周期的功耗相对低(但完成一个任务的功耗未必低),可能需要多次访问,这里只是简单聊下,不展开讲,不同的场景这些利弊也可能不同,不是绝对的,但不会差的太远,这里的权衡不会像我讲的那么简单。 值得关注的是Zen5的L2 TLB非常巨大,给出个横向对比,今年(2024年)ARM的旗舰服务器核V3的L2 TLB是共享的2048 entry,Intel今年的Lion Cove是1024 entry+1024entry的大小,各家的设计基本都在2K的样子,而AMD则是指令2048 entry,数据4096entry+1024entry大小,4096 entry的TLB可以理解为采用了非常激进的预取,但尤其奇怪的是给1GB的页面单独分配了一个1024的TLB,目前的软件生态真的会需要如此多的1GB页面吗?这很难说,也许考虑到了CPU的长期维护寿命。 可能会有人奇怪为什么X86常规的页面是4K/2M/1G,但TLB会存储16K/4M呢?如果大家关注过ARM的微架构,也会有类似的情况,不同于架构常规定义的页面大小,这些大小的页面是因为有硬件聚合技术,smash技术,连续技术等产生的。简单说硬件聚合就是将连续的VA和连续的PA放入同一个TLB entry来增加存储密度的,一般设计是4聚合,即4个4K页面聚合存成16K的大小。Smash技术是大页面粉碎成小页面存到TLB,这个我没有注意是不是架构支持的,如果仅是微架构支持的话可能维护需要稍微注意点。连续页面技术是架构支持的,软件配置标志位,表示连续的页面可以使用,例如RISC-V的拓展可以实现16个连续4K实现64K的页面,ARM也有类似的机制,基本都是16连续,只是更完善,连续的页面也更多。 硬件页面翻译,Zen5有6个并行的页面翻译模块,考虑到核内的TLB是单核私有的,所以在相对短的时间不会有巨大的流量访问,一般6~8个PTW就属于相对冗余的设计值了。 PWC(page walk cache)加速页面转换的过程,减少对Cache的访问,常用的技术。 在CPU上的MMU相关的微架构都非常成熟了,不同于GPU,CPU各家做的差异不是很大,都是围绕那几个点权衡,架构上和软件上的支持倒是在不停跟进,目前笔者看到的论文都没有什么微架构的创新了,对安全/虚拟化的一些支持比较多,软硬件结合的技术也很多。 解码(Decode) 解码模块比较有特色的是采用双流水线,双流水线解码32byte x2以支持ICache最多出64byte指令,每个decode流水线有20深度的队列IBQ用于对预测/取指等单元的解耦。每个解码流水线可以扫描2个IBQ entry,最多出4条指令。可惜双流水线只能给单线程使用,不可以共享,甚至当只有一个线程的时候,也只能使用一个解码簇,我不确定这个解码簇和Intel E核的解码簇技术是否类似,从各方消息来看是不一样的。不能线程共享的解码簇是一个瓶颈,不过和intel E核相比,毕竟Zen5的目标频率更高,希望后续AMD能处理掉这个问题。 两条Decode流水线来自不同的基础block,独立运行,并且这里发往Decode流水线是乱序的,这和常规我们认为Rename是乱序分界线的认知有些差异,因为X86是变长指令,所以会有类似的解码簇技术将复杂指令转换为类似RISC的微指令,来规避X86的Decode的一些固有的问题,AMD的这个模块不清楚和Intel的是否一样。
整数执行单元(IEU) 整数执行单元包含三个单元,调度器,执行单元,退休单元。整数Rename宽度为8,ALU Scheduler和 AGU Scheduler均可以每周期接受8 macro,ALU Scheduler每周期可以issue 6 micro-ops,而AGU Scheduler则是每周期可以issue4个micro-ops。 一共有6个通用的整数执行流水线,其中ALU0/ALU1/ALU2有multiply/CRC能力,ALU3/ALU4/ALU5具有PDEP/PEXT/shift/branch执行能力,ALU3额外具有divide功能。考虑到Zen5每周期可以预测2个分支,配置3个分支执行能力是一个比较合适的数值。整数multiply单元可以处理最多64 bits × 64 bits的乘法,并且是纯流水的3cycle延迟。除法单元典型延迟是3cycle,商每增加9bits就会增加一个cycle的延迟。
浮点执行单元(FPU) 该处理器原生支持 32 位单精度、64 位双精度和 80 位扩展精度主浮点数据类型,以及 128 位、256 位和 512 位压缩整数、单精度、双精度和 bfloat16 精度矢量浮点数据类型。浮点加载和存储路径宽度为 512 位。 浮点单元支持AVX-512。 浮点单元具有96 entry的NSQ,浮点Rename每周期可以接受6 macro ops,调度器有3个,均是38 entry,每周期可以issue`` 1个micro-op给流水线,一共6个流水线。退休queue和整数单元共享。
访存单元(LSU) 访存单元用于处理数据访问,L1 Dcache是12路组相联,具有48KB大小,和前代Zen4的32KB/8路相比,不管是容量还是路数都有提升,理论上讲命中率会有不少的提升,但是延迟保持的不错,DCache有8个Bank。 LSU每个周期支持最多4个对Cache的操作,所有的操作均可以是load,支持最大2个128/256bit的load或者1个512bit的load,最大支持2个store操作,如果是512bit的store,则支持最多一个store操作,带宽有了很大提升,是前代的2倍。 LSU可以跟踪64个未完成的load,并且不限制完成load的数量,同时支持动态追踪操作,可以load bypass更老的load,也可以load bypass不冲突的更老的store,做这些操作确保不会违反架构规定的load和store顺序。同时LSU可以跟踪124个未完成的L1 MISS。 关于访问延迟,简单的地址生成,L1 Cache命中,有4cycle的load-use延迟,浮点有7cycle load-use延迟。 简单的地址生成,L2 Cache命中则14cycle的延迟,浮点有17cycle的延迟。L3命中,简单地址生成有46cycle的延迟,浮点有53cycle的延迟。如果是复杂的地址生成模式,则在简单地址生成模式上增加一个周期的延迟。
二级缓存(L2C) Zen5的L2是1MB/16路,和Zen4相比大小没有变化,相联度为Zen4 L2的2倍,考虑到这点,L2的命中率应该会增加,AMD在L2的设计上和ARM/Intel这些厂商相比向来是比较小的,AMD更加重视L2的访问延迟。但是坦白说,我自己的观点,L2的容量是很重要的,延迟问题可以通过更好的预取,预测机制来覆盖,现在尤其是服务器的工作集越来越大,L2能覆盖更大的数据和指令范围真的非常重要,L2如果MISS,很多时候代价昂贵。但AMD的设计有自己的微架构考量,并且AMD的3DV Cache很受市场好评,所以这些问题可能通过3DV Cache掩盖了。
L1和L2之间带宽增加到512bit,并且优化了预取机制,官方介绍时新的2D stride预取。 本代将8T SRAMs改为6T SRAMs,密度有很可观的提升,整个核在增大不少资源投入的情况下,面积没有明显增加。下图有个Zen4和Zen5的L2和L3的面积比较,相同容量,Zen5的面积更小,当然这得益于工艺的提升,这可以让核内投入更多的资源去提高IPC,而整个处理器的面积却不会变得很大。
Zen5和Zen4比较 AMD和自己架构的纵向对比,从Zen4到Zen5从参数上升级非常激进,像类似TLB量的升级基本走了ARM5代的升级量,而某些部分的带宽升级Zen5是Zen4的两倍,L1 BTB甚至是前代的10倍,有些地方的设计让人觉得没那么关注细节,这种升级也秉承了AMD设计的一贯“大力出奇迹”设计思路,尽管据测试显示,Zen5有些方面在某些特定情况下性能甚至低于Zen4,但如果能践行一些有趣的设计思路并且完善Zen5的设计缺陷,后面的几代Zen系列架构依然值得期待。
|