我已经了解了不同的缓存映射技术,如直接映射,关联映射和集合关联映射技术,还学习了权衡.但我很好奇现在在intel core i7或AMD处理器中使用了什么.以及这些技术是如何演变的.还有哪些事情需要改进?
1> Peter Cordes..:
直接映射的缓存基本上从未在现代高性能CPU中使用.对于相同大小的组关联高速缓存,命中率的巨大优势抵消了功率节省,而控制逻辑中的复杂性稍高.如今,晶体管预算非常庞大.
对于软件来说,至少有一对彼此相距4k的倍数的阵列是很常见的,这会在直接映射的高速缓存中产生冲突丢失.(如果循环需要一次遍历所有数组,那么调整具有多个数组的代码可能涉及使它们倾斜以减少冲突丢失)
现代CPU速度非常快,DRAM延迟超过200个核心时钟周期,即使对于强大的乱序执行CPU而言,它也非常大,可以很好地隐藏缓存未命中.
多级高速缓存是必不可少的(并且用于所有高性能CPU),以便为最热门的数据提供低延迟(~4个周期)/高吞吐量(例如,每个时钟最多2个负载和1个存储,128,256或者甚至是L1D缓存和向量加载/存储执行单元之间的512位路径),同时仍然足够大以缓存合理大小的工作集.在物理上不可能构建一个非常大/非常快/高度关联的缓存,其执行与典型工作负载的当前多级缓存一样好; 数据必须物理移动远的光速延迟是一个问题.电力成本也是令人望而却步的.(事实上,功率/功率密度是现代CPU的主要限制因素,请参阅现代微处理器:90分钟指南!)
所有级别的缓存(除了uop缓存)都在我所知道的所有x86 CPU中进行物理索引/物理标记.大多数设计中的L1D高速缓存从页面偏移量以下获取其索引位,因此也是VIPT,允许TLB查找与标记获取并行发生,但没有任何混叠问题.因此,不需要在上下文切换或任何事情上刷新高速缓存.(有关一般多级缓存和VIPT速度技巧以及某些实际x86 CPU的一些缓存参数的更多信息,请参阅此答案.)
私有(每核)L1D/L1I和L2高速缓存是传统的组关联高速缓存,对于小/快速高速缓存通常为8路或4路.所有现代x86 CPU上的高速缓存行大小为64字节.回写数据高速缓存.(除了AMD Bulldozer系列,其中L1D是通过一个小的4kiB写入组合缓冲区进行直写.)
http://www.7-cpu.com/具有良好的缓存组织/延迟数量,带宽和TLB组织/性能数字,适用于各种微体系结构,包括许多x86,如Haswell.
英特尔Sandybridge系列中的"L0"解码uop缓存是集关联的,并且是虚拟寻址的.最多3个块,最多6个uop可以缓存来自32字节机器代码块中的指令的解码结果.相关:涉及Intel SnB系列CPU上的微编码指令的循环分支对齐.(uop缓存是x86的一大进步:x86指令是可变长度的,难以快速/并行解码,因此缓存内部解码结果以及机器代码(L1I $)具有显着的功率和吞吐量优势.仍然需要解码器,因为uop缓存不大;它在循环中最有效(包括中到大循环).这避免了具有弱解码器并依赖于Pentium4的错误(或基于当时的Transitor大小的限制)跟踪缓存.)
现代英特尔(和AMD,我认为)L3 aka LLC又称最后一级缓存使用的索引功能不仅仅是一系列地址位.它是一个散列函数,可以更好地分配内容以减少固定步幅的冲突. 根据英特尔的说法,我的缓存应该是24路关联,虽然它的12路,这是怎么回事?.
从Nehalem开始,英特尔使用了大型的包容性共享L3缓存,可以过滤核心之间的一致性流量.即,当一个核读取另一个核的L1d中处于修改状态的数据时,L3标签表示哪个核,因此RFO(Read For Ownership)只能发送到该核,而不是广播. 现代英特尔CPU L3缓存是如何组织的?.包容性属性很重要,因为这意味着没有私有L2或L1缓存可以拥有缓存行的副本而不知道L3.如果它在私有缓存中处于"独占"或"修改"状态,则L3将具有该行的无效数据,但标记仍将说明哪个核心可能具有副本.绝对没有副本的核心不需要发送有关它的消息,从而节省核心和L3之间的内部链接的功率和带宽.有关英特尔"i7"(即Nehalem和Sandybridge系列,它们是不同的架构但使用相同的缓存层次结构)的片上高速缓存一致性的详细信息,请参阅为什么要保留片上高速缓存一致性.
Core2Duo有一个共享的最后一级缓存(L2),但在L2未命中时产生RFO(Read-For-Ownership)请求的速度很慢.因此,具有适合L1d的小缓冲区的核之间的带宽与不适合L2的大缓冲区(即DRAM速度)一样慢.当缓冲区适合L2而不是L1d时,存在快速的大小范围,因为写入核心将其自己的数据驱逐到L2,而其他核心的负载可以在不产生RFO请求的情况下进行.(参见图3.27: Ulrich Drepper的" 2个线程的核心2带宽 ""每个程序员应该了解的内存".(此处为完整版).
Skylake-AVX512具有更大的每核L2(1MiB而不是256k),以及每核更小的L3(LLC)切片.它不再具有包容性.它使用网状网络而不是环形总线将核心相互连接.请参阅此AnandTech文章(但在其他页面的微架构详细信息中有一些不准确之处,请参阅我留下的评论).
从英特尔®至强®处理器扩展系列技术概述
由于LLC的非包容性,LLC中缺少高速缓存行并不表示该行不存在于任何核的私有高速缓存中.因此,当未在LLC中分配时,使用监听过滤器来跟踪核心的L1或MLC中的高速缓存行的位置.在上一代CPU上,共享LLC本身负责这项任务.
这种"窥探过滤器"仅在不能出现假阴性的情况下才有用.可以将无效或RFO(MESI)发送到没有行副本的核心.当另一个核心请求对其进行独占访问时,让核心保留一行副本是不正确的.因此,它可能是一个包含标签的跟踪器,它知道哪些核心可能具有哪一行的副本,但不会缓存任何数据.
或者,在不严格包含所有L2/L1标签的情况下,探听过滤器仍然可以使用.我不是多核/多插口侦听协议的专家.我认为相同的监听过滤器也可以帮助过滤套接字之间的窥探请求.(在Broadwell和早期,只有四插槽和更高的Xeon有一个用于核心间流量的监听过滤器; 仅支持双插槽的Broadwell Xeon和早期版本不会过滤两个套接字之间的监听请求.)
AMD Ryzen 对核心集群使用单独的L3缓存,因此必须在L3中为每个集群复制跨多个核心共享的数据.同样重要的是,来自一个集群中的核心的写入需要更长时间才能对另一个集群中的核心可见,其中一致性请求必须通过集群之间的互连.(类似于多插槽Intel系统中的插槽,每个CPU封装都有自己的L3.)
所以这给了我们NUCA(非统一高速缓存访问),类似于你在多插槽系统中获得的通常的NUMA(非统一内存访问),其中每个处理器都有一个内置的内存控制器,并且访问本地内存是比访问连接到另一个套接字的内存更快.
最近的英特尔多插槽系统具有可配置的监听模式,因此理论上您可以调整NUMA机制,使其最适合您正在运行的工作负载.有关可用监听模式的表格+说明,请参阅英特尔关于Broadwell-Xeon的页面.
另一个进步/发展是在IvyBridge和更高版本的L3中的自适应替换策略.当某些数据具有时间局部性但工作集的其他部分更大时,这可以减少污染.(即,使用标准LRU替换来循环一个巨大的阵列将驱逐所有内容,使L3缓存仅缓存来自阵列的数据,不会很快再次触及.自适应替换尝试缓解该问题.)
进一步阅读:
每个程序员应该了解的内存?
为什么Skylake比Broadwell-E在单线程内存吞吐量方面要好得多??(多核Xeon CPU上的单线程内存带宽受max_concurrency/latency,而不是DRAM带宽限制).
http://users.atw.hu/instlatx64/用于内存性能计时结果
http://www.7-cpu.com/用于缓存/ TLB组织和延迟数量.
http://agner.org/optimize/用于微体系结构细节(主要是关于执行管道,而不是内存)和asm/C++优化指南.
Stack Overflow的x86标签wiki有一个性能部分,其中包含指向这些内容的链接.