Skip to main content

memory

📅 2026-03-30 ✏️ 2026-03-30 CS

1 · memory#

S CPU 与内存速度差距持续扩大,内存访问已成为程序性能的主要瓶颈 C 硬件设计者引入了缓存等加速技术,但这些技术需要程序员配合才能发挥最佳效果;大多数程序员并不理解内存子系统的结构和代价 Q 程序员需要了解哪些内存知识,才能写出高性能代码? A 理解缓存层级、局部性原理、NUMA 拓扑,并在代码中应用数据局部性优化、预取、缓存行对齐、避免伪共享等技术


https://people.freebsd.org/~lstewart/articles/cpumemory.pdf Ulrich Drepper, “What Every Programmer Should Know About Memory”, 2007

1.1 · 硬件基础 (§2)#

  • SRAM(快、贵、用于缓存)vs DRAM(慢、便宜、用于主存)
  • 内存控制器架构:北桥(Northbridge)连接 CPU 与内存
  • UMA(统一内存访问)vs NUMA(非一致性内存访问)
  • DMA:网卡、存储控制器等设备直接访问内存,绕过 CPU

1.2 · CPU Cache (§3)#

  • 缓存层级:L1i(指令)/ L1d(数据)、L2、L3
  • 缓存行(cache line):缓存操作的最小单位(通常 64 字节)
  • 关联度:直接映射 / N 路组相联 / 全相联
  • 写策略:
    • write-through:写缓存同时写主存,简单但慢
    • write-back:只标记 dirty,驱逐时才写回,性能更好
  • MESI 缓存一致性协议:Modified / Exclusive / Shared / Invalid 四状态
    • dirty cache line 不会同时存在于多个处理器缓存中
    • clean 副本可以存在于任意多个缓存中
  • 伪共享(false sharing):不同核心写同一缓存行的不同变量,导致缓存行频繁失效

1.3 · 虚拟内存 (§4)#

  • 多级页表(最多 4 级),稀疏树结构节省内存
  • TLB(Translation Lookaside Buffer):缓存页表查询结果,避免每次访问都做页表遍历
  • 大页(Huge Pages):减少 TLB miss,适用于大内存工作集

1.4 · NUMA (§5)#

  • 每个 CPU 有本地内存,访问远端 CPU 的内存代价更高
  • 内存亲和性:将数据和线程绑定到同一 NUMA 节点

1.5 · 程序员优化实践 (§6) ⭐#

  • 数据局部性:顺序访问优于随机访问、结构体字段重排、冷热数据分离
  • 预取(prefetch):硬件自动预取 + 软件预取指令(__builtin_prefetch
  • 缓存行对齐posix_memalign__attribute__((aligned(64)))
  • 多线程优化
    • 避免伪共享:将不同线程写的数据放在不同缓存行
    • CPU 亲和性:cpu_set_t / sched_setaffinity 绑定线程到特定核心

1.6 · 性能工具 (§7)#

  • cachegrind(Valgrind):模拟缓存行为,统计 L1/L2 miss 率
  • oprofile / perf:利用硬件性能计数器采样
  • 关注比率而非绝对值(如每次调用的分支预测失败率)

1.7 · 展望 (§8)#

  • 事务内存(transactional memory):用缓存实现原子操作,避免昂贵的主存写回