当 CPU 尝试访问最近访问过的随机内存时,内存数据可能仍在处理器缓存中,因此 CPU 可以从此缓存中检索数据。使用这种技术,CPU 可以避免与 RAM 通信,因为 RAM 的通信速度会更慢。
CPU 是否能够对最近的计算采用类似的技术?换句话说,CPU 是否能够查看它之前是否进行过类似的计算,并仅依靠缓存的结果?
答案1
CPU 缓存的思考方式比“计算”更细致;正如您所写,它处理地址,无论地址包含什么。但是,程序/应用程序本身可以管理这种缓存。例如,数据库服务器的用户定义函数可以具有缓存的属性,因为 UDF 通常意味着一定数量的工作量,通过存储和获取先前的结果可能值得避免。
答案2
现代 x86/x64 处理器上有三个缓存,L1、L2 和 L3。
L1 缓存分为指令缓存和数据缓存。两者之间存在关联,因此指令缓存中位置 x 的指令对应于数据缓存中位置 x 的结果。因此,如果指令确实相同,CPU 可以从缓存中提供计算结果,但如果只是相似的换句话说,2+5 与 3+4 虽然结果相同,但并不相同。
L2 缓存仅用于存储数据,基本上可以被视为超高速 RAM。
L3 与 L2 相同,不同之处在于它在所有处理器核心之间共享(每个核心都有自己的 L1 和 L2 缓存)。
以下是一些与您的问题相关的其他优化技术。
指令预取:CPU 可以在流水线中提前读取指令,并在实际请求指令之前执行指令。结果被缓存,这样当指令最终到达时,CPU 只需从缓存中获取结果即可。
分支预测:当预取器看到出现条件跳转指令(代码中的 If/Then 语句)时,它可以决定哪个分支更有可能被采用(或者如果可能,并行执行两个分支)并预先计算结果。如果它猜对了(或者如果它并行执行了两个分支),那么结果就会从缓存中直接传出。
无序执行: 指令解码器可以重新排列预取器中的指令,以便它们按照对 CPU 最有效的顺序执行。结果直接保存在缓存中,因此可以按照程序期望的正确顺序输出。
SIMD(单指令,多数据)指令: CPU 可以使用一条指令对多个数据点执行相同的计算。例如,将 5 添加到整数数组中的每个整数。CPU 可以重复执行该指令,而无需为每次计算解码 ADD 指令。
有很多我们已经了解了现代 CPU 为提高性能所做的各种优化,但也不能排除优化编译器的影响。优秀的编译器知道 CPU 架构的优点和缺点,甚至可以在代码到达 CPU 之前对其进行优化。例如,编译器可能知道两个特定值在整个程序中永远不会改变,因此它可以让 CPU 计算它们在编译时并将它们直接嵌入到代码中,而不是让 CPU 在运行时完成工作。它还可以知道某个 CPU 的读取速度比跳转速度快,因此它可以对相同的数据值进行 5 次硬编码,而不是让 CPU 进行 5 次跳转。
这是一个很好的资源关于内存缓存如何工作。