2026-05-25 学习日志
今日主题
- Git LFS 核心机制
- LFS 指针识别与边界
- KV Cache与注意力机制
- Prefix Cache匹配机制
- MLA压缩技术
- 推理两阶段流程
新增认知
Git LFS 核心机制
-
LFS 不引入新 Git 对象类型:Git 的对象类型只有 blob/tree/commit/tag 四种,
LFS 存进 .git/objects/ 的仍然是一个普通 blob,内容是指针文本(~130字节)而非真实文件。魔法不在对象层,
而在更上层的 clean/smudge filter——add 时 clean filter 把真实文件替换成指针文本再交给 Git,
checkout 时 smudge filter 识别指针、从 .git/lfs/objects/ 读回真实文件。
wheel 链条 index→tree→blob 和普通文件完全一样,Git 核心不知道 LFS 的存在。 -
smudge 指 checkout 时的"涂抹还原":clean filter 的方向是工作区→暂存区(把大文件清理成干净指针),
smudge filter 的方向是暂存区→工作区(把指针"涂抹还原"回真实文件)。命名来自 Git 原始的设计意图:checkin 前先净化(clean),
checkout 后再弄脏(smudge),LFS 拿这套机制做了指针↔真实文件的双向替换。读路径和写路径完全对称。
LFS 指针识别与边界
-
指针内容本身就是判断依据:smudge filter 被触发后,
只需读文件第一行是否以 version https://git-lfs.github.com/spec/v1 开头即可判断是不是 LFS 指针——
三行严格格式(version→oid→size,单空格分隔,无多余行)区分了"这是要还原的指针"和"这恰好是 LFS 格式的普通文本"。
OID 用 SHA-256(不是 Git 自己的 SHA-1),体量远大于 160 位。判断成本极低,只是读个头部。 -
.gitattributes 规则删除后指针不会自动转回:
git checkout 只按目标 commit 附带的 .gitattributes 决定哪些文件走 smudge filter。
如果某次 commit 删除了 *.psd filter=lfs 规则,后续检出时 smudge 不触发,文件按普通 blob 原样写入工作区——
此时若 blob 仍是指针文本,用户就会看到 130 字节的乱码。这是用户侧的维护责任,
需要用 git lfs migrate 在删规则前把指针转回真实文件再提交,LFS 不兜底。
KV Cache与注意力机制
-
KV Cache只存K/V不存Q:Q是当前token发出的"探针",用完即丢,下个token不需要;
K和V被所有后续token反复用来计算注意力分数和语义融合,所以必须缓存。这就是为什么KV Cache叫KV不叫QKV -
Q/K/V的职责分工:Q是主动查询者("我要找什么"),K是被匹配的标签("你可以找我"),V是实际传递的语义内容("我身上带着什么信息")。
Attention的计算流程是Q与所有历史K做点积算出权重,再按权重加权求和所有历史V——K负责"匹配",V负责"交付"
Prefix Cache匹配机制
- Prefix Cache匹配非固定长度:从第1个token开始逐个对比,直到第一个不同token即中断。
底层基于token ID序列哈希匹配而非原始文本——即使文本相同但tokenize边界不同(上下文变化导致分词偏移)也不会命中。
写入缓存有门槛(如Anthropic要求最少1024 token),太短的前缀不值得缓存
MLA压缩技术
- MLA的核心思路是"算力换显存":写入KV Cache时不存原始的大K/V向量,而是压缩成512维隐向量(Latent Vector);
Decoding时用多余的算力在Runtime实时解压还原K和V。
这让DeepSeek V4(1.6T参数)的128K上下文KV Cache从几十GB砍到5.48GB,而同样是MLA架构的GLM5(~700B)需要60GB——
说明压缩效果不仅取决于用不用MLA,还取决于压缩注意力的具体实现
推理两阶段流程
- Prefill与Decoding的本质区别:Prefill是"并行建仓"——所有输入token同时在每一层算出各自的QKV,
K/V打包存入KV Cache,最后一层的输出投射出第一个生成字;Decoding是"单步提货"——每个新token只为自己算Q和KV,Q去缓存取历史K算权重,
取历史V做融合,新KV追加到缓存末尾。理解了这两个阶段的交替,就理解了整个自回归生成的底层运转逻辑