TLB & cahce & 缓存对齐

本文详细解析了内存管理的关键组件:TLB(旁路转换缓存)、Cache(缓存)和Buffer(缓冲区)。通过阐述它们在虚拟地址到物理地址转换、数据访问加速以及缓存对齐方面的核心作用,揭示了如何优化系统性能。同时,文章还讨论了TLB在上下文切换时的刷新策略及缓存对齐的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  关于内存,总是少不了TLB, cache,buffer, 最近有了点粗浅的概念理解。

  • TLB 

   处理器为每个processor都分配了虚拟地址,具体的map方式可以通过/proc/${PID}/map 查看进程的具体映射,这是通过MMU(内存管理单元)实现的。Linux虚拟地址到物理地址的映射通过多级分页方式(具体分级和体系结构有关),如果页表是存在于主存中的,那么我们针对这各级的页表,都需要逐次访问内存,这很慢,实际上,即使是把他们缓存在cache中,也仍然很慢,因为各级之间的访问并不能并行,必须要得到前面的访问结果之后才能进行下一个访问,加上可能存在的cache miss,缓存带宽将会被消耗。所以针对这种缓存条目目录的方式,如果能针对虚拟地址一次性得到物理地址将会极大提升性能,实际上,也是这么做的。TLB(旁路转换缓存)就是MMU改进虚拟地址到物理地址转换的方法,TLB实质上也是一种cache,它会将地址转换中最频繁出现的地址,保存到TLB的高速CPU缓存中,这样就可以直接从TLB中直接取得地址数据。

  当CPU执行读操作时,需要将虚拟地址转换为物理地址,在这里需要访问TLB,TLB保存着虚拟地址前20位到页框号的映射关系,之后根据得到的页框号,再加上后面12位的物理偏移地址,就可以迅速定位到物理地址。如果TLB中虚拟地址不存在,就出现TLB丢失,需要到页表中查找页表项(如果找到,需要将找到的页表项替换TLB中的一个条目), 如果在页表中也不存在,则需要到磁盘中去取。

  具体页表的建立在这里不做描述,目前Linux是支持Huge TLB的,因为随着可用内存的加大,继续使用4KB的分页,将会导致大量的TLB miss 和 缺页中断。

  在上下文切换时,都需要重新刷新TLB,但是存在两种情况避免刷新TLB,实际上就我自己理解来说,需要的寄存器数据等都改变了,自然需要刷新TLB,但是如果你需要的内容没有被改变呢?

  1. 使用相同页表的进程切换
  2. 普通进程切换到内核进程(lazy-tlb模式)

  • cache

    cache是为了解决高速CPU和慢速内存设备之间的速率差异出现的,存在这L1 cache(L1D,L1I), L2 cache 和 L3 cache,出现较多的情况是L1 cache做在CPU内,为CPU私有,其指令和CPU一样, L2 cache是SRAM,存在位置有在CPU外的,也有在CPU内的,速率略低于CPU指令周期;L3 cache是逻辑概念,为所有L2 cache的集合。

   cache line 是 cache 和 DRAM 同步的最小单位,一般一个 cache line 为 32字节或者是 64 字节,在第一次访问一块区域时,会将内容同时复制到cache中,之后读写访问就可以通过cache 实现了。

  对于通过cache超找到地址对应的数据的过程如下:


  针对需要读写的地址,分成三部分,高t位用来检验是否是CPU需要访问的单元,s位用来计算该内存单元映射到哪一个组,而最低的b位表示了该单元在cache line中的偏移量



  一个cahce分成S个组,每个组有E个cache line,每个cahe line中存在B个内存单元(1字节),对应内存单元,很容易看出S = 2 ^ s, B = 2 ^ b。

  一条 cache entry包含以下部分:

  1. cache line, 即上图中的per cache block,包含B个字节(32位体系为4字节,64位8字节)
  2. tag, 标记cache line对应内存的高t位,因为可能有多个内存地址对应到同一个cache line(一个cache line有B个单位), 所以这个位用来校验是否是CPU需要访问的内存单元
  3. valid, 标记该cache line是否是有效的,如果该cache line并没有内存映射,就是无效的

  通过以上方法,如果cache hit,就直接得到cache line,如果cache miss,则会将内存中cache line的数据load 进处理的同时 load 进cache中。


  • 缓存对齐

    cpu和cache的交换是以字为单位的,但是从上文可以看到,cahce 和 内存之间的交换是以块(cahce line)为单位的,这样就引出了缓存对齐的概念,实际上就是内存边界对齐,对齐的好处在于可以减少cache交换数据的次数。

    比如现在有个变量int x, 32位机上占用4个字节,如果它的起始地址是0x1234567F;那么它占用的内存范围就在0x1234567F-0x12345682之间。如果现在Cache   Line长度为32个字节,那么每次内存同Cache进行数据交换时,都必须取起始地址时32(0x20,起始地址后5位为0)倍数的内存位置开始的一段长度为32的内存同 Cache   Line进行交换。如0x1234567F落在范围0x12345660~0x1234567F上,但是0x12345680~0x12345682落在范围 0x12345680~0x1234569F上,也就是说,为了将4个字节的整数变量0x1234567F~0x12345682装入Cache,我们必须调入两条Cache   Line的数据。但是如果int   x的起始地址按4的倍数对齐,比如是0x1234567C~0x1234567F,那么必然会落在一条Cache   Line上,所以每次访问变量x就最多只需要装入一条Cache   Line的数据了。比如现在一般的malloc()函数,返回的内存地址已经是8字节对齐的,这个就是为了能够让大部分程序有更好的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值