CSDN|如何写出让 CPU 跑得更快的代码?


CSDN|如何写出让 CPU 跑得更快的代码?
本文插图
作者|小林coding
代码都是由 CPU 跑起来的 , 我们代码写的好与坏就决定了 CPU 的执行效率 , 特别是在编写计算密集型的程序 , 更要注重 CPU 的执行效率 , 否则将会大大影响系统性能 。
CPU 内部嵌入了 CPU Cache(高速缓存) , 它的存储容量很小 , 但是离 CPU 核心很近 , 所以缓存的读写速度是极快的 , 那么如果 CPU 运算时 , 直接从 CPU Cache 读取数据 , 而不是从内存的话 , 运算速度就会很快 。
但是 , 大多数人不知道 CPU Cache 的运行机制 , 以至于不知道如何才能够写出能够配合 CPU Cache 工作机制的代码 , 一旦你掌握了它 , 你写代码的时候 , 就有新的优化思路了 。
那么 , 接下来我们就来看看 , CPU Cache 到底是什么样的 , 是如何工作的呢 , 又该写出让 CPU 执行更快的代码呢?
CSDN|如何写出让 CPU 跑得更快的代码?
本文插图
CPU Cache 有多快
你可能会好奇为什么有了内存 , 还需要 CPU Cache?根据摩尔定律 , CPU 的访问速度每 18 个月就会翻倍 , 相当于每年增长 60% 左右 , 内存的速度当然也会不断增长 , 但是增长的速度远小于 CPU , 平均每年只增长 7% 左右 。 于是 , CPU 与内存的访问性能的差距不断拉大 。到现在 , 一次内存访问所需时间是 200~300 多个时钟周期 , 这意味着 CPU 和内存的访问速度已经相差 200~300 多倍了 。为了弥补 CPU 与内存两者之间的性能差异 , 就在 CPU 内部引入了 CPU Cache , 也称高速缓存 。CPU Cache 通常分为大小不等的三级缓存 , 分别是 L1 Cache、L2 Cache 和 L3 Cache 。由于 CPU Cache 所使用的材料是 SRAM , 价格比内存使用的 DRAM 高出很多 , 在当今每生产 1 MB 大小的 CPU Cache 需要 7 美金的成本 , 而内存只需要 0.015 美金的成本 , 成本方面相差了 466 倍 , 所以 CPU Cache 不像内存那样动辄以 GB 计算 , 它的大小是以 KB 或 MB 来计算的 。在 Linux 系统中 , 我们可以使用下图的方式来查看各级 CPU Cache 的大小 , 比如我这手上这台服务器 , 离 CPU 核心最近的 L1 Cache 是 32KB , 其次是 L2 Cache 是 256KB , 最大的 L3 Cache 则是 3MB 。
CSDN|如何写出让 CPU 跑得更快的代码?
本文插图
其中 , L1 Cache 通常会分为「数据缓存」和「指令缓存」 , 这意味着数据和指令在 L1 Cache 这一层是分开缓存的 , 上图中的 index0 也就是数据缓存 , 而 index1 则是指令缓存 , 它两的大小通常是一样的 。另外 , 你也会注意到 , L3 Cache 比 L1 Cache 和 L2 Cache 大很多 , 这是因为 L1 Cache 和 L2 Cache 都是每个 CPU 核心独有的 , 而 L3 Cache 是多个 CPU 核心共享的 。程序执行时 , 会先将内存中的数据加载到共享的 L3 Cache 中 , 再加载到每个核心独有的 L2 Cache , 最后进入到最快的 L1 Cache , 之后才会被 CPU 读取 。 它们之间的层级关系 , 如下图:CSDN|如何写出让 CPU 跑得更快的代码?
本文插图
越靠近 CPU 核心的缓存其访问速度越快 , CPU 访问 L1 Cache 只需要 2~4 个时钟周期 , 访问 L2 Cache 大约 10~20 个时钟周期 , 访问 L3 Cache 大约 20~60 个时钟周期 , 而访问内存速度大概在 200~300 个 时钟周期之间 。 如下表格:CSDN|如何写出让 CPU 跑得更快的代码?
本文插图
所以 , CPU 从 L1 Cache 读取数据的速度 , 相比从内存读取的速度 , 会快 100 多倍 。
CPU Cache 的数据结构和读取过程是什么样的?CPU Cache 的数据是从内存中读取过来的 , 它是以一小块一小块读取数据的 , 而不是按照单个数组元素来读取数据的 , 在 CPU Cache 中的 , 这样一小块一小块的数据 , 称为 Cache Line(缓存块) 。


推荐阅读