CPU Cache笔记

前言

学习Unity Dots框架时被推荐的有关CPU Cache的大牛的视频后写一下笔记,视频链接:

codedive conference 2014 - Scott Meyers Cpu Caches and Why You Care_哔哩哔哩_bilibili

1、CPU缓存中,为了防止频繁的Cache Miss,数据结构最好的就是数组,且数组越小越好,因为一个缓存行大概是64节,如果数组大于64节的话可能一个缓存行会无法装下导致后续的Cache Miss。且在现在的计算机中,cpu会预测我们取数据的方式,举例来说,如果我们以增量形式从头遍历数组(如果数组大于64节需要cpu分多个缓存行),在我们还没读完这个缓存行中的数组元素时,cpu就会提前把数组下一段的数据从内存中以缓存行的形式放入Cache;反之亦然,如果以自减形式从末尾开始遍历,cpu会预判并提前把前一段数据取进来。且这个预判不需要逐个遍历,哪怕一个隔着一个或者一个隔着两个都行,只要是相对规则的遍历方式基本都会被cpu预判。

2、在面对非大量数据时,使用合适的变量方式以及数据结构是可以让譬如O(log2n)时间复杂度的算法比O(1)复杂度的算法还要快的,但在面对超大数据的时候(视频中的举例是如google或者facebook之类的拥有海量数据的软件),还是需要遵循基本的时间复杂度来设计算法与数据结构,因为这时候不管是什么数据结构都很难避免大量的Cache Miss。

3、在特定情况下,如果两个cpu核的缓存都使用了同一片CacheLine,而两个缓存改动的是同一片CacheLine中不同的位置,就会导致频繁的脏数据改动。具体举例来说就是,缓存1想要改动CacheLine中的变量a,而缓存2的缓存行也有这个变量,就会导致两个缓存中的同一个缓存行一起变成了“脏”数据,此时如果缓存2中的同一片缓存行想要修改另一个变量b,但此时他发现这个缓存行早就变成dirty了,就要重新向内存发起缓慢地数据请求,而重新拿到数据并改写变量b后,又将此缓存行标记为了“dirty”(注意这时候缓存1还用引用这同一片内存的缓存行),就会导致缓存1的缓存行又一次跟着一起变成了“dirty”,导致缓存1需要修改时又要重新向内存发起请求更新数据,如此往复。 这种情况被称为FlaseSharing。

4、发生FalseSharing的几个必要条件(全满足时才会发生):1)在同一个缓存行里有多个不同的变量或者值。2)需要两个及以上的不同核的Cache获取了这个缓存行,如果只有一个核的Cache拥有这个缓存行也就不会存在写入时脏掉其他核的Cache缓存行了。3)在运行期间时常发生,如果只是偶发的发生FalseSharing就不会造成什么性能瓶颈 4)几个Cache中最少要有一个是写入的,如果全是读取CacheLine的操作就不会有脏数据,也就不会存在反复地从内存更新数据了。

5、在每个缓存行从内存中取数据时,会有三种放入CPU的方式,

  1. 直接映射(Direct-Mapped Cache):每个缓存行只能映射到缓存中的一个特定位置。这是通过将内存地址的某些位用作缓存中位置的索引来实现的。这种方式简单、成本低,但可能会导致较高的冲突缺失率(两个频繁访问的数据块映射到同一个缓存位置)。

  2. 全相联映射(Fully Associative Cache):每个缓存行可以映射到缓存中的任何位置。这种方式可以最小化冲突缺失,但查找特定缓存行的成本较高,因为需要检查整个缓存。

  3. 组相联映射(Set-Associative Cache):这是直接映射和全相联映射的折中方案。缓存被分成多个组(Set),每个组有多个缓存行。每个内存地址可以映射到一个特定的组,但在这个组内,它可以映射到任何位置。例如,如果一个缓存是4路组相联的,这意味着每个组有4个缓存行,一个内存地址的缓存行可以映射到这4个位置中的任何一个。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值