Locality 是整个 CS 栈的同一根线:从 CPU cache 到 AI agent

这篇是一次思想梳理。起点是一个看似简单的问题——locality 是不是 trade-off?顺着这个问题往下挖,挖到了信息论,挖穿了整个 CS 抽象栈,最后在 AI agent 时代落了地。


一、起点:一个值得追问的命题

我先抛一个命题,然后批判它:

Locality 是 trade-off。不管 CPU 层面的 L1/L2 cache,还是后端的 cache/DB,还是 AI agent 的 context/memory——所以 memory 再大也无法解决这个问题。

观察的部分是对的。这三个层级确实都体现 locality。但"因此 locality 是 trade-off"这个推论错了。

Trade-off 的定义是"在某个维度上让步换另一个维度的收益"。Locality 不是你选的——它是光速 + 经济学强加的现实

  • 光速有限。1ns 内信号最多走 30cm。CPU 3GHz 一个周期约 10cm 往返。L1 必须贴着核——这是物理强制。
  • 存储金字塔的成本曲线。SRAM/DRAM/SSD/HDD/Tape,$/GB 差 5-6 个数量级。容量和速度的成本不在一条曲线上。
  • AI 的注意力成本。Transformer attention 是 O(n²),context 越长不只是装不下,是算力线性翻倍后还是要扔东西。

所以更精确的说法是:

Locality 是"无法逃避的约束"。Hierarchical caching 是应对它的工程响应。真正的 trade-off 在"用什么策略应对它",不在"要不要 locality"。

二、“memory 再大也解决不了” —— 部分错

这里要分两种情况。

容量瓶颈:memory 大能解决。L3 从 8MB 变 128MB,很多工作集就装下了。DB buffer pool 从 16G 变 1T,热点数据全在内存。LLM context 从 8k 变 1M,很多任务真的不需要 RAG。

访问代价瓶颈:memory 大解决不了,反而变严重

  • 内存越大,平均寻址路径越长。NUMA 跨 socket 延迟比本地大 50%。
  • 1M context 的 attention 比 8k 慢 ~16000 倍(O(n²))。即便装下了,每 token 都要扫一遍的代价是真的。
  • Agent memory 越大,检索/排序/相关性判断的开销越大,信噪比反而下降。

关键洞察:memory 变大时,“哪些是热点"的问题反而更突出了。容量解决了"装不下”,但暴露了"找不快、看不准"。这才是 locality 的硬核——不是空间问题,是注意力分配问题

三、换掉 attention 能解决吗

下一个值得追问的问题。Attention 是 O(n²),那如果未来 LLM 不再是 attention 机制呢?

先看候选替代方案能做到什么:

架构 复杂度 解决了 没解决
Attention (Transformer) O(n²) 全局可访问 算力爆炸
SSM / Mamba O(n) 算力线性 固定 state 装不下所有历史
Linear attention O(n) 算力线性 表达力下降
RAG 算力可控 容量可扩 检索/相关性判断变核心瓶颈
MemGPT (外部记忆) 算力可控 容量可扩 swap 策略本身就是新的 locality

每个替代方案都在"算力 vs 状态容量 vs 表达力"三角里换一个角,但没有一个能同时把三角的三个角都拉满

更深一层:locality 的根源不在 attention,在更底:

  1. 信息论约束。一个有限大小的 state(无论是 KV cache、SSM hidden state、还是 RAG index)要表示潜在无界的历史,必须有损压缩。有损就意味着"什么留什么扔"的问题永远存在。这是 Shannon 级别的。
  2. 计算的物理约束。处理 N bits 至少需要 N×kT×ln2 焦耳 + 物理距离决定的延迟。即使算法 O(1),数据搬运也不是 O(1)。
  3. 相关性判断本身的复杂度。就算把所有历史都装下了,判断"现在哪些相关"这个动作本身也要遍历或索引。这个开销不会因换架构而消失,只会换地方收费:
    • Attention:在 forward pass 里收
    • Mamba:在 selective scan 的 gating 里收(其实就是 implicit attention)
    • RAG:在 embedding similarity search 里收
    • MemGPT:在 swap policy 里收

一个反证思想实验。假设有"无 locality"系统——O(1) 时间、零损耗访问任意历史的任意细节。那它必须满足:存储无限(违反物理) + 信号超光速(违反物理) + 相关性自动浮现无需计算(违反信息论——相关性是 query-dependent 的)。逻辑上不可能

所以 locality 不是"我们暂时没解决的工程问题",是信息处理系统的本体属性

四、三层约束栈

把上面的论证整理成一张层级图:

1
2
3
4
Layer 0 (物理):    光速 + 热力学              ← 不可逾越
Layer 1 (信息论): 有限 state vs 无界历史 ← 不可逾越
Layer 2 (架构): attention/SSM/RAG/MemGPT ← 可换,但只是把成本搬地方
Layer 3 (策略): cache 策略 / 记忆策略 ← 真正的 trade-off 在这层

Layer 0 和 1 是约束,不是 trade-off,换什么架构都摆脱不掉。Layer 2 是设计选择,不同架构在三角里取不同点。Layer 3 才是真正的 trade-off:记多少 vs 找多快 vs 准确率。

Attention 不是 locality 的来源。Attention 是 locality 的一种应对方式。换掉 attention,locality 不消失,只是换一张脸出现:

  • 在 SSM 里它叫"hidden state 容量不够"
  • 在 RAG 里它叫"召回率"
  • 在 MemGPT 里它叫"swap 策略"
  • 在人脑里它叫"遗忘曲线"

五、一张图把整个 CS 栈接起来

理解了 locality 是结构性约束之后,再回头看整个计算机系统——它就是一座由 locality 砌成的金字塔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
延迟        容量      层级                                  "热点"是什么
──────────────────────────────────────────────────────────────────────
~0.3ns ~kB CPU 寄存器 当前指令的操作数
~1ns ~64KB L1 cache (核内) 当前函数的局部变量
~3ns ~256KB L2 cache (核内) 当前调用栈
~12ns ~32MB L3 cache (共享 / per-socket) 线程间共享的热数据
~100ns ~GB-TB DRAM (本 socket) 程序工作集
~150ns ~GB-TB DRAM (跨 NUMA socket) 远 socket 的数据
~10µs ~TB NVMe / 本地 SSD OS page cache 之外
~100µs ~TB-PB LAN 内存 (Redis/Memcached) 分布式热数据
~1ms ~PB 本地数据中心数据库 业务数据库
~10ms ~PB 同区数据库副本 跨 AZ 数据
~100ms ∞ 跨区域 / 对象存储 (S3) 冷数据 / 归档
~秒 ∞ CDN edge → origin 用户内容
~秒-分 ∞ LLM context (in-window) 当前会话相关
~分-时 ∞ RAG / vector DB 会话相关的外部知识
~天-年 ∞ 模型权重(pre-training) 人类知识的有损压缩
~年 ∞ 文档 / wiki / 代码注释 团队长期记忆

九个数量级的延迟差,统一靠 locality 缝起来

六、每一层都在做同样四件事

不管哪一层,"locality 系统"都由四个组件组成:

组件 CPU DB Agent
Hot tier(贵、小、快) L1/L2 Buffer pool Context window
Cold tier(便宜、大、慢) DRAM/SSD Disk/对象存储 Vector DB / docs
Promotion(冷→热) cache fill on miss page fault → load RAG 检索注入
Eviction(热→冷) LRU/PLRU Clock-sweep Context 截断/压缩

还有一个隐形的第五件事:Relevance judgment(谁是热点)。

  • CPU:硬件按访问历史统计推断(程序局部性是统计规律)
  • DB:query optimizer + buffer pool 决定
  • Agent:embedding 相似度 + 显式 prompt 决定

层级越高,"什么算相关"越主观、越可设计。这是 agent 时代真正的护城河。

七、locality 的三种类型在每层重现

类型 CPU DB Agent
时间局部性 刚访问的会再访问 热点行反复读 刚说的 token 在 context 里
空间局部性 a[i] 后会访 a[i+1] 同一页的行一起读 同一文档段落一起召回
语义局部性 (无) (弱) 主题相关的知识被一起激活

关键观察:从下到上,语义局部性逐渐主导,物理局部性逐渐让位。

  • CPU 层:“相关 = 地址连续”
  • DB 层:“相关 = 索引相邻 + 业务关联”
  • Agent 层:“相关 = 含义接近”——已经完全脱离物理位置

这是为什么 vector DB 在 agent 时代爆发:它是语义局部性的索引结构,就像 B-tree 是空间局部性的索引结构

八、栈是嵌套的,每一层都假设它下层的 cache 在工作

你写一行 agent.run() 调 RAG,背后被这 11 层 cache 接力服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
你的 agent context(in-window)

▼ Vector DB(HNSW 索引常驻内存)

▼ LLM serving(KV cache、prefix cache、prompt cache)

▼ 网络(TCP 窗口、HTTP cache、CDN)

▼ Redis(process memory)

▼ 数据库(buffer pool)

▼ 文件系统(inode cache、dentry cache)

▼ 磁盘控制器(NVMe 内置 DRAM cache)

▼ 操作系统(page cache、TLB)

▼ JIT/native 代码(CPU 指令 cache)

▼ Python 解释器(字节码 cache、global dict cache)

▼ CPU L1/L2/L3

洞察:当系统变慢,瓶颈通常是某一层的 cache miss rate 飙升——不是 CPU 不够。SRE 调优的核心永远是"找到哪一层的 working set 装不下了"。

九、贯穿全栈的 5 条统一原则

1. Working Set Theory(Denning, 1968)

任何时刻,程序/服务/agent 只活跃使用一小部分数据。只要 hot tier 装得下 working set,整体性能就接近 hot tier 的速度;装不下,性能塌到 cold tier

设计任何系统先问:working set 多大?hot tier 容量够吗?

2. 80/20 法则

20% 的数据承担 80% 的访问。这条规律在每层都成立:CPU 少数热点函数,DB 少数热点行,Agent 少数关键 context。

Cache 设计的甜区是"覆盖 top 20% 热点",不是"装下全部"

3. 失效是更难的问题(Phil Karlton)

There are only two hard things in computer science: cache invalidation and naming things.

有了 cache 就有 staleness。每一层都要解决:

  • CPU:MESI 协议保证 cache 一致性
  • DB:buffer pool 写回策略 + WAL
  • Agent:context 里的事实和现实分叉怎么办?

Agent 时代这条最被低估:context 里的"事实"过期了,agent 自己不知道。

4. Locality 是程序的属性,不是硬件的属性

硬件 cache 之所以有用,是因为程序天然有局部性(人写代码倾向于循环、函数复用、聚类访问)。如果访问完全随机,cache 命中率 = cache_size / total_size——基本没用。

推论:写"对 cache 友好"的代码是工程师的责任。array 比 linked list 快不是因为 array 更"先进",是因为它配合了硬件假设的局部性

Agent 时代同理:写"对 context 友好"的 prompt 和"对 RAG 友好"的知识库结构,是工程师的责任。

5. 每一层的 cache 都会变成下一层的瓶颈

你优化了 L1 命中率,瓶颈跑到 L2;优化了 buffer pool,瓶颈跑到磁盘 I/O;优化了 Redis,瓶颈跑到 DB;优化了 RAG,瓶颈跑到 LLM serving。

Locality 优化是无穷套娃,瓶颈永不消失,只会逐层后退

十、AI agent:塔顶新加的一层石头

AI agent 不是这座金字塔的颠覆者——它是在塔顶加了一层新石头。

  • 这层石头处理的不是物理 locality(地址相邻),而是语义 locality(含义相近)
  • 它的 hot tier 叫 context window,cold tier 叫 vector DB / docs
  • 它的 eviction 叫"压缩 / 总结 / 遗忘"
  • 它的 promotion 叫"RAG 检索"
  • 它的 working set 叫"当前任务相关的知识"

理解了这个同构性,你就理解了为什么传统系统设计的智慧在 agent 时代依然适用,也理解了 agent infra 需要新发明什么:

旧智慧依然适用:分层、淘汰、命中率监控、prefetching、working set 估算、LRU/LFU/W-TinyLFU。

需要新发明:语义相似度索引、显式相关性判断、跨会话记忆 coherence、"遗忘"作为一等公民。

十一、用一句话串联整个 CS 栈

如果只能留一句话:

整个计算机系统就是一座由 locality 砌成的金字塔。每层负责把"足够热"的东西留在自己手上,把"暂时冷"的东西交给下层;每层都假设自己服务的工作负载有局部性。任何性能问题,本质上都是"某层 cache 装不下 working set"。任何架构演进,本质上都是"在某层引入新的 cache 或重新定义热点"。

十二、对 AI infra 实践的落地推论

  1. 不要赌"下一代架构会让 context 问题消失"——它只会换形式。三层记忆架构(全局规则 / 动态记忆 / 当前会话)这种分层 + 显式遗忘策略是架构无关的,押对了。

  2. Memory 系统的核心 IP 是"忘什么",不是"存什么"。LRU/LFU/W-TinyLFU 几十年前的智慧在 agent 时代依然适用,只是单位从 page 变成 fact。

  3. Agent ops 的可观测性要监控 attention 命中率,不是 token 数。哪些 context 进来后真的影响了输出?这个指标在任何架构下都成立——是结果导向的 locality 度量。

  4. Locality 决定能否规模化。Agent fleet 多了之后,每个 agent 维护自己的 hot context 比共享一个巨型 memory 更可扩展(参考 NUMA)。共享越多,"远"的 cost 越高。

  5. 把容量预算花在"分级"上,不是"单层做大"上。L3 再大都不如 L1+L2+L3 分级有效——这是 cache hierarchy 几十年的经验,在 AI agent 时代仍然成立。


结语

最危险的认知陷阱:把 attention 的 O(n²) 当成 locality 的根因,期待"换个架构就好了"。实际上 attention 只是 locality 的当前世代表现。

第二个陷阱:以为 memory 越大越好。Memory 增长会线性提升容量、平方级提升检索成本、对数级下降信噪比。盲目扩容的尽头是"装了一堆没用的东西,关键的反而找不到"。

正确的心智:

  • 把 locality 当成天气,不是 bug——你不能消灭它,只能为它穿衣服
  • 真正值得投资的是应对策略:分层、淘汰、相关性判断、显式遗忘
  • 在任何抽象层级,问"什么是热点、什么该忘"都是设计的核心问题

CPU 不会消失,cache 不会消失,locality 不会消失。它只是一层一层往上长,直到长到 agent 的 context window 里。理解这条线的人,在 AI 时代不需要重新学一遍系统设计——他们已经会了