CPU缓存结构

CPU缓存结构 现代CPU为了提升执行效率,减少CPU与内存的交互(交互影响CPU效率),一般在CPU上集 成了多级缓存架构,
常见的为三级缓存结构 

  • L1 Cache,分为数据缓存和指令缓存,逻辑核独占 
  • L2 Cache,物理核独占,逻辑核共享 
  • L3 Cache,所有物理核共享

存储器存储空间大小:内存>L3>L2>L1>寄存器;

存储器速度快慢排序:寄存器>L1>L2>L3>内存;

缓存行:缓存是由最小的存储区块-缓存行(cacheline)组成;

缓存行大小通 常为64byte(比如你的L1缓存大小是512kb,而cacheline = 64byte,那么就是L1里有512 * 1024/64个 cacheline)

处理器如何处理原子操作?

首先处理器会自动保证基本的内存操作的原子性,但是复杂的内存操作处理器不能自动保证其原子性,比如跨总线宽度, 跨多个缓存行,跨页表的访问。但是处理器提供总线锁定和缓存锁定两个机制来保证复杂内 存操作的原子性;

32位 IA-32处理器使用基于对缓存加锁 和 总线加锁的方式来实现多处理器之间的原子操作

1. 使用总线锁保证原子性

所谓总线锁就是使用处理器提供的一个 LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该 处理器可以独占使用共享内存

2. 使用缓存锁保证原子性

总线索你锁定的是CPU和内存之间的通信,使得在锁定期间,其他处理器不能操作其他内存地址的数据,总线锁的开销比较大;某些场合下使 用缓存锁定代替总线锁定来进行优化。

“缓存锁定”就是如果缓存在处理器缓存行中内存区域在LOCK操作期间被锁定,当它执行锁操作回写内存时,处理器不在总线上声言 LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子 性,因为缓存一致性机制会阻止同时修改被两个以上处理器缓存的内存区域数据,当其他处 理器回写已被锁定的缓存行的数据时会起缓存行无效

处理器不会使用缓存锁定情况:

1. 当操作的数据不能被缓存 在处理器内部,或操作的数据跨多个缓存行(cache line),则处理器会调用总线锁定

2. 有些处理器不支持缓存锁定

Java当中如何实现原子操作

在java中可以通过锁和循环CAS的方式来实现原子操作。

JVM中的CAS操作正是利用了上文中提到的处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止;

补充:

三级缓存(L3)在多核(多个逻辑CPU)的情况下,是每个核共享的,CAS的行为就发生在多核的情况下,CPU在处理CAS时使用的是mesi协议,因此,就存在加乐观锁的问题,解决乐观锁的问题,目前就是采用CPU缓存行填充(将数据打散到L2)的方式

LongAdder 通过CAS操作cellsBusy去操作这个变量 实现了缓存行填充,对数组中的单元进行了缓存行填充,打散到一二级缓存,cell在每个CPU自己独享的一二级缓存中,就不需要加锁,性能提升(Contended注解,实现缓存行填充,将cells打散,填充到CPU的一二级缓存)

CPU -> 缓存行 -> 内存,前面两者是CAS操作,后面两个环节是操作系统行为,包含write through和write back

CAS是CPU行为,和内存无关

volatile关键字简单理解是操作的CPU缓存行,不是内存

Java中的CAS是告诉操作系统,让CPU使用CAS来更新数据,不是借鉴

L3是多个逻辑CPU共享的,所以,才需要CAS指令去加锁更新L3

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Go 中进 CPU 缓存优化的主要思路是减少 CPU 缓存未命中率,即尽可能使用局部性较好的数据结构和算法,以减少 CPU 访问内存的次数。 以下是一些可以优化 CPU 缓存的技巧: 1. 使用数组而非切片:数组是一段连续的内存空间,能够更好地利用 CPU 缓存。而切片则可能会分散在内存的不同位置,增加 CPU 缓存未命中率。 2. 多使用结构体而非接口:结构体是一段连续的内存空间,而接口则需要额外的内存空间来存储类型信息。因此,多使用结构体可以减少 CPU 缓存未命中率。 3. 避免 false sharing:False sharing 指的是两个不同的变量在同一个 CPU 缓存中,当其中一个变量被修改时,会导致整个 CPU 缓存失效,使得另一个变量的访问效率下降。可以使用 padding 来解决 false sharing 的问题。 4. 使用 sync.Pool:sync.Pool 是一个对象池,可以重复利用已经分配的对象,避免频繁进内存分配和垃圾回收,从而减少 CPU 缓存未命中率。 5. 避免内存分配:频繁进内存分配会导致 CPU 缓存未命中率增加,因此可以通过预分配内存、复用对象等方式来避免内存分配。 6. 使用局部变量:局部变量存储在栈上,访问速度更快,可以减少 CPU 缓存未命中率。 需要注意的是,进 CPU 缓存优化需要在保证代码可读性和可维护性的前提下进,不要过度追求性能而导致代码难以理解和维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值