Skip to content

Repository files navigation

hccl-capture

hccl-capture 是一个独立于 HCCL 源码的工作负载捕获与 Trace Bundle 生成工程。HCCL 以只读 Git submodule 固定版本,捕获代码、schema、适配层和导出器全部位于本仓库。

当前能力

推荐使用 native_dockernative_local 后端。每次捕获显式选择 HCCL source variant;工程按“submodule commit + overlay + CANN header”指纹,在隔离目录构建同源的 host libhccl.solibhccl_compat.so 和 ST AICPU 内核。两条后端共用相同 spec、Runner、Bundle 和分析逻辑,均不修改 third_party/hccl

当前原生 Runner 已覆盖 AllToAll、AllGather、AllReduce、ReduceScatter、Broadcast、Reduce、Scatter、 AllGatherV、ReduceScatterV、AllToAllV/VC、相邻配对 Send/Recv 和 BatchSendRecv。逐算子的参数语义、 Device、Execution Engine、拓扑、算子、算法实现和 HCCL/CANN 版本的全景见 能力边界矩阵;逐算子的参数语义、实跑 algTag 与细节见 算子兼容矩阵

每次运行只生成 5 个核心文件:

  • manifest.json:输入、算法选路、指标、校验、requested/observed topology、endpoint 和 channel 的统一元数据。
  • tasks.jsonl:完整 Task DAG 节点,并内联逐 task 的 Jetty/channel/port 注解。
  • edges.jsonl:stream 顺序、LocalPost/Wait、跨 rank Post/Wait 依赖。
  • p2p_flows.csv:逐 P2P activity 保存 payload、all-of 前驱 activity、ready wave、 launch group 和 SendRecvWrite/Read 双向 rendezvous;它不再是缺少依赖的 rank-pair 汇总表。
  • raw.log.gz:压缩原始执行日志。

旧的拆分 Bundle 仍可读取,并可用 hccl-capture compact <目录> --recursive 原地升级。

原生后端的依赖边来自 TaskNode.parents/children,不是 stdout 推断。旧的 docker_st 日志后端仍保留作兼容兜底,其中 queue 顺序精确、Post/Wait 匹配为 best-effort。

Device 与算子能力(9.1.0-beta.3)

Device 同输入实跑结果 当前捕获状态
DEV_TYPE_950 当前 Runner 中 13 类 workload 均已实跑,可导出真实 task、依赖和 P2P channel 可选
DEV_TYPE_910B 回退 HcclAlltoAllInner,当前 ST stub 返回 not support 页面可见但禁用
DEV_TYPE_910_93 回退 HcclAlltoAllInner,当前 ST stub 返回 not support 页面可见但禁用

这张表是“当前 HCCL tag + 当前 native ST 捕获入口”的能力矩阵,不代表 910B/910_93 不支持其他集合通信或实机 HCCL。Device 会从 spec 一直传到 SimWorld::Init,并写入 Bundle 的 requested/runtime 校验字段;不支持的组合在 Web、HTTP 和 CLI 三层都会拒绝。

Execution Engine(beta3 ST)

spec 可用 execution.engine,页面可用 Execution Engine 下拉框选择:

Engine 当前捕获结果 已验证拓扑
AI_CPU 完整 Task DAG、P2P、ready/join 与 channel 950 的单 Server、两级 stock、UBX
HOST_DPU 完整 Task DAG、P2P 与 channel;algTag 含 DPU_host 950 的两级多 Server;2×2、2×4 和 2+3 非对称已实跑
AIV selection-only:真实 AIV algTag 与 engine code 可见,但 beta3 ST 不展开 AIV kernel,Task/P2P 为 0 950 的单 Server和两级 stock;UBX replay 不兼容

HostDPU 的底层仍设置 HCCL_OP_EXPANSION_MODE=AI_CPU,并额外设置 ENABLE_HOSTDPU_FOR_LLT=1;AIV 设置 HCCL_OP_EXPANSION_MODE=AIV。AIV 为穿过 beta3 ST 缺失资源桩, Runner 会把 ST 链路协议适配为 UB_MEM,并提供 host-backed engine context/registered-memory loopback; 这些适配名称全部写进 manifest,不能作为真实硬件端口或时延证据。

Task ID 形如 r0-q2-p3rrankIdxq 是该 rank 内的逻辑 task queue/stream queIdxp 是 task 在该 queue 中从 0 开始的 pos。它在一份 Bundle 内可稳定引用,但 queue 分配和位置会随算法改变,因此不能当作跨算法的语义 flow ID。

仓库还包含本地 HCCL Capture Studio:标准前端工程位于 frontend/,采用 React、TypeScript、Vite、 TanStack Query 和 Lucide;生产构建作为 Python package 的静态资源随 CANN 容器直接启动,运行时不依赖 Node。 页面可以配置算子、算法、拓扑和消息参数,异步执行捕获, 并查看可交互 Task DAG、单-rank 拓扑无关通信调度、P2P rank 流量矩阵、Jetty/channel/端口字段和全部原始产物。Web 层 只调用上述 bundle 接口,不修改 HCCL,也不维护第二套分析逻辑。

五分钟启动

推荐让服务和劫持都运行在 CANN 容器内,宿主机只需要 Docker:

git clone --recurse-submodules https://github.com/ubsim-dev/hccl-capture.git
cd hccl-capture
tools/start_containerized_studio.sh
docker logs -f hccl-capture-studio

仓库将 HCCL submodule 固定在官方 v9.1.0-beta.3 tag,并直接使用与之配套的公开 CANN beta.3 开发镜像,不覆盖镜像内的 libhccl.sohccl-st-work 保存 variant/ST/runner 编译缓存;源码以只读方式挂载到 /project,宿主机 out/ 以读写方式挂载到 /out,因此删除容器不会删除捕获结果。空卷会在首次启动时 快速启动服务,并在第一次使用某个 variant 时构建;后续按指纹复用缓存。

默认 CANN tag 同时提供 linux/arm64linux/amd64。启动脚本按宿主机架构选择镜像 manifest,并将 CANN 目录解析为 aarch64-linuxx86_64-linux;远程 Docker daemon 场景可通过 HCCL_CAPTURE_PLATFORM=linux/amd64(或 linux/arm64)覆盖。

启动脚本默认继承宿主机 shell 中的 HTTP_PROXYHTTPS_PROXYALL_PROXYNO_PROXY(同时写入大小写两套变量)。如果代理监听在宿主机的 127.0.0.1localhost::1,脚本会在容器内改写为 host.docker.internal,Linux Docker 也会自动添加 host-gateway 映射。可用 HCCL_CAPTURE_INHERIT_PROXY=0 禁用;镜像拉取仍由宿主机 Docker daemon 完成,因此 Registry 代理需要在 Docker daemon / Docker Desktop 中配置。

重复执行启动脚本不会无条件删除容器。镜像、源码、端口、挂载路径和代理配置的指纹一致且健康检查 通过时会直接复用;配置变化时先保留旧容器,只有新容器通过 /api/health 后才提交替换,失败则自动 回滚。需要明确重建时设置 HCCL_CAPTURE_RECREATE=1out/ bind mount 和 /work Docker volume 独立于容器生命周期,首次 variant 构建中断后再次执行会复用健康服务和已有构建缓存。

bootstrap.sh 是同一流程的一键封装:它创建 Python 虚拟环境、启动容器化服务,并默认预热原版 variant:

git clone --recurse-submodules https://github.com/ubsim-dev/hccl-capture.git
cd hccl-capture
tools/bootstrap.sh

本机访问 http://127.0.0.1:8787/,远程访问 http://<服务器IP>:8787/,默认 API Key 为 1234。 两种启动方式都会把固定的 HCCL submodule 以只读方式挂载, 按 variant 指纹构建完整 host HCCL 与同源 ST;可重复执行。完整的前置条件、镜像替换、HCCL 升级和 故障排查见 从零启动指南

已有兼容容器时,也可以手动安装:

git submodule update --init --recursive
python3 -m venv .venv
.venv/bin/python -m pip install -e .
tools/prepare_st_container.sh hccl-capture-studio

运行

当前示例默认使用 hccl-capture-studio。也可以显式预热某个 variant:

tools/prepare_st_container.sh hccl-capture-studio stock_beta3
tools/prepare_st_container.sh hccl-capture-studio ubx_pipelined_beta3

该脚本创建指纹化源码副本并成对构建 host HCCL 与 ST,不修改 submodule 或镜像内 CANN 安装。

.venv/bin/hccl-capture run \
  examples/alltoall-single-server.json \
  -o out/alltoall-single-server

.venv/bin/hccl-capture run \
  examples/allgather-single-server.json \
  -o out/allgather-single-server

.venv/bin/hccl-capture run \
  examples/allreduce-single-server.json \
  -o out/allreduce-single-server

检查 submodule 和接口兼容性:

python3 tools/check_compatibility.py

运行单元测试:

PYTHONPATH=src python3 -m unittest discover -s tests -v

修改 Web 前端时运行:

cd frontend
npm install
npm run dev       # /api 自动代理到 127.0.0.1:8787
npm test
npm run build     # 更新 Python package 内的生产静态资源

启动可视化服务

启动或重建容器化服务:

tools/start_containerized_studio.sh

浏览器在本机访问 http://127.0.0.1:8787,或从其他机器访问 http://<服务器IP>:8787。首次进入需要 API Key,技术穿刺阶段默认值为 1234。服务会直接加载 out/ 中已有的 Trace Bundle,新捕获保存到 out/web-runs/。也可以使用安装后的 CLI:

hccl-capture serve --host 127.0.0.1 --port 8787 --bundle-root out

容器化启动默认发布到所有 IPv4 网卡。生产或共享环境应通过 HCCL_CAPTURE_API_KEY=<强密钥> 覆盖默认值,并配合服务器防火墙限制来源;仅需本机访问时设置 HCCL_CAPTURE_HOST_BIND=127.0.0.1。页面和 API 的结构、扩展方式见 Capture Studio 设计与接口

不使用页面时,直接运行 .venv/bin/hccl-capture run <spec> -o <output>;不传 -o 时默认保存到 out/<run.name>/。需要异步调度时也可以直接调用 POST /api/runs 并轮询任务状态。完整 CLI、HTTP 示例 和文件保存规则见 无网页捕获接口

如果代码已经位于安装好 CANN 的开发机或容器内,可先运行 tools/prepare_hccl_variant.sh stock_beta3,再使用 native_local backend;此时 CLI 不调用 Docker, variant 仍负责生成隔离的 host HCCL 与同源 ST。

算法配置

auto 使用 HCCL 自动选择:

{"algorithm": {"variant": "stock_beta3", "mode": "auto"}}

CLI/core 仍允许用 configured 设置 HCCL 原生 HCCL_ALGO,用于兼容性诊断和版本回归;值使用 CANN 规定的完整语法:

{"algorithm": {"variant": "stock_beta3", "mode": "configured", "hccl_algo": "alltoall=level0:NA;level1:pairwise"}}

在当前 HCCL v9.1.0-beta.3 + AllToAll/AllGather AICPU 路径中,两套 selector 虽然解析该环境变量, 却都没有消费 configAlgMap。AllToAll 系统遍历 15 组配置、AllGather 实跑 Ring/Pairwise 对照后,实际 algTag、Task DAG 和 P2P 都没有变化。因此 Web 页面禁用这个无效选项;真正替换算法应使用 algorithm.variant 构建并加载新的 HCCL template/selector。CLI 保留该输入,是为了验证未来版本是否 开始消费它,而不是承诺它会改变当前 AllToAll。

是否真正改变执行必须同时看 manifest.json.selection 和 Bundle 对比,不能把 requested_hccl_algo 当成实际算法。原生后端会捕获实际 algTagselection_verified=true 表示实际 选择可观察,不表示请求一定生效。

比较两个运行:

PYTHONPATH=src python3 -m hccl_capture compare \
  out/alltoall-auto out/alltoall-pairwise \
  -o out/compare.json

报告中的 requested_change_observed 只有在实际选路、HCCL 观察到的拓扑、Task DAG 或 P2P 流量 至少一项发生变化时才为 true。这样可以区分“输入拓扑没有传进去”和“拓扑传进去了,但算法回退后 执行图仍相同”。

拓扑观测与重放

原生 runner 通过主程序符号抢占记录 HcclRankGraphGetTopoInstsByLayerHcclRankGraphGetRanksByTopoInstHcclRankGraphGetTopoType 和 endpoint 查询,不修改 HCCL。 当前 beta3 AllToAll 原生 ST 已验证单 Server 和单 SuperPod 内多 Server 两级拓扑:

PYTHONPATH=src python3 -m hccl_capture run \
  examples/alltoall-single-server.json -o out/alltoall-single
PYTHONPATH=src python3 -m hccl_capture run \
  examples/alltoall-2level.json -o out/alltoall-2level

examples/alltoall-3level-pod.json 保留为负向能力探针。beta3 的 TopoMatch1D 会拒绝三层 topoLevelNum,ST 的 endpoint 模型也不支持 layer 2,因此多 SuperPod 输入会在执行前得到明确错误, 不会生成看似成功但不真实的 DAG。自定义非对称拓扑目前支持一个 SuperPod 内不同规模的 Server, 例如 3+5 Rank。

ubx_mesh1d_clos overlay 已支持板内 Mesh endpoint/link、跨板 CLOS endpoint/link、4 个对称 Jetty channel,以及 channel 到 P2P task 的关联:

PYTHONPATH=src python3 -m hccl_capture run \
  examples/alltoall-ubx.json -o out/ubx-16p

v9.1.0-beta.3 使用该版本自己的 TopoMatchUBX/TopoMatchUBX1d 和 CCU/AICPU UBX 模板,Runner 按源码能力识别这条旧版原生路径,并在 manifest.json/ubx_multijetty_provider 中记录 native_beta3_legacy_ubx。若未来切换到新版 HCCL,版本化能力探测会区分新版 CANN 原生实现与外部 兼容实现,不会把两套算法混为同一个 baseline。

优化版 variant 会把 algorithms/ubx_pipelined_beta3/files/ 中可直接阅读的算法源码 安装到独立的指纹化 HCCL checkout,再应用小型 integration.patch。它把后续版本的 UBX 分轮调度作为 真实 HCCL template 回移到 beta3,并让同源 selector 发出独立 tag InsAlltoAllMesh1DUBXPipelined。上游 submodule 保持干净;manifest 保存 variant 指纹、源码 commit、 实际加载路径和 host/ST SHA-256。原版和优化版不会重绑定同一个 tag。

输入边界

原生 AlltoAll 的 workload 只保存 dtypesend_count_per_peer 和诊断用途的可选 HCCL_ALGO。拓扑是独立的 显式层级树 SuperPod[] → Server[] → physical_device_ids[],Rank ID 按树的稳定遍历顺序生成, rank_count、Server 数和每层规模都是派生值。输入结构可以表达任意层级,但当前 beta3 AllToAll 执行能力限制为一个 SuperPod、至多两级;同一 SuperPod 内支持 Server 规模不同的非对称布局。UBX 的 boards/Jetty 作为 rank_graph overlay 保存,不冒充物理 Server。

AllGather 选路与流量语义

AllGather 已通过同一个原生 HcclAllGather 入口验证五条实际选路:单机 Mesh1D、两层小消息 NHR、两层大消息 ParallelMesh1DNHR、UBX 4P ConcurrentMesh1DNHR,以及 UBX 8P ParallelMesh1DNHRMultiJetty。这些选路由拓扑、Rank 数和 payload 阈值自动决定,不由当前版本的 HCCL_ALGO 决定。

p2p_flows.csv 表示真正执行的物理 P2P task,而不是抽象的“源数据贡献矩阵”。在 Mesh1D 中每个 Rank 直接从所有其他 Rank 读取,因此 8P 恰好有 56 条有向 activity,并形成 28 个精确的 SendRecvRead rendezvous。NHR/Parallel 路径包含转发和并行分支,同一份贡献数据可能经过中间 Rank;应使用 predecessor_activity_idsready_wave 和 task slice offset 还原执行依赖,不能把每一行都解释为源数据 所有者到最终接收者的直达流。

当前 beta3 ST 的单 Server stock AllGather 已实跑确认最多稳定到 8 Rank;9–14P 会在通道就绪阶段超时, 15P 以上还会触发 TopoMatch/运行时资源错误。页面和 CLI 在执行前统一门禁这一已知边界。两层 2×4 与 UBX 8P 正常,不受该“单 Server stock”门禁影响。大于 1 GiB 聚合数据才会触发的 Sequence/Z-axis 分支 超出当前 ST 200 MiB CCL 内存模型,暂不宣称已验证。

AllToAll 回归矩阵

下面的命令使用临时 Bundle 遍历 Rank 边界、拓扑、payload、dtype、UBX 源码变体和全部可解析的 HCCL_ALGO,只保留一个聚合 JSON,避免产生大量调试目录:

PYTHONPATH=src python3 tools/run_alltoall_matrix.py \
  --output out/regression/alltoall-matrix.json

可用 --case hccl-algo-pairwise 只跑一个 case,或用 --resume 复用已有结果并补跑新增 case。 当前 beta3/DEV_TYPE_950/ST 基线为 49 个 case:41 个通过、8 个已解释的预期失败、0 个未知失败。 已知边界包括 stock Mesh1D 的 9/11/13/15/17 Rank channel-ready timeout、多 SuperPod 三级拓扑不支持, 以及非法 HCCL_ALGO 语法被拒绝。

对于 AICPU InsAlltoAllMesh1D*,阶段解码器严格复现 HCCL 的 CalcCommRankSetForOneLoop:每个 rank 同时覆盖最多 16 个远端,17 rank 仍是一轮,18 rank 起才是多轮。 多轮之间按复用 queue/lane 流水依赖,不被解释为全局 barrier。dag_level 是真实 DAG 的 ASAP 拓扑深度,algorithm_round 才是算法语义轮次,两者不能混用。

成功执行时,UBX 的实际分支由外部 DFX algTag 捕获,原始 Task DAG 完整导出。阶段解码器复现 GetBoardSendRecvMatrixGetRankSendRecvMatrix:跨板使用 round-robin board pairing,每个 board pair 包含“每板 Rank 数”个 rank step;板内 fullmesh 标注为与 board round 0 重叠。跨 step 依赖只收缩 真实 DAG 中已经存在的路径,不添加推测边。

端口字段分两层:jetty_index/logical_plane 是 task 实际使用的逻辑平面;port_selector 是 endpoint EID 中参与 HCCL 建链筛选的字节。当前 replay 的兼容值为 127,它不是物理 NIC/交换机端口号。 若要得到真实硬件端口,必须录制实机 rank graph endpoint/link 或联合设备 profiling;ST 不能凭空恢复。

这份 trace 是 HCCL ST 模型展开出的逻辑任务与依赖,不是网卡抓包,也没有真实硬件上的排队、拥塞和协议头开销。适合算法仿真、依赖分析和解析流量建模;若目标是拟合实机时延,还需要用真实 profiling 数据校准链路带宽、启动开销和资源竞争参数。详见 设计说明

版本策略

  • 每次提交固定一个 HCCL submodule SHA。
  • 每份 bundle 分别保存 submodule 和实际执行后端的 HCCL commit、dirty 文件、容器镜像及关键 CANN/ST 动态库 SHA-256,禁止把镜像 tag 相同误判为运行时完全一致。
  • 更新 submodule 后先运行兼容性检查和 golden tests。
  • 不允许直接修改 third_party/hccl;CI 应检查其 git status --porcelain 为空。

后续里程碑

  1. 扩展 native workload adapter:AlltoAllV/VC、AllReduce、AllGather、ReduceScatter、Send/Recv。
  2. 批量矩阵运行与 golden baseline/CI 回归。
  3. libhccl_capture.so:LD_PRELOAD 录制真实应用的 endpoint/link/workload,再离线重放。
  4. 把实机 profiling 的物理 port、带宽和拥塞计数器与逻辑 Jetty trace 对齐。

About

Out-of-tree HCCL Task DAG and P2P traffic capture studio

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages