news 2026/9/18 10:50:52

HIXL 端到端冒烟测试(E2E Smoke Tests)实战指南:四种部署模式的传输验证与调试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HIXL 端到端冒烟测试(E2E Smoke Tests)实战指南:四种部署模式的传输验证与调试

HIXL 端到端冒烟测试(E2E Smoke Tests)实战指南:四种部署模式的传输验证与调试

【免费下载链接】hixlHIXL(Huawei Xfer Library)是一个灵活、高效的昇腾单边通信库,面向集群场景提供简单、可靠、高效的点对点数据传输能力。项目地址: https://gitcode.com/cann/hixl

本文基于 HIXL(Huawei Xfer Library)开源仓库中的端到端测试套件(tests/e2e/README_en.md),系统讲解该套件如何跨进程验证 HIXL 的 D2D、D2RH、D2RD 等点对点数据传输能力与数据完整性,覆盖 Real-Real、Standalone Same-Host、Dummy-Real 共享内存、Scale Reconnect 四种部署模式。读完本文,你将掌握 HIXL E2E 测试的环境准备、运行方式、环境变量调优、测试架构设计(设备/端口/内存分配策略)以及常见问题的排查方法,并能参照现有模式编写新的端到端用例。

一、E2E 冒烟测试的定位与价值

HIXL 面向集群场景提供简单、可靠、高效的点对点数据传输能力,其核心能力体现在跨进程、跨设备的 RDMA/HCCS 读写。端到端冒烟测试(End-to-End Smoke Test)用于在真实硬件上快速验证两件事:

  1. 传输功能可用性:不同部署模式下,HIXL 引擎能否完成建链、WRITE、READ、断链、解注册、销毁的全流程;
  2. 数据完整性:写入端与读取端的数据模式字节是否完全一致,是否存在丢包或错位。

该套件以 pytest 为框架,使用multiprocessingspawn上下文拉起多个独立进程模拟真实部署拓扑,每个测试用例都是一个可独立运行的"迷你集群"。

二、前置条件与环境准备

在运行 E2E 测试前,需要满足以下软硬件要求(以当前仓库 README 声明的版本为准):

类别要求
硬件至少 2 张 NPU 卡(Atlas A2/A3)
驱动Ascend NPU Driver >= 25.5.0
CANNCANN >= 9.1.0
PythonPython 3.10+

依赖安装命令:

pip install pytest torch==2.13.0+cpu --index-url https://download.pytorch.org/whl/cpu pip install torch-npu==2.13.0rc1

其中torch-npu用于在进程内执行torch.npu.set_device()与 NPU 内存分配;hixlPython 包来自本仓库(src/python/hixl_py),通过 pybind11 暴露了Hixl引擎类与register_memtransfer_sync等接口(见 hixl_py.cc)。

三、测试场景总览

套件包含四个测试文件,分别模拟四种典型部署形态:

测试文件部署模式核心验证点
test_real_real.pyReal-RealD2D、D2RH 跨设备批量读写
test_standalone_same_host.pyStandalone Same-HostStore Service + App 同主机 D2RH
test_dummy_real_shared_mem.pyDummy-Real 共享内存跨进程 Device 内存共享 + D2RD/D2RH 全流程
test_scale_reconnect.py大规模多链路 + 设备抖动每设备 250 条逻辑链路传输、抖动重连

3.1 Real-Real 模式(test_real_real.py

模拟两个独立的 RealClient(类似于 vLLM 的 Prefill 节点与 Decode 节点),Client 与 Server 分属两个进程,使用错位设备分配策略保证两进程不共享物理设备。

用例

  • test_normal_full_flow_d2rd_batch_read_write:D2D(Device to Device)跨设备批量读/写
  • test_normal_full_flow_d2rh_batch_read_write:D2RH(Device to Remote Host)跨设备批量读/写

架构(以 4 卡ASCEND_RT_VISIBLE_DEVICES=0,1,2,3为例):

Client Process (devices [0,1,2,3]) Server Process (devices [1,2,3,0]) ├─ engine[0] (dev 0) ──────────────> engine[0] (dev 1) ├─ engine[1] (dev 1) ──────────────> engine[1] (dev 2) ├─ engine[2] (dev 2) ──────────────> engine[2] (dev 3) └─ engine[3] (dev 3) ──────────────> engine[3] (dev 0)

数据流(对应 test_real_real.py 中的执行序列):

  1. Client 填充0xDD,Server 填充0xCC
  2. Client 执行 WRITE,将0xDD写入 Server 内存;
  3. Client 将本地内存清零;
  4. Client 执行 READ 从 Server 读回数据,期望读到0xDD(验证 WRITE 成功)——注意 READ 验证的是"读回的数据与本地原始填充一致",从而证明远端确实保存了客户端写入的内容。

代码实现上,Server 进程在_server_worker中为每个引擎分配设备内存并注册为hixl.MEM_DEVICE;D2RH 场景则使用alloc_host_mem_pinned分配 pinned 主机内存并注册为hixl.MEM_HOST(见 test_real_real.py)。Client 进程在_client_worker中完成 connect → WRITE → 清零 → READ → verify → disconnect → deregister → finalize 的完整闭环(test_real_real.py)。

3.2 Standalone Same-Host 模式(test_standalone_same_host.py

模拟 Mooncake 的 standalone 部署:Store Service 与 App 同主机共存。Store 进程分配一大块pinned 主机内存(大小为MEM_SIZE * N),每个引擎都注册同一base_addrtotal_size;App 进程的每个引擎分配设备内存。

用例

  • test_normal_full_flow_same_host_d2rh_write:D2RH 同主机写

架构

App Process (devices [0,1,2,3]) Store Process (devices [1,2,3,0]) ├─ engine[0] (dev 0) ──────────────> engine[0] (dev 1) ├─ engine[1] (dev 1) ──────────────> engine[1] (dev 2) ├─ engine[2] (dev 2) ──────────────> engine[2] (dev 3) └─ engine[3] (dev 3) ──────────────> engine[3] (dev 0) └─ shared host memory (base_addr)

数据流

  1. App 填充0xFF
  2. App[i] WRITE0xFF到 Store 主机内存偏移i * MEM_SIZE处——多引擎各写各的偏移段,避免写同一段内存造成冲突(见 test_standalone_same_host.py);
  3. App 清零本地内存;
  4. App[i] READ 同一偏移,期望读到0xFF

3.3 Dummy-Real 共享内存模式(test_dummy_real_shared_mem.py

该场景模拟 Mooncake dummy-real 部署模式,核心是验证跨进程的 Device 内存共享:Dummy 进程分配 Device 内存并通过 ACL IPC key 导出,Real 进程通过 IPC key 导入后注册到 HIXL 引擎,从而让对端可以直接对这段内存发起 RDMA 读写。

用例

  • test_normal_full_flow_d2rd_d2rh_read:D2RD + D2RH 全流程

进程架构

Local Dummy (devices [0,1,2,3]) Local Real (devices [0,1,2,3]) ├─ allocate device memory ├─ import IPC key ├─ fill 0xAA ├─ create engines └─ export IPC key └─ register device + host memory │ ▼ Remote Real (devices [1,2,3,0]) Remote Dummy (devices [1,2,3,0]) ├─ import IPC key ├─ allocate device memory ├─ create engines ├─ fill 0xBB ├─ register device + host memory └─ export IPC key └─ verify D2RH WRITE result

数据流(完整 15 步时序见 test_dummy_real_shared_mem.py):

  1. D2RD WRITE:Local Device(0xAA)→ Remote Device;
  2. D2RD READ:Remote Device → Local Device(期望 0xAA);
  3. D2RH WRITE:Local Device(0xAA)→ Remote Host;
  4. D2RH READ:Remote Host → Local Device(期望 0xAA)。

IPC 关键点:导出时使用ACL_RT_IPC_MEM_EXPORT_FLAG_DISABLE_PID_VALIDATION0x1)标志跳过 PID 校验,允许任意进程导入(需要 driver >= 26.1.1);导入使用默认标志0x0。对应代码为 test_dummy_real_shared_mem.py 中的_export_ipc_key/_import_ipc_key

3.4 Scale Reconnect 大规模链路与设备抖动(test_scale_reconnect.py

验证两个高可用能力:大规模多链路传输设备抖动(flapping)后的重连

用例

  • test_normal_flow_multi_links:N 设备 × 每设备 250 条逻辑链路批量传输(默认HIXL_E2E_LINKS_PER_DEV=250);
  • test_flapping_dev_reconnect:指定设备(FLAP_DEV = 2)抖动场景下的重连能力。

架构

Client Process (devices [0,1,2,3]) Server Process (devices [1,2,3,0]) ├─ engine[0] (dev 0) ──┐ ├─ engine[0] (dev 1) │ ├─ link 0 │ │ ├─ link 0 │ ├─ link 1 │ │ ├─ link 1 │ └─ ... │ │ └─ ... │ └─ link 249 │ │ └─ link 249 ├─ engine[1] (dev 1) ──┤ ├─ engine[1] (dev 2) ├─ engine[2] (dev 2) ──┤ ├─ engine[2] (dev 3) └─ engine[3] (dev 3) ──┘ └─ engine[3] (dev 0)

多链路场景中,Client 为每个 engine 分配TRANSFER_SIZE_PER_LINK * LINKS_PER_DEV大小的设备内存,逐条构造TransferOpDesc(local_addr, remote_addr + offset, len)执行 WRITE(见 test_scale_reconnect.py)。抖动场景则按"Pre-flap 正常 WRITE → Server 端 deregister + finalize 模拟设备下线 → Client 尝试传输 → Server 重新初始化 + 重新注册(新内存地址经队列回传)→ Client disconnect + reconnect → Post-reconnect WRITE"的节奏验证断线重建能力(test_scale_reconnect.py 与_client_worker_flap)。

四、运行测试

4.1 基本用法

# 设置环境变量 export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3 source /usr/local/Ascend/cann/set_env.sh # 运行全部测试 python3 -m pytest tests/e2e/ -v # 运行单个测试文件 python3 -m pytest tests/e2e/test_real_real.py -v # 显示详细输出(包含日志) python3 -m pytest tests/e2e/test_real_real.py -v -s

pytest 的 e2e 配置由仓库根目录的 pytest_e2e.ini 提供,指定了testpaths = tests/e2e、用例收集规则(test_*.py/Test*/test_*)以及requires_fabric_mem标记(FabricMem 相关用例需要 A3 硬件)。

4.2 环境变量说明

变量默认值说明
ASCEND_RT_VISIBLE_DEVICES0,1,2,3可见 NPU 设备列表
HIXL_E2E_MIN_NPU2最低 NPU 数量要求,低于该值测试被跳过
HIXL_E2E_LINKS_PER_DEV250每设备逻辑链路数(scale-reconnect 场景)
HIXL_E2E_TRANSFER_SIZE4096每条链路的传输大小,单位字节(scale-reconnect 场景)
HIXL_E2E_REGISTER_SIZE268435456(256MB)注册内存大小(scale-reconnect 场景)

其中HIXL_E2E_MIN_NPU在 conftest.py 中读取,由 session 级 autouse fixture 统一检查:若get_npu_count()小于阈值则pytest.skip,并提示可通过HIXL_E2E_MIN_NPU覆盖。HIXL_E2E_LINKS_PER_DEV等三个变量在 test_scale_reconnect.py 中解析,且均做了> 0的参数校验。

4.3 典型运行示例

# 4 卡运行全部用例 export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3 python3 -m pytest tests/e2e/ -v # 自定义链路参数 export HIXL_E2E_LINKS_PER_DEV=500 export HIXL_E2E_TRANSFER_SIZE=8192 python3 -m pytest tests/e2e/test_scale_reconnect.py -v # 跳过 NPU 数量检查(用于调试) export HIXL_E2E_MIN_NPU=0 python3 -m pytest tests/e2e/test_real_real.py -v

五、测试架构设计原理

5.1 设备分配策略(错位分配)

utils.py 中的get_device_lists()ASCEND_RT_VISIBLE_DEVICES解析设备数量并返回两组错位列表:

  • Client/App[0, 1, 2, 3](前半/全部逻辑设备)
  • Server/Store[1, 2, 3, 0](偏移 +1 取模)

server_devs[i] = (i + 1) % n。这样保证client[i]server[i]一定落在不同的物理设备上,所有连接都是真实的跨设备 D2D 路径,避免资源冲突,也杜绝了"同设备伪 D2D"掩盖传输问题的可能。

5.2 端口分配策略

get_port()(utils.py)基于固定基址与偏移生成互不冲突的监听端口:

BASE_PORT = 39000 port = BASE_PORT + scenario_idx * 100 + role_offset + dev_id + engine_offset

其中:role_offset为 0(server/remote)或 100(client);engine_offset为 200(fabric/hccs/alt 引擎)或 0。不同测试文件使用不同的SCENARIO_IDX(如 real_real 的 D2D 用 0、D2RH 用 5,standalone 用 7,scale 用 4)进行场景隔离。

示例SCENARIO_IDX=3dev_id=0):

角色端口
server39300
client39400
server_fabric39500
client_fabric39600

5.3 内存管理

  • Device 内存torch.zeros(size, dtype=torch.uint8, device="npu")分配,通过data_ptr()取地址(见alloc_device_mem);
  • Host 内存torch.empty(size, dtype=torch.uint8).pin_memory()分配页对齐内存,保证可被 ACL 注册(见alloc_host_mem_pinned);
  • IPC 共享:跨进程共享 Device 内存时,通过acl.rt.ipc_mem_get_export_key/acl.rt.ipc_mem_import_by_key导出/导入 IPC key;
  • 内存注册RegisteredMem封装了engine.register_mem(hixl.MemDesc(addr, size), mem_type)与析构时自动deregister_mem,内存类型区分hixl.MEM_DEVICEhixl.MEM_HOST(utils.py);
  • 传输描述build_op_descs16 * 1024字节块把一段连续内存切分为多个hixl.TransferOpDesc(local_addr, remote_addr, len),供transfer_sync批量下发(utils.py)。

5.4 资源清理顺序

为确保多进程场景下不残留连接与内存句柄,清理顺序为:

  1. Client 侧disconnectderegisterfinalize
  2. Server 侧deregisterfinalize

所有测试文件(包括异常分支)都遵循这一顺序,异常处理中也会逐个disconnectderegisterfinalize,并通过result_queue.put(False)上报失败。

5.5 引擎初始化参数

所有用例共用create_engine()(utils.py),默认初始化参数为:

options = { hixl.OPTION_AUTO_CONNECT: "1", hixl.OPTION_GLOBAL_RESOURCE_CONFIG: '{"comm_resource_config.protocol_desc": ["roce:device", "roce:host"]}', }

即开启 Auto Connect(可跳过显式建链直接传输)并声明使用 roce:device 与 roce:host 两种通信协议。这些 option 的取值含义可参考 docs/zh/api/python/HIXL-interface.md 中initialize的 options 说明表。

六、调试技巧

6.1 查看详细日志

# 启用控制台输出(-s 显示 print 与日志) python3 -m pytest tests/e2e/test_real_real.py -v -s

各 worker 进程的日志前缀带有角色标签,便于区分,例如[S1-SERVER][S0-CLIENT][S2-R-DUMMY][S5-CLIENT-FLAP]等。conftest.pylogging.basicConfig统一格式化时间戳与级别,并抑制了torch._inductortorch的噪声日志。

6.2 查看 HIXL 底层日志

# 设置日志级别:0=DEBUG, 1=INFO, 2=WARNING, 3=ERROR export ASCEND_GLOBAL_LOG_LEVEL=1 # 设置日志路径 export ASCEND_PROCESS_LOG_PATH=/tmp/hixl_logs mkdir -p /tmp/hixl_logs # 运行测试 python3 -m pytest tests/e2e/test_real_real.py -v # 查看日志 ls /tmp/hixl_logs/plog-*.log

6.3 常见问题排查

Q:测试被跳过,提示 "Need >= 2 NPUs"

# 检查 NPU 数量 npu-smi info -l | grep "NPU" # 覆盖环境变量阈值 export HIXL_E2E_MIN_NPU=0

Q:连接超时(Connection timeout)

# 检查端口是否被占用(端口范围在 39xxx) netstat -tlnp | grep 39 # 增大超时(修改代码中的 CONNECT_TIMEOUT_MS)

代码中CONNECT_TIMEOUT_MS = 10000TRANSFER_TIMEOUT_MS = 30000定义于 utils.py,可作为调参入口。

Q:数据校验失败

  • 检查日志中 WRITE/READ 的返回值是否均为hixl.SUCCESS
  • 核对设备分配是否正确:client[i]server[i]应落在不同物理设备上(错位策略失效通常会导致跨进程共享设备冲突)。

七、文件结构与扩展新用例

7.1 目录结构

tests/e2e/ ├── __init__.py # 包初始化文件 ├── conftest.py # pytest 配置与 fixture(NPU 数量检查、FabricMem 标记) ├── utils.py # 公共工具函数(设备列表、端口、内存、引擎封装) ├── test_real_real.py # Real-Real 模式测试 ├── test_standalone_same_host.py # Standalone 同主机模式测试 ├── test_dummy_real_shared_mem.py # Dummy-Real 共享内存模式测试 ├── test_scale_reconnect.py # 大规模链路 + 设备抖动重连测试 ├── README.md # 中文文档 └── README_en.md # 本文档 pytest_e2e.ini # pytest e2e 配置(仓库根目录)

7.2 编写新用例的约定

参照现有模式新增用例时,应遵守以下约定(对应 README 的 Contributing 一节):

  1. 新测试用例遵循现有模式(多进程 spawn + Queue/Event 同步 + 断言验证);
  2. 关键步骤使用logger.info(...)记录(包含角色标签、设备映射、操作与返回码);
  3. 使用result_queue传递 worker 执行结果,主进程统一断言;
  4. 保证资源清理顺序正确:disconnectderegisterfinalize
  5. 提交前运行ruff checkruff format校验代码风格。

八、总结

HIXL E2E 冒烟测试套件以四种部署模式(Real-Real、Standalone Same-Host、Dummy-Real 共享内存、Scale Reconnect)为骨架,通过错位设备分配、场景化端口隔离、IPC 内存共享与多进程同步机制,在真实 NPU 硬件上完整覆盖了 D2D、D2RD、D2RH 的 WRITE/READ 全链路与数据一致性验证,是快速定位 HIXL 传输问题、评估集群部署可行性的第一道防线。结合 tests/e2e 目录下的源码与本文的调试指南,开发者可以快速上手运行、排查乃至扩展自己的端到端验证场景。

【免费下载链接】hixlHIXL(Huawei Xfer Library)是一个灵活、高效的昇腾单边通信库,面向集群场景提供简单、可靠、高效的点对点数据传输能力。项目地址: https://gitcode.com/cann/hixl

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 10:50:24

Gartner数据治理成熟度模型:自评方法与跃迁路径

简介:加特纳企业信息管理成熟度模型(中文版)定义文档,面向IT管理者、企业架构师与数据治理人员,用于快速评估企业信息管理现状并规划升级路径。资源系统阐述从0级无认知型到5级高效型的完整六级框架,逐级说…

作者头像 李华
网站建设 2026/9/18 10:49:12

人大金仓KingbaseES V8R3 License更新实操指南:从备份到验证全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 10:46:53

基于AT89C52与ADC0832的一氧化碳检测报警器设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 10:46:50

VSCode Remote-SSH + conda 实现 Linux 服务器远程 Python 调试全攻略

人在公司,突如其来的一次线上事故,逼着我第一次正儿八经地在Linux服务器上调试Python代码。手里的笔记本性能倒是不错,但目标服务只在内网的一台CentOS机器上,没显卡没桌面,只有一个SSH登录窗口。那会儿我还在用vim改代…

作者头像 李华
网站建设 2026/9/18 10:46:43

磁盘I/O为何成为性能瓶颈?物理结构、寻道时间与IOPS详解

你有没有遇到过这种情况:程序跑起来CPU使用率不高、内存也很充裕,但整个系统就像被什么东西卡住了一样,点一下窗口要等好几秒才反应。我这些年排查类似的性能问题,十次里有七次最后都指向同一个地方——磁盘I/O。磁盘I/O这个东西&…

作者头像 李华