Today’s picks

CPU 是如何读写内存的?

乍一看,关于 CPU 如何读写内存的问题似乎很简单,但实际情况远比表面复杂得多。CPU 并不会自行做出决策,它只是严格按照编译器生成的指令执行。编译器会将高级编程语言翻译为机器指令,而这些机器指令最终...

Source: https://www.myzaker.com/

乍一看,关于 CPU 如何读写内存的问题似乎很简单,但实际情况远比表面复杂得多。CPU 并不会自行做出决策,它只是严格按照编译器生成的指令执行。编译器会将高级编程语言翻译为机器指令,而这些机器指令最终告诉 CPU 去执行相应的操作。在 RISC(精简指令集)架构下,数据不能直接从内存中获取,必须通过 Load/Store 指令先搬运到寄存器中再进行操作。相比之下,x86 这种复杂指令集架构允许指令直接操作内存,也就是说,它可以直接从内存或寄存器中取数。除了数据之外,CPU 还会不断地从内存中读取下一条要执行的指令,因为在冯·诺依曼架构下,程序和数据是平等的,都存放在内存之中。正是这种双重需求——既要取数据,又要取指令——驱动了 CPU 的内存访问。问题在于速度:CPU 的运算速度极快,而内存的速度却远远落后,两者之间存在巨大的性能差距。为缩小差距,工程师引入了缓存(Cache),并利用了程序的局部性原理——时间局部性(最近访问过的数据很可能会再次访问)和空间局部性(与已访问数据相邻的数据很可能会被访问)。缓存使用 SRAM 构建,速度远快于 DRAM,它位于 CPU 与主存之间,保存高频访问的数据,避免 CPU 频繁等待内存响应。即使缓存容量很小,也能凭借局部性显著提升性能。然而,写操作带来了复杂性:如果 CPU 更新了缓存但没有同步更新内存,就会产生数据不一致问题。为了解决这一点,通常有两种策略:其一是写直达(write-through),即同时更新缓存和内存,方法简单但速度较慢;其二是回写(write-back),即先更新缓存,再在需要时将数据写回内存,这种方式更高效但实现更复杂。现代 CPU 进一步发展出了多级缓存架构:L1(最小、最快)、L2(更大但稍慢)和 L3(容量更大但仍快于 DRAM)。CPU 会依次在各级缓存中查找,若未命中才访问主存,从而在速度与成本之间取得平衡。在多核系统中,问题更加棘手。假设内存中的变量 X 初始值为 2,核心 C1 将其缓存并更新为 4,而核心 C2 缓存的是旧值 2,并在此基础上加 4,最终写回的结果是 6。正确结果应为 8,但由于多个核心的缓存中存在不同副本,最终导致不一致。为解决这一问题,现代 CPU 引入了缓存一致性协议,如 MESI 协议,用于确保不同核心的缓存能够保持同步。对程序员而言,这些细节同样重要。程序如果具有良好的局部性,就能更好地利用缓存;反之,不合理的访问模式会导致缓存频繁失效,性能下降。事实上,现代 CPU 芯片上有相当大一部分面积都用于缓存设计,因为它是弥合 CPU 与内存速度鸿沟的关键。总的来说,CPU 访问内存并不是一个简单的过程,而是一个由编译器、缓存、多级结构以及一致性协议共同 orchestrate 的复杂系统,目的就是让处理器能够尽可能高效地运转。在每一次看似简单的读写操作背后,隐藏着支撑现代计算机性能的精密机制。

Keep a little curiosity for the next story.

Back to reading

Read next

All