DualPath KV Loading

导言

Agentic LLM 的每轮新增输入很短,累计上下文却很长。高 KV Cache 命中率把重复计算变成了外部存储读取,但传统 P/D 分离系统只让 Prefill 节点承担读取,结果往往不是 GPU 算力不足,而是 Prefill 侧 Storage NIC 先堵住。DualPath 的核心不是压缩 KV,也不是换一种 Attention,而是把 Decode 侧闲置的存储入口和计算网络一起纳入 KV 加载路径,再用 QoS 与两级调度防止新路径干扰推理。本文进一步判断:昇腾 AIV 直驱可以成为其中一段细粒度 RDMA 控制路径的候选优化,但不能直接替代 DualPath 系统。

结论先行

DualPath 可以概括为三项必须一起成立的改造:

  1. 双路径加载。Storage → Prefill 外,增加 Storage → Decode → Prefill,把 Decode 节点原本闲置的 Storage NIC 带宽也用于读取命中 KV。
  2. CNIC 流量管理。让 GPU 入站和出站流量都经过成对的 Compute NIC,并用硬件 QoS 让模型通信高优先、KV 搬运低优先但不饿死。
  3. 自适应调度。联合观察未完成 Token、存储读队列、Decode 请求数和 HBM,用请求放置与读路径选择把新增带宽真正转化为端到端吞吐。

论文在其 Hopper、InfiniBand、3FS 与生产 Agent Trace 的实验边界内,报告了最高 1.87× 离线吞吐平均 1.96× 在线吞吐;组件消融中,Layerwise Prefill、Dual-Path Loading 与调度依次把平均 JCT 降低扩展到 17.21%、38.19% 和 45.62%。这些数值不是跨框架、跨硬件的常数。

对 AIV 直驱的结论是:能用,但只能把它当作局部、条件式的数据面优化,不能把它当作 DualPath 的开关。最佳候选是 Decode 到 Prefill 的 Layer Block 传输,以及反向返回 Miss KV 的细粒度工作提交。它不能直接加速 3FS/SNIC 读取,不能替代全局调度,也不能自动提供网络 QoS。更关键的是,公开 CANN 资料尚不足以证明 AIV 能无额外 Staging 地覆盖论文中以 Host DRAM 为源或目的的全部单边 RDMA。

DualPath 环节 AIV 直驱判断 关键原因
3FS → Host DRAM 不能直接加速 这是存储客户端、SNIC 与文件系统路径,不是 AIV 通信提交路径
本机 Host DRAM → HBM 高适配成本、条件成立 论文通过 CNIC 做本地 RDMA;公开 AIV 路径更强调 Device HCCL Buffer
Decode → Prefill Layer Block 最值得验证 小而频繁的 WQE 可能让固定提交时延占比可见
Prefill → Decode Miss KV 条件成立 目标是论文中的 Decode Host Buffer,必须先证明地址可达性
IB VL / RoCE TC QoS AIV 不替代 QoS 属于 NIC、交换网络和通信类映射策略
跨引擎与批内调度 AIV 不替代 它们是请求级控制面,而不是通信 Kernel

论文要解决的问题

传统 KV Cache 命中通常带来一个直觉:既然不必重算长前缀,系统应该更快。DualPath 指出,在 Agentic 场景中,命中只把主要成本从 Prefill 计算转移到了长上下文 KV 的外部存储 I/O。当每轮只追加少量 Token、历史上下文却达到数万 Token 时,读出的命中 KV 可能远多于新算出的 Miss KV。

在论文研究的 P/D 分离架构里,每个节点有多张 GPU 和多张 Compute NIC(CNIC),却只有一张 Storage NIC(SNIC)。旧路径规定 KV 必须先由 Prefill 节点从 3FS 读取。于是 Prefill 节点的 SNIC 满载,而 Decode 节点的 SNIC 闲置;继续增加 Prefill GPU 也无法同比增加单节点存储入口。

![小黑打开 Decode 侧第二个 KV 取货口](https://pic.shaojiemike.top/shaojiemike/2026/08/f9d45a77728aa999a0de26563b76ba91.png){ width=92% }
原创认知插图:拥堵的 Prefill 取货口代表旧的单路径读取,小黑打开 Decode 侧入口,并通过计算网络把 KV 包裹送到 Prefill。它表达带宽池化直觉,不是论文实验图。

真正的矛盾

系统缺的未必是更多存储总带宽,而是让全部现有存储入口同时为同一批请求工作的方法。这使问题从“如何更快计算 Attention”转变为“谁负责读、读到哪里、何时转交、谁有优先权”。

小白版:多开一个取货口

把长上下文 KV 想成仓库里的旧档案。Prefill 是负责把旧档案和新问题合并的审阅员,Decode 是根据合并结果逐字输出的写作者。

旧流程只有审阅员一侧能从仓库取档案。即使写作者旁边也有一扇空闲取货门,所有货车仍排在审阅员门前。DualPath 允许一部分旧档案从写作者的门取出,再通过内部高速桥分层送给审阅员;审阅员每处理完一层,又把该层新补出的内容送回写作者,最后写作者拿到完整档案开始生成。

这个类比能解释三件事:

  • 第二个门对应 Decode 侧 SNIC,解决入口利用率失衡。
  • 高速桥对应 CNIC/RDMA,承担 Decode 与 Prefill 间的 Layer Block 搬运。
  • 交通警察对应 QoS 和调度器,避免搬档案的车堵住推理关键通信。

类比也有边界:KV 不是可以任意拆放的普通文件。它按 Layer、Token 和 KV Head 组织;Prefill 必须遵守逐层计算依赖;Decode 开始前必须拥有可消费的完整上下文 KV;Host DRAM、HBM、PCIe、SNIC 与 CNIC 都有独立容量和竞争关系。

Dual-Path Loading

关键对象

DualPath 使用两种粒度:持久化存储以 Full Block 保存跨层 KV,Prefill 与 Decode 之间按 Layer Block 流式传输。前者利于存储管理,后者把 Prefill HBM 的瞬时驻留限制在当前层附近。

对象 生产者 形状或内容 消费者 生命周期
hit_full_block 前序轮次持久化 [T_hit, L, C_KV] 的语义视图 PE 或 DE 读路径 持久化对象
hit_layer[l] Full Block 分层切片 [T_hit, C_KV] Prefill 第 l 当前层内短暂存在
miss_layer[l] Prefill 新增 Token 计算 [T_miss, C_KV] Decode Buffer 合并 当前层计算后产生
complete_layer[l] Hit 与 Miss 合并 [T_all, C_KV] Decode 阶段 请求结束前可复用
pe_buffer Prefill SNIC 读入 Host DRAM 中的流式缓冲 PE HBM、DE Buffer 有界流式生命周期
de_buffer Decode SNIC 或 PE 回传 Host DRAM 中的完整 Prompt KV 最终 Decode H2D H2D 完成后释放
wqe 通信控制路径 地址、长度、对端、操作码 CNIC/RDMA 队列 提交至完成

两条读路径

PE Read Path 保留旧的存储入口,但改为逐层工作:Prefill 从存储把命中 KV 读入 pe_buffer,当前层的 Hit KV 进入 PE HBM;Prefill 计算新增 Token 的 Miss KV,组成完整 Layer KV 后写入 de_buffer。所有层完成后,Decode 再把完整 Prompt KV 送入 HBM。

DE Read Path 使用新的入口:Decode 从存储把命中 KV 读入 de_buffer;每到一层,Hit KV 经 Decode CNIC 发到 Prefill HBM;Prefill 只返回该层新算出的 Miss KV,Decode 在 Host Buffer 中合并。这样,Decode 侧 SNIC 承担了存储读取,Prefill 侧 HBM 仍按层消费。

下面的伪代码刻意展开对象的产生、使用与释放。它是教学化重构,不冒充论文未公开的实现源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def pe_read_path(request, storage, pe, de):
pe_buffer = storage.read_full_blocks(
node=pe.node,
block_ids=request.hit_block_ids,
)
de_buffer = de.allocate_host_prompt_buffer(request.total_kv_shape)

for layer_id in range(request.layer_count):
hit_layer = pe_buffer.slice_layer(layer_id)
pe_hbm_slot = pe.allocate_layer_slot(layer_id, hit_layer.shape)
pe.local_rdma_write(hit_layer, pe_hbm_slot)
pe.wait_until_ready(pe_hbm_slot)

miss_layer = pe.compute_appended_kv(
request=request,
layer_id=layer_id,
cached_kv=pe_hbm_slot,
)
complete_layer = concatenate_tokens(hit_layer, miss_layer)
destination = de_buffer.layer_slot(layer_id)
pe.rdma_write(complete_layer, destination)
pe.wait_for_write_completion(destination)

pe.release_layer_slot(pe_hbm_slot)
release_transient(miss_layer)
release_transient(complete_layer)

de_hbm_cache = de.allocate_hbm_cache(request.total_kv_shape)
de.local_rdma_write(de_buffer, de_hbm_cache)
de.wait_until_ready(de_hbm_cache)
de.release_host_prompt_buffer(de_buffer)
pe.release_host_read_buffer(pe_buffer)
return de_hbm_cache


def de_read_path(request, storage, pe, de):
de_buffer = storage.read_full_blocks(
node=de.node,
block_ids=request.hit_block_ids,
)

for layer_id in range(request.layer_count):
hit_layer = de_buffer.slice_layer(layer_id)
pe_hbm_slot = pe.allocate_layer_slot(layer_id, hit_layer.shape)
de.rdma_write(hit_layer, pe_hbm_slot)
de.wait_for_write_completion(pe_hbm_slot)

miss_layer = pe.compute_appended_kv(
request=request,
layer_id=layer_id,
cached_kv=pe_hbm_slot,
)
destination = de_buffer.miss_slot(layer_id)
pe.rdma_write(miss_layer, destination)
pe.wait_for_write_completion(destination)
de_buffer.merge_layer(layer_id, miss_layer)

pe.release_layer_slot(pe_hbm_slot)
release_transient(miss_layer)

de_hbm_cache = de.allocate_hbm_cache(request.total_kv_shape)
de.local_rdma_write(de_buffer, de_hbm_cache)
de.wait_until_ready(de_hbm_cache)
de.release_host_prompt_buffer(de_buffer)
return de_hbm_cache
![DualPath 双路径加载五视图](https://pic.shaojiemike.top/shaojiemike/2026/08/3dffee9c33c8d6f6dfe0078832508c1a.png){ width=100% }
自绘五视图技术图:从物理前后对比、因果链、PE/DE 分支流程、对象生命周期和 KV 数据流解释 Dual-Path Loading。语义来自论文 §3–§4 与 Figure 4,不是周期精确 Trace。
![DualPath 论文 Figure 4 双路径读取流程](https://pic.shaojiemike.top/shaojiemike/2026/08/49a16c5a6bd432518a6234c31938cb67.png){ width=96% }
论文 Figure 4 的原始局部裁剪:左侧为 PE Read Path,右侧为 DE Read Path。图片仅用于解释论文逻辑,版权归原作者与出版方所有。

第二条路径不是免费午餐

DE Read Path 增加了 Decode Host DRAM 容量、Host 内存带宽、CNIC 流量以及最终一次 H2D。论文提到可以用 GPU Direct RDMA 进一步旁路 Host Buffer,但其实现选择 Host Buffer 来减少 Decode 开始前的 HBM 占用。因此,DualPath 的收益来自重新分配瓶颈,不是消除字节。

CNIC Traffic Manager

DualPath 让 KV、模型并行通信和本机 H2D/D2H 都竞争 PCIe 与 Compute NIC。论文没有只依赖软件限速,而是把 GPU 相关流量集中到成对 CNIC,通过 InfiniBand Virtual Lane 区分优先级:模型通信使用高优先级,KV 使用低优先级;实验配置把约 99% 仲裁权重给关键推理流量,同时为 KV 留少量份额防止饥饿。

论文选择 CNIC RDMA 而不是普通 CUDA Copy/GDS 的主要理由是可控干扰:PCIe Copy Engine 本身缺少同等的流量类别隔离,而 Collective 的突发持续时间可能低于毫秒,软件整形难以及时反应。论文测试中,单次 cudaMemcpyAsync 提交约为 5–7 微秒,RDMA Write 提交约为 1 微秒;这是特定软件栈和硬件上的观测,不能当作所有平台的固定比例。

在论文的简化带宽模型中,若每节点有 g 张 GPU/CNIC,单 CNIC 带宽为 B,单节点存储带宽为 sB,Prefill 与 Decode 节点数为 PD,Host 内存带宽为 M,无瓶颈的节点比例满足:

$$
\frac{s}{g-s}\leq\frac{P}{D}\leq
\min\left(
\frac{g-2s}{s},
\frac{g-s}{2s},
\frac{M/(Bs)-3}{2}
\right)
$$

以论文示例 g=8s=1M≈500 GB/sBs≈50 GB/s 代入,得到 1/7 ≤ P/D ≤ 7/2。这个区间成立的前提包括 PCIe 拓扑配置合理、负载均衡、计算网络没有额外拥塞且存储读能饱和,它是条件式可行域,不是部署容量保证

Adaptive Scheduler

只增加路径仍可能让某个节点排长队。DualPath 的调度分两层:跨引擎调度为请求选 PE、DE 和读路径;PE 内部调度用 Compute Quota 组织 Batch,减少 Data-Parallel Attention 的长尾 Rank 和 Bubble。

跨引擎状态不只看请求数:tok_e 表示引擎未完成 Token,seq_e 表示未完成序列,read_q_n(e) 表示所在节点的存储读队列。Prefill 先排除 Token 超过 β 的过载引擎,再优先选择读队列不超过 α 的候选;Decode 还联合 HBM、请求数和 Token;最后比较 PE 与 DE 所在节点的读队列,决定走哪一侧 SNIC。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
def choose_dualpath_assignment(request, prefill_engines, decode_groups, alpha, beta):
eligible_prefill = []
fallback_prefill = []

for engine in prefill_engines:
if engine.unfinished_tokens > beta:
continue
if engine.node.read_queue <= alpha:
eligible_prefill.append(engine)
else:
fallback_prefill.append(engine)

if eligible_prefill:
pe = min(eligible_prefill, key=lambda item: item.unfinished_tokens)
elif fallback_prefill:
pe = min(fallback_prefill, key=lambda item: item.unfinished_tokens)
else:
pe = min(prefill_engines, key=lambda item: item.unfinished_tokens)

de_group = min(
decode_groups,
key=lambda group: sum(engine.unfinished_tokens for engine in group.engines),
)
hbm_candidates = [
engine
for engine in de_group.engines
if engine.free_hbm_bytes >= request.required_decode_hbm_bytes
]
if not hbm_candidates:
raise AdmissionDeferred("no Decode engine has sufficient HBM")

high_token_threshold = derive_decode_token_threshold(hbm_candidates)
low_token_candidates = [
engine
for engine in hbm_candidates
if engine.unfinished_tokens <= high_token_threshold
]
if low_token_candidates:
de = min(
low_token_candidates,
key=lambda item: (item.unfinished_sequences, item.unfinished_tokens),
)
else:
de = min(
hbm_candidates,
key=lambda item: (item.unfinished_tokens, item.unfinished_sequences),
)

if pe.node.read_queue <= de.node.read_queue:
read_path = "PE_READ_PATH"
else:
read_path = "DE_READ_PATH"

return pe, de, read_path


def build_prefill_batch(waiting_requests, estimate_attention_time, compute_quota):
batch = []
consumed_quota = 0.0

for request in waiting_requests:
predicted_cost = estimate_attention_time(request)
if batch and consumed_quota + predicted_cost > compute_quota:
break
batch.append(request)
consumed_quota += predicted_cost

if not batch and waiting_requests:
batch.append(waiting_requests[0])
return batch
![DualPath 自适应调度五视图](https://pic.shaojiemike.top/shaojiemike/2026/08/29b018e7d643f14a09b00c6118d26b3e.png){ width=100% }
自绘五视图技术图:展示 Round-Robin 失效原因、指标与阈值、PE/DE/路径/Quota 决策过程、调度时序和控制数据流。依据论文 §6 与 Algorithm 1,不表示作者未公开的精确代码。

这里有两个重要边界。第一,tok_e 是设备负载的代理量,不等于精确执行时间;Compute Quota 依赖拟合或估计。第二,论文只在 PE Read Path 与 DE Read Path 之间二选一,把单个请求同时拆到两条存储路径读取仍是未来工作

实验证据

论文实现对内部推理框架修改约 5K 行,使用 FlashMLA、DeepGEMM、DeepEP 和 3FS。3FS 采用类似 io_uring 的 Kernel-Bypass I/O,且实验关闭 3FS 内部 DRAM Cache,以便更直接观察存储路径。测试节点包含 8 张 NVIDIA Hopper GPU、8 张 400 Gbps RDMA CNIC 和 1 张 400 Gbps SNIC,计算网与存储网物理隔离。

维度 论文设置 外推边界
模型 DeepSeek V3.2 660B、内部 DS 27B、Qwen2.5-32B 参数量、KV 头数与并行方式都会改变比例
负载 3 组生产 Agentic RL Trace,各 500 条轨迹 命中率与追加长度并非所有在线业务都相同
上下文 最大 32K、48K、64K,短追加 短上下文或低命中场景可能不受 SNIC 限制
网络 Hopper + InfiniBand + 独立 SNIC/CNIC 昇腾 RoCE/UB、PCIe 与 QoS 语义需重新验证
基线 内部 Basic、Oracle,并展示 SGLang 论文明确指出 SGLang 对比不公平,只报告 Basic→Ours 改善
![DualPath 论文 Figure 12 组件消融](https://pic.shaojiemike.top/shaojiemike/2026/08/7da92c0cab264f4e9667a4b2f1e51b7b.png){ width=86% }
论文 Figure 12 的原始局部裁剪:展示在线 TTFT 分解和离线组件消融。Layerwise Prefill、Dual-Path Loading 与调度的收益均绑定 DeepSeek 660B、64K 上下文及图中并发设置,不能直接迁移为 AIV 收益预测。

论文报告调度把跨节点存储 NIC 最大/平均利用率比从 1.53 降到 1.18,部分早期 Attention 阶段的最大/平均时间比低至 1.06。这些结果说明调度的价值不只是“选到空闲网卡”,还包括把 I/O 与计算的不均衡限制在可重叠范围。对较小模型,通信和协调开销更容易暴露,论文也把 TPOT 开销继续优化列为未来工作。

反向拆解

Reverse Deconstruction 不从论文目录复述,而是从成品倒推“它服务谁、为何必须长成这样”。

反推维度 论文成品 隐含设计判断
服务对象 多轮 Agent 推理平台 真正客户是希望把 KV 命中转化为 SLO-safe Goodput 的平台运营者
真实目标 消除 Prefill 侧存储带宽失衡 不是追求更高命中率,而是让命中 KV 更快进入计算
结构 数据路径 + Traffic Manager + 两级 Scheduler 第二条箭头不够,所有权、仲裁与放置必须一起改变
关键取舍 Host Buffer + CNIC RDMA + 硬件 QoS 用额外 Buffer 和跳数换可控 HBM 占用与干扰隔离
完成标准 JCT、吞吐、SLO、消融、扩展性 不能只展示 SNIC 带宽上涨,还要证明端到端无干扰
迁移边界 内部 Hopper/IB/3FS 系统 换平台时需重建存储、Buffer、传输、QoS、调度和异常闭环

可复用规则

  1. 先找闲置的对称入口。资源池里一侧拥塞、另一侧空闲时,先问能否改变请求所有权,而不是立即扩容热点侧。
  2. 数据路径与控制面同时设计。新增路径会制造新的队列、故障和干扰,必须同时定义调度、优先级与回退。
  3. 把对象生命周期画出来。从 Full Block 到 Layer Block,再到 Host Buffer 与 HBM Slot,生命周期决定峰值内存和可重叠区间。
  4. 优化可控瓶颈,不承诺消灭总字节。DualPath 改善入口利用率;AIV 可能减少提交时间;二者都不会让 KV 字节凭空消失。
  5. 数值结论绑定系统边界。模型、Trace、P/D 比、网络、版本和 QoS 任何一项改变,都需要重新测量。

设计检查表

  • 是否证明旧系统由 Prefill SNIC 限制,而不是 GPU、Host DRAM 或 Decode 限制?
  • PE/DE Host Buffer 的上限、背压和失败释放是否明确?
  • Full Block 与 Layer Block 的转换是否保持 Token、Layer 和 KV Head 顺序?
  • 高优先级 Collective 是否能抢占或隔离 KV 流量,同时避免 KV 饥饿?
  • 调度状态是否包含 Token、序列、读队列、HBM 与请求超时?
  • 路径失败时能否回退到单路径,且不会留下半完成 Buffer?
  • JCT、TTFT、TPOT、Goodput、P99、显存和 Host 内存是否在同一窗口报告?

迁移练习

给定一个 P=4、D=8 的 RoCE 集群,先采集两侧 SNIC/CNIC/Host DRAM/PCIe 利用率与 KV Block 分布,再只实现 DE → PE 的单层固定大小传输原型。验收要求是:结果逐字节一致;高优先级模型通信 P99 不退化;在固定 Trace 下 T_submit 或空洞可重复下降;若端到端 JCT 没有改善,必须能用带宽或计算证据指出新瓶颈。

AIV 直驱可行性

能加速的是哪一段

HCCL 的 AIV 通信引擎让 Vector Core 执行通信过程并使用 HCCS 或 RoCE;更窄的 AIV 直驱 RDMA 路径还可以让 AIV 直接准备和提交 WQE,旁路 AICPU 对细粒度工作的逐次下发。它主要影响:

$$
T_{comm}=T_{launch}+T_{submit}+T_{transport}+T_{sync}+T_{post}
$$

其中 AIV 直驱最直接改变的是 T_submit,并可能通过设备侧流水掩盖一部分 T_transportT_syncT_post。它不改变 SNIC 的物理带宽,也不自动提高 RoCE 线速。

因此,DualPath 中最自然的候选是 DE CNIC → PE HBM 的 Hit Layer Block,以及 PE → DE 的 Miss Layer Block。它们按层发生、次数多,固定提交开销可能可见。若实际每块很大、链路已经饱和,AIV 把 1 次提交缩短几微秒也不会产生明显端到端收益。

三层实现判断

  • L0:现成开关,不成立。设置 HCCL_OP_EXPANSION_MODE=AIV 只选择部分 HCCL 通信执行方式,不会实现 3FS 读归属、PE/DE Host Buffer、任意单边地址、DualPath Scheduler 或 QoS 策略。
  • L1:Device Buffer 原型,可做。把 Layer Block 放入已注册、AIV 可访问的 GM/HCCL Buffer,用自定义通信算子或已支持能力验证 AIV 提交、Notify 和 RoCE 搬运。
  • L2:保持论文 Host Buffer 语义,证据不足。必须证明 AIV 可直接以注册 Host DRAM 为源或目的提交对应单边操作;否则需要 Host → GM Staging,可能重新引入 Copy、Buffer 和同步开销。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def aiv_candidate_layer_transfer(layer_block, remote_slot, channel_ctx, notify):
if not channel_ctx.product_supports_aiv_direct:
return host_or_aicpu_rdma_write(layer_block, remote_slot, channel_ctx)
if not channel_ctx.topology_supports_protocol("RoCE"):
return host_or_aicpu_rdma_write(layer_block, remote_slot, channel_ctx)

source = layer_block
staged_buffer = None
if not channel_ctx.aiv_can_address(layer_block.memory_region):
staged_buffer = channel_ctx.allocate_device_hccl_buffer(layer_block.nbytes)
copy_host_or_device_to_gm(layer_block, staged_buffer)
source = staged_buffer

if source.nbytes > channel_ctx.max_single_aiv_payload_bytes:
segments = split_into_supported_segments(
source,
channel_ctx.max_single_aiv_payload_bytes,
)
else:
segments = [source]

request_ids = []
for segment in segments:
destination = remote_slot.offset(segment.byte_offset)
wqe = build_write_descriptor(
source_address=address_of(segment),
destination_address=destination.address,
byte_length=segment.nbytes,
peer=destination.peer,
operation="WRITE",
)
request_id = post_wqe_from_aiv(channel_ctx, wqe)
request_ids.append(request_id)

for request_id in request_ids:
wait_for_completion(request_id, notify)

publish_remote_ready(remote_slot, notify)
if staged_buffer is not None:
channel_ctx.release_device_hccl_buffer(staged_buffer)
return remote_slot
![AIV 直驱适配 DualPath 五视图](https://pic.shaojiemike.top/shaojiemike/2026/08/e5d56f77241ab10a93c52534438b4b0f.png){ width=100% }
自绘五视图技术图:区分 Host/AICPU 与 AIV 提交、AIV 可缩短的固定开销、兼容性闸门、WQE 时序及 Host/GM/Remote KV 数据流。AIV 部分依据公开 CANN 文档,是候选设计而非 DualPath 论文结果。

为什么可能不快

公开 HCCL 指南把 AIV 引擎定位在小数据量、时延敏感的推理通信,同时明确它会占用 Vector Core。DualPath 搬运的是长上下文 KV,总字节量可能很大;若瓶颈在 3FS、SNIC、Host DRAM、PCIe 或 RoCE 线速,控制路径缩短只覆盖很小比例。AIV 还可能与激活、量化、重排或其他 Vector 工作竞争。

公开任务编排资料中的 Device HCCL Buffer 默认值为 200 MB;超过对应限制的工作可能需要切分并由 Host 多次启动。公开支持矩阵还存在产品、拓扑、算子、零拷贝与重执行等限制。因此,不能把 MoE 案例中“多个 AIV 核并行下发 WQE、相对旧 AIV+AICPU 方案提升 10%+”直接套到 DualPath。

RoCE 的 Traffic Class 或 Service Level 可以为迁移 QoS 提供配置基础,但这不证明它等价复现论文的 InfiniBand VL 仲裁。AIV 负责提交 WQE,不负责决定交换网络的 PFC、ECN、DSCP/TC 映射、带宽权重和饥饿策略。

最小验证方案

  1. 固定变量。锁定模型、精度、KV Block、P/D 比、Trace、CANN、固件、拓扑、Allocator 和 QoS。
  2. 三路对照。比较 Host/AICPU RDMA、AIV + Device Buffer、AIV + Host/GM Staging;每路都验证结果一致和异常回退。
  3. 分层测量。报告 WQE 准备/提交/完成、有效带宽、链路空洞、AIV 利用率、Vector 冲突、Buffer 峰值和 CPU/AICPU 占用。
  4. 端到端验收。同时报告 TTFT、TTST、TPOT、JCT、Goodput、P50/P99 和 SLO 违约率,而不是只报告通信微基准。
  5. 停止条件。T_submit 低于请求关键路径的 5%,或 Staging/Vector 竞争抵消收益,则保留 Host/CNIC 路径,不继续扩大改造。

显存、带宽与收益边界

DualPath 主要改善 I/O 利用率,不降低 KV 理论字节数。请求关键路径可以粗略写成:

$$
T_{request}\approx\max(T_{storage},T_{layer\ transfer},T_{prefill})
+T_{queue}+T_{handoff}+T_{unhidden}
$$

AIV 只能减少 T_unhidden 中的一部分固定提交开销,并改善部分重叠。若这部分在原系统只占 3%,即使被完全消除,Amdahl 上限也只有约 1 / 0.97 ≈ 1.031×。先测占比,再讨论速度提升。

峰值内存则至少包含:

$$
M_{peak}=M_{model}+M_{saved}+M_{workspace}+M_{comm}
+M_{live\ I/O}+M_{reserved}+M_{margin}
$$

Layerwise Prefill 缩短 PE HBM 中完整 KV 的驻留,但 de_buffer 把 Prompt KV 暂存在 Host DRAM,AIV/HCCL 还可能增加 Device HCCL Buffer、Channel、Notify 和 WQE 状态。不能只按 Layer 数或并行度给出显存“反比下降”,因为模型状态、固定 Buffer、Workspace、碎片和 Runtime Margin 都不会同比缩放。

双层对应与易错点

小白概念 专业对象 不能遗漏的边界
第二个取货口 Decode-side SNIC + DE Read Path 仍需经 CNIC 把 Hit KV 送到 PE
分层送档案 Full Block → Layer Block 必须保持层、Token 与 KV Head 顺序
内部高速桥 CNIC/RDMA 受 PCIe、网络 QoS 和 Buffer 可达性限制
交通警察 VL/TC QoS + Adaptive Scheduler 网络仲裁与请求放置是两个不同控制面
AIV 自己填快递单 AIV 直接提交 WQE 传输硬件搬字节,AIV 不提高线速

常见误解包括:

  1. DualPath 等于从两边同时读同一个请求。论文当前实现为每个请求选择 PE 或 DE 读路径,请求级拆分仍属未来工作。
  2. 高 KV 命中必然更快。命中只避免重算;若存储与传输更慢,仍会由 I/O 限制。
  3. AIV 直驱可以替代 CNIC QoS。AIV 是提交与执行控制路径,网络优先级仍由 NIC/交换网络策略实现。
  4. 开启 AIV 就能直接写 Host Buffer。这取决于产品、版本、协议、内存注册和地址可达性,公开资料尚不能证明 DualPath 所需的完整覆盖。

检查理解

  1. 为什么 DualPath 宁愿增加 Decode Host Buffer 与一次最终 H2D,也不让完整 Prompt KV 从一开始就驻留 Decode HBM?
  2. T_storage 已显著大于 T_submit + T_transport 时,AIV 直驱为什么几乎不改变端到端 JCT?
  3. 若把论文从 InfiniBand/Hopper 迁移到 RoCE/Ascend,哪些语义属于 DualPath 必须保留,哪些实现可以替换?

参考资料

  1. ACM DOI:DualPath
  2. arXiv 2602.21548v2:DualPath
  3. CANN:HCCL 通信引擎
  4. CANN:AIV 算法选择
  5. CANN:AIV 任务编排
  6. CANN:AIV 通信资源
  7. 昇腾社区:MoE 通算融合与 AIV 直驱 RDMA
  8. CANN:HCCL 通信算子支持矩阵
  9. CANN:HcclCommConfig 的 Traffic Class 与 Service Level
Author

Shaojie Tan

Posted on

2026-08-24

Updated on

2026-08-24

Licensed under