笔记本也能跑 128k 上下文 LLM?SolidAttention 把 SSD 玩出了新花样
笔记本也能跑 128k 上下文 LLM?SolidAttention 把 SSD 玩出了新花样
原文:SolidAttention: Low-Latency SSD-based Serving on Memory-Constrained PCs
1. 前言
你有没有想过,在自己的笔记本上本地跑一个长上下文的 LLM,体验一下”私有 AI 助手”到底是什么感觉?
这个想法很美好,现实很骨感。
现在主流的笔记本——就是那种配个 16GB 内存、8GB 显存的标配机器——在面对 128k token 上下文时,连 KV cache 都装不下。一个 8B 参数的模型,光 KV cache 就需要 16GB 内存,比模型权重本身多 4 倍多。这还是 INT4 量化之后的情况,没量化更夸张。
所以现在的本地部署方案(llama.cpp、Ollama 这些)基本默认你的内存够用,但大多数人的机器其实根本不够用。
今天想和大家聊聊 FAST 2026 的这篇工作——SolidAttention,来自交大 IPADS 实验室。他们的思路是:内存不够,SSD 来凑。但怎么凑,里面有很多讲究。
2. 核心矛盾:KV Cache 的内存危机
先交代下背景。
LLM 的 autoregressive decode 阶段,每生成一个 token,都需要把之前所有 token 的 Key 和 Value 矩阵拿出来做 attention。为了不重复计算,就把这些 K/V 缓存下来,这就是 KV cache。
问题在于,KV cache 随着序列长度线性增长。如下图,Llama-3.1-8B(INT4 量化权重)在 128k context 下,KV cache 就需要 16GB,而模型权重本身只要 4GB 左右:

更难受的是,市面上大部分笔记本只有 8-16GB 内存、6-8GB 显存。在这种机器上,128k context 不是说”慢一点”,是直接装不下。
那量化 KV cache 行不行?
INT4 量化之后效果很差。论文里测了,Qwen-2.5-7B 的 KV cache 量化到 INT4 后,平均精度从 71.39% 暴跌到 18.63%。KV cache 里有很多异常值(outlier),激进量化直接把精度打烂了。所以这路走不通。
那把 KV cache 卸载到 SSD 呢?
这个方向是对的,但之前的工作(比如 FlexGen)有一个核心假设:系统里有足够多的并发请求,让 SSD 加载数据的时候,GPU 还有别的请求可以算。高并发场景下,I/O 延迟可以被计算”藏住”。
但笔记本本地推理的场景,根本就没有并发。只有你一个人在用,batch size=1。SSD 加载数据的时候,GPU 只能干等。加载 1k token 的 KV cache(128MB)大约需要 40ms,这能占一次 decode step 将近一半的时间。
这就是 SolidAttention 要解决的核心问题。
3. 问题的根源:SSD 和稀疏 Attention 天生不兼容
现有 SSD offloading + attention sparsity 方案的毛病,不只是”并发不够”这一个。
更深层的矛盾是:动态稀疏 attention 的访问模式,和 SSD 的特性天生相克。
你看上图右边那个 SSD 随机读带宽的测试:读取单元越大,带宽越高。4KB 以下的随机读,吞吐量可能只有 1GB/s 左右;到了 1MB 以上的顺序/大块读,能上 6GB/s。这是 SSD 内部并行通道特性决定的,没办法改。
而动态稀疏 attention 是怎么工作的?它每个 decode step 都要根据当前 query,动态选出需要的 KV 块,加载进来。这些块是按 token 粒度选的,单块可能只有几 KB,产生大量细粒度随机 I/O,SSD 带宽利用率极低。
所以问题不是”SSD 慢”,是怎么让 SSD 的带宽被充分用上。
SolidAttention 的核心 insight 就是:要把稀疏 attention 算法和 SSD 存储管理协同设计(co-design),让数据访问的粒度对齐 SSD 的特性,同时精细编排计算和 I/O 的重叠。
4. SolidAttention 三刀解决三大挑战
论文把问题分解成三个挑战,对应三个技术模块:
挑战 1:如何在不牺牲精度的情况下,把细粒度访问变成粗粒度访问? → KV Consolidator
挑战 2:动态 attention 在算完才知道需要哪些块,来不及提前加载,怎么办? → Speculative Prefetcher
挑战 3:内存受限时,GPU 读数据和 SSD 预取数据可能发生冲突(写覆盖),怎么安全调度? → SSD-aware Scheduler
整体架构如下图:

整个 KV cache 存在 SSD 里,decode 时按需加载到 GPU。三个模块协同工作,把 I/O 延迟尽量藏在计算背后。
5. KV Consolidator:让 K 和 V “手拉手”走
动态稀疏 attention 的一个基础操作是:把 KV cache 切成 block,每个 block 提取一个 representative vector 作为”身份证”,decode 时根据 query 和这些 representative vector 的相似度,选出 top-k 个 block 参与 attention 计算。
如下图,SolidAttention 把 KV cache 按 context 长度切成三类 block:Init Block(处理 attention sink)、Local Block(最近的 token)、Selected Block(动态选出的 block)。
Block 越大,SSD 读的粒度越大,带宽利用率越高——但每个 block 对应的 representative vector 要概括更多 token 的信息,精度就会下降。这是一个 accuracy vs. 带宽利用率的 trade-off。
SolidAttention 的解法很巧妙:不增大 block 里的 token 数量,而是把 K 和 V 交织在一起,把每次 I/O 的单元大小翻倍。
K 和 V 的形状完全一样(都是 N×H 的矩阵)。传统方式是 K 和 V 分开存、分开读,每次传输只搬一半的数据。SolidAttention 改成按 token 粒度交织:K₁, V₁, K₂, V₂, …,这样每次传输就能把同一个 token 的 K 和 V 一起搬过来,传输单元翻倍,I/O 次数减半,SSD 带宽利用率直接 double。
更妙的是:精度完全不受影响。因为每个 block 里的 token 数量没变,representative vector 的质量不变。
实现上,为了避免交织之后运行时还要做 reshape(开销很大),SolidAttention 在模型初始化时就把 K projection 和 V projection 的权重矩阵预先拼接成一个统一的矩阵,然后用一次矩阵乘法直接生成交织的 K/V 输出。attention kernel 里用 stride=2H 的访问模式来逻辑上分开 K 和 V,不需要改底层 kernel。实测 stride 访问的延迟开销 ≤2%,几乎可以忽略。
6. Speculative Prefetcher:历史会重演,让 SSD 提前读
动态 attention 的另一个麻烦:每一层选哪些 KV block,是根据这一层的 query 计算出来的,而计算这一层 attention 之前,下一层要哪些 block 根本不知道。
这意味着:系统没办法提前给下一层预取数据。等到上一层算完、知道下一层需要哪些 block,再去 SSD 读,就产生了 blocking latency——GPU 干等 SSD。
SolidAttention 的突破口是:相邻层之间的 block 选择结果高度相似。
论文在 LongBench 多个 benchmark 上做了统计,跨层的 block 选择相似度平均在 81% 左右。直觉也说得通:模型在处理同一个输入时,不同层关注的 context 区域往往差不多。
有了这个观察,就可以做 speculative prefetching:用上一层的选择结果来预测下一层需要哪些 block,提前发起 I/O。因为命中率达到 81%,大多数情况下数据到 attention 计算开始时就已经在内存里了。
对于预测错误的情况:
- 漏掉的 block(false negative):实际计算时再补传,延迟加载
- 多预取了的 block(false positive):新 block 直接覆盖,不需要重排序(KV pair 在 attention 计算里不需要严格顺序)
这个 misprediction 的处理方式很轻巧,没有额外的排序开销。
7. SSD-aware Scheduler:细粒度调度,让 GPU 别闲着
内存受限时,同一块 DRAM 缓冲区既要给 GPU 提供数据,又要接收 SSD 预取来的数据。一个 naive 的实现是:等所有 I/O 完成,GPU 再开始算。但这样 GPU 和 SSD 就变成串行的了。
SolidAttention 把 attention module 分解成多个 microtask:
- q proj.(query projection)
- kv proj.(key/value projection)
- select(选择 block)
- prefetch(预取 block)
- load(加载漏选的 block)
- attention(self-attention 计算)
- store(把新生成的 KV 写回 SSD)
用 DAG(有向无环图)建模这些 microtask 之间的数据依赖关系。调度器找出关键路径(critical path),关键路径上的任务最高优先级;非关键任务(比如写回新 KV 到 SSD)在不影响关键路径的情况下尽量和其他任务并行执行。
另一个优化是同步点复用(synchronization point reuse):多个 microtask 共享一个同步点,减少 CPU-GPU 之间的同步频率。比如把”等待 selected block 加载完成”和”等待 init/local block 加载完成”两个同步点合并成一个,减少握手开销。
消融实验结果:细粒度 overlap 提升性能约 25%,同步点复用再额外减少 22% 的 attention 延迟。两个加在一起效果相当可观。
8. 实验:到底快了多少?
8.1 实验设置
实验在两台真实笔记本 PC 上测:
- CUDA 后端:Intel Ultra 9 185H + RTX 4070 Laptop GPU(8GB VRAM)+ 64GB DDR5 + 1TB Samsung 990 PRO PCIe 4.0 SSD
- SYCL 后端:Intel Ultra 7 255H + Intel Arc 140T 集成显卡 + 64GB DDR5 + 同款 SSD
测试模型:Llama-3.2-3B、Llama-3.1-8B、Qwen-2.5-7B(权重都 INT4,KV cache FP16)
关键约束:DRAM 限制在 16GB 以内,模拟真实内存受限场景。batch size = 1,模拟本地单用户使用。
Baseline:
- Offload:全部 KV cache 卸载到 SSD,不做稀疏化
- Offload+Sparse:KV cache 卸载 + InfLLM 稀疏 attention
- FlexGen:经典的 SSD offloading + attention sparsity 方案(只支持 CUDA)
8.2 端到端性能
如下图,CUDA 后端的端到端推理速度:

几个关键数字:
- CUDA backend,128k token:SolidAttention 比 Offload+Sparse 快 2.8×、3.1×、2.4×(三个模型)
- CUDA backend,16k token:比 FlexGen 快 58.9×(FlexGen 在大上下文时直接 OOM)
- SYCL backend,128k token:比 Offload+Sparse 快 2.1×、2.5×、1.9×
FlexGen 在内存受限情况下惨不忍睹——因为它产生大量 page fault 触发的细粒度 SSD 随机访问,带宽浪费严重,而且在 batch=1 的情况下根本没有计算量可以用来隐藏 I/O 延迟。
8.3 内存占用
SolidAttention 只在 DRAM 里保留一层 1k token 的 KV cache buffer(加上 representative vector),其余全在 SSD。结果:KV cache 内存占用比 llama.cpp 降低 62×(约 98%)。
8.4 精度
如下是在多个 benchmark 上的精度对比:

结论很清晰:
- INT4 KV 量化(Quant)精度损失严重,Qwen-2.5-7B 从 71.39% 跌到 18.63%,直接不可用
- SolidAttention 各项 benchmark 精度与原始模型几乎持平,在 LongBench 上略有下降(约 1-2%),但远优于量化方案
8.5 消融实验
三个核心模块的贡献:
- Speculative Prefetcher:在 CUDA 上把 blocking latency 降低 3.9×,SYCL 上降低 3.1×
- KV Consolidator(KV 交织):attention 延迟降低 22%
- SSD-aware Scheduler:fine-grained overlap 提升 25%,同步点复用再降 22% 延迟
另外,论文还测了 SSD offloading 相对于纯内存推理(InDRAM)的额外开销:≤11% 的吞吐量损失。也就是说,SolidAttention 把 KV cache 塞进 SSD,性能几乎和全内存方案持平。
9. 总结
SolidAttention 这篇工作的切入点很准:
- 确认了一个被大家忽视的核心矛盾:动态稀疏 attention 和 SSD 特性天生不匹配,细粒度随机 I/O 导致 SSD 带宽严重浪费
- co-design 思路:不把 attention 算法和存储系统看作两个独立的问题,而是协同设计,让数据访问粒度对齐 SSD 特性
- 三个技术点都很实在:KV 交织(不增加 token 压缩比,纯粹工程技巧)、投机预取(利用跨层选择相似性)、DAG 调度(精细化计算/I/O 重叠)
从工程完成度来看也比较扎实:CUDA + SYCL 双后端,25k 行代码,在真实笔记本上跑出了这些数字。
对做本地推理的同学来说,这个工作提供了一种不量化 KV cache 就能大幅降低内存占用的路子。当然现在还是研究原型,能不能接进 llama.cpp/Ollama 主线还是个问题,但思路是对的。
感兴趣的朋友可以去 FAST 2026 看原文,写得很清楚,B 站和 GitHub 上应该也会陆续有复现出来的版本。
欢迎评论区聊聊你对本地部署 LLM 的看法——有没有在自己的笔记本上实际跑过长上下文推理,感受如何?