前言大模型推理正在经历一场架构层面的变革。当模型参数量突破千亿单卡已经无法装下完整的推理流程PD分离架构应运而生——Prefill阶段和Decode阶段分别部署在不同的昇腾NPU上。这种拆分让两个阶段可以独立扩缩容但也带来了一个物理层面的问题Prefill产出的KV Cache必须搬到Decode所在的卡上数据搬运的延迟直接吃掉了分离架构的收益。hixl就是为解决这个数据搬运问题而生的通信库。它位于昇腾CANN生态的第五层——计算基础层提供put/get语义的单边通信能力支持零拷贝和跨步内存访问。与上层的hccl集合通信库不同hixl更像是通信领域的快递专线不需要收件人签收寄件人直接把东西放进对方信箱收件人随时来取。通信的两种姿势双边与单边理解hixl之前需要先搞清楚单边通信到底是什么意思。这里用一个日常场景做类比。想象两个人之间传递一份文件。双边通信就像打电话你必须拨号、对方必须接听两个人同时在线才能完成一次传递。任何一方不在通信就阻塞。hccl的集合通信操作AllReduce、Broadcast等就属于这种模式——所有参与方必须同步到场数据才能流动。单边通信则像往对方信箱里投信你把信塞进去就可以走了不需要对方此刻站在信箱旁。对方什么时候来取信、取哪封信都由对方自己决定。hixl的put操作就是这个投信动作——发起方直接把数据写入远端内存不需要远端进程参与。get操作则反过来——发起方直接从远端内存读取数据远端进程同样无感。这两种模式的差异在PD分离场景下被放大。Prefill卡产出一批KV Cache后如果用双边通信搬运Decode卡必须同步等待两边的计算节奏被强制耦合。换成单边通信Prefill卡算完直接put到Decode卡的内存Decode卡按自己的节奏消费数据两边的计算流水线解耦了。这就是hixl在PD分离架构中的核心价值——用通信模式的切换换取计算流水线的独立。零拷贝省掉那趟多余的搬运单边通信解决了谁参与的问题零拷贝解决的是搬几次的问题。继续用类比。假设你要把一摞文件从A办公室搬到B办公室。常规做法是先从A的柜子里拿出来放到推车上推到B办公室再从推车放到B的柜子里。文件被搬了两次——从柜子到推车、从推车到柜子。这就是传统通信中的拷贝开销应用缓冲区到通信库内部缓冲区是一次拷贝通信库内部缓冲区到对端应用缓冲区又是一次拷贝。零拷贝的做法是直接把A柜子里的文件标记为通信区通信硬件从这块区域直接读取数据发到对端对端硬件直接写入B柜子中预先标记好的区域。文件始终在柜子里没有被搬到推车上过。hixl的零拷贝实现依赖昇腾NPU的DMA能力。应用在初始化时注册好内存区域后续的put/get操作直接在这些注册内存上工作数据从源端内存经HCCS链路直接到达目的端内存中间不经过任何软件缓冲区。对于KV Cache这种动辄数百兆的大块数据省掉一次拷贝就意味着省掉数百兆的内存带宽和对应的搬运时间。HXLResult rethxl_put(src_npu,dst_npu,src_addr,dst_addr,size);这行代码的语义是把src_npu上src_addr处的size字节数据直接写入dst_npu的dst_addr处。没有中间缓冲区参与没有对端进程的配合。src_addr和dst_addr都必须是预先注册过的通信内存区域hixl在内部把这些地址映射到硬件可识别的DMA描述符由昇腾NPU的通信引擎执行实际的数据搬运。整个过程中CPU侧只负责下发这条指令不参与数据搬运本身。跨步内存访问不连续数据的连续传输KV Cache在内存中的布局往往不是连续的。以Transformer的多头注意力为例每个头的KV数据在内存中是按头维度连续存储的但头与头之间可能隔着其他数据。如果要把多个头的KV Cache搬过去最直观的做法是逐头搬运——每头发一次put每次搬运一个头的连续数据。但这样通信次数太多每次通信都有启动开销小包密集传输的效率很低。跨步内存访问Strided Access解决的就是这个问题。它的思路是告诉硬件起始地址在哪、每个元素的长度是多少、相邻元素之间的间距是多少硬件就能自动跳着步子把不连续的数据拼成连续的流发出去。类比来看就像你告诉快递员这栋楼3层到10层每隔一层的门口都有一个包裹你按这个规律走一遍全收走而不是你自己跑八趟每趟拿一个。hixl通过HXLStridedDescriptor来描述这种跨步内存布局HXLStridedDescriptor desc;desc.countnum_heads;desc.sizehead_dim*sizeof(float);desc.stridehead_stride;rethxl_put_strided(src_npu,dst_npu,src_base,dst_base,desc);count是要搬运的元素个数这里是注意力头数size是每个元素的字节长度一个头的KV数据长度stride是相邻元素起始地址之间的间距包含头间填充。硬件根据这三个参数自动计算每次访问的地址第i个元素的地址是base i * stride。这样一次hxl_put_strided调用就完成了所有头的搬运通信次数从num_heads次降为一次启动开销被摊薄到所有元素上。跨步访问还有一个隐含的约束64字节对齐。昇腾NPU的DMA引擎以64字节为最小传输单元所以src_base、dst_base以及stride都必须是64字节的整数倍。这不是hixl的任意限制而是硬件通信引擎的物理要求。如果应用层的内存布局不满足对齐条件需要在注册通信内存时做对齐处理。hixl与hccl底层原语与上层编排在CANN的通信体系中hixl和hccl的关系类似于汇编指令和高级语言的关系。hccl提供的是集合通信原语AllReduce、AllGather、ReduceScatter、Broadcast等。这些操作关注的是一组NPU之间如何协同完成某个全局计算比如AllReduce是把所有卡上的梯度求和再分发回去。hccl内部会根据NPU数量、拓扑结构和数据量自动编排通信步骤——谁先发、谁后发、数据走哪条链路。这种编排依赖底层的点对点通信能力而hixl就是提供这种点对点能力的底层库。从调用链来看hccl的集合通信操作最终会分解为大量的点对点send/recv或put/get操作。hixl为这些底层操作提供了更高效的实现路径零拷贝减少了中间拷贝单边语义减少了对端参与开销跨步访问减少了通信次数。hccl可以选择性地使用hixl作为其底层传输引擎也可以使用其他传输实现——这取决于具体的硬件平台和通信拓扑。对于应用开发者来说直接使用hixl的场景是你需要精细控制点对点通信的行为比如PD分离中KV Cache的定向搬运。直接使用hccl的场景是你需要集合通信的语义比如训练中的梯度同步。两者不是替代关系而是不同抽象层次上的互补。hixl与shmem跨步通信与共享内存CANN生态中另一个容易与hixl混淆的通信库是shmem。两者都支持单边通信但设计侧重点不同。shmem的模型是共享内存所有参与通信的NPU把一部分内存映射到一个共享地址空间每个NPU可以像访问本地内存一样访问远端数据。这种模型适合需要频繁读写远端内存的场景比如图计算中的顶点数据更新——每个NPU都可能随时读写任意远端顶点的数据共享内存提供了最自然的编程接口。hixl的模型是消息传递通信以显式的put/get操作发起每次操作搬运一块或跨步的多块数据。这种模型适合数据搬运模式可预测的场景——你知道数据从哪来、到哪去、搬多少。PD分离中的KV Cache搬运就是典型的可预测模式Prefill产出的KV Cache地址和大小在计算前就能确定Decode侧的消费地址也可以预先分配好。跨步访问是hixl区别于shmem的关键能力。shmem的共享内存访问是按地址直接读写如果数据布局不连续应用需要自己逐个元素访问。hixl的跨步描述符让硬件自动完成跳步访问对于KV Cache这种固定步长的不连续布局通信效率显著更高。选择hixl还是shmem取决于你的通信模式如果数据搬运路径明确且步长规则用hixl如果需要随机访问远端内存用shmem。PD分离场景中的hixl工作流把前面的概念串起来看hixl在PD分离推理中的完整工作流。Prefill阶段用户请求到达Prefill卡模型执行前向计算产出当前请求的KV Cache。这些KV Cache按照多头注意力的布局存储每个头的数据在头维度内连续头与头之间有固定间距。Prefill卡在产出KV Cache后通过hixl的跨步put操作将KV Cache直接写入Decode卡的预留内存区域。HXLStridedDescriptor kv_desc;kv_desc.countnum_layers*num_heads;kv_desc.sizehead_kv_bytes;kv_desc.stridehead_stride_bytes;for(intl0;lnum_layers;l){void*srckv_base_prefill[l];void*dstkv_base_decode[l];hxl_put_strided(prefill_npu,decode_npu,src,dst,kv_desc);}这里按层循环每层执行一次跨步put。count设为num_heads每层的头数stride是头间步长。一次调用就把该层所有头的KV Cache从Prefill卡搬到Decode卡不需要逐头搬运。dst地址是Decode卡上预先分配好的KV Cache存储区Prefill卡直接写入Decode侧无需参与。Prefill卡在put返回后就可以继续处理下一个请求的Prefill计算不会因为等待Decode侧而阻塞。Decode阶段Decode卡从自己的内存中读取已经就位的KV Cache执行token生成计算。每生成一个token只需要访问本地内存中的KV Cache不需要跨卡通信。只有当新的Prefill请求的KV Cache被put过来时Decode卡才需要把新的KV Cache纳入注意力计算的范围。这个工作流的关键特征是Prefill和Decode的计算完全解耦。Prefill只管产出和投递Decode只管消费和生成。hixl的单边通信让这种解耦成为可能——双边通信要求两边同步那Prefill就必须等Decode准备好才能发两边的流水线又被耦合回去了。64字节对齐的工程实践前面提到hixl要求所有通信地址和步长64字节对齐这在工程实践中需要特别处理。KV Cache的内存分配通常由框架的内存池管理。框架在分配内存时需要确保KV Cache的起始地址和头间步长都满足64字节对齐。起始地址的对齐比较容易——在内存池初始化时按64字节边界分配即可。步长的对齐需要根据模型结构计算如果head_dim是128float16下每头256字节步长天然满足对齐如果head_dim是96float16下每头192字节步长是192字节不满足64字节对齐需要在头间填充16字节使步长对齐到256字节。这种填充会带来少量内存浪费但相比跨步通信的性能收益浪费是值得的。而且填充后的内存布局对Decode侧的注意力计算也有好处——对齐的访存地址让NPU的向量单元可以更高效地加载数据。使用前后的效率对比维度使用传统RMA方式使用hixl跨步通信原语差异来源数据传输粒度每次传输只能操作连续内存块非连续数据需要先打包再复制支持自定义跨度和跳步直接操作非连续地址空间hixl的跨步通信原语在硬件层面处理地址偏移计算中间缓冲区非连续数据传输前需要申请中间缓冲区完成数据整理不需要中间缓冲区源地址到目标地址直写Put语义的硬件单边访问消除了缓冲区拷贝PD分离KV交换场景需要多轮RMA操作完成注意力头数据的组合传输一次跨步Put即可传输完整层级的KV Cache数据stride参数的灵活配置适配了多层注意力头的数据布局编程复杂度开发者需要手动编排数据打包和缓冲区管理逻辑只需配置src、dst、count、size、stride五个参数简洁的API参数设计将地址计算和偏移管理的底层细节封装在内多NPU同步需要在每次数据传输后跨NPU同步时间开销较大跨步通信完成后即可直接访问hixl保证数据可见性单边通信语义本身就保证了数据一致性不需要额外同步操作下表对比了PD分离场景中使用hixl前后在关键指标上的差异指标使用常规拷贝通信使用hixl单边零拷贝通信KV Cache搬运路径应用缓冲区→通信库缓冲区→对端应用缓冲区两次拷贝源端内存→对端内存DMA直搬零拷贝通信参与方Prefill卡和Decode卡必须同步双边参与Prefill卡单边发起Decode卡无感不连续数据搬运方式逐头发起通信通信次数等于头数跨步描述符一次发起通信次数为一通信启动开销每次通信均有启动开销总开销与头数成正比启动开销仅一次被所有头摊薄Prefill与Decode耦合度强耦合Prefill必须等Decode就绪解耦Prefill算完即投递不等待内存带宽占用拷贝过程消耗额外内存带宽无额外拷贝内存带宽全部留给计算对齐要求无特殊对齐要求地址和步长需64字节对齐从表中可以看出hixl在搬运路径、参与方、通信次数、耦合度、内存带宽五个维度上都有明显优势。代价是64字节对齐的约束这在框架层面的内存分配器中很容易满足工程代价很小。hixl在CANN分层架构中的位置CANN的软件栈分为五层最上层是推理框架适配层如MindSpore Lite往下是计算图编译层GE再往下是算子库层Ascend C再往下是计算基础层最底层是硬件驱动层。hixl位于计算基础层与hccl、shmem同层。这一层的库有两个共同特征直接面向NPU硬件能力编程不经过上层的图编译或算子调度被上层库或框架间接调用应用开发者通常不直接使用。hixl也不例外——大多数开发者通过hccl间接使用hixl的传输能力只有在需要精细控制点对点通信时如PD分离场景才会直接调用hixl的API。计算基础层的库之间也有分工hccl管集合通信的编排hixl管点对点单边通信的执行shmem管共享内存的映射与访问。三者共同构成了CANN通信能力的完整基础上层的分布式训练和分布式推理都构建在这套基础之上。从概念到实践的映射回顾全文hixl的核心概念可以用一条线索串起来单边通信解耦了通信参与方零拷贝消除了中间搬运跨步访问合并了不连续数据的通信次数。这三个能力叠加在一起让PD分离场景中的KV Cache搬运从同步、多次、有中间拷贝变为异步、一次、直搬。对于初次接触hixl的开发者建议从三个维度建立认知通信语义维度put/get与send/recv的差异、内存布局维度连续访问与跨步访问的选择、系统架构维度hixl在CANN分层中的位置和与hccl/shmem的关系。这三个维度交叉起来就能判断自己的场景是否适合使用hixl以及应该使用hixl的哪些能力。仓库地址https://atomgit.com/cann/hixl
从寄信到直投:hixl单边通信库如何拆掉PD分离场景中的数据搬运墙——昇腾CANN计算基础层的跨步通信原语深度拆解
前言大模型推理正在经历一场架构层面的变革。当模型参数量突破千亿单卡已经无法装下完整的推理流程PD分离架构应运而生——Prefill阶段和Decode阶段分别部署在不同的昇腾NPU上。这种拆分让两个阶段可以独立扩缩容但也带来了一个物理层面的问题Prefill产出的KV Cache必须搬到Decode所在的卡上数据搬运的延迟直接吃掉了分离架构的收益。hixl就是为解决这个数据搬运问题而生的通信库。它位于昇腾CANN生态的第五层——计算基础层提供put/get语义的单边通信能力支持零拷贝和跨步内存访问。与上层的hccl集合通信库不同hixl更像是通信领域的快递专线不需要收件人签收寄件人直接把东西放进对方信箱收件人随时来取。通信的两种姿势双边与单边理解hixl之前需要先搞清楚单边通信到底是什么意思。这里用一个日常场景做类比。想象两个人之间传递一份文件。双边通信就像打电话你必须拨号、对方必须接听两个人同时在线才能完成一次传递。任何一方不在通信就阻塞。hccl的集合通信操作AllReduce、Broadcast等就属于这种模式——所有参与方必须同步到场数据才能流动。单边通信则像往对方信箱里投信你把信塞进去就可以走了不需要对方此刻站在信箱旁。对方什么时候来取信、取哪封信都由对方自己决定。hixl的put操作就是这个投信动作——发起方直接把数据写入远端内存不需要远端进程参与。get操作则反过来——发起方直接从远端内存读取数据远端进程同样无感。这两种模式的差异在PD分离场景下被放大。Prefill卡产出一批KV Cache后如果用双边通信搬运Decode卡必须同步等待两边的计算节奏被强制耦合。换成单边通信Prefill卡算完直接put到Decode卡的内存Decode卡按自己的节奏消费数据两边的计算流水线解耦了。这就是hixl在PD分离架构中的核心价值——用通信模式的切换换取计算流水线的独立。零拷贝省掉那趟多余的搬运单边通信解决了谁参与的问题零拷贝解决的是搬几次的问题。继续用类比。假设你要把一摞文件从A办公室搬到B办公室。常规做法是先从A的柜子里拿出来放到推车上推到B办公室再从推车放到B的柜子里。文件被搬了两次——从柜子到推车、从推车到柜子。这就是传统通信中的拷贝开销应用缓冲区到通信库内部缓冲区是一次拷贝通信库内部缓冲区到对端应用缓冲区又是一次拷贝。零拷贝的做法是直接把A柜子里的文件标记为通信区通信硬件从这块区域直接读取数据发到对端对端硬件直接写入B柜子中预先标记好的区域。文件始终在柜子里没有被搬到推车上过。hixl的零拷贝实现依赖昇腾NPU的DMA能力。应用在初始化时注册好内存区域后续的put/get操作直接在这些注册内存上工作数据从源端内存经HCCS链路直接到达目的端内存中间不经过任何软件缓冲区。对于KV Cache这种动辄数百兆的大块数据省掉一次拷贝就意味着省掉数百兆的内存带宽和对应的搬运时间。HXLResult rethxl_put(src_npu,dst_npu,src_addr,dst_addr,size);这行代码的语义是把src_npu上src_addr处的size字节数据直接写入dst_npu的dst_addr处。没有中间缓冲区参与没有对端进程的配合。src_addr和dst_addr都必须是预先注册过的通信内存区域hixl在内部把这些地址映射到硬件可识别的DMA描述符由昇腾NPU的通信引擎执行实际的数据搬运。整个过程中CPU侧只负责下发这条指令不参与数据搬运本身。跨步内存访问不连续数据的连续传输KV Cache在内存中的布局往往不是连续的。以Transformer的多头注意力为例每个头的KV数据在内存中是按头维度连续存储的但头与头之间可能隔着其他数据。如果要把多个头的KV Cache搬过去最直观的做法是逐头搬运——每头发一次put每次搬运一个头的连续数据。但这样通信次数太多每次通信都有启动开销小包密集传输的效率很低。跨步内存访问Strided Access解决的就是这个问题。它的思路是告诉硬件起始地址在哪、每个元素的长度是多少、相邻元素之间的间距是多少硬件就能自动跳着步子把不连续的数据拼成连续的流发出去。类比来看就像你告诉快递员这栋楼3层到10层每隔一层的门口都有一个包裹你按这个规律走一遍全收走而不是你自己跑八趟每趟拿一个。hixl通过HXLStridedDescriptor来描述这种跨步内存布局HXLStridedDescriptor desc;desc.countnum_heads;desc.sizehead_dim*sizeof(float);desc.stridehead_stride;rethxl_put_strided(src_npu,dst_npu,src_base,dst_base,desc);count是要搬运的元素个数这里是注意力头数size是每个元素的字节长度一个头的KV数据长度stride是相邻元素起始地址之间的间距包含头间填充。硬件根据这三个参数自动计算每次访问的地址第i个元素的地址是base i * stride。这样一次hxl_put_strided调用就完成了所有头的搬运通信次数从num_heads次降为一次启动开销被摊薄到所有元素上。跨步访问还有一个隐含的约束64字节对齐。昇腾NPU的DMA引擎以64字节为最小传输单元所以src_base、dst_base以及stride都必须是64字节的整数倍。这不是hixl的任意限制而是硬件通信引擎的物理要求。如果应用层的内存布局不满足对齐条件需要在注册通信内存时做对齐处理。hixl与hccl底层原语与上层编排在CANN的通信体系中hixl和hccl的关系类似于汇编指令和高级语言的关系。hccl提供的是集合通信原语AllReduce、AllGather、ReduceScatter、Broadcast等。这些操作关注的是一组NPU之间如何协同完成某个全局计算比如AllReduce是把所有卡上的梯度求和再分发回去。hccl内部会根据NPU数量、拓扑结构和数据量自动编排通信步骤——谁先发、谁后发、数据走哪条链路。这种编排依赖底层的点对点通信能力而hixl就是提供这种点对点能力的底层库。从调用链来看hccl的集合通信操作最终会分解为大量的点对点send/recv或put/get操作。hixl为这些底层操作提供了更高效的实现路径零拷贝减少了中间拷贝单边语义减少了对端参与开销跨步访问减少了通信次数。hccl可以选择性地使用hixl作为其底层传输引擎也可以使用其他传输实现——这取决于具体的硬件平台和通信拓扑。对于应用开发者来说直接使用hixl的场景是你需要精细控制点对点通信的行为比如PD分离中KV Cache的定向搬运。直接使用hccl的场景是你需要集合通信的语义比如训练中的梯度同步。两者不是替代关系而是不同抽象层次上的互补。hixl与shmem跨步通信与共享内存CANN生态中另一个容易与hixl混淆的通信库是shmem。两者都支持单边通信但设计侧重点不同。shmem的模型是共享内存所有参与通信的NPU把一部分内存映射到一个共享地址空间每个NPU可以像访问本地内存一样访问远端数据。这种模型适合需要频繁读写远端内存的场景比如图计算中的顶点数据更新——每个NPU都可能随时读写任意远端顶点的数据共享内存提供了最自然的编程接口。hixl的模型是消息传递通信以显式的put/get操作发起每次操作搬运一块或跨步的多块数据。这种模型适合数据搬运模式可预测的场景——你知道数据从哪来、到哪去、搬多少。PD分离中的KV Cache搬运就是典型的可预测模式Prefill产出的KV Cache地址和大小在计算前就能确定Decode侧的消费地址也可以预先分配好。跨步访问是hixl区别于shmem的关键能力。shmem的共享内存访问是按地址直接读写如果数据布局不连续应用需要自己逐个元素访问。hixl的跨步描述符让硬件自动完成跳步访问对于KV Cache这种固定步长的不连续布局通信效率显著更高。选择hixl还是shmem取决于你的通信模式如果数据搬运路径明确且步长规则用hixl如果需要随机访问远端内存用shmem。PD分离场景中的hixl工作流把前面的概念串起来看hixl在PD分离推理中的完整工作流。Prefill阶段用户请求到达Prefill卡模型执行前向计算产出当前请求的KV Cache。这些KV Cache按照多头注意力的布局存储每个头的数据在头维度内连续头与头之间有固定间距。Prefill卡在产出KV Cache后通过hixl的跨步put操作将KV Cache直接写入Decode卡的预留内存区域。HXLStridedDescriptor kv_desc;kv_desc.countnum_layers*num_heads;kv_desc.sizehead_kv_bytes;kv_desc.stridehead_stride_bytes;for(intl0;lnum_layers;l){void*srckv_base_prefill[l];void*dstkv_base_decode[l];hxl_put_strided(prefill_npu,decode_npu,src,dst,kv_desc);}这里按层循环每层执行一次跨步put。count设为num_heads每层的头数stride是头间步长。一次调用就把该层所有头的KV Cache从Prefill卡搬到Decode卡不需要逐头搬运。dst地址是Decode卡上预先分配好的KV Cache存储区Prefill卡直接写入Decode侧无需参与。Prefill卡在put返回后就可以继续处理下一个请求的Prefill计算不会因为等待Decode侧而阻塞。Decode阶段Decode卡从自己的内存中读取已经就位的KV Cache执行token生成计算。每生成一个token只需要访问本地内存中的KV Cache不需要跨卡通信。只有当新的Prefill请求的KV Cache被put过来时Decode卡才需要把新的KV Cache纳入注意力计算的范围。这个工作流的关键特征是Prefill和Decode的计算完全解耦。Prefill只管产出和投递Decode只管消费和生成。hixl的单边通信让这种解耦成为可能——双边通信要求两边同步那Prefill就必须等Decode准备好才能发两边的流水线又被耦合回去了。64字节对齐的工程实践前面提到hixl要求所有通信地址和步长64字节对齐这在工程实践中需要特别处理。KV Cache的内存分配通常由框架的内存池管理。框架在分配内存时需要确保KV Cache的起始地址和头间步长都满足64字节对齐。起始地址的对齐比较容易——在内存池初始化时按64字节边界分配即可。步长的对齐需要根据模型结构计算如果head_dim是128float16下每头256字节步长天然满足对齐如果head_dim是96float16下每头192字节步长是192字节不满足64字节对齐需要在头间填充16字节使步长对齐到256字节。这种填充会带来少量内存浪费但相比跨步通信的性能收益浪费是值得的。而且填充后的内存布局对Decode侧的注意力计算也有好处——对齐的访存地址让NPU的向量单元可以更高效地加载数据。使用前后的效率对比维度使用传统RMA方式使用hixl跨步通信原语差异来源数据传输粒度每次传输只能操作连续内存块非连续数据需要先打包再复制支持自定义跨度和跳步直接操作非连续地址空间hixl的跨步通信原语在硬件层面处理地址偏移计算中间缓冲区非连续数据传输前需要申请中间缓冲区完成数据整理不需要中间缓冲区源地址到目标地址直写Put语义的硬件单边访问消除了缓冲区拷贝PD分离KV交换场景需要多轮RMA操作完成注意力头数据的组合传输一次跨步Put即可传输完整层级的KV Cache数据stride参数的灵活配置适配了多层注意力头的数据布局编程复杂度开发者需要手动编排数据打包和缓冲区管理逻辑只需配置src、dst、count、size、stride五个参数简洁的API参数设计将地址计算和偏移管理的底层细节封装在内多NPU同步需要在每次数据传输后跨NPU同步时间开销较大跨步通信完成后即可直接访问hixl保证数据可见性单边通信语义本身就保证了数据一致性不需要额外同步操作下表对比了PD分离场景中使用hixl前后在关键指标上的差异指标使用常规拷贝通信使用hixl单边零拷贝通信KV Cache搬运路径应用缓冲区→通信库缓冲区→对端应用缓冲区两次拷贝源端内存→对端内存DMA直搬零拷贝通信参与方Prefill卡和Decode卡必须同步双边参与Prefill卡单边发起Decode卡无感不连续数据搬运方式逐头发起通信通信次数等于头数跨步描述符一次发起通信次数为一通信启动开销每次通信均有启动开销总开销与头数成正比启动开销仅一次被所有头摊薄Prefill与Decode耦合度强耦合Prefill必须等Decode就绪解耦Prefill算完即投递不等待内存带宽占用拷贝过程消耗额外内存带宽无额外拷贝内存带宽全部留给计算对齐要求无特殊对齐要求地址和步长需64字节对齐从表中可以看出hixl在搬运路径、参与方、通信次数、耦合度、内存带宽五个维度上都有明显优势。代价是64字节对齐的约束这在框架层面的内存分配器中很容易满足工程代价很小。hixl在CANN分层架构中的位置CANN的软件栈分为五层最上层是推理框架适配层如MindSpore Lite往下是计算图编译层GE再往下是算子库层Ascend C再往下是计算基础层最底层是硬件驱动层。hixl位于计算基础层与hccl、shmem同层。这一层的库有两个共同特征直接面向NPU硬件能力编程不经过上层的图编译或算子调度被上层库或框架间接调用应用开发者通常不直接使用。hixl也不例外——大多数开发者通过hccl间接使用hixl的传输能力只有在需要精细控制点对点通信时如PD分离场景才会直接调用hixl的API。计算基础层的库之间也有分工hccl管集合通信的编排hixl管点对点单边通信的执行shmem管共享内存的映射与访问。三者共同构成了CANN通信能力的完整基础上层的分布式训练和分布式推理都构建在这套基础之上。从概念到实践的映射回顾全文hixl的核心概念可以用一条线索串起来单边通信解耦了通信参与方零拷贝消除了中间搬运跨步访问合并了不连续数据的通信次数。这三个能力叠加在一起让PD分离场景中的KV Cache搬运从同步、多次、有中间拷贝变为异步、一次、直搬。对于初次接触hixl的开发者建议从三个维度建立认知通信语义维度put/get与send/recv的差异、内存布局维度连续访问与跨步访问的选择、系统架构维度hixl在CANN分层中的位置和与hccl/shmem的关系。这三个维度交叉起来就能判断自己的场景是否适合使用hixl以及应该使用hixl的哪些能力。仓库地址https://atomgit.com/cann/hixl