小tree_666 小tree_666
关注数: 333 粉丝数: 520 发帖数: 2,956 关注贴吧数: 43
66的u-arch小课堂——trace cache 拖更的有点久,emm,理解万岁()。那么话不多说,直接进入正题。 我们都知道,Apple的微架构还是非常强的,尤其是front-end,业界除了IBM,最强就是Apple了,但是我们也知道Apple缺失了2-taken branch这个feature,什么是2-taken?顾名思义,1个cycle里处理两个jump的预测技术,以提高fetch的吞吐量。传统的分支预测器通常在一个周期内只能预测“1-taken”(即最多一个分支为 taken),遇到连串的分支指令时,后一条分支要等前一条预测完成才能继续预测,会导致取指停顿。2-taken 则将这一带宽扩展到同时预测两条taken分支,减少了流水线空泡,提高了分支密集型代码的执行效率。在日常的workload中,按照一般3-4条指令一次跳转,两三次跳转一个taken来算的话,基本上让超过6-wide的部分用处不大了,这个还是挺要命的,所以,2-taken就十分之重要,虽然Apple在Donan做了一个比较简化的2-taken,即只要在同一个fetch group中间加个小direct taken,target也在fg里面,但是这个2-taken的泛用性太差了,聊胜于无。如果像ARM,AMD,intel去做完整的2-taken,那么消耗将非常大,你需要做双端口指令获取与解码流水线,双端口 BTB 与分层 BTB 结构,多窗口预测与第三预测窗口,对于Apple来说,完整的做2-taken会推翻目前Apple现有的front-end和对应的pipeline,这是一个吃力不一定讨好的策略,所以我们是否有基于现状的更好的策略,可以通过小改实现同样甚至翻倍效果的技术呢?有的兄弟,有的,trace cache,或许是新的解法。 那么今天我们来讨论一下有关trace cache以及其衍生技术,不过首先我们需要了解一下,什么是trace cache。 Trace Cache是一种用于processor’s fetch front-end(处理器取指前端)的高速缓存结构,其核心思想是缓存一条条“trace”——即跨越多个基本块(basic block)的连续指令序列,而非传统上按basic block(基本块)或cache line(缓存行)存储指令。这样做的目的是提高指令提取带宽,减少因重复访问指令缓存而引入的延迟及功耗,同时改善pipeline(流水线)的continuity(连续性)。通过caching(缓存)整个trace,当程序沿着predited execution path(预测的执行路径)运行时,处理器可以一次性提取较长的指令序列,从而降低branch misprediction(分支预测失误)对front-end performance(前端性能)的影响。 在了解了什么是trace cache后,我们来讲讲基于trace cache的技术——Optimized Design of a Trace Cache Architecture Based on Bias-Controlled Transfer Instructions(基于偏向性控制转移指令的Trace Cache架构优化设计) 摘要: 本文将详细介绍一种处理器Trace Cache(迹缓存)优化架构,其核心思想是利用控制转移指令的偏向性(bias)来提高迹缓存的有效性和效率。该架构将控制jumpinstructions(转移指令)按execution history(执行历史)分为“稳定”(stable)和“不稳定”(unstable)两类,仅允许stable jump control instructions(稳定控制转移指令)作为trace cache中的内部指令,而将unstable jump control instructions(不稳定控制转移指令)限制为只能出现在迹缓存末端。通过这一策略,processor(处理器)能够在保证高指令提取带宽的同时显著reduce trace cache misprediction(降低因迹缓存误预测)而导致的开销,并减少实现复杂度和硬件资源消耗,因而在性能和能效上相对传统架构具有优势。接下来本文会从,对该架构进行背景介绍、技术方案描述、模块与流程分析,并结合专利图示深入阐述“Less-Stable Before End (LBE)”方案的意义与作用,最后讨论其性能优势和应用前景。
66的u-arch思绪飞扬 听说8E2的CPU cluster,all core use shared L2 cache,这个desigb很有想法,这让我想到了HPCA25的一个paper,IBM的latera cache persistence algorithm,每个 L2 在eviction (替换)时,会把被换出的cache line通过ring bus“latera”(横向)write到最空闲或最少活动的 L2 里(这是“虚拟 L3”的实现原理:把原本要逐层写到大 L3 的数据转而写到某个在同作用域的 L2)。 在server层面同理:若在本芯片 L2 都无法容纳了,就把该行再“横向”写到另一个芯片上最空闲 L2(对应 vL4 作用域)。这样数据在 cache line 的生存期中会多次“lateral move”(横向移动),直到最终write back memory。 这样就让各个 L2 协同,像一个共用大缓存一样工作,无需真正构建巨大的统一物理 L3 / L4,还可以在配置更改、技术演进、芯片数量/server数量变动时灵活适配。 我们来看原理 基本原理 1.依赖活动计数器跟踪每个缓存单元(片内:8 个 L2;机柜内:8 片芯片)的安装/驱逐事件;时选取最低计数器的单元作为溢出目标(即 LRU 范围扩展); 2. miss时选取最低计数器的单元作为溢出目标(即 LRU 范围扩展); 3.溢出事件分级触发: (1)Primary Castout (PCO):本地 L2 → 目标 L2; (2)Secondary Castout (SCO):若目标 L2 再驱逐,则流向最低活动芯片的 L2; (3)Tertiary Castout (TCO):最终写回对应内存端口或失效。 该机制将 L2 作为多级“Victim Cache”,在片内/机柜内构建虚拟 L3/L4,镜像传统包容性层级行为,又充分利用所有 L2 资源 自适应插入策略当应用工作集能驻留本地 L2 时,单一缓存计数器失衡会导致重复溢出并驱逐自身常用数据;引入中间 LRU插入:横向溢出行插入至行内第 1/n MRU 位置,而非最 MRU;若检测到溢出内容占满该插槽,则切换为 MRU 安装,以支持小工作集。 为什么会这样?因为传统的设计当你在L1 miss了,你就得snoop to L2,L2再miss你得上L3,SLC,隔壁L2/L3,DRAM。这样会产生 long latency,并且产生更多的energy waste。所以,我们可以让临近的不怎么用的shared L2/3 cache block当virtual L3/4。可以在一些high cache stress上获得+9-11% performance。 但是这么做,这是有代价的,IBM有好像17种L2 cache state,并且核心一多coherency直接裂开,想想每次L2 miss就要给所有L2发snoop……hhh,snoop满天飞。并且必然要解决你放data的时候别的L2 cache不忙,你读data的时候人家开始忙了的问题。
1 下一页