分布式推理里最烦的不是模型切不好,而是切完了之后卡和卡之间传数据太慢。hixl 就是来修这条高速路的。
分布式推理有一个让人头疼的问题:你把模型切到多张 NPU 卡上,每张卡算自己那部分,算完了要交换中间结果才能继续往下走。这个「交换」的过程,如果做得不好,会吃掉你一大半的推理时间。
举一个直观的例子:PD 分离(Prefill-Decode 分离)架构下,Prefill 阶段在一个节点算完 KV Cache,需要把这个 Cache 传给 Decode 节点继续推理。KV Cache 的数据量巨大------一个 70B 模型、BatchSize 64 的场景下,单次传输的 KV Cache 可能有几 GB。如果用常规的集合通信(比如 HCCL 的 AllReduce),这些数据要经过多次拷贝和同步,延迟很高。
hixl 做的事情,就是给这种场景修一条「直达专线」。
一、hixl 是什么?
hixl 是昇腾 CANN 生态中的单边通信库,支持零拷贝数据传输,主要用于 PD 分离等分布式推理场景。
从 CANN 五层架构来看,hixl 位于执行层,与 HCCL(集合通信库)同级但定位不同。HCCL 擅长多卡之间的同步通信(AllReduce、AllGather 等),而 hixl 擅长点对点的异步通信------一端写数据,另一端直接读,不需要对方参与。
如果打个比方(只用这一次):HCCL 像是公司里「开全员会议」,所有人必须到场才能开始;hixl 像是「发快递」,你把包裹放上传输带,收件人随时取走就行,寄件人不需要等收件人到场。
二、零拷贝:为什么它很重要?
传统的数据传输流程是这样的:
发送端应用内存
→ 拷贝到发送端通信缓冲区
→ 通过网络传输
→ 拷贝到接收端通信缓冲区
→ 拷贝到接收端应用内存
数据从 A 到 B,至少被拷贝了 4 次。每次拷贝都要消耗内存带宽和 CPU 时间。
零拷贝的做法是这样的:
发送端应用内存
→ 通过网络传输
→ 直接写入接收端应用内存
两次拷贝变零次。发送端把数据直接「推」到接收端的内存地址上,接收端的应用代码不需要做任何拷贝操作就能读到数据。这就像你从书架上抽一本书递给对面桌的同事,而不需要先把书放进快递盒、再让快递员送、对方再拆盒------直接递过去就行。
但零拷贝有一个前提:发送端必须知道接收端内存的地址。这需要双方提前做一次「注册」操作,交换彼此的内存地址信息。hixl 的 API 封装了这个注册过程。
三、hixl 的核心能力
能力一:单边写(Remote Direct Write)
发送端可以直接把数据写入远端 NPU 的显存地址,不需要接收端发起任何操作。
c
// 发送端:把本地 buffer 直接写到远端 NPU 的显存
// addr 和 rkey 是之前注册交换得到的远端内存信息
hixl_rdma_write(
ep, // 通信端点
local_buf, // 本地数据地址
size, // 数据大小
remote_addr, // 远端内存地址
rkey // 远端内存密钥
);
注释解释WHY:
rkey不是密码学意义上的密钥,而是远端注册内存段的访问令牌。没有它,网卡不知道该把数据写到哪个内存区域,所以注册阶段必须正确交换这个信息。
能力二:异步语义
hixl 的通信操作是异步的------你发出一个写请求,不需要等它完成就能做别的事情。完成通知通过 Completion Queue(CQ)来获取。
c
// 发起一次 RDMA 写
hixl_rdma_write(ep, buf, size, remote_addr, rkey);
// 不用等,继续准备下一批数据
prepare_next_batch();
// 检查之前的写是否完成
hixl_cq_poll(cq, &wc, 1); // wc 里是完成状态
异步带来的好处是计算和通信可以重叠。你在准备下一批数据的同时,上一批数据已经在网络上传输了。这对高吞吐的推理场景很关键。
能力三:内存注册与保护
零拷贝的前提是内存必须先注册。hixl 提供了 hixl_mr_reg 接口来注册一块内存区域,注册后得到 lkey(本地访问令牌)和 rkey(远端访问令牌)。
c
// 注册一块 NPU 显存用于 RDMA
hixl_mr_reg(
pd, // Protection Domain
npu_buf, // NPU 显存地址
buf_size, // 大小
access_flags, // 访问权限(读/写/远程写等)
&lkey, // 输出:本地访问令牌
&rkey // 输出:远端访问令牌
);
// 把 rkey 和地址信息发给对端
send_to_remote(npu_buf_addr, rkey);
内存注册的本质是告诉网卡:「我授权你直接访问这块内存,地址是这个,令牌是这个」。没有注册的内存区域,网卡不允许直接写入,这是硬件层面的安全机制。
四、hixl 在 PD 分离中的应用
PD 分离是目前 hixl 最重要的应用场景。
传统推理架构中,Prefill(首token计算)和 Decode(逐token生成)在同一个节点上串行执行。PD 分离的做法是把 Prefill 和 Decode 分到不同的节点上------Prefill 节点专门处理长上下文的首轮计算,Decode 节点专门做逐 token 生成,两者通过 KV Cache 传递状态。
这个架构对数据传输的要求是:
- 低延迟:Prefill 算完 KV Cache 后必须尽快送到 Decode 节点,否则 Decode 节点在空等
- 高吞吐:大批量场景下,KV Cache 数据量巨大,传输带宽要够
- 少拷贝:拷贝次数越多,延迟越高,有效带宽越低
hixl 的零拷贝特性正好匹配这三个要求。Prefill 节点算完 KV Cache 后,通过 hixl 直接把数据写到 Decode 节点的显存上,Decode 节点不需要做任何额外操作就能拿到数据继续推理。
性能数据上,对比使用 HCCL AllGather 的方案,hixl 在 KV Cache 传输环节的延迟通常可以降低 30-50% ,有效带宽利用率提升 20-40%。具体数字取决于网络拓扑和 BatchSize,但趋势是明确的。
五、hixl 与 HCCL 怎么选?
| 维度 | HCCL | hixl |
|---|---|---|
| 通信模式 | 集合通信(全员同步) | 点对点通信(单边异步) |
| 典型操作 | AllReduce, AllGather, Broadcast | RDMA Write, RDMA Read |
| 适用场景 | 分布式训练(梯度同步) | 分布式推理(状态传递) |
| 数据拷贝 | 有通信缓冲区拷贝 | 零拷贝 |
| 参与方 | 所有节点必须参与 | 发送端单边即可完成 |
| 延迟特征 | 与参与节点数正相关 | 与参与节点数无关 |
简单来说:训练场景用 HCCL,推理场景用 hixl。如果你的任务不需要全员同步、只需要把数据从一个节点搬到另一个节点,hixl 更合适。
六、从哪里开始?
如果你有昇腾 NPU 集群且需要做分布式推理,hixl 值得一看。建议路径:
-
第一步:阅读仓库 README,确认你的网络环境(RoCE 还是 TCP)是否被 hixl 支持。
-
第二步:跑通仓库里的基础示例(两节点 RDMA Write),确认零拷贝通信链路正常。
-
第三步:在你的 PD 分离框架中,把 KV Cache 传输环节替换为 hixl 接口,对比替换前后的端到端延迟和吞吐。
-
第四步:如果效果达标,进一步优化异步流水线------让 Prefill 的计算和 KV Cache 传输重叠起来,Prefill 算完一个 Batch 的 KV Cache 就立即发送,不必等整个序列算完。