音乐
暂未播放
DAK 完全拆解:绕过 HBM 预取,用 TMA 直连远端内存
GPU 内存卸载通常被描述成一个容量问题:HBM 放不下权重和 KV Cache,就把一部分数据留在 CPU 主存,需要时再预取回来。这个描述遗漏了更棘手的一面——预取的数据最终仍要经过 HBM。远端数据先写入 HBM,计算时又从 HBM 读进 SM 的共享内存,不但没有把主存带宽与 HBM 带宽真正相加,反而让两股流量在 HBM 端口上互相争抢。
DAK(Direct Access Kernel)改变的正是这条数据路径。它不把远端内存当作等待换入的慢速仓库,而是让一部分 GPU SM 通过 Tensor Memory Accelerator(TMA)把权重或 KV Cache tile 从主存直接搬进共享内存;另一部分 SM 同时从本地 HBM 取数。只要两条路径的工作量分配得当,算子看到的就不再是“先搬运、后计算”,而是本地与远端带宽并行供数。
这项工作由 Cornell University 的 Shouxu Lin、Zhiyuan Guo 与 Jiaxin Lin 于 2026 年 4 月发布。论文不仅给出两个直接访问 kernel,还回答了三个决定方案能否落地的问题:不同算子应卸载多少、远端 TMA 请求如何避免拖垮本地 HBM、不可被 GPU L2 缓存的主存数据如何避免成倍重复读取。
卸载为什么不只是“显存不够就搬到 CPU”#
推理阶段主要有两类常驻数据:模型权重与 KV Cache。前者随参数量增长,后者随批大小和上下文长度近似线性增长。以 FP16 表示的 671B 参数模型仅权重就需要约 1.34 TB;论文还举例指出,70B 模型在 batch size 为 16、上下文为 100K 时,KV Cache 可以超过 100 GB。单卡 HBM 很容易同时遭遇容量不足与带宽不足。
分层内存系统提供了一条看似自然的出路。GPU 保留高带宽、低容量的 HBM,CPU 一侧提供较大但较慢的主存,中间由 PCIe、NVLink-C2C 或未来的 CXL 类互连连接。以论文采用的 GH200 为例,测试系统包含 96 GB HBM3、480 GB 主存、约 4.0 TB/s HBM 带宽和 900 GB/s 双向 NVLink-C2C 带宽。远端层显著扩充容量,但能否转化为推理性能,取决于数据如何穿过互连。
设参与某个算子的权重或 KV 数据总量为 C,必须放在主存中的比例为 x。x 不是一个随意的调优参数。若模型与 KV Cache 总占用为 M,可用 HBM 容量为 H,忽略运行时工作区后,系统至少要满足:
xglobal≥max(0,MM−H)xglobal 是全局容量约束,却不意味着每个算子都应该采用相同的卸载比例。注意力和线性层的算术强度不同,同一种算子在 prefill、decode、不同 batch size 下也可能跨过 memory-bound 与 compute-bound 的边界。DAK 的关键判断是:容量只规定“总共必须卸载多少”,具体卸载到哪些算子,应该由性能模型决定。
预取路径的三笔隐性成本#
FlexGen 一类系统采用按层预取。执行第 X 层时,把第 X+1 层需要的数据从主存复制到 HBM;理想情况下,通信被当前层的计算遮蔽。问题在于,这种重叠只在时间线上看起来并行,数据路径并没有独立。

图中上半部分是预取式路径。绿色权重复制和蓝色 GPU 计算之间仍有通信气泡与计算气泡。增加双缓冲或把预取深度从一层扩到多层,确实能缩短空隙,却必须在 HBM 里预留更大的 staging buffer;这部分空间本可用于更多权重、KV Cache 或更大的 batch。为了提高权重复用率,FlexGen 还会让多个 micro-batch 依次通过同一层,这有利于离线吞吐,却会增加首 token 延迟和逐 token 延迟。
更根本的代价来自 HBM 的重复经过。传统路径分两步:
- 主存中的远端数据经过互连写入 HBM。
- 计算 kernel 再从 HBM 把同一份数据读入 SMEM。

对内存受限的解码 kernel 来说,后台预取写与前台计算读会竞争 HBM 资源。论文测得,后台复制可让 GH200 的本地内存性能下降最多约 10%;在论文讨论的 PCIe 消费级配置中,下降约为 4% 到 7%。因此,远端链路提供的带宽不是无条件增量。若每个远端字节都要写入再读出 HBM,系统同时付出了互连流量、HBM 写流量和 HBM 读流量。
DAK 将远端 tile 直接送到 SMEM,省掉中间落盘式的 HBM staging。图中的蓝色虚线路径与本地 HBM 到 SMEM 的红色路径可以由不同 SM 并行使用。这带来三个结果:
- 远端读取不再制造额外 HBM 写入,两级带宽才有机会真正聚合。
- 不需要按预取深度常驻 staging buffer,释放出的 HBM 可以保留更多模型数据。
- 搬运粒度从“下一层”缩小到 kernel 内部的 tile,可以用软件流水线覆盖远端访问延迟。
论文用实测与理论曲线对比了两条路线。在较低卸载比例下,直接访问的有效带宽可以逼近 HBM 与远端路径的聚合上限;预取方案则从一开始就受额外 HBM 流量和流水气泡影响。

这里不能把“直接访问更好”误解成远端内存与 HBM 等速。当 x 继续增大,越来越多数据必须穿过较慢的主存链路,最终性能仍会下降。DAK 消除的是不必要的中转与空泡,不会消除物理互连本身的带宽上限。
整体架构:全局容量约束,逐算子选择比例#
DAK 的执行过程可以分成放置与运行两个阶段。放置阶段先根据模型、KV Cache、工作区和 HBM 容量得到全局卸载比例,再为每个线性层和注意力算子计算独立比例。运行阶段用 SplitK_GEMM 和 SplitK_FlashAttn 替换原算子,让本地 tile 与远端 tile 在同一次算子执行中并行供数。

图中的示意系统需要把约 36% 的总体数据放到主存,但三个算子并没有都取 36%。QKV 投影可以卸载 75%,注意力 KV Cache 只卸载 25%,输出投影卸载 33%。这些数字用于说明逐算子分配,并不是适用于所有模型的固定配置。实际比例取决于矩阵形状、batch、序列长度、GPU 算力、本地带宽和互连带宽。
这个区分非常重要。若对所有层统一设置 36%,本来能够用计算完全隐藏远端读取的算子可能没有承担足够的容量,而对远端带宽敏感的算子却被迫卸载过多。全局比例解决“放得下”,逐算子比例解决“跑得快”。
一个矩阵如何同时住在 HBM 与主存#
考虑矩阵乘法:
C=AB论文的记号中,A∈RM×K 表示权重或 KV 相关矩阵,B∈RK×N 与 C∈RM×N 表示隐藏状态。DAK 沿 A 的 M 维切成若干形状为 m×K 的 tile row,再把一部分 tile row 放在主存,其余留在 HBM。

沿 M 维切分有一个直接好处:每个 tile row 对应输出 C 中一组独立的行块。负责远端 tile 的 SM 与负责本地 tile 的 SM 可以各算各的,不需要先把两边结果做跨 SM 求和。图中 t0,t1 对应主存中的权重行,其余输出 tile 对应 HBM 中的权重行。
这也解释了 DAK 为什么强调“每个 SM 只走一条数据路径”。若同一 SM 在一个工作片段中交替从主存和 HBM 取权重,请求队列、延迟与带宽行为会混在一起,既难建模也难做拥塞控制。DAK 按 tile 分派 SM:host SM 负责远端 tile,HBM SM 负责本地 tile。两组 SM 并行工作,最后写入输出矩阵的不同区域。

注意力的切法略有不同。SplitK_FlashAttn 沿 batch 维划分 KV Cache:一部分请求的 KV 留在 HBM,另一部分请求的 KV 放在主存。这样每个请求的注意力仍能在一个内存层内完成,避免把同一条序列的 softmax 归一化拆成复杂的跨层归并。它保持精确注意力语义,卸载本身不引入量化或稀疏近似。
矩阵切分还受执行波对齐约束。假设某组有 nt 个 tile、分到 ns 个 SM,所需执行波数为:
w=⌈nsnt⌉若 nt 不能被 ns 良好整除,最后一波只有少数 SM 工作,其他 SM 空等,这就是尾部气泡。DAK 在满足目标卸载比例的同时调整 tile 与 SM 的分配,使每一波尽量饱满。论文的消融显示,这项 alignment 优化在不同矩阵形状上可带来最高约 1.2 倍吞吐提升。
TMA 如何把远端延迟藏进 kernel 内部#
直接访问并不等于让普通 CUDA 线程逐元素执行 host load。那样会让地址计算与 load 指令占用线程发射槽和寄存器,远端高延迟也很难被少量同步线程隐藏。DAK 复用 Hopper 开始提供的 TMA,将多维 tile 搬运交给专用异步数据通路。
一个 SM 内部采用 warp specialization:
- producer warp 构造并发起 TMA 请求,把下一块 A 从主存或 HBM搬到 SMEM,同时取得相应的 B tile。
- consumer warp 等待当前 SMEM slot 就绪,然后让 Tensor Core 或 CUDA Core 执行矩阵运算。
- producer 在 consumer 计算当前 slot 时填充另一个 slot,形成双缓冲或多级环形缓冲。
抽象后的 kernel 主循环可以写成:
1预装前若干 tile 到 SMEM slots2for each output tile:3 等待当前 slot 的 TMA 完成4 consumer 对当前 tile 执行矩阵运算5 producer 向空闲 slot 发起下一次 TMA6 轮换 slot7写回输出 tileTMA 的价值不只是“复制更快”,而是把搬运从计算 warp 的指令流中解耦出来。只要某个 tile 的计算时间足以覆盖下一个 tile 的传输时间,远端延迟就不会完整暴露在关键路径上。与按层预取相比,这种重叠发生在同一个 kernel 的 tile 粒度,不需要猜测下一层何时开始,也不需要把完整层权重先塞进 HBM。
TMA 本来面向 global memory 到 shared memory 的多维异步搬运。DAK 的硬件发现是:当 global address 指向可由 GPU 访问的 host-homed memory 时,TMA 同样能够让数据经互连直接到达 SMEM。论文称这是首次将 TMA 用于这种远端卸载路径。需要注意,这一能力依赖 Hopper 及之后架构的 TMA、统一地址可达性以及相应互连,并不是旧 GPU 上只改几行软件就能获得的通用技巧。
卸载比例的数学模型#
只实现直访 kernel 还不够。若主存链路只有 HBM 的一小部分带宽,把过多 tile 分给 host SM,远端路径会成为长板中的短板;把过少 tile 分给 host SM,又可能浪费可并行利用的带宽。
对算子 i 定义:
- Ci:要读取的权重或 KV 数据量。
- xi:其中放在主存的比例。
- Bg:GPU 本地 HBM 的可用带宽。
- Bh:主存到 GPU 的有效远端带宽。
- Tcomp,i:算子纯计算时间。
由于本地和远端两条路径并行,二者的传输时间分别为:
Tg,i=Bg(1−xi)CiTh,i=BhxiCi理想重叠下,算子时间由三者中的最大值决定:
Ti(xi)=max(Tcomp,i,Tg,i,Th,i)论文用有效带宽统一描述不同算子:
EBi(xi)=Ti(xi)Ci这里的 EB 不是某条物理总线的原始带宽,而是“本算子涉及的数据量除以完成时间”。它可以高于单独的远端带宽,因为本地 HBM、远端链路和计算正在并行工作。

memory-bound 算子的峰值#
若 xi=0 时 Tcomp,i<Ci/Bg,算子由本地内存读取限制。随着少量数据被移到主存,本地传输量下降,远端路径同时加入供数,EB 上升。最优点出现在两条传输时间相等:
Bg(1−xi)Ci=BhxiCi约去 Ci 并整理可得:
xi⋆=Bh+BgBh此时两边恰好同时完成,理论有效带宽为 Bg+Bh。若继续增大 xi,远端读取时间 xiCi/Bh 超过本地路径,EB 反而按 Bh/xi 下降。
以论文 GH200 的标称测试参数作直觉计算,若取 Bg=4.0 TB/s、Bh=0.9 TB/s,则平衡点约为:
x⋆≈4.0+0.90.9≈18.4%这不是实际 kernel 的固定最佳值,因为协议损耗、矩阵形状、并发请求与拥塞都会改变可用带宽;它说明了一条原则:对 memory-bound 算子,适量卸载可以加速,超过带宽平衡点则开始减速。
compute-bound 算子的无损区间#
若算子在 xi=0 时由计算限制,少量卸载不会改变总时间,因为本地与远端传输都被 Tcomp,i 遮蔽。定义该算子的计算等效带宽:
Bi=Tcomp,iCi远端读取开始暴露到关键路径的临界点满足:
BhxiCi=Tcomp,i于是:
xi⋆=BiBh在 xi≤xi⋆ 的区间里,EB 维持在 Bi,也就是“可以免费卸载”的容量区间。一旦越过阈值,算子转成远端内存受限,性能开始随 xi 增加而下降。
decode 与 prefill 为什么不能套同一比例#
decode 注意力读取不断增长的 KV Cache,其计算量和内存流量都随 B⋅L⋅Dh 增长,算术强度保持在常数量级,通常严格 memory-bound。decode 中的线性层则会随 batch 增大获得更高权重复用,可能从 memory-bound 转向 compute-bound。
prefill 注意力的计算量近似为 O(BL2Dh),KV 流量近似为 O(BLDh),算术强度随 L 增长;长 prompt 下它可能 compute-bound。prefill 的线性层算术强度近似随 B⋅L 增长,通常也更偏计算受限。因此,“注意力优先卸载”或“权重优先卸载”都不是普遍规则,必须结合阶段和形状判断。
三阶段贪心分配为什么是最优的#
设全局卸载比例为 R,所有算子的卸载数据量必须满足:
i∑Cixi=Ri∑Ci端到端目标是最小化各算子延迟之和:
{xi}mini∑EBi(xi)Cis.t.0≤xi≤1观察上一节的分段曲线,就能得到 DAK 的三阶段策略。
第一阶段,把卸载预算给尚未到峰值的 memory-bound 算子。这一段每增加一点 xi 都会减少本地数据量,并通过远端并行带宽降低算子时间;此时把同样预算给 compute-bound 算子只会保持时间不变。通过交换论证可以证明,只要仍有 memory-bound 算子处于上升段,把预算从 compute-bound 算子挪给它就不会更差,而且通常会严格变好。
第二阶段,所有 memory-bound 算子到达 Bh/(Bh+Bg) 后,将剩余预算分配给仍处于无损区间的 compute-bound 算子。它们的 Tcomp 尚能遮住远端读取,所以增加卸载量不增加执行时间。
第三阶段,若容量压力大到所有算子都越过各自转折点,额外主存流量已经无法被计算或本地带宽遮蔽。此时必须在远端受限区继续分配。在所有相关算子均保持在各自转折点之上的条件下,其远端延迟项之和与固定的总卸载字节数成正比,额外预算如何分摊不再改变理想模型中的总时间。
这个“最优”有明确边界:证明建立在算子串行求和、带宽稳定、两级传输可理想重叠、性能曲线服从上述分段模型等假设上。真实 GPU 还有 tile 离散化、执行波尾部、共享内部队列与地址对齐,因此 DAK 仍需要 profiler 和 kernel-level 修正。贪心算法解决的是宏观比例,不能代替底层调度。
论文在 batch size 512 的混合负载上比较了贪心与统一比例。卸载比例低于 60% 时,贪心策略最高约快 1.5 倍;超过 60% 后,两者逐渐收敛,因为大部分操作都已落入远端互连受限区。

远端 TMA 请求为什么会拖慢本地 HBM#
直访绕过 HBM staging,不代表远端与本地路径在 GPU 内部完全隔离。DAK 发现,无约束地增加远端请求,会连带降低 SM 到 HBM 的带宽。远端并发量可粗略写成:
Qremote∝NSM,host⋅NinflightNSM,host 是负责主存 tile 的 SM 数量,Ninflight 是每个 SM 同时挂起的 TMA 请求数。增加前者可以暴露更多并行度,增加后者可以遮蔽长延迟;但二者乘积太大时,远端请求会在内部互连中堆积。

GH200 实验固定 100 个 SM 读取 HBM,并逐步增加 host SM。host SM 超过 8 个后,本地 HBM 带宽明显下降。固定 SM 数、增加每个 SM 的在途请求也出现相同趋势。论文没有公开 GPU 内部实现,因而把根因谨慎表述为推测:NVLink-C2C 饱和后,未完成的远端请求可能占满 L2 MSHR、路由 buffer 或其他共享资源,使本地请求也无法及时推进。
DAK 为此引入类似网络拥塞窗口的静态 credit:
- 限制每个 host SM 的最大在途 TMA 数,只保留足以填满远端链路的并发度。
- 限制 host SM 总数,避免为了处理少量远端 tile 启动过多请求源。
- 在 kernel 启动前做轻量参数扫描,为特定硬件和矩阵形状选择窗口,而不在 kernel 内动态调整。
之所以不用类似 TCP 的运行时增减窗口,是因为 GPU kernel 内做复杂反馈控制会引入同步、计数与分支开销。论文的离线 profile 把控制成本移出热路径。消融实验中,拥塞控制在六组矩阵形状上带来 1.06 到 1.22 倍有效带宽提升。

这项结果还有一个系统层含义:聚合带宽不是简单的 Bg+Bh。只有远端请求没有污染本地路径时,两者才近似可加。若共享资源发生反压,继续追求更高远端并发反而会降低总带宽。
不可缓存主存与读放大#
即使 GH200 提供 CPU-GPU cache coherence,论文观察到 host-homed memory 的直接读取仍绕过 GPU L2。PCIe 系统也有同样问题。于是,当多个 SM 需要同一块远端权重 tile 时,L2 不能像处理 HBM 数据那样把第一次读取留给后续 SM 命中,每个 SM 都会在互连上重新取一次。
论文固定远端矩阵为约 98 MB,改变隐藏状态矩阵的 N 维。测得结果如下:
| N | host-GPU 流量 | 读放大 |
|---|---|---|
| 256 | 102.76 MB | 1.05 倍 |
| 512 | 205.52 MB | 2.10 倍 |
| 1024 | 411.04 MB | 4.19 倍 |
| 2048 | 822.08 MB | 8.39 倍 |
| 4096 | 1.64 GB | 16.78 倍 |
远端数据本身没有变大,流量却随消费者数量接近线性增长。batch 越大、同一权重 tile 被更多输出 tile 复用,这个问题越严重。若不处理,GEMM 原本希望通过复用提高算术强度,反而会把复用次数变成跨互连的重复传输次数。
DAK 用 TMA multicast 与 host-locality-first scheduling 配合解决:
- 把会消费同一远端 tile 的 SM 组织到同一个 thread block cluster,并保证它们同时驻留。
- 只由 cluster 中一个 producer 发起远端 TMA,把 tile 穿过 host-GPU 互连一次。
- 数据到达 GPU 后,通过片上 NoC 和 Distributed Shared Memory 广播到多个 SM 的 SMEM。
- 各 consumer 从自己的 SMEM slot 计算,不再重复访问主存。
调度目标因此从传统的“HBM/L2 局部性优先”变成“远端 tile 局部性优先”。昂贵的跨封装传输只做一次,复制发生在带宽更高、距离更短的片上网络。

在 7168×7168 权重矩阵实验中,N=512 时 multicast 相对无 multicast 提升约 1.3 倍;N=1024 时提升扩大到约 2.5 倍。收益随 N 增大,正好与读放大随消费者数量增长的分析一致。
实现落地:两个替换算子与 CUDA Graph#
论文实现约包含 1300 行 Python 和 2700 行 CUDA C++,并借助 CUTLASS/CUTE 构建底层 kernel。面向框架暴露两个 PyTorch 模块:
SplitK_GEMM替换nn.Linear,负责跨 HBM 与主存放置的权重矩阵。SplitK_FlashAttn对齐 PyTorch SDPA 接口,负责按 batch 切分的 KV Cache。
这种接口把模型结构与内存放置分开。模型初始化时替换对应层,placement 模块决定 tile 所在内存层,运行时 kernel 根据映射选择本地或远端 TMA 描述符。它不是透明 UVM:开发者获得可预测的 tile 级路径,代价是必须使用定制算子。
decode 每步工作量较小,Python 与 CPU launch 开销可能盖过 kernel 优化。DAK 预先用 PyTorch StaticCache 分配 KV Cache,并捕获 CUDA Graph;后续 token 通过 graph replay 发射,避免每步重新走 Python 调度和大量 kernel launch。论文也指出,OPT-6.7B 上 FlexGen 的部分劣势来自小模型下启动开销占比变大,而 DAK 和 vLLM 使用 CUDA Graph 消除了这部分开销。因此,比较结果既反映数据路径,也混合了运行时优化差异。
开源仓库当前默认面向 GH200 的 sm_90a 构建,也提供 RTX PRO 6000 Blackwell 的 sm_120a 构建参数;split attention 的 -gencode 仍需手工调整。不同架构需要替换 CUTE MMA atom,并重新校准 TMA chunk、SM 数与最大在途请求。它更接近研究原型和硬件协同 kernel,而不是任意 CUDA GPU 上即装即用的通用后端。
实验结果应该怎样读#
论文在两套单 GPU 系统上做离线 batched inference:
| 平台 | 本地显存 | 本地带宽 | 主存 | host-GPU 链路 |
|---|---|---|---|---|
| GH200 | 96 GB HBM3 | 4.0 TB/s | 480 GB | 900 GB/s NVLink-C2C |
| RTX 6000 Pro Blackwell | 96 GB GDDR7 | 1.8 TB/s | 512 GB | 64 GB/s 单向 PCIe Gen5 |
工作负载包含 OPT-30B、OPT-6.7B 和 Llama-2-7B,每个请求解码 32 个 token,默认 prompt 长度为 32。基线包括 FlexGen、论文实现的 vLLM-prefetch,以及依赖 UVM page fault 与迁移的 vLLM-uvm。指标主要是 TPOT 与有效带宽:
EB=TPOT模型数据规模在 batch size 8、主要卸载权重的实验中,DAK 在 GH200 的卸载比例扫描中保持最高 EB。OPT-30B 在 10% 卸载比例时达到约 3300 GB/s。论文正文针对不同模型与比例报告 1.5 到 5 倍的局部对比,而摘要用更保守的总体表述给出相对先进卸载基线最高 3 倍的 NVLink-C2C 收益、1.8 倍的 PCIe 收益。二者分母与配置不同,不能把所有最大值拼成同一个结论。

PCIe 平台的远端带宽只有 64 GB/s,远低于 1.8 TB/s GDDR7。在 0% 到 40% 的低中卸载范围,DAK 相对 FlexGen 与 vLLM-prefetch 仍有约 1.3 到 3 倍收益;超过 40% 后三者趋于接近,因为权重读取最终都被 PCIe 物理带宽限制。直接访问可以避免额外中转,不能把 64 GB/s 变成 HBM 级带宽。
batch size 512 时,KV Cache 增至约 45 GB,线性层与注意力分别表现出 compute-bound 和 memory-bound 特征。DAK 相对基线最高提升约 2.1 倍,收益来自三项叠加:两级带宽并行、逐算子比例分配、multicast 抑制大 batch 的权重读放大。
论文还让真实容量需求决定比例,而不是人为扫描。OPT-30B 的模型权重约 55.6 GB;当 batch 与 prompt 增大时,KV Cache 从 0.7 GB 增至 186.03 GB,全局卸载比例从 0% 增至 60%。DAK 在这些配置上相对 vLLM 提升 1.06 到 1.83 倍,相对 FlexGen 提升 1.53 到 21 倍。21 倍出现在特定高压力配置,并不等于常规请求都能获得同等加速。

DAK 与 PagedAttention、UVM、存储卸载的边界#
DAK 解决的是物理数据路径和跨层带宽利用,不替代上层 KV 内存管理。
- PagedAttention 解决 KV Cache 的逻辑分块、非连续映射、共享与写时复制,减少显存碎片。DAK 决定这些数据实际位于 HBM 还是主存,以及 kernel 如何直接读取。两者可以组合;前者可参考 PagedAttention 完全拆解。
- UVM 提供统一地址与按页迁移,但 4 KB page fault、迁移串行化和不可控抖动不适合规则的大矩阵热路径。DAK 同样利用 GPU 可寻址的主存,却用显式 tile、TMA 和静态放置避开按需缺页。
- DualPath 让空闲网络路径参与 KV Cache 加载,关注跨推理节点的缓存传输;DAK 关注单机 CPU-GPU 分层内存和 SMEM 直达。共同点是都不把数据移动视为计算前的附属阶段,而是把多条物理路径纳入调度。
- H³ 混合内存架构 把层次扩展到高带宽闪存,解决更大容量的长上下文问题。DAK 的 tile 直访思想提供了 kernel 侧启发,但闪存延迟远高于主存,不能直接照搬同一流水深度与比例模型。
因此,DAK 最适合的不是“任何显存不足场景”,而是 GPU 能以细粒度访问远端内存、互连带宽足以参与供数、算子可按 tile 独立切分、硬件又支持 TMA 与 cluster multicast 的系统。PCIe 也能获益,但适用卸载比例窗口明显更窄。
局限与仍需验证的问题#
第一,评测是离线批推理,不是带动态到达、优先级、取消请求和 SLO 的在线服务。真实服务关心 P50/P99 TTFT、TPOT 抖动与吞吐之间的约束。静态 offload ratio 和离线 profile 在请求形状快速变化时是否仍接近最优,需要在线系统实验。
第二,模型集合以 OPT-30B、OPT-6.7B 和 Llama-2-7B 为主,没有覆盖更现代的 GQA、MLA、MoE 或强量化模型。GQA/MLA 会改变 KV Cache 与权重流量比例;MoE 每步只访问部分专家,路由不确定性会破坏静态 tile 放置;INT4/FP8 权重则降低字节量并提高算术强度,使原来的转折点整体移动。
第三,所谓“可证明最优”针对论文的分段带宽模型。模型没有显式表示不同算子间的 cache 状态、NUMA 放置、页面粒度、TMA descriptor 开销、功耗、多个并发模型的互相干扰。实际系统依赖 profile 校准,跨机器复制配置并不可靠。
第四,host memory 绕过 GPU L2 是 multicast 必要性的来源,但不同 CPU-GPU 一致性实现、未来 CXL.cache 设备或新一代 GPU 的缓存策略可能改变这一前提。multicast 本身也受 thread block cluster 规模、DSMEM 容量与同步成本限制。
第五,论文展示了吞吐与 TPOT,却没有系统报告功耗和每 token 能耗。把数据跨 NVLink-C2C 或 PCIe 持续送入 GPU,可能减少 HBM 流量,却增加互连与主存功耗。对部署成本的完整判断还需要能效数据。
从 DAK 得到的系统设计启示#
DAK 最有价值的结论并不是某个固定加速倍数,而是重新定义“卸载”。传统卸载的抽象是换入换出:远端层只负责容量,计算仍以 HBM 为唯一入口。DAK 的抽象是异构供数:每一级内存既贡献容量,也在 kernel 执行期间贡献带宽。
这个抽象成立需要四层协同:
- 算法层知道哪些操作 memory-bound,哪些操作有可免费卸载的 compute-bound 区间。
- 放置层把全局容量缺口转换为逐算子比例,而不是统一百分比。
- kernel 层按独立输出 tile 切分工作,用 warp specialization 把远端传输藏在计算后面。
- 体系结构层控制共享互连拥塞,并用 multicast 把远端复用转移到片上网络。
少任何一层,理论上的带宽相加都可能落空。只改放置算法而继续预取,会有 HBM staging;只写直访 kernel 而不控请求,会让远端流量拖慢本地 HBM;只限制拥塞而不做 multicast,大 batch 会制造十几倍读放大;只做底层优化而统一卸载比例,又会把容量压给最敏感的算子。
最终可以用一句话概括 DAK:它没有让远端内存变快,而是让远端内存不再先假装成 HBM。通过 TMA 直达 SMEM、逐算子比例、拥塞窗口与 cluster multicast,主存第一次以独立供数通路参与 LLM kernel,卸载也从容量补丁变成了可调度的带宽资源。
参考资料#
- DAK: Direct-Access-Enabled GPU Memory Offloading with Optimal Efficiency for LLM Inference
- DirectAccessKernel 官方代码仓库
- CUDA C++ Programming Guide:Tensor Memory Accelerator
- NVIDIA Hopper Architecture In-Depth
- NVIDIA Grace Hopper Superchip
- FlexGen: High-Throughput Generative Inference of Large Language Models with a Single GPU
- Understanding Data Movement in Tightly Coupled Heterogeneous Systems: A Case Study with the Grace Hopper Superchip
- FlashAttention-3: Fast and Accurate Attention with Asynchrony and Low-precision
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
评论区
分享你的想法,与大家交流讨论
音乐
暂未播放



