
文章插图
作者 | 小林coding
来源 | 小林coding(ID:CodingLin)

文章插图
前言你清楚下面这几个问题吗?
- 有了内存 , 为什么还需要 CPU Cache?
- CPU 是怎么读写数据的?
- 如何让 CPU 能读取数据更快一些?
- CPU 伪共享是如何发生的?又该如何避免?
- CPU 是如何调度任务的?如果你的任务对响应要求很高 , 你希望它总是能被先调度 , 这该怎么办?
- …

文章插图

文章插图
CPU 如何读写数据的?先来认识 CPU 的架构 , 只有理解了 CPU 的 架构 , 才能更好地理解 CPU 是如何读写数据的 , 对于现代 CPU 的架构图如下:

文章插图
可以看到 , 一个 CPU 里通常会有多个 CPU 核心 , 比如上图中的 1 号和 2 号 CPU 核心 , 并且每个 CPU 核心都有自己的 L1 Cache 和 L2 Cache , 而 L1 Cache 通常分为 dCache(数据缓存) 和 iCache(指令缓存) , L3 Cache 则是多个核心共享的 , 这就是 CPU 典型的缓存层次 。
上面提到的都是 CPU 内部的 Cache , 放眼外部的话 , 还会有内存和硬盘 , 这些存储设备共同构成了金字塔存储层次 。如下图所示:

文章插图
从上图也可以看到 , 从上往下 , 存储设备的容量会越大 , 而访问速度会越慢 。至于每个存储设备的访问延时 , 你可以看下图的表格:

文章插图
你可以看到 , CPU 访问 L1 Cache 速度比访问内存快 100 倍 , 这就是为什么 CPU 里会有 L1~L3 Cache 的原因 , 目的就是把 Cache 作为 CPU 与内存之间的缓存层 , 以减少对内存的访问频率 。
CPU 从内存中读取数据到 Cache 的时候 , 并不是一个字节一个字节读取 , 而是一块一块的方式来读取数据的 , 这一块一块的数据被称为 CPU Line(缓存行) , 所以 CPU Line 是 CPU 从内存读取数据到 Cache 的单位 。
至于 CPU Line 大小 , 在 linux 系统可以用下面的方式查看到 , 你可以看我服务器的 L1 Cache Line 大小是 64 字节 , 也就意味着 L1 Cache 一次载入数据的大小是 64 字节 。

文章插图
那么对数组的加载 , CPU 就会加载数组里面连续的多个数据到 Cache 里 , 因此我们应该按照物理内存地址分布的顺序去访问元素 , 这样访问数组元素的时候 , Cache 命中率就会很高 , 于是就能减少从内存读取数据的频率 , 从而可提高程序的性能 。
但是 , 在我们不使用数组 , 而是使用单独的变量的时候 , 则会有 Cache 伪共享的问题 , Cache 伪共享问题上是一个性能杀手 , 我们应该要规避它 。
接下来 , 就来看看 Cache 伪共享是什么?又如何避免这个问题?
现在假设有一个双核心的 CPU , 这两个 CPU 核心并行运行着两个不同的线程 , 它们同时从内存中读取两个不同的数据 , 分别是类型为 long 的变量 A 和 B , 这个两个数据的地址在物理内存上是连续的 , 如果 Cahce Line 的大小是 64 字节 , 并且变量 A 在 Cahce Line 的开头位置 , 那么这两个数据是位于同一个 Cache Line 中 , 又因为 CPU Line 是 CPU 从内存读取数据到 Cache 的单位 , 所以这两个数据会被同时读入到了两个 CPU 核心中各自 Cache 中 。

文章插图
我们来思考一个问题 , 如果这两个不同核心的线程分别修改不同的数据 , 比如 1 号 CPU 核心的线程只修改了 变量 A , 或 2 号 CPU 核心的线程的线程只修改了变量 B , 会发生什么呢?
推荐阅读
- 一口气看完45个寄存器,CPU核心技术大揭秘
- CPU越来越热吗 一文带你看懂怎么选
- 2020年 你到底需要什么样的CPU来满足你的日常使用呢?
- 关于路由器的2.4G以及5G,你不知道的那些事
- CPU处理器|打造下一个ASML?荷兰投资77亿元研发硅光子芯片技术
- CPU针脚密密麻麻,几千根针脚坏了一两个竟然还能点亮?
- 因为没选对CPU,小万元的3080废了!论电脑CPU如何选购
- i3,i5,i7的cpu到底有什么区别?
- JVM常见线上问题 → CPU 100%、内存泄露 问题排查
- 都是芯片 为什么电脑CPU不能用在手机里