CPU cache(上)

本文深入探讨了CPU、内存和缓存之间的关系,解释了为何在现代计算机架构中引入缓存至关重要,以及如何通过缓存提高数据访问效率。文章详细阐述了局部性原理在预测即将使用的数据方面的作用,并介绍了缓存的组织结构和操作原理。

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

一、CPU,内存和cache之间的关系           

       如今的CPU和二十几年前的相比,其精密程度和运作速度可谓天壤之别。在以前,CPU的工作频率和内存总线的频率是处于一个等级的,CPU对内存的访问速度也只是比对寄存器的访问速度要慢那么一点儿,所以CPU直接访问内存是再合理不过了。但是近十几年来,CPU发展迅猛,其工作频率大大增加,而内存的发展却无法跟上大哥的步伐。当然,并不是做不出访问频率高的内存,而是SRAM那样的高速度内存相对于作为普通内存的DRAM而言,成本过高。因此,一个折中的选择就是在CPU和内存之间引入高速缓存(cache),作为CPU和内存之间的渠道。CPU将接下来最有可能用到的数据存放在cache中,那么CPU是如何预测到接下来将要用到的数据的呢?这种预测是基于程序代码和数据在时间和空间上的局部性原理(locality)。所谓局部性原理,就是指由于循环结构的存在,在最近这段时间,同样的代码和数据很有可能再被使用。下图给出了CPU,cache和内存之间的基本关系

 

           

      

       虽然计算机采用的是冯诺依曼架构,但是经验表明,将代码用的cache和数据用的cache分离开来效率更高。Intel正是从1993年开始,针对代码和数据使用相互独立的cache。随着cache的引入,cache和内存之间的工作频率差别又开始慢慢拉大,这样,又引入了下一级的cache,其容量比第一级大,速度比第一级慢。这同样是速度和经济的折中考虑,如今甚至有系统引入三级高速缓存,如下图所示

 

其中L1d是第一级数据缓存,L1i是第一级指令缓存,要注意的一点事该图只是一个概略的描述,实际上数据从任何一个CPU Core流向主存是不用经过高级缓存(L2,L3)的。

 

二、cache的操作   

           当CPU需要数据时,首先到cache内部去寻找,如果找到了,则称为命中了(cache hit),如果没有找到,则称为丢失(cache miss),这时CPU必须到内存去读取数据,并且将其保存在cache中以备后用。

       cache中需要保存数据字在主存中的地址,cache的每个入口都被相应数据的地址所标记,当CPU要完成一次读或写操作时,会在cache中寻找匹配的标记。cache中存储的地址可以是虚拟地址,也可以是物理地址,根据cache的实现而不同。由于标记在cache中本身要占用空间,所以如果以字为粒度在cache中标记主存的地址单元那就显得有些低效。解决的办法很简单,还记得cache是基于空间的局部性原理的,由于被标记的内存字的邻近单元也有可能被使用,所以会把它们也一起加载到cache中去。因此一个cache的入口处存储的并不是单一的字,而是几个连续的字,它们被称为缓存行(cache line).

       对应每个cache line,都有这样一个结构

          

 

       data bolck存放的是缓存行中所保存的就是从主存取过来的数据,tag表示的是数据块在主存中的地址(并不是完整的地址),flag bits是一些在操作过程中涉及到的标志位。

       而对于主存中的每个地址单元,我们都可以按下图的结构进行解析

      

        我们已经知道,一个cache line对应的是主存中连续的几个字,那么这些字的低位对于映射一个cache line是没用的,比如说在一个32位系统中,一个cache line的大小是16个字,也就是64个字节,那么其低6位在映射一个cache时是没有用的,其作用是用来指定该内存单元在对应cache line中的偏移。Cache Set则指明了该内存单元位于哪一个cache set(一个cache set 可以包含一个或多个cache line,这与cache和内存之间的映射关系有关,在后面会进行讲解),S的长度为以2为底的log(cache sets),由于一个cache set可以包含多个cache line,所以还需要高T位的tag域来指明该内存单元是位于哪个cache line中。

       下面来说说flag bits域。对于指令cache来说,flag bits位只有一位,即valid位。顾名思义,valid位指明了相应的cache line中是否装载了有效的数据。系统刚上电时,所有的cache line中的valid位都被设置为invalid.对于数据cache来说,flag bits除了有valid位外,还有一个dirty位。对于cache line来说,如果读进来的数据还未被修改,则称为clean;相反,如果数据被修改了但是还没被写回内存,这时将dirty置位表示内存和cache里的数据不同步。在SMP系统中,所有的处理器都必须协调工作保证它们所看到的内存里的内容必须是一样的,这种问题被称为缓存一致性(cache coherency).假设一个处理器的cache内对某一内存有一份clean cache copy,而这时该处理器监测到另一个处理器对相应的该内存单元发出一个写请求,那么前一个处理器将会把相应的cache line给设置为dirty,等待后者的写操作完成并进行重装载,以保证数据的同步性。显然,读操作是不会影响cache的一致性的。对于cache的实现的一些细节将在下一篇中给出。

 

由于个人水平有限,文中描述不当或出错之处还请指出,转载请注明出处,谢谢http://blog.youkuaiyun.com/vanbreaker/article/details/7470830

 

### CPU缓存简介 CPU缓存是一种高速的小型存储器,位于中央处理单元(CPU)内部或紧邻其旁。这种存储器旨在缓解由于主存响应时间较慢而导致的瓶颈问题[^1]。 ### 缓存的工作原理 当CPU请求特定的数据时,它首先查询最近级别的缓存(通常是L1)。如果所需数据存在于该级别,则称为“命中”。此时,CPU可以直接从中获取数据而不必访问更远且速度相对较慢的主存。然而,若发生“未命中”,则意味着目标数据不在当前缓存中,因此需要向更低层次的缓存或者直接从主存检索,并可能替换掉某些现有条目以腾出空间给新加载的内容[^2]。 ### 多级缓存结构及其原因 现代计算机通常采用多层次的缓存体系——即除了最接近CPU核心的第一层(L1),还存在第二层甚至第三层(L2, L3)缓存。随着每增加一层,这些额外缓冲区不仅扩大了总可用容量,而且有助于进一步优化平均访问延迟与成本之间的平衡关系。例如,在一级缓存达到满载状态之后,通过引入二级缓存可以在不影响太多功耗的情况下显著改善整体性能表现。 ### 组织方式的影响 不同类型的映射策略决定了如何将来自外部地址空间的数据项分配至各个缓存行之中。常见的方法包括直接映射、全相联以及介于两者间的组相联模式。后者允许一定灵活性的同时保持合理的实现难度,使得大多数情况下能够获得较好的综合效益。特别是针对较小规模的一级缓存而言,超过四路组相联后的边际收益变得微乎其微[^4]。 ```python def calculate_cache_index(address_bits, offset_bits): """ 计算给定地址位数和偏移量位数下的索引部分长度 参数: address_bits (int): 地址总宽度 offset_bits (int): 单个cache line内的字节数对应的二进制表示所需的位宽 返回: int: 表示cache index所占有的比特数目 """ block_size = 2 ** offset_bits total_lines = 2**(address_bits - offset_bits) # 对于一个典型的4-way set associative cache, # 如果已知总的line数量为total_lines, # 则set的数量等于total_lines除以way数。 sets_count = total_lines / 4 return int(math.log2(sets_count)) ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值