CPU、Cache、内存三者的交互关系,是计算机体系结构里最基础也最容易让人犯迷糊的一块。很多人背过"CPU快、内存慢、Cache居中"这句话,但真正到了排查性能问题、优化代码的时候,就会发现这句话根本不够用——Cache是怎么组织起来的?为什么多核CPU访问同一份数据会慢?为什么free命令里buff/cache占了几十G内存又"变"成了可用内存?这些问题的答案,全藏在三者的交互细节里。这篇文章我从数量级差异讲起,再把映射、替换、写策略、缓存一致性这些关键机制逐一拆开,最后落到上机实战,聊聊page cache、堆外内存和kv cache这些经常在工作里捣乱的东西到底是怎么回事。
1. 数量级的鸿沟:为什么CPU不能直接面对内存
1.1 一个时钟周期 vs 上百个时钟周期
先看一组实测数据。现代桌面级CPU的主频普遍在3GHz到5GHz之间,一个时钟周期大约0.2到0.33纳秒。而一根DDR5内存的典型访问延迟(CAS延迟加上总线传输时间)在80到120纳秒左右。这意味着什么?CPU执行一条简单指令可能只需要1到3个周期,但它如果要等一次内存访问,就得白白等上几百个周期。
几百个周期的空转是什么概念?以3GHz的CPU为例,等一次内存访问相当于傻等了几百条指令的执行时间。换句话说,如果CPU每执行一条访存指令都要直接面对内存,那整个处理器的性能会瞬间退化到五六年前的嵌入式水平。这是Cache存在的最根本原因:内存的延迟跟CPU的执行速度之间隔了两三个数量级,不插一层Cache根本没法干活。
内存带宽其实也没有好看多少。单通道DDR5的理论带宽大约在30到50GB/s,听起来很夸张,但CPU内部的L1缓存带宽可以做到几百GB/s甚至上TB/s级别。所以Cache缓解的不仅是延迟问题,还有带宽压力。很多初学者只盯着延迟差,忽略带宽差,后面看一些性能问题时容易走偏。
1.2 DRAM为什么这么慢,SRAM为什么这么贵
这里要用两个生活类比把存储原理解释清楚。DRAM(内存条上的颗粒)本质上是一个个电容加晶体管的小阵列,电容充电代表1,放电代表0。问题是电容会漏电,所以要不停地刷新(refresh),刷新的时候整行都不能访问。而且读一个电容的电压后,数据就被破坏了,得再写回去。这套"读-破坏-恢复-刷新"的流程决定了DRAM的随机访问天生就慢,但它贵在密度高——一个晶体管加一个电容就能存一个bit,所以能做到单条几十GB。
SRAM(Cache用的存储单元)就不一样,它用6个晶体管组成一个锁存器,只要不断电,数据就一直稳定存在,不需要刷新,访问起来也快得多。代价是单元面积大,同样面积的晶圆,SRAM的容量只有DRAM的几十分之一,成本直接高出一两个数量级。
所以你会看到一个非常有意思的取舍逻辑:SRAM快但贵,DRAM慢但便宜。CPU厂商的做法是:在CPU核心附近放几层SRAM作为Cache,容量从几十KB到几十MB不等;内存条用DRAM,做主存;硬盘则更慢更便宜,由操作系统用page cache来弥补差距。整条存储体系就是一个金字塔,越往上越快越贵越靠近CPU,越往下越慢越便宜容量越大。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Cache的三件大事:映射、替换、写策略
2.1 映射方式:直接映射、组相联与全相联
Cache的核心功能是把内存中的一小块数据"缓存"到高速存储里。但缓存总要有个规则——内存中某地址的数据,到底能放在Cache的哪个位置?这就是映射方式。教科书上有三种,实操中你只需要吃透前两种。
直接映射是最简单的规则:内存地址按固定大小切块,每个内存块只能放到Cache中唯一对应的行。假设Cache有1024行,那么内存地址对1024取模,余数就是它唯一能去的位置。这个方案硬件实现极简,但问题非常致命——如果程序反复访问两个恰好映射到同一行的内存地址,Cache行就会被来回踢,命中率骤降,这就是"抖动"现象。
组相联映射是折中方案,也是当今主流CPU普遍采用的做法。它把Cache行分成若干组,内存块可以先通过取模定位到
