cache

为什么需要高速缓存

解决处理器访问速度与内存速度严重不匹配的问题;

高速缓存架构

alt text

  • l1 cache:分为dcache,icache,存在于每个cpu内部;
  • l2 cache:不区分dcache, icache,由一个cluster内的cpu共享;
  • l3 cache:不区分dcache, icache,各个cluster共享

访问延时

系统存在两种内存体系结构:uma,numa

  • uma:系统中只存在一个内存结点,所有cpu通过相同的总线去访问同一个内存结点;
    alt text
  • numa:每个cpu结点存在对应的内存结点,可以通过总线直接访问;也可以通过upi总线访问非本地的内存结点,速度更慢;****
    alt text
  • 访问延时:l1 < l2 < l3 < 远端l3 < 本地ddr < 远端ddr
  • cache的访问延时都是可以以时钟周期进行度量,到ddr级需要60ns以上;

如何理解组和路

路:把一个cache分为平均分为几列就是几路
组:然后想象放在一起平铺,有几行就是有多少组
每组有多少cacheline,就是每组有多少列,就是多少路;(网上画的就是把这些路重叠了一下)
alt text

如图:有5列,就是5路;有3行,就是3组;

  • 每组有5个cacheline;(5列)
  • 每路有3个cacheline;(cacheline总数/路)

寻址:如何通过内存地址找到所在cache中的位置?

tag,index,offset

  • offset: 全称是字节索引,cacheline内偏移;
  • index:全称是行索引,定位到是哪个组;(哪行)
  • tag:index定位到是哪一组之后,需要定位到是哪路(哪列);还有可能这个组中的每一路都没有对应地址的数据,需要tag去比较;

VIPT:virtual address 寻址具体cache的具体过程

  • 虚拟地址同时传递给TLB和高速缓存
    • 传递给tlb的目的是获取pfn
      • 如果tlb命中,直接从tlb获取pfn;
      • 如果tlb没有命中,则需要查询页表获取pfn;
    • 根据虚拟地址的index域找到高速缓存行对应的组;
  • 如果cache没有命中,则需要到主存获取进行数据获取;

映射方式

直接映射:

只有一路
alt text

全相连

只有一组
alt text

组相连

  • 有多少行就是多少组
  • 有多少列就是多少路
    alt text

高速缓存策略

分配:cache miss的情况

  • 读分配(read allocation) :当CPU读数据时,发生cache缺失,这种情况下都会分配一个cache line缓存从主存读取的数据。默认情况下,cache都支持读分配。
  • 写分配(write allocation) :当CPU写数据发生cache缺失时,才会考虑写分配策略。
    • 当我们不支持写分配的情况下,写指令只会更新主存数据,然后就结束了。
    • 当支持写分配的时候,我们首先从主存中加载数据到cache line中(相当于先做个读分配动作),然后会更新cache line中的数据

更新:cache 命中的情况

  • 写直通(write through): 当CPU执行store指令并在cache命中时,我们更新cache中的数据并且更新主存中的数据。cache和主存的数据始终保持一致。
  • 写回(write back) :当CPU执行store指令并在cache命中时,我们只更新cache中的数据。并且每个cache line中会有一个bit位记录数据是否被修改过,称之为dirty bit。我们会将dirty bit置位。主存中的数据只会在cache line被替换或者显示的clean操作时更新。因此,主存中的数据可能是未修改的数据,而修改的数据躺在cache中。cache和主存的数据可能不一致。
  • (只有写的策略,没有读的策略)

共享属性

共享属性

  • 内部共享的高速缓存:CPU内部继承的高速缓存;
  • 外部共享的高速缓存:系统总线扩展的高速缓存;

共享域:

目的:指定可以访问内存的硬件单元实现一致性的范围;

分为以下四个域:

  • 不可共享域:
  • 内部共享域:通常是cpu之间
  • 外部共享域:是cpu + 访问内存的ip(DMA、GPU)
  • 系统共享域:

pou和poc

  • poc:就是上面所描述的外部共享域;一致范围是CPU + 访问内存的IP
  • pou:系统的内部;比如cpu之间;

高速缓存维护指令

操作:

  • invalid:使整个高速缓存行失效
  • clean:将标记为脏的整个高速缓存写入下一级高速缓存或内存中,然后清除脏位
  • zeor:主动写入零数据到cacheline;

指令:

  • 数据缓存:DC
  • 指令缓存:IC

在指令中会指定观察点,也就是POC,POU;

cache问题

颠簸、伪共享:都是cacheline的数据由于其他cpu对其的更新,导致本地的cacheline又得不停的更新,进而性能下降;

参考

https://cloud.tencent.com/developer/article/2206026

什么是歧义

不同的物理地址映射到同一个虚拟地址,如果是vivt,那么就会造成不同的地址映射到同一个cacheline;

vipt存在歧义吗?

歧义的前提同一个虚拟地址映射到不同的物理地址。虚拟地址相同,物理地址不相同,那么这两个物理地址一定有这么一个特征:以4k page为例,这两个物理地址的[11:0]必定是相同的;

  • 虚拟地址相同,那么虚拟地址的[11:0]也一定相同,[11:0]是页内偏移,和物理地址完全能对上;所以一定有以上特征;
    物理地址可以看成pfn + 页内偏移,现在这两个物理地址的页内偏移相同了,那么他们两的pfn一定是不相同的;
    vipt会将是物理地址的pfn作为tag;他们pfn一定不相同,所以他们的tag也一定不相同;
  • 所以vipt,会因为index相同映射到同一个组中,但是他们的tag不同,任然会定位到不同的cacheline,所以不存在歧义问题;

存在别名问题吗?

同一个物理地址对应不同虚拟地址,pfn一定相同,也就是tag一定相同;
如果两个虚拟地址的index 与 offset 任一不相同就会映射到不同的cacheline,造成别名问题;
index 与 offset 的来自于虚拟地址,也就是虚拟地址的[index+offset, 0]完全一样,就不会出现同名问题;
怎么能保证完全一样呢?[index+offset, 0]在一个page中;因为他们对应的是同一个物理地址,页内偏移是完全一样的;[index+offset, 0]构成一路,也就是一路小于4k;

  • 同一物理地址对应不同虚拟地址,这两个虚拟地址一定有[11: 0]完全相同的特性

总结

  • 不同的物理地址正常应该映射到不同的cacheline。歧义,就是不同物理地址映射到了同一cacheline,想要不存在问题就得映射到不同的cacheline;
  • 同一物理地址应该映射到同一cacheline。同名,就是同一物理地址映射到了不同cacheline,想要不存在问题就得映射到同一cacheline;
    按照这两个分析就完事;

pivt

歧义

虚拟地址相同,所以vt一定相同;想要映射到不同的cacheline就得靠pi不同,虽然物理地址不同,但是pi不能保证一定不同。所以还是存在歧义问题

别名

虚拟地址不同,vt一定不同,所以一定存在同名问题;

解决

歧义

解决不同物理地址在同一cacheline问题;

  • 为了防止数据丢失,进程切换时得进行cache flush;
  • 为了不使用其他物理地址的cache数据,进程切换还要invalid

别名

  • 直接映射 + 虚拟地址是cache大小对齐;
  • 如果是多路组相连高速缓存的话,返回的虚拟地址必须是满足一路cache大小对齐。
    这时候就算是vi不同,但由于循环存放,就能刚好存放在那个cacheline; 太巧妙了;
    解决原理:
  • tag一定是相同的,保证index可以进行循环存放即可;也就是虚拟地址是cacheline对齐;
  • 由于tag是相同的,就算是多路,也一定是在同一路的;
posted @   _xingxing  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示