文章插图
好久没有写一些微观方面的文章了,今天写一篇关于CPU Cache相关的文章,这篇文章会讲述一些多核 CPU 的系统架构以及其原理,包括对程序性能上的影响,以及在进行并发编程的时候需要注意到的一些问题 。这篇文章我会尽量地写简单和通俗易懂一些,主要是讲清楚相关的原理和问题,而对于一些细节和延伸阅读我会在文章最好给出相关的资源 。
本文比较长,主要分成这么几个部分:基础知识、缓存的命中、缓存的一致性、相关的代码示例和延伸阅读 。
因为无论你写什么样的代码都会交给CPU来执行,所以,如果你想写出性能比较高的代码,这篇文章中的技术还是应该认真学习的 。
基础知识首先,我们都知道现在的CPU多核技术,都会有几级缓存,老的CPU会有两级内存(L1和L2),新的CPU会有三级内存(L1,L2,L3 ),如下图所示:
文章插图
其中:
- L1缓分成两种,一种是指令缓存,一种是数据缓存 。L2缓存和L3缓存不分指令和数据 。
- L1和L2缓存在第一个CPU核中,L3则是所有CPU核心共享的内存 。
- L1、L2、L3的越离CPU近就越小,速度也越快,越离CPU远,速度也越慢 。
- L1 的存取速度: 4 个CPU时钟周期
- L2 的存取速度: 11 个CPU时钟周期
- L3 的存取速度: 39 个CPU时钟周期
- RAM内存的存取速度 :107 个CPU时钟周期
于是我们的数据就从内存向上,先到L3,再到L2,再到L1,最后到寄存器进行CPU计算 。为什么会设计成三层?这里有下面几个方面的考虑:
- 一个方面是物理速度,如果你要更在的容量就需要更多的晶体管,除了芯片的体积会变大,更重要的是大量的晶体管会导致速度下降,因为访问速度和要访问的晶体管的位置成反比,也就是当信号路径变长时,通信速度会变慢 。这部分是物理问题 。
- 另外一个问题是,多核技术中,数据的状态需要在多个CPU中进行同步,并且,我们可以看到,cache和RAM的速度差距太大,所以,多级不同尺寸的缓存有利于提高整体的性能 。
- 一个是比较简单的缓存的命中率的问题 。
- 另一个是比较复杂的缓存更新的一致性问题 。
缓存的命中在说明这两个问题之前 。我们需要要解一个术语 Cache Line 。缓存基本上来说就是把后面的数据加载到离自己进的地方,对于CPU来说,它是不会一个字节一个字节的加载的,因为这非常没有效率,一般来说都是要一块一块的加载的,在CPU的缓存技术中,这个术语叫“Cache Line”(有的中文编译成“缓存线”),一般来说,一个主流的CPU的Cache Line 是 64 Bytes(也有的CPU用32Bytes和128Bytes),也就是16个32位的整型 。也就是说,CPU从内存中捞数据上来的最小数据单位 。
比如:Cache Line是最小单位(64Bytes),所以先把Cache分布多个Cache Line,比如:L1有32KB,那么,32KB/64B = 500 个 Cache Line 。
一方面,缓存需要把内存里的数据放到放进来,英文叫 CPU Associativity 。Cache的数据放置的策略决定了内存中的数据块会拷贝到CPU Cache中的哪个位置,因为Cache的大小远远小于内存,所以,需要有一种地址关联的算法,能够让内存中的数据可以被映射到cache中来 。这个有点像内存管理的方法 。
基本上来说,我们会有如下的一些方法 。
- 一种方法是,任何一个内存地址的数据可以被缓存在任何一个Cache Line里,这种方法是最灵活的,但是,如果我们要知道一个内存是否存在于Cache中,我们就需要进行O(n)复杂度的Cache遍历,这是很没有效率的 。
- 另一种方法,为了降低缓存搜索算法,我们需要使用像Hash Table这样的数据结构,最简单的hash table就是做“求模运算”,比如:我们的L1 Cache有500个Cache Line,那么,公式:`(内存地址 mod 500)x 64` 就可以直接找到所在的Cache地址的偏移了 。但是,这样的方式需要我们的程序对内存地址的访问要非常地平均,这成了一种非常理想的情况了 。
推荐阅读
- 每个程序员都必须知道的8种通用数据结构
- 服务器又崩溃了?看看专业的程序员怎么解决
- 交换机与路由器相比的五点优势
- 祁门红茶十大名牌,祁门红茶的前世与今生
- 家居住宅财富运势:如何寻找财位与如何催财
- 碧螺春功效,碧螺春的功效与作用
- 砖茶功效作用,砖茶的作用与功效
- 皇菊功效,金丝皇菊的功效与禁忌
- 百香果茶,苹果茶的功效与作用
- 寻茶之旅:一片单株古树茶与茶人的千年之约