CANN HIXL LLM-DataDist Python 快速入门:从零构建大模型推理 PD 分离框架
【免费下载链接】hixlHIXL(Huawei Xfer Library)是一个灵活、高效的昇腾单边通信库,面向集群场景提供简单、可靠、高效的点对点数据传输能力。项目地址: https://gitcode.com/cann/hixl
LLM-DataDist 是 CANN HIXL 单边通信库中的大模型分布式集群与数据管理组件,面向昇腾集群提供高性能、零拷贝的点对点 KV Cache 传输能力。本文基于 docs/zh/guide/python/quick_start.md 展开,讲解如何将 LLM-DataDist 使能到大模型推理框架中,完成 PD(Prefill/Decode)分离式部署,并配套介绍环境准备、关键环境变量、完整样例参考与底层源码佐证。读完本文,你将掌握 PD 分离框架的整体开发流程、LLM-DataDist 初始化/建链/注册/传输/释放的完整接口调用链,以及如何在本地运行官方样例验证整套流程。
整体开发流程:推理框架中的四个抽象模块
为了统一描述不同推理框架的改造点,LLM-DataDist 将推理框架抽象为四个模块:
- 资源初始化模块:负责框架底层资源(Device、通信等)的初始化。
- KV Cache 管理模块:负责 KV Cache 内存的创建、分配(PA/PagedAttention 场景)与销毁。
- 模型推理模块:负责实际的 Prefill / Decode 推理执行。
- 资源释放模块:负责框架退出时的资源清理。
LLM-DataDist 的核心目标就是在这四个模块中,以最小侵入方式使能 PD 之间高性能的 KV Cache 传输能力。整体开发流程分为五步:
- 资源初始化阶段使能 LLM-DataDist:找到推理框架的资源初始化模块,在该阶段调用 LLM-DataDist 的初始化接口(
LLMDataDist()构造 +init())和建链接口(link_clusters/link)。 - KV Cache 管理阶段注册内存:在 KV Cache 管理模块调用 LLM-DataDist 的 KV Cache 注册接口(
register_cache/register_blocks_cache),将推理框架自行申请的内存注册到 LLM-DataDist 中,供后续远端访问。 - 拆分解耦 Prefill 与 Decode:将推理脚本拆分为 Prefill(全量)脚本与 Decode(增量)脚本,分离部署到不同的集群节点上。Decode 阶段执行前,需要接收 Prefill 阶段的输出作为输入,并调用 LLM-DataDist 的 KV Cache 传输接口(
pull_cache/pull_blocks/push_cache/push_blocks等)拉取或推送 Prefill 侧缓存的 KV Cache。 - 分别执行推理脚本:在各自集群上运行 Prefill 推理脚本和 Decode 推理脚本。
- 释放 LLM-DataDist 资源:在框架的资源释放模块调用
unlink_clusters(或unlink)断链并调用finalize()释放 LLM-DataDist 相关资源。
从源码结构看,这五步与 src/llm_datadist/llm_datadist_v2.cc 及 src/llm_datadist/api/llm_datadist_impl.cc 中的接口实现一一对应,init/finalize/link_clusters/unlink_clusters等能力均由底层引擎调度完成。
环境准备:硬件形态、网络检测与环境变量
支持的硬件形态
LLM-DataDist 支持的产品形态如下(当前仓库文档口径):
- Atlas A2 训练/推理系列产品:仅支持 Atlas 800I A2 推理服务器、A200I A2 Box 异构组件。该场景下 Server 内采用 HCCS 传输协议时,仅支持 D2D。
- Atlas A3 训练/推理系列产品:采用 HCCS 传输协议时,不支持 Host 内存作为远端 Cache。
- Ascend 950PR/Ascend 950DT:超节点内使用 UB 协议,超节点间使用 RoCE 协议。
使用前请参照《CANN 软件安装》安装好驱动、固件以及 CANN 软件,并确认已安装hccn_tool工具。
卡间网络检测:hccn_tool 常用命令
LLM-DataDist 依赖集群节点之间的 RDMA 链路,使用前必须用hccn_tool查询 Device IP 并进行卡间网络检测,要求各个集群上的卡间有 RDMA 链路连接,否则无法使能 LLM-DataDist 能力。常用命令如下:
| 命令 | 使用场景 |
|---|---|
hccn_tool [-i %d] -link -g | 获取指定 Device 网口 Link 状态。-i指定 Device。样例:hccn_tool -i 0 -link -g |
hccn_tool [-i %d] -ip -g | 获取 IP 地址和子网掩码。样例:hccn_tool -i 0 -ip -g |
hccn_tool [-i %d] -ip -inet6 -g | 获取 IPv6 地址和子网掩码。样例:hccn_tool -i 0 -ip -inet6 -g |
hccn_tool [-i %d] -ping -g [address %s] | 获取指定设备到目的地址的 ping 结果。样例:hccn_tool -i 0 -ping -g address 192.168.2.1 |
在仓库样例中也能看到hccn_tool的实际用法:例如 examples/python/llm_datadist/pull_cache_sample.py 通过subprocess.run(["hccn_tool", "-i", str(device_id), "-ip", "-g"])解析本机 Device IP,用于构造单机场景下的 rank table,这印证了-ip -g输出中包含ipaddr:关键字的实现细节。
关键环境变量
| 名称 | 使用场景 |
|---|---|
HCCL_RDMA_TC、HCCL_RDMA_SL | 当客户对参数面网络做了自己的规划,规定了各种业务流量的类型与优先级时,通过这两个环境变量设置参数面集合通信流量在网络上的流量类型和优先级,以适配客户网络流量规划要求。 |
HCCL_RDMA_RETRY_CNT、HCCL_RDMA_TIMEOUT | 分别对应 RDMA 硬件重试次数和重试超时时间。设置太大对网络异常反应不敏感,无法感知网络故障;设置太小则容易造成网络闪断直接中断业务,无法被网卡硬件屏蔽。推荐按下式配置以减少网络抖动影响:HCCL_RDMA_TIMEOUT = log2(pull kv超时时间 * 10^6 / (HCCL_RDMA_RETRY_CNT + 1) / 4.096),向上取整。当 pull kv 超时时间和HCCL_RDMA_RETRY_CNT都取默认值时,HCCL_RDMA_TIMEOUT建议配置为 15。 |
HCCL_INTRA_ROCE_ENABLE | 用于配置 Server 内是否使用 RoCE 环路进行多卡间的通信。 |
AUTO_USE_UC_MEMORY | 控制系统是否允许算子搬移数据不经过 L2 Cache 的功能。使用 LLM-DataDist 之前,如果未配置该环境变量,使用过程中会将其设置为 0,表示所有算子搬移数据都必须经过 L2 Cache。 |
HCCL_INTRA_ROCE_ENABLE=1在官方样例中高频出现(如 examples/python/README.md 中所有双机样例均以该前缀启动),用于强制使用 RoCE 环路通信;同时样例要求先执行source ${HOME}/Ascend/cann/set_env.sh加载昇腾运行环境。
完整样例参考:以 transformers LLAMA 模型为例的 PD 分离改造
官方以 transformers 的 LLAMA 模型为例,展示 PD 分离前后脚本的变化点,提供如何从非分离脚本改为 PD 分离脚本的参考。样例将全量模型和增量模型分离,部署到不同集群节点上执行(可在配套版本配套表中从npu_tuned_model/llm/llama/benchmark/pd_separate目录获取)。
分离脚本在整个推理流程中的服务层调度过程如下:
- 用户请求触发时,服务层将请求调度到全量(Prefill)集群,执行全量脚本推理,并将增量脚本需要的信息传输到增量脚本执行节点;此时全量集群节点可继续接收服务层下发的新的用户请求。
- 增量(Decode)集群接收全量集群对应的请求信息,拉取对应请求的 KV Cache(在全量集群节点上已计算好),同时按照增量模型的 batch 大小进行组 batch 操作,执行增量推理。
- 当增量集群上有请求推理完成、空出对应 batch 位置时,再接收全量集群发来的新请求,重复步骤 2 和 3。
- 全量集群重复步骤 1,增量集群重复步骤 2 和 3,直到业务结束,全量和增量集群退出。
这套调度模型充分利用了 KV Cache 复用与 Continuous Batching 机制:Prefill 阶段是计算密集型(决定 TTFT),Decode 阶段是访存密集型(决定 TBT),PD 分离后两阶段互不阻塞,系统可以提供更稳定的 TBT。相关背景概念(Prefill/Decode 阶段、KV Cache、PagedAttention、block_table、cluster_id、动态扩缩容等)可参考 docs/zh/guide/python/appendices.md。
可运行样例:从双机 pull_cache 到多后端传输
本仓库提供了 9 个 LLM-DataDist Python 样例,全部位于 examples/python/llm_datadist 目录,覆盖一般 Cache 传输、Blocks(PA)传输、角色切换、xPyD 多机扩展、异步分层传输以及 HIXL 传输后端等场景。
双机执行 pull_cache 样例
pull_cache_sample.py展示配置内存池场景下使用allocate_cache、双边建链(link),并从远端pull_cache的完整流程。双机执行命令如下(device_id为要使用的设备号,cluster_id为集群 ID 且在所有参与建链范围内需唯一):
# Prompt 主机: HCCL_INTRA_ROCE_ENABLE=1 python llm_datadist/pull_cache_sample.py --device_id 0 --cluster_id 1 # Decoder 主机: HCCL_INTRA_ROCE_ENABLE=1 python llm_datadist/pull_cache_sample.py --device_id 0 --cluster_id 2单机执行时,需要在同一台主机上同时启动 Prompt 与 Decoder 两个进程:
# Prompt 进程: HCCL_INTRA_ROCE_ENABLE=1 python llm_datadist/pull_cache_sample.py --device_id 0 --cluster_id 1 --is_single true --host_ip 10.10.10.1 # Decoder 进程: HCCL_INTRA_ROCE_ENABLE=1 python llm_datadist/pull_cache_sample.py --device_id 1 --cluster_id 2 --is_single true --host_ip 10.10.10.1运行前需要修改样例顶部的 IP 配置:将PROMPT_IP_LIST改为 Prompt 主机的各device_ip,PROMPT_HOST_IP改为 Prompt 主机host_ip,DECODER_IP_LIST与DECODER_HOST_IP对应改为 Decoder 主机的信息,且两台机器脚本保持一致。
从源码理解 pull_cache 样例的执行主线
从 examples/python/llm_datadist/pull_cache_sample.py 的代码可以看到完整调用链:
- 初始化:
LLMDataDist(role, cluster_id)构造对象后,通过LLMConfig()设置device_id、enable_cache_manager=True与mem_pool_cfg,再调用generate_options()生成配置字典并交给datadist.init(llm_options); - 建链:
cluster_rank_info = {1: 0, 2: 1}表示集群 1 对应 rank 0、集群 2 对应 rank 1,随后调用datadist.link("link", cluster_rank_info, rank_table)发起双边建链,并通过query_register_mem_status(comm_id)轮询内存注册状态直至RegisterMemStatus.OK; - Cache 分配:Prompt 侧用
CacheKey(prompt_cluster_id=1, req_id=0, model_id=0)标识请求,调用allocate_cache(cache_desc, [cache_key_0, cache_key_1])分配并关联两个请求的 KV Cache; - 传输:Decoder 侧调用
cache_manager.pull_cache(cache_key_0, cache, batch_index=0)按 batch 位置拉取远端 KV Cache; - 清理:传输结束后 Prompt 侧调用
remove_cache_key解除 cache key 与请求的关联(pull 失败时确保 cache 可释放),两侧调用deallocate_cache、unlink与finalize完成资源回收。
其他样例的运行方式与适用场景
pull_blocks / pull_from_cache_to_blocks:PA 场景下按 block 拉取,
pull_blocks_sample.py使用 torch 自行申请内存并双向建链;pull_from_cache_to_blocks.py演示从一般 Cache 拉取到 Blocks 内存布局。双机与单机执行方式与 pull_cache 相同。push_blocks / push_cache:单侧建链(
link_clusters)方式,Decoder 发起建链并 push。默认走通信域传输后端,可加--transfer_backend hixl切换为 HIXL CS 后端;A5(Ascend 950PR/Ascend 950DT)环境必须指定--transfer_backend hixl,未手动配置local_comm_res时默认走 UB 链路,也可手动配置以使用 RDMA 链路:# Prompt 主机: python llm_datadist/push_blocks_sample.py --device_id 0 --role p --local_host_ip 10.10.10.0 --remote_host_ip 10.10.10.1 --transfer_backend hixl # Decoder 主机: python llm_datadist/push_blocks_sample.py --device_id 1 --role d --local_host_ip 10.10.10.1 --remote_host_ip 10.10.10.0 --transfer_backend hixlswitch_role_sample:先由 Decoder 建链 pull blocks,随后两侧切换角色,由 Prompt 发起建链并 push blocks,演示
switch_role接口的角色与 Client/Server 双向切换能力。pull_blocks_xpyd_sample:支持 xPyD 测试场景(任意 P 个 Prompt 进程、D 个 Decoder 进程),每个 Decoder 与所有 Prompt 建链并 pull blocks 到本地。
--remote_ip_port参数由所有 Prompt 侧的local_ip:port以分号;连接组成。transfer_cache_async_sample:单侧建链,Prompt 侧发起建链并通过
transfer_cache_async+LayerSynchronizer异步分层传输 cache。hixl_transfer_backend_sample:以 HIXL 作为 LLM-DataDist 传输后端,完成内存注册、建链和传输,Decoder 发起建链 push blocks,Prompt 发起建链 pull blocks。
关键配置项与接口约束
LLMConfig 核心配置项
LLMConfig用于构造init所需的配置字典(对应 docs/zh/api/python/LLMConfig.md):
| 配置项 | 对应底层配置 | 说明 |
|---|---|---|
device_id | ge.exec.deviceId | 必填,当前进程 Device ID,当前只支持配置一个。 |
enable_cache_manager | llm.EnableCacheManager | 是否开启 CacheManager 模式,需配置为 True。Decode 和 Prompt 可双向拉取 Cache。Ascend 950PR/Ascend 950DT 场景不支持配置为 False。 |
enable_remote_cache_accessible | — | 是否开启远端 Cache 可直接访问。开启后本地缓存远端 Cache 元数据(索引、内存地址等)以加速 Pull,更适用于 PA 场景(Cache 只在初始化阶段分配/注册,不会频繁变化)。Atlas A3 场景不开启时仅支持 RDMA 传输协议;Ascend 950PR/Ascend 950DT 不支持配置为 False。 |
sync_kv_timeout | llm.SyncKvCacheWaitTime | pull_cache/pull_blocks/push_cache/push_blocks的超时时间(ms),默认 1000ms。 |
listen_ip_info | llm.listenIpInfo | Host 侧 IP 和端口,例如"192.168.1.1:26000"。配置后本端即作为 Server 监听,可用于单边建链。 |
local_comm_res | — | 本地通信资源(JSON 字符串)。不配置或为空串时自动生成相关信息,使用集合通信通信域方式建链(单卡链路上限 512);配置version为"1.0"/"1.2"的 ranktable 格式时同样走通信域建链;配置version为"1.3"(推荐,需要 HDK ≥ 25.5.0 且 toolkit ≥ 9.1.0)时使用 HixlCS 能力建链,无链路上限。配置了该 option 后,若未显式配置,enable_cache_manager与enable_remote_cache_accessible默认置为 True。 |
rdma_traffic_class/rdma_service_level | 与HCCL_RDMA_TC/HCCL_RDMA_SL等效 | 分别配置 RDMA 网卡 traffic class([0,255],需为 4 的整数倍,默认 132)与 service level([0,7],默认 4)。与对应环境变量同时配置时,option 优先级更高。 |
link_total_time/link_retry_count | — | HCCL 建链失败的总超时时间(秒,[0, 2^32-1],默认 0,传入 0 时读取HCCL_CONNECT_TIMEOUT,默认 120s)与重试次数([1,100],默认 1)。 |
transfer_backend | — | 取值为"hixl"时指定 HIXL 作为传输引擎后端。使用 hixl 后端时需在 init 的 options 中指定listen_ip_info,每个传输端既可作 Client 也可作 Server,且与对端发起传输前需先调用link_clusters建链。 |
global_resource_config | — | 仅当transfer_backend为"hixl"时生效,JSON 格式,内容透传至 HIXL 引擎解析校验,例如'{"comm_resource_config.listen_port": 26666, "comm_resource_config.max_active_channels": 128}'。 |
ge_options | ge.* | 额外 GE 配置项,其中ge.flowGraphMemMaxSize表示所有 KV Cache 占用的最大内存,设置过大将压缩模型可用内存,需按实际情况指定。 |
建链方式与链路上限
LLM-DataDist 提供两种建链方式(对应 docs/zh/api/python/LLMDataDist.md):
- 单边建链
link_clusters(推荐):由 Client 单侧发起,是否作为 Server 与角色 Prompt/Decoder 无关,设置listen_ip_info标识端口监听即为 Server 端。返回值为二元组(LLMStatusCode, List[LLMStatusCode]),分别表示接口返回值与每个集群的建链结果。约束包括:建议超时时间配置 200ms 以上,TLS 开启时建议 2000ms 以上(可用hccn_tool [-i %d] -tls -g [host]查询 TLS 状态);调用前需提前注册所有内存,否则建链后注册不支持远端访问。 - 双边建链
link:通过建立通信域方式建链,需要rank_table文件,通信域内节点数量最大支持 4,通信域数量建议不超过 16、最大 512,最多支持 16 条链路并发建链(超过 16 条底层排队)。unlink为对应的断链接口,query_register_mem_status配合link查询注册内存状态。Ascend 950PR/Ascend 950DT 不支持link、unlink和query_register_mem_status。
建链数量过多存在内存 OOM 及 KV Cache 传输性能风险:使用集合通信通信域方式建链时允许的最大通信数量为 512;使用 HixlCS 能力(local_comm_res配置version为"1.3")建链时没有链路上限限制。
容器与网络约束
- 容器场景若未配置
local_comm_res或配置为空,需在容器内映射/etc/hccn.conf文件,或确保默认路径/usr/local/Ascend/driver/tools下存在hccn_tool;两者都不满足时需将hccn_tool所在路径配置到PATH中:export PATH=$PATH:{hccn_tool_install_path}。 - 使用 Device RoCE 场景时,同一通信集群内 Device RoCE 地址配置需保持一致,不支持 IPv6-only 节点与 IPv4/IPv6 双栈节点混合接入(约束适用于 Atlas A2 与 Atlas A3 训练/推理系列产品)。
更进一步:接口参考与示例代码的完整地图
- 接口参考(Python):docs/zh/api/python/README.md 汇总了
LLMDataDist、LLMConfig、CacheManager、Cache、LLMRole、LLMClusterInfo、CacheDesc、CacheKey、BlocksCacheKey、TransferConfig、LLMStatusCode等全部组件文档,接口约束与错误码处理可查阅 docs/zh/api/python/LLMStatusCode.md。 - 链路管理与 KV Cache 管理的接口功能与伪代码示例:见 docs/zh/guide/python/functions.md,其中包含一般 Cache 传输(
register_cache/pull_cache/transfer_cache_async)与 Blocks Cache 传输(register_blocks_cache/pull_blocks/push_blocks)两套完整示例。 - 底层实现参考:LLM-DataDist 的初始化与链路管理实现在 src/llm_datadist/llm_datadist_v2.cc,缓存管理实现在 src/llm_datadist/cache_mgr/cache_manager.cc,传输后端抽象位于 src/llm_datadist/transfer_engine,HIXL 传输引擎实现在 src/llm_datadist/transfer_engine/hixl_transfer_engine.cc。
- 更多完整可运行样例:除本仓库 examples/python/llm_datadist 目录外,也可在配套版本的
examples/python目录中获取更多代码样例。
结语
以 docs/zh/guide/python/quick_start.md 为主线,本文完整还原了在推理框架中使能 LLM-DataDist 的五步开发流程,并补充了环境准备、关键环境变量、配置项约束与可运行样例。核心要点可概括为:初始化(init)→ 建链(link_clusters/link)→ 注册内存(register_cache/register_blocks_cache)→ 传输 KV Cache(pull_*/push_*/transfer_cache_async)→ 断链与释放(unlink_*/finalize)。建议读者结合 examples/python/llm_datadist/pull_cache_sample.py 等样例先跑通双机最小闭环,再参照 docs/zh/guide/python/functions.md 与 docs/zh/api/python/LLMDataDist.md 将接口迁移到自己的推理框架中。
【免费下载链接】hixlHIXL(Huawei Xfer Library)是一个灵活、高效的昇腾单边通信库,面向集群场景提供简单、可靠、高效的点对点数据传输能力。项目地址: https://gitcode.com/cann/hixl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考