Merged
同步 CheckerL2 最新代码到 hccl_vm #6047
git_qkAdd on 24 days ago
同步 CheckerL2 最新代码到 hccl_vm #6047
Merged
git_qkAdd on 24 days ago
Total: 154 files changed+20883-1365
@@ -31,3 +31,4 @@ oat_reports/
31__pycache__/31__pycache__/
32**/__pycache__/32**/__pycache__/
33*.pyc33*.pyc
34+/graph_dump/
@@ -24,6 +24,8 @@ set(HCCLVM_OPT_LEVEL "-O2" CACHE STRING "Optimization level for host targets (us
24function(hcclvm_apply_common_flags target)24function(hcclvm_apply_common_flags target)
25 target_compile_options(${target} PRIVATE25 target_compile_options(${target} PRIVATE
26 -Werror26 -Werror
27+ # GCC13 -O2 false positive: empty-vector copy -> memmove(null,null,0). Keep after -Werror.
28+ -Wno-error=nonnull
27 -fno-common29 -fno-common
28 -fno-strict-aliasing30 -fno-strict-aliasing
29 -pipe31 -pipe
@@ -4,6 +4,8 @@
4 4 
5HCCL-VM是面向华为昇腾NPU卡的高性能集合通信的虚拟执行环境,该工具旨在无真实昇腾硬件的条件下,实现HCCL集合通信算子的开发和功能验证。5HCCL-VM是面向华为昇腾NPU卡的高性能集合通信的虚拟执行环境,该工具旨在无真实昇腾硬件的条件下,实现HCCL集合通信算子的开发和功能验证。
6 6 
7+工具提供三种运行模式:`normal`(真实多卡通信,结果正确性无损)、`check-only`(仅校验,大块内存复用共享池,大幅压低内存占用)、`estimate`(估算,跳过真实通信阻塞,快速产出任务清单),支持启动时指定与运行期通过 `hccl-vm mode` 命令即时切换,详见[运行模式](#49-运行模式normal--check-only--estimate)。
8+ 
7![hccl-vm GIF](docs/hccl-vm.gif)9![hccl-vm GIF](docs/hccl-vm.gif)
8 10 
9## 2. 前置依赖11## 2. 前置依赖
@@ -36,13 +38,13 @@ hccl_test是昇腾官方提供的HCCL性能测试工具,详见[HCCL性能测
36 38 
37### 2.3 QEMU 部署(仅 AICPU 模式、x86_64 宿主需要)39### 2.3 QEMU 部署(仅 AICPU 模式、x86_64 宿主需要)
38 40 
39-AICPU 展开模式在 x86_64 宿主上需要 QEMU 用户态模拟(linux-user 模拟 aarch64)。系统自带的 qemu-user-static 可直接使用;版本低于 **10.2.4** 时不支持 `-tb-size` 限制翻译代码缓存,QEMU 常驻内存较大,可能严重影响性能,建议安装 **10.2.4 及以上**版本。41+AICPU 展开模式在 x86_64 宿主上需要 QEMU 用户态模拟(linux-user 模拟 aarch64)。系统自带的 qemu-user-static 可直接使用;版本低于 **10.2.4** 时不支持 `-tb-size` 限制翻译代码缓存,QEMU 常驻内存较大,可能严重影响性能,按照如下操作安装 **10.2.4 及以上**版本。
40 42 
41```bash43```bash
42# 1) 构建依赖(gcc/make/ninja 一般已随系统或本工具安装存在)44# 1) 构建依赖(gcc/make/ninja 一般已随系统或本工具安装存在)
43sudo apt-get install -y meson flex bison libglib2.0-dev libpcre2-dev libffi-dev45sudo apt-get install -y meson flex bison libglib2.0-dev libpcre2-dev libffi-dev
44 46 
45-# 2) 官方源码归档(示例为 10.2.4,建议 10.2.4 及以上版本)47+# 2) 官方源码归档(示例为 10.2.4,10.2.4 及以上版本均可)
46curl -fsSL -O https://download.qemu.org/qemu-10.2.4.tar.xz48curl -fsSL -O https://download.qemu.org/qemu-10.2.4.tar.xz
47tar -xf qemu-10.2.4.tar.xz && cd qemu-10.2.449tar -xf qemu-10.2.4.tar.xz && cd qemu-10.2.4
48 50 
@@ -69,6 +71,14 @@ export HCCL_VM_QEMU_TB_SIZE=16
69 71 
70## 3. 快速上手72## 3. 快速上手
71 73 
74+### 一键安装
75+ 
76+拉取完整 CheckerL2 源码后,在仓库根目录执行:
77+ 
78+```bash
79+bash ./hccl_vm_installer
80+```
81+ 
72### 3.1 手动构建&安装82### 3.1 手动构建&安装
73 83 
74```bash84```bash
@@ -101,9 +111,6 @@ bash build_pkg.sh
101 111 
102若/etc路径下已存在hccl_rootinfo.json文件,请手动删除该文件。112若/etc路径下已存在hccl_rootinfo.json文件,请手动删除该文件。
103 113 
104-存储初始化与连接配置请先阅读[存储后端导航](src/storage_backends/README.md),确认是否需要额外配置;
105-然后回到本节按对应执行模式运行算子。
106- 
107#### 3.2.2 CCU模式114#### 3.2.2 CCU模式
108 115 
1091. 环境变量配置。1161. 环境变量配置。
@@ -704,7 +711,7 @@ HCCL-VM Runner插件支持数据类如下:
704 711 
705**硬件规格**:712**硬件规格**:
706 713 
707-目前本工具仅适配支持Ascend950芯片。单server内最大支持8张卡;超过8张卡,需要跨server运行。714+目前本工具仅适配支持Ascend950芯片。单server内最大支持8张卡;超过8张卡,需要跨server运行。默认内置存储适用 1~128 卡的通信域,无需配置数据库。
708 715 
709### 4.6 HCCL-VM插件功能716### 4.6 HCCL-VM插件功能
710 717 
@@ -817,18 +824,80 @@ data_size(Bytes): | aveg_time(us): | alg_bandwidth(GB/s): | check_result:
817```824```
818 825 
819---826---
820-### 4.9 大块内存复用(仅校验模式)827+### 4.9 运行模式(normal / check-only / estimate)
821 828 
822-仅校验模式用于大规模集群仅运行 Checker 校验的场景。开启后,单块 200MB 到 4GB 的大内存申请复用同一块 4GB 共享区 `HcclCommPool`,各 rank 共享、允许互相覆盖,以此大幅降低 `/dev/shm` 占用。此时大块内容不保证正确,仅适用于不读取缓冲区数据的 Checker V3 校验链路,需要数值正确的结果时请勿开启。829+HCCL-VM 有三种运行模式,任意时刻有且仅有一个生效,默认为 `normal`:
823 830 
824-仅校验模式是会话级开关,在 `start` 子命令后追加 `--check-only` 显式开启;不加时为默认的普通模式,大块走真实独立分配,正确性无损。小于 200MB 的申请始终走真实分配,单块大于 4GB 在仅校验模式下直接报错拒绝。仅校验模式与 Runner 不互斥,但在仅校验模式开启时安装 Runner,大块复用仍会生效、可能覆盖 Runner 数据,工具会打印告警。831+| 模式 | 定位 | 说明 |
832+| ---- | ---- | ---- |
833+| `normal` | 普通模式(默认) | 真实独立分配与完整多 rank 通信,结果正确性无损 |
834+| `check-only` | 仅校验模式 | 大块内存复用 4GB 共享池,大幅压低内存占用;只保证 Checker 校验链路,缓冲区数据内容不保证正确 |
835+| `estimate` | 估算模式 | 单卡(rank0)构造幻影对端跳过真实通信阻塞点,快速产出任务清单,不真跑数据传输(需先关闭链路心跳与一致性校验,见 [4.9.4](#494-估算模式限制说明)) |
836+ 
837+#### 4.9.1 启动时指定模式
838+ 
839+`start` 与 `run`(one-shot)子命令均支持 `--check-only` / `--estimate` 标志(二者互斥),不加任何标志即为 `normal`:
825 840 
826```bash841```bash
827- 842+# 以仅校验模式启动
828-# 启动工具时开启仅校验模式
829./hccl-vm start ascend950_cluster_32_server_normal.yaml --check-only843./hccl-vm start ascend950_cluster_32_server_normal.yaml --check-only
844+ 
845+# 以估算模式启动
846+./hccl-vm start ascend950_cluster_32_server_normal.yaml --estimate
830```847```
831 848 
849+#### 4.9.2 运行时查询与切换模式
850+ 
851+在已启动的 VM 命令行内,可通过 `hccl-vm mode` 即时查询与切换模式,无需重启 VM:
852+ 
853+```bash
854+# 查询:列出全部支持模式与当前模式(不带参数等价于 show,无副作用)
855+(hvm)$> hccl-vm mode show
856+Supported modes:
857+ check-only : 仅校验模式,大块内存复用 4GB 共享池 HcclCommPool,大幅降低 /dev/shm 占用;只保证校验链路,缓冲区数据内容不保证正确
858+ estimate : 估算模式,单卡(rank0)构造幻影对端跳过真实通信阻塞点,快速产出任务清单,不真跑数据传输
859+ normal : 普通模式(默认),真实独立分配与完整多 rank 通信,结果正确性无损
860+Current mode: normal
861+ 
862+# 切换模式
863+(hvm)$> hccl-vm mode check-only
864+(chk-only)$> hccl-vm mode estimate
865+(estimate)$> hccl-vm mode normal
866+```
867+ 
868+切换成功后,终端提示符随模式变化:normal → `(hvm)$>`、check-only → `(chk-only)$>`、estimate → `(estimate)$>`。
869+ 
870+**切换行为与约束**:
871+ 
872+- **拼写严格**:模式名须严格使用小写连字符拼写,`CHECK-ONLY`、`check_only` 等变体及非法串均被拒绝,当前模式不受影响。
873+- **幂等**:切换到当前已处的模式为空操作,提示已处于该模式。
874+- **复用池随模式建/拆**:切入 check-only 时自动创建 4GB 共享复用池(创建前先清理残留),切走时自动释放;normal / estimate 模式下不存在该池。
875+- **切换前卸载 runner**:切向非 normal 模式前,若 runner 插件驻留则先卸载;卸载失败则中止切换。切向 normal 不触发卸载。
876+- **切换原子性**:切换过程中任一步骤失败(建池失败、拆池失败等)即报错中止,模式与资源保持切换前原状。已知局限:切换失败时提示符仍可能变更,此时以 `hccl-vm mode show` 的查询结果为准。
877+- **对新算例生效**:新模式对切换成功后新启动的业务算例生效;切换前已在运行的算例不受影响,仍按其启动时的模式运行。
878+- **不跨重启保留**:模式不跨 VM 重启保留,重启后回到由启动参数决定的初始模式(未指定即 normal)。
879+ 
880+#### 4.9.3 仅校验模式大块内存复用说明
881+ 
882+check-only 模式用于大规模集群仅运行 Checker 校验的场景。开启后,单块 200MB 到 4GB 的大内存申请复用同一块 4GB 共享区 `HcclCommPool`,各 rank 共享、允许互相覆盖,以此大幅降低 `/dev/shm` 占用。此时大块内容不保证正确,仅适用于不读取缓冲区数据的 Checker V3 校验链路,需要数值正确的结果时请勿开启。
883+ 
884+小于 200MB 的申请始终走真实分配;单块大于 4GB 在 check-only 模式下直接报错拒绝。check-only 模式与 Runner 不互斥,但在 check-only 模式开启时安装 Runner,大块复用仍会生效、可能覆盖 Runner 数据,工具会打印告警。
885+ 
886+#### 4.9.4 估算模式限制说明
887+ 
888+estimate 模式单卡执行、对端为构造出的幻影对端,链路上没有真实对端参与,链路心跳与一致性校验无法正常完成,会带来误报或异常退出。因此**使用 estimate 模式前必须先关闭链路心跳与一致性校验**:
889+ 
890+```bash
891+export HCCL_DFS_CONFIG=cluster_heartbeat:off,inconsistent_check:off
892+```
893+ 
894+该环境变量需在业务算例启动前生效,`start` 与 `run`(one-shot)两种方式均适用;基于 README 中的 `start.sh` 示例修改时,注意其默认只关闭了心跳(`cluster_heartbeat:off`),用于 estimate 模式时需按上式补上 `inconsistent_check:off`。
895+ 
896+其余限制:
897+ 
898+- 仅构造单卡(rank0)执行路径,跳过真实通信阻塞点,用于快速产出任务清单,不真跑数据传输。
899+- 需要功能正确性校验或真实通信行为时,请改用 `normal` 模式。
900+ 
832***901***
833 902 
834## 5 附录903## 5 附录
@@ -4,6 +4,8 @@
4 4 
5HCCL-VM是面向华为昇腾NPU卡的高性能集合通信的虚拟执行环境,该工具旨在无真实昇腾硬件的条件下,实现HCCL集合通信算子的开发和功能验证。5HCCL-VM是面向华为昇腾NPU卡的高性能集合通信的虚拟执行环境,该工具旨在无真实昇腾硬件的条件下,实现HCCL集合通信算子的开发和功能验证。
6 6 
7+工具提供三种运行模式:`normal`(真实多卡通信,结果正确性无损)、`check-only`(仅校验,大块内存复用共享池,大幅压低内存占用)、`estimate`(估算,跳过真实通信阻塞,快速产出任务清单),支持启动时指定与运行期通过 `hccl-vm mode` 命令即时切换,详见[运行模式](#49-运行模式normal--check-only--estimate)。
8+ 
7![hccl-vm GIF](docs/hccl-vm.gif)9![hccl-vm GIF](docs/hccl-vm.gif)
8 10 
9## 2. 前置依赖11## 2. 前置依赖
@@ -36,13 +38,13 @@ hccl_test是昇腾官方提供的HCCL性能测试工具,详见[HCCL性能测
36 38 
37### 2.3 QEMU 部署(仅 AICPU 模式、x86_64 宿主需要)39### 2.3 QEMU 部署(仅 AICPU 模式、x86_64 宿主需要)
38 40 
39-AICPU 展开模式在 x86_64 宿主上需要 QEMU 用户态模拟(linux-user 模拟 aarch64)。系统自带的 qemu-user-static 可直接使用;版本低于 **10.2.4** 时不支持 `-tb-size` 限制翻译代码缓存,QEMU 常驻内存较大,可能严重影响性能,建议安装 **10.2.4 及以上**版本。41+AICPU 展开模式在 x86_64 宿主上需要 QEMU 用户态模拟(linux-user 模拟 aarch64)。系统自带的 qemu-user-static 可直接使用;版本低于 **10.2.4** 时不支持 `-tb-size` 限制翻译代码缓存,QEMU 常驻内存较大,可能严重影响性能,按照如下操作安装 **10.2.4 及以上**版本。
40 42 
41```bash43```bash
42# 1) 构建依赖(gcc/make/ninja 一般已随系统或本工具安装存在)44# 1) 构建依赖(gcc/make/ninja 一般已随系统或本工具安装存在)
43sudo apt-get install -y meson flex bison libglib2.0-dev libpcre2-dev libffi-dev45sudo apt-get install -y meson flex bison libglib2.0-dev libpcre2-dev libffi-dev
44 46 
45-# 2) 官方源码归档(示例为 10.2.4,建议 10.2.4 及以上版本)47+# 2) 官方源码归档(示例为 10.2.4,10.2.4 及以上版本均可)
46curl -fsSL -O https://download.qemu.org/qemu-10.2.4.tar.xz48curl -fsSL -O https://download.qemu.org/qemu-10.2.4.tar.xz
47tar -xf qemu-10.2.4.tar.xz && cd qemu-10.2.449tar -xf qemu-10.2.4.tar.xz && cd qemu-10.2.4
48 50 
@@ -69,6 +71,14 @@ export HCCL_VM_QEMU_TB_SIZE=16
69 71 
70## 3. 快速上手72## 3. 快速上手
71 73 
74+### 一键安装
75+ 
76+拉取完整 CheckerL2 源码后,在仓库根目录执行:
77+ 
78+```bash
79+bash ./hccl_vm_installer
80+```
81+ 
72### 3.1 手动构建&安装82### 3.1 手动构建&安装
73 83 
74```bash84```bash
@@ -101,9 +111,6 @@ bash build_pkg.sh
101 111 
102若/etc路径下已存在hccl_rootinfo.json文件,请手动删除该文件。112若/etc路径下已存在hccl_rootinfo.json文件,请手动删除该文件。
103 113 
104-存储初始化与连接配置请先阅读[存储后端导航](src/storage_backends/README.md),确认是否需要额外配置;
105-然后回到本节按对应执行模式运行算子。
106- 
107#### 3.2.2 CCU模式114#### 3.2.2 CCU模式
108 115 
1091. 环境变量配置。1161. 环境变量配置。
@@ -704,7 +711,7 @@ HCCL-VM Runner插件支持数据类如下:
704 711 
705**硬件规格**:712**硬件规格**:
706 713 
707-目前本工具仅适配支持Ascend950芯片。单server内最大支持8张卡;超过8张卡,需要跨server运行。714+目前本工具仅适配支持Ascend950芯片。单server内最大支持8张卡;超过8张卡,需要跨server运行。默认内置存储适用 1~128 卡的通信域,无需配置数据库。
708 715 
709### 4.6 HCCL-VM插件功能716### 4.6 HCCL-VM插件功能
710 717 
@@ -817,18 +824,80 @@ data_size(Bytes): | aveg_time(us): | alg_bandwidth(GB/s): | check_result:
817```824```
818 825 
819---826---
820-### 4.9 大块内存复用(仅校验模式)827+### 4.9 运行模式(normal / check-only / estimate)
821 828 
822-仅校验模式用于大规模集群仅运行 Checker 校验的场景。开启后,单块 200MB 到 4GB 的大内存申请复用同一块 4GB 共享区 `HcclCommPool`,各 rank 共享、允许互相覆盖,以此大幅降低 `/dev/shm` 占用。此时大块内容不保证正确,仅适用于不读取缓冲区数据的 Checker V3 校验链路,需要数值正确的结果时请勿开启。829+HCCL-VM 有三种运行模式,任意时刻有且仅有一个生效,默认为 `normal`:
823 830 
824-仅校验模式是会话级开关,在 `start` 子命令后追加 `--check-only` 显式开启;不加时为默认的普通模式,大块走真实独立分配,正确性无损。小于 200MB 的申请始终走真实分配,单块大于 4GB 在仅校验模式下直接报错拒绝。仅校验模式与 Runner 不互斥,但在仅校验模式开启时安装 Runner,大块复用仍会生效、可能覆盖 Runner 数据,工具会打印告警。831+| 模式 | 定位 | 说明 |
832+| ---- | ---- | ---- |
833+| `normal` | 普通模式(默认) | 真实独立分配与完整多 rank 通信,结果正确性无损 |
834+| `check-only` | 仅校验模式 | 大块内存复用 4GB 共享池,大幅压低内存占用;只保证 Checker 校验链路,缓冲区数据内容不保证正确 |
835+| `estimate` | 估算模式 | 单卡(rank0)构造幻影对端跳过真实通信阻塞点,快速产出任务清单,不真跑数据传输(需先关闭链路心跳与一致性校验,见 [4.9.4](#494-估算模式限制说明)) |
836+ 
837+#### 4.9.1 启动时指定模式
838+ 
839+`start` 与 `run`(one-shot)子命令均支持 `--check-only` / `--estimate` 标志(二者互斥),不加任何标志即为 `normal`:
825 840 
826```bash841```bash
827- 842+# 以仅校验模式启动
828-# 启动工具时开启仅校验模式
829./hccl-vm start ascend950_cluster_32_server_normal.yaml --check-only843./hccl-vm start ascend950_cluster_32_server_normal.yaml --check-only
844+ 
845+# 以估算模式启动
846+./hccl-vm start ascend950_cluster_32_server_normal.yaml --estimate
830```847```
831 848 
849+#### 4.9.2 运行时查询与切换模式
850+ 
851+在已启动的 VM 命令行内,可通过 `hccl-vm mode` 即时查询与切换模式,无需重启 VM:
852+ 
853+```bash
854+# 查询:列出全部支持模式与当前模式(不带参数等价于 show,无副作用)
855+(hvm)$> hccl-vm mode show
856+Supported modes:
857+ check-only : 仅校验模式,大块内存复用 4GB 共享池 HcclCommPool,大幅降低 /dev/shm 占用;只保证校验链路,缓冲区数据内容不保证正确
858+ estimate : 估算模式,单卡(rank0)构造幻影对端跳过真实通信阻塞点,快速产出任务清单,不真跑数据传输
859+ normal : 普通模式(默认),真实独立分配与完整多 rank 通信,结果正确性无损
860+Current mode: normal
861+ 
862+# 切换模式
863+(hvm)$> hccl-vm mode check-only
864+(chk-only)$> hccl-vm mode estimate
865+(estimate)$> hccl-vm mode normal
866+```
867+ 
868+切换成功后,终端提示符随模式变化:normal → `(hvm)$>`、check-only → `(chk-only)$>`、estimate → `(estimate)$>`。
869+ 
870+**切换行为与约束**:
871+ 
872+- **拼写严格**:模式名须严格使用小写连字符拼写,`CHECK-ONLY`、`check_only` 等变体及非法串均被拒绝,当前模式不受影响。
873+- **幂等**:切换到当前已处的模式为空操作,提示已处于该模式。
874+- **复用池随模式建/拆**:切入 check-only 时自动创建 4GB 共享复用池(创建前先清理残留),切走时自动释放;normal / estimate 模式下不存在该池。
875+- **切换前卸载 runner**:切向非 normal 模式前,若 runner 插件驻留则先卸载;卸载失败则中止切换。切向 normal 不触发卸载。
876+- **切换原子性**:切换过程中任一步骤失败(建池失败、拆池失败等)即报错中止,模式与资源保持切换前原状。已知局限:切换失败时提示符仍可能变更,此时以 `hccl-vm mode show` 的查询结果为准。
877+- **对新算例生效**:新模式对切换成功后新启动的业务算例生效;切换前已在运行的算例不受影响,仍按其启动时的模式运行。
878+- **不跨重启保留**:模式不跨 VM 重启保留,重启后回到由启动参数决定的初始模式(未指定即 normal)。
879+ 
880+#### 4.9.3 仅校验模式大块内存复用说明
881+ 
882+check-only 模式用于大规模集群仅运行 Checker 校验的场景。开启后,单块 200MB 到 4GB 的大内存申请复用同一块 4GB 共享区 `HcclCommPool`,各 rank 共享、允许互相覆盖,以此大幅降低 `/dev/shm` 占用。此时大块内容不保证正确,仅适用于不读取缓冲区数据的 Checker V3 校验链路,需要数值正确的结果时请勿开启。
883+ 
884+小于 200MB 的申请始终走真实分配;单块大于 4GB 在 check-only 模式下直接报错拒绝。check-only 模式与 Runner 不互斥,但在 check-only 模式开启时安装 Runner,大块复用仍会生效、可能覆盖 Runner 数据,工具会打印告警。
885+ 
886+#### 4.9.4 估算模式限制说明
887+ 
888+estimate 模式单卡执行、对端为构造出的幻影对端,链路上没有真实对端参与,链路心跳与一致性校验无法正常完成,会带来误报或异常退出。因此**使用 estimate 模式前必须先关闭链路心跳与一致性校验**:
889+ 
890+```bash
891+export HCCL_DFS_CONFIG=cluster_heartbeat:off,inconsistent_check:off
892+```
893+ 
894+该环境变量需在业务算例启动前生效,`start` 与 `run`(one-shot)两种方式均适用;基于 README 中的 `start.sh` 示例修改时,注意其默认只关闭了心跳(`cluster_heartbeat:off`),用于 estimate 模式时需按上式补上 `inconsistent_check:off`。
895+ 
896+其余限制:
897+ 
898+- 仅构造单卡(rank0)执行路径,跳过真实通信阻塞点,用于快速产出任务清单,不真跑数据传输。
899+- 需要功能正确性校验或真实通信行为时,请改用 `normal` 模式。
900+ 
832***901***
833 902 
834## 5 附录903## 5 附录
@@ -0,0 +1,168 @@
1+# HCOMM CCU 数据面 SO 拆分架构图
2+ 
3+HCOMM 将 CCU(Collective Communication Unit)能力拆分为**控制面**(本仓 hcomm,产出 `libhcomm.so`)与**数据面**(asc-comm 仓,产出 `libasccomm_ccu_dataplane.so`)两个独立 SO,通过 POD ABI 契约层交互,可独立编译、独立版本演进。
4+ 
5+## 架构图(Mermaid 渲染版)
6+ 
7+```mermaid
8+flowchart TD
9+ subgraph CALLER["调用方"]
10+ FW["AI 框架"] --> HCCL["libhccl.so(cann/hccl 仓)"]
11+ OP["CCU 自定义通信算子"]
12+ end
13+ 
14+ subgraph CTRL["libhcomm.so · 控制面(hcomm 仓)"]
15+ C1["通信域 / CCU 实例 / 资源池"]
16+ C2["建链握手 Channel / Jetty"]
17+ C3["指令下发(TLV → 驱动)"]
18+ end
19+ 
20+ subgraph DP["libasccomm_ccu_dataplane.so · 数据面(asc-comm 仓)"]
21+ D1["Kernel 注册 · 录制 REP"]
22+ D2["REP 翻译微码 + 调度优化"]
23+ D3["Launch(rtCCULaunch)"]
24+ end
25+ 
26+ DRV["驱动 / 运行时<br/>TLV 指令槽 · urma(Jetty) · stream"]
27+ HW["CCU 硬件单元(IO Die)<br/>Mission × 微码 · URMA 搬数 · XN/GSA/CKE 同步"]
28+ 
29+ HCCL -->|"(1) 控制面 C API"| CTRL
30+ OP -->|"(2) 数据面 DSL(弱符号)"| DP
31+ CTRL -.->|"(3) RegisterContext 只读快照"| DP
32+ DP -.->|"(4) controlOps 回调 / 4 个 C API"| CTRL
33+ DP -->|"(5) rtCCULaunch 提交任务"| DRV
34+ CTRL -->|"(6) TLV 驱动交互"| DRV
35+ DRV --> HW
36+ 
37+ classDef caller fill:#F3E5F5,stroke:#7B1FA2
38+ classDef ctrl fill:#E3F2FD,stroke:#1565C0
39+ classDef dp fill:#E8F5E9,stroke:#2E7D32
40+ classDef infra fill:#FFF3E0,stroke:#E65100
41+ class FW,HCCL,OP caller
42+ class C1,C2,C3 ctrl
43+ class D1,D2,D3 dp
44+ class DRV,HW infra
45+```
46+ 
47+## 简版架构图(文本版,适配终端/纯文本场景)
48+ 
49+```text
50+ AI 框架 ──► libhccl.so〔dlsym 加载 hcomm〕 CCU 自定义通信算子
51+ 
52+ 控制面 C API 数据面 DSL(弱符号)
53+ │ │
54+ ▼ ▼
55+ 
56+╭─────────────────────────────────╮ ╭───────────────────────────────────╮
57+│ │ │ │
58+│ libhcomm.so · 控制面 │ │ libasccomm_ccu_dataplane.so │
59+│ 〔 hcomm 仓〕 │ │ 〔 asc-comm 仓 〕· 数据面 │
60+│ │ ◄═══ POD ABI ═══► │ │
61+│· 通信域 / CCU 实例 / 资源池 │ RegisterContext 快照 │· Kernel 注册 · 录制 REP │
62+│· 建链握手 Channel / Jetty │ + controlOps 回调 │· REP 翻译微码 + 调度优化 │
63+│· 指令下发 TLV → 驱动 │ │· Launch(rtCCULaunch) │
64+│ │ │ │
65+╰─────────────────────────────────╯ ╰───────────────────────────────────╯
66+ 
67+ │ │
68+ (6) TLV (5) rtCCULaunch
69+ ▼ ▼
70+ 
71+╭─────────────────────────────────────────────────────────────────────────────────────────────╮
72+│ 驱 动 / 运 行 时 层:TLV 指令槽 · urma(Jetty) · stream │
73+╰─────────────────────────────────────────────────────────────────────────────────────────────╯
74+ ▼
75+ 
76+╭─────────────────────────────────────────────────────────────────────────────────────────────╮
77+│ CCU 硬件单元(IO Die):Mission × 微码 · URMA 搬数 · XN/GSA/CKE 同步 │
78+╰─────────────────────────────────────────────────────────────────────────────────────────────╯
79+```
80+ 
81+一句话流程:算子经数据面 DSL 注册 Kernel(录制 REP → 翻译微码)→ 控制面经 POD ABI 交付资源快照并提供回调(建链、指令下发)→ 数据面 `rtCCULaunch` 提交任务 → CCU 硬件执行微码搬数。
82+ 
83+## 完整架构图
84+ 
85+```text
86+┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
87+│ 调用方: AI框架 ──► libhccl.so〔cann/hccl仓, dlsym加载hcomm〕 // CCU自定义通信算子开发者 │
88+│ (custom_ccu_allreduce/allgather/broadcast... 样例链接数据面SO) │
89+└────────────────────┬────────────────────────────────────────────────────────────────────┬──────────────────────────┘
90+ (1) 建通信域·绑CCU实例·资源预约 (2) Kernel注册·下发(数据面DSL)
91+ │ │
92+ ▼ ▼
93+┌──────────────────────────────────────┐ ╔══════════════════════════╗ ┌────────────────────────────────────────┐
94+│libhcomm.so 〔hcomm 仓〕 │ ║跨 SO ABI 契约层 ║ │libasccomm_ccu_dataplane.so │
95+│━━━━━ CCU 控制面 ━━━━━ │ ║(pkg_inc/hcomm/*.h) ║ │〔asc-comm 仓〕━ CCU 数据面 ━ │
96+│coll_communicator_mgr 通信域/拓扑 │ ║ ║ │primitives/ CcuXxx 原语实现 │
97+│ HcclCommAssignCcuIns │──► ║──► 控制面交付数据面: ║──► │ HcommCcuKernelRegisterStart/ │
98+│ HcclCommQueryCcuRegisterContext │ ║ RegisterContextPod ║ │ Register/End (弱符号入口) │
99+│ccu_instance/ 实例与资源预约 │ ║ (CCU2只读快照+代际句柄) ║ │resource/kernel/ Kernel录制 │
100+│ CcuInstanceMgr / CcuInstance │ ║ LaunchContext/Channel/ ║ │ CcuKernel·Mgr·Registry │
101+│ CcuResDescMgr 资源描述符 │ ║ InstructionLoad POD ║ │resource/representation/ REP IR │
102+│ CcuVarEventResMgr XN/CKE预约 │ ║ ║ │ ~45种节点(算术/搬运/同步/ │
103+│ccu_transport/ 建链握手 │◄── ║◄── 数据面回调控制面: ║◄── │ 控制流/循环) │
104+│ CcuTransport/Conn/Jetty │ ║ controlOps 函数表7项 ║ │ + InsGenerator V1(A5)/V2(A6) │
105+│ccu_device/ 设备资源·驱动交互 │ ║ channelQuery/loadInstr ║ │resource/microcode(+microcode_opt) │
106+│ CcuComponent·CcuResBatchAlloc │ ║ missionCtx/loopCtx/cke/ ║ │ 32B定长微码·指令调度优化 │
107+│ CcuChannelCtxMgr V1/V2·PFE │ ║ xn/gsa Query ║ │resource/common/ 资源快照 │
108+│ RegisterContextRegistry │ ║ + hcomm侧4个C API ║ │launch: GeneTaskParams │
109+│ (代际句柄防悬挂) │ ║ ║ │ (dieId/missionId/args[13]) │
110+│对上层: include/hccl·hcomm │ ║契约: 只传POD不传C++对象 ║ │ ──► rtCCULaunch(stream) │
111+│ HcclComm*/HcommCcuIns* C API │ ║ 16B ABI头(magic/ver/ ║ │(链接 acl_rt / runtime) │
112+│ │ ║ size) + static_assert ║ │ │
113+└──────────────────────────────────────┘ ╚══════════════════════════╝ └────────────────────────────────────────┘
114+ │ │
115+ ▼ ▼
116+ (6) TLV驱动交互(指令/通道) (5) rtCCULaunch提交Mission任务
117+┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
118+│ 驱动/运行时层: runtime(rtCCULaunch) · ascend_hal(HccpRaTlvCcuCustomChannel TLV: │
119+│ SET/GET_INSTRUCTION·CHANNEL·JETTY_CTX·MISSION_CTX·LOOP_CTX·GSA/XN/CKE) · urma(Jetty) · Socket(握手) │
120+└──────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┘
121+ ▼
122+┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
123+│ 硬件: Ascend IO Die 内 CCU 集合通信单元 —— Mission(硬件线程)×微码指令槽 · XN/GSA/CKE/MS 资源 │
124+│ URMA 统一远端内存访问引擎搬运数据 (950PR/950DT, 高带宽低时延) │
125+└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
126+```
127+ 
128+## 运行时主流程
129+ 
130+1. **建域与资源预约**:框架/HCCL → 控制面,建通信域,`HcclCommAssignCcuIns` / `HcommCcuInsCreate` 创建 CCU 实例,Variable(XN)/Event(CKE) 资源预约与 VA 映射。
131+2. **Kernel 注册录制**:算子 → 数据面,`HcommCcuKernelRegisterStart/Register/End`(弱符号,落在数据面 SO),执行用户 kernelFunc,`CcuXxx` 原语录制 REP 中间表示。
132+3. **交付快照**:控制面 → 数据面,`HcclCommQueryCcuRegisterContext` 交付 RegisterContext 只读快照(资源 range 视图 + die 元数据 + controlOps 函数表)。
133+4. **回调控制面**:数据面 → 控制面,经 controlOps 表 / 4 个 C API(`include/hcomm/hcomm_ccu_{res,channel,instruction,launch}_api.h`)查询 Channel POD、下发微码;翻译产物由控制面走 TLV 驱动接口写入硬件指令槽。
134+5. **任务提交**:数据面组 `CcuTaskParam(dieId/missionId/instStartId/args[13])` → `rtCCULaunch` 提交流。
135+6. **硬件执行**:CCU Mission 执行微码,URMA 引擎搬运数据,XN/GSA/CKE 完成同步。
136+ 
137+## 构建期边界保障
138+ 
139+| 机制 | 说明 |
140+|------|------|
141+| 双 SO 联合编译 | 本仓按候选路径查找 / FetchContent 拉取 asc-comm(`cmake/third_party/asccomm-ccu.cmake`),数据面 SO 随 hcomm 包交付;找不到则只构建控制面 |
142+| 源归属校验(双向) | `hcomm_check_source_ownership(hcomm/hccl_v2)` + asc-comm 侧对称校验,禁止跨仓引用源文件 |
143+| 链接期校验(双向) | 双方均 `-Wl,--no-undefined`,不允许无意识依赖对方符号 |
144+| 单源双头 | 资源仓库类型 `pub_inc/ccu_res_repo.h` ⇔ `internal/hcomm/resource/common/ccu_res_repository_local.h` 宏互斥定义 |
145+| POD 契约 | 跨 SO 只传 POD(16B ABI 头 magic/version/size + `static_assert` 锁布局),不传 C++ 对象 |
146+ 
147+> 注:当前 dev_rename 分支为过渡态,libhcomm 内仍保留一套进程内旧实现(`src/base_comm/resources/ccu/{ccu_kernel,ccu_representation,ccu_microcode}` + `primitives/api_c_adpt/ccu`)作兼容,图中为目标拆分形态。
148+ 
149+## 关键路径速查
150+ 
151+```
152+hcomm 仓(控制面)
153+├── include/ccu/ # DSL 头(Variable/Event/Buffer/Loop + ccu_res.h/ccu_launch.h 弱符号)
154+├── include/hcomm/hcomm_ccu_*_api.h # 数据面调用的 4 个 C API
155+├── pkg_inc/hcomm/hcomm_ccu_*.h # 跨 SO POD ABI(abi/common/res/control/channel/instruction/launch/dfx)
156+├── src/base_comm/resources/ccu/
157+│ ├── ccu_instance/ # CcuInstanceMgr/CcuInstance/CcuResDescMgr/CcuVarEventResMgr
158+│ ├── ccu_transport/ # CcuTransport/CcuConnection/CcuJetty 建链握手
159+│ └── ccu_device/ # CcuComponent/资源分配器/ChannelCtxMgr V1,V2/RegisterContextRegistry
160+└── cmake/third_party/asccomm-ccu.cmake # 数据面 SO 联合编译与交付
161+ 
162+asc-comm 仓(数据面)
163+├── src/ccu/hcomm/primitives/ # CcuXxx 原语实现 + Kernel 注册/Launch
164+├── src/ccu/hcomm/resource/kernel/ # CcuKernel/CcuKernelMgr/CcuKernelRegistry
165+├── src/ccu/hcomm/resource/representation/ # REP IR + InsGenerator V1(A5)/V2(A6) 翻译器
166+├── src/ccu/hcomm/resource/microcode(+_opt)/ # 32B 定长微码 + 指令调度优化
167+└── include/ccu/hcomm/ # 数据面公共 DSL 头(安装供 CCU 算子开发者使用)
168+```
@@ -0,0 +1,168 @@
1+# HCOMM CCU 数据面 SO 拆分架构图
2+ 
3+HCOMM 将 CCU(Collective Communication Unit)能力拆分为**控制面**(本仓 hcomm,产出 `libhcomm.so`)与**数据面**(asc-comm 仓,产出 `libasccomm_ccu_dataplane.so`)两个独立 SO,通过 POD ABI 契约层交互,可独立编译、独立版本演进。
4+ 
5+## 架构图(Mermaid 渲染版)
6+ 
7+```mermaid
8+flowchart TD
9+ subgraph CALLER["调用方"]
10+ FW["AI 框架"] --> HCCL["libhccl.so(cann/hccl 仓)"]
11+ OP["CCU 自定义通信算子"]
12+ end
13+ 
14+ subgraph CTRL["libhcomm.so · 控制面(hcomm 仓)"]
15+ C1["通信域 / CCU 实例 / 资源池"]
16+ C2["建链握手 Channel / Jetty"]
17+ C3["指令下发(TLV → 驱动)"]
18+ end
19+ 
20+ subgraph DP["libasccomm_ccu_dataplane.so · 数据面(asc-comm 仓)"]
21+ D1["Kernel 注册 · 录制 REP"]
22+ D2["REP 翻译微码 + 调度优化"]
23+ D3["Launch(rtCCULaunch)"]
24+ end
25+ 
26+ DRV["驱动 / 运行时<br/>TLV 指令槽 · urma(Jetty) · stream"]
27+ HW["CCU 硬件单元(IO Die)<br/>Mission × 微码 · URMA 搬数 · XN/GSA/CKE 同步"]
28+ 
29+ HCCL -->|"(1) 控制面 C API"| CTRL
30+ OP -->|"(2) 数据面 DSL(弱符号)"| DP
31+ CTRL -.->|"(3) RegisterContext 只读快照"| DP
32+ DP -.->|"(4) controlOps 回调 / 4 个 C API"| CTRL
33+ DP -->|"(5) rtCCULaunch 提交任务"| DRV
34+ CTRL -->|"(6) TLV 驱动交互"| DRV
35+ DRV --> HW
36+ 
37+ classDef caller fill:#F3E5F5,stroke:#7B1FA2
38+ classDef ctrl fill:#E3F2FD,stroke:#1565C0
39+ classDef dp fill:#E8F5E9,stroke:#2E7D32
40+ classDef infra fill:#FFF3E0,stroke:#E65100
41+ class FW,HCCL,OP caller
42+ class C1,C2,C3 ctrl
43+ class D1,D2,D3 dp
44+ class DRV,HW infra
45+```
46+ 
47+## 简版架构图(文本版,适配终端/纯文本场景)
48+ 
49+```text
50+ AI 框架 ──► libhccl.so〔dlsym 加载 hcomm〕 CCU 自定义通信算子
51+ 
52+ 控制面 C API 数据面 DSL(弱符号)
53+ │ │
54+ ▼ ▼
55+ 
56+╭─────────────────────────────────╮ ╭───────────────────────────────────╮
57+│ │ │ │
58+│ libhcomm.so · 控制面 │ │ libasccomm_ccu_dataplane.so │
59+│ 〔 hcomm 仓〕 │ │ 〔 asc-comm 仓 〕· 数据面 │
60+│ │ ◄═══ POD ABI ═══► │ │
61+│· 通信域 / CCU 实例 / 资源池 │ RegisterContext 快照 │· Kernel 注册 · 录制 REP │
62+│· 建链握手 Channel / Jetty │ + controlOps 回调 │· REP 翻译微码 + 调度优化 │
63+│· 指令下发 TLV → 驱动 │ │· Launch(rtCCULaunch) │
64+│ │ │ │
65+╰─────────────────────────────────╯ ╰───────────────────────────────────╯
66+ 
67+ │ │
68+ (6) TLV (5) rtCCULaunch
69+ ▼ ▼
70+ 
71+╭─────────────────────────────────────────────────────────────────────────────────────────────╮
72+│ 驱 动 / 运 行 时 层:TLV 指令槽 · urma(Jetty) · stream │
73+╰─────────────────────────────────────────────────────────────────────────────────────────────╯
74+ ▼
75+ 
76+╭─────────────────────────────────────────────────────────────────────────────────────────────╮
77+│ CCU 硬件单元(IO Die):Mission × 微码 · URMA 搬数 · XN/GSA/CKE 同步 │
78+╰─────────────────────────────────────────────────────────────────────────────────────────────╯
79+```
80+ 
81+一句话流程:算子经数据面 DSL 注册 Kernel(录制 REP → 翻译微码)→ 控制面经 POD ABI 交付资源快照并提供回调(建链、指令下发)→ 数据面 `rtCCULaunch` 提交任务 → CCU 硬件执行微码搬数。
82+ 
83+## 完整架构图
84+ 
85+```text
86+┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
87+│ 调用方: AI框架 ──► libhccl.so〔cann/hccl仓, dlsym加载hcomm〕 // CCU自定义通信算子开发者 │
88+│ (custom_ccu_allreduce/allgather/broadcast... 样例链接数据面SO) │
89+└────────────────────┬────────────────────────────────────────────────────────────────────┬──────────────────────────┘
90+ (1) 建通信域·绑CCU实例·资源预约 (2) Kernel注册·下发(数据面DSL)
91+ │ │
92+ ▼ ▼
93+┌──────────────────────────────────────┐ ╔══════════════════════════╗ ┌────────────────────────────────────────┐
94+│libhcomm.so 〔hcomm 仓〕 │ ║跨 SO ABI 契约层 ║ │libasccomm_ccu_dataplane.so │
95+│━━━━━ CCU 控制面 ━━━━━ │ ║(pkg_inc/hcomm/*.h) ║ │〔asc-comm 仓〕━ CCU 数据面 ━ │
96+│coll_communicator_mgr 通信域/拓扑 │ ║ ║ │primitives/ CcuXxx 原语实现 │
97+│ HcclCommAssignCcuIns │──► ║──► 控制面交付数据面: ║──► │ HcommCcuKernelRegisterStart/ │
98+│ HcclCommQueryCcuRegisterContext │ ║ RegisterContextPod ║ │ Register/End (弱符号入口) │
99+│ccu_instance/ 实例与资源预约 │ ║ (CCU2只读快照+代际句柄) ║ │resource/kernel/ Kernel录制 │
100+│ CcuInstanceMgr / CcuInstance │ ║ LaunchContext/Channel/ ║ │ CcuKernel·Mgr·Registry │
101+│ CcuResDescMgr 资源描述符 │ ║ InstructionLoad POD ║ │resource/representation/ REP IR │
102+│ CcuVarEventResMgr XN/CKE预约 │ ║ ║ │ ~45种节点(算术/搬运/同步/ │
103+│ccu_transport/ 建链握手 │◄── ║◄── 数据面回调控制面: ║◄── │ 控制流/循环) │
104+│ CcuTransport/Conn/Jetty │ ║ controlOps 函数表7项 ║ │ + InsGenerator V1(A5)/V2(A6) │
105+│ccu_device/ 设备资源·驱动交互 │ ║ channelQuery/loadInstr ║ │resource/microcode(+microcode_opt) │
106+│ CcuComponent·CcuResBatchAlloc │ ║ missionCtx/loopCtx/cke/ ║ │ 32B定长微码·指令调度优化 │
107+│ CcuChannelCtxMgr V1/V2·PFE │ ║ xn/gsa Query ║ │resource/common/ 资源快照 │
108+│ RegisterContextRegistry │ ║ + hcomm侧4个C API ║ │launch: GeneTaskParams │
109+│ (代际句柄防悬挂) │ ║ ║ │ (dieId/missionId/args[13]) │
110+│对上层: include/hccl·hcomm │ ║契约: 只传POD不传C++对象 ║ │ ──► rtCCULaunch(stream) │
111+│ HcclComm*/HcommCcuIns* C API │ ║ 16B ABI头(magic/ver/ ║ │(链接 acl_rt / runtime) │
112+│ │ ║ size) + static_assert ║ │ │
113+└──────────────────────────────────────┘ ╚══════════════════════════╝ └────────────────────────────────────────┘
114+ │ │
115+ ▼ ▼
116+ (6) TLV驱动交互(指令/通道) (5) rtCCULaunch提交Mission任务
117+┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
118+│ 驱动/运行时层: runtime(rtCCULaunch) · ascend_hal(HccpRaTlvCcuCustomChannel TLV: │
119+│ SET/GET_INSTRUCTION·CHANNEL·JETTY_CTX·MISSION_CTX·LOOP_CTX·GSA/XN/CKE) · urma(Jetty) · Socket(握手) │
120+└──────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┘
121+ ▼
122+┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
123+│ 硬件: Ascend IO Die 内 CCU 集合通信单元 —— Mission(硬件线程)×微码指令槽 · XN/GSA/CKE/MS 资源 │
124+│ URMA 统一远端内存访问引擎搬运数据 (950PR/950DT, 高带宽低时延) │
125+└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
126+```
127+ 
128+## 运行时主流程
129+ 
130+1. **建域与资源预约**:框架/HCCL → 控制面,建通信域,`HcclCommAssignCcuIns` / `HcommCcuInsCreate` 创建 CCU 实例,Variable(XN)/Event(CKE) 资源预约与 VA 映射。
131+2. **Kernel 注册录制**:算子 → 数据面,`HcommCcuKernelRegisterStart/Register/End`(弱符号,落在数据面 SO),执行用户 kernelFunc,`CcuXxx` 原语录制 REP 中间表示。
132+3. **交付快照**:控制面 → 数据面,`HcclCommQueryCcuRegisterContext` 交付 RegisterContext 只读快照(资源 range 视图 + die 元数据 + controlOps 函数表)。
133+4. **回调控制面**:数据面 → 控制面,经 controlOps 表 / 4 个 C API(`include/hcomm/hcomm_ccu_{res,channel,instruction,launch}_api.h`)查询 Channel POD、下发微码;翻译产物由控制面走 TLV 驱动接口写入硬件指令槽。
134+5. **任务提交**:数据面组 `CcuTaskParam(dieId/missionId/instStartId/args[13])` → `rtCCULaunch` 提交流。
135+6. **硬件执行**:CCU Mission 执行微码,URMA 引擎搬运数据,XN/GSA/CKE 完成同步。
136+ 
137+## 构建期边界保障
138+ 
139+| 机制 | 说明 |
140+|------|------|
141+| 双 SO 联合编译 | 本仓按候选路径查找 / FetchContent 拉取 asc-comm(`cmake/third_party/asccomm-ccu.cmake`),数据面 SO 随 hcomm 包交付;找不到则只构建控制面 |
142+| 源归属校验(双向) | `hcomm_check_source_ownership(hcomm/hccl_v2)` + asc-comm 侧对称校验,禁止跨仓引用源文件 |
143+| 链接期校验(双向) | 双方均 `-Wl,--no-undefined`,不允许无意识依赖对方符号 |
144+| 单源双头 | 资源仓库类型 `pub_inc/ccu_res_repo.h` ⇔ `internal/hcomm/resource/common/ccu_res_repository_local.h` 宏互斥定义 |
145+| POD 契约 | 跨 SO 只传 POD(16B ABI 头 magic/version/size + `static_assert` 锁布局),不传 C++ 对象 |
146+ 
147+> 注:当前 dev_rename 分支为过渡态,libhcomm 内仍保留一套进程内旧实现(`src/base_comm/resources/ccu/{ccu_kernel,ccu_representation,ccu_microcode}` + `primitives/api_c_adpt/ccu`)作兼容,图中为目标拆分形态。
148+ 
149+## 关键路径速查
150+ 
151+```
152+hcomm 仓(控制面)
153+├── include/ccu/ # DSL 头(Variable/Event/Buffer/Loop + ccu_res.h/ccu_launch.h 弱符号)
154+├── include/hcomm/hcomm_ccu_*_api.h # 数据面调用的 4 个 C API
155+├── pkg_inc/hcomm/hcomm_ccu_*.h # 跨 SO POD ABI(abi/common/res/control/channel/instruction/launch/dfx)
156+├── src/base_comm/resources/ccu/
157+│ ├── ccu_instance/ # CcuInstanceMgr/CcuInstance/CcuResDescMgr/CcuVarEventResMgr
158+│ ├── ccu_transport/ # CcuTransport/CcuConnection/CcuJetty 建链握手
159+│ └── ccu_device/ # CcuComponent/资源分配器/ChannelCtxMgr V1,V2/RegisterContextRegistry
160+└── cmake/third_party/asccomm-ccu.cmake # 数据面 SO 联合编译与交付
161+ 
162+asc-comm 仓(数据面)
163+├── src/ccu/hcomm/primitives/ # CcuXxx 原语实现 + Kernel 注册/Launch
164+├── src/ccu/hcomm/resource/kernel/ # CcuKernel/CcuKernelMgr/CcuKernelRegistry
165+├── src/ccu/hcomm/resource/representation/ # REP IR + InsGenerator V1(A5)/V2(A6) 翻译器
166+├── src/ccu/hcomm/resource/microcode(+_opt)/ # 32B 定长微码 + 指令调度优化
167+└── include/ccu/hcomm/ # 数据面公共 DSL 头(安装供 CCU 算子开发者使用)
168+```
@@ -0,0 +1,432 @@
1+# CCU 模式北向接口调用时序(首次下发 / 快速下发 / 回退 AICPU)
2+ 
3+> 范围:以 HCCL 仓(`cann/hccl`)AllReduce 为样本算子,梳理 CCU 模式的三种主要流程下 **HCCL → HCOMM 的 CCU 北向接口**(dlsym C ABI)调用时序。
4+>
5+> 术语:
6+> - **北向接口** = HCCL 调 HCOMM 的 C ABI 边界(`hccl/src/common/hcomm_dlsym/` 中的弱符号 + `dlsym`,HCOMM 侧 `HCOMM_WEAK_SYMBOL` 导出)。南向 = HCOMM 之下的 Runtime/Driver 边界(`rtCCULaunch` / TLV / `hrtMemcpy`),本文只作终点标注。
7+> - **CCU 三段式**:注册期「就地执行 kernelFunc 录制 rep」→ 翻译期「rep 翻成微码并装载指令空间」→ 发射期「只换 taskArgs 下发」。
8+>
9+> 代码基线:`hccl/` 与 `hcomm/` 与 `CheckerL2/` 同层目录。
10+ 
11+---
12+ 
13+## 0. 三条流程的判定入口(一张图)
14+ 
15+```mermaid
16+flowchart TD
17+ A["HcclAllReduce<br/>(all_reduce.cc:AllReduceOutPlaceCommon)"] --> B["HcclGetOpExpansionMode<br/>param.engine = COMM_ENGINE_CCU"]
18+ B --> C{"ShouldGoCcuFastLaunch?<br/>(op_common.cc:386)"}
19+ C -->|"① engine==CCU 且非 OFFLOAD<br/>② engineCtx 命中 fastLaunchTag"| FAST["★ 流程二:快速下发<br/>HcclExecOpCcuFastLaunch<br/>(op_common.cc:559)"]
20+ C -->|"未命中"| SEL["Selector<br/>(op_common.cc:159)"]
21+ SEL --> SEL2["CheckCcuParamAndFallback<br/>(ccu_fallback.cc:482)<br/>跨 rank 协商 opExecuteConfig"]
22+ SEL2 --> EXEC["HcclExecOp<br/>(op_common.cc:787)<br/>★ 流程一:首次下发(慢路径)"]
23+ EXEC --> RES{"HcclGetAlgRes<br/>资源是否 UNAVAIL?"}
24+ RES -->|"可用"| REG["资源申请 + Kernel 注册 + Orchestrate<br/>→ HcommCcuKernelLaunch"]
25+ RES -->|"UNAVAIL"| FB["★ 流程三:回退<br/>FallbackOp (op_common.cc:652)<br/>CCU_MS→CCU_SCHED→AICPU_TS"]
26+ FB --> EXEC
27+ REG --> SAVE["FastLaunchSaveCtx<br/>写 engineCtx(供流程二命中)"]
28+```
29+ 
30+三条流程的本质区别只有「走到哪一段、跳过哪一段」:
31+ 
32+| 流程 | 入口 | 是否选算法 | 是否申请资源/注册 kernel | 运行期北向调用 |
33+|---|---|---|---|---|
34+| ① 首次下发 | `HcclExecOp` 慢路径 | 是(Selector) | 是(三件套 + 84 原语录制 + 翻译) | `HcommCcuKernelLaunch` |
35+| ② 快速下发 | `ShouldGoCcuFastLaunch` 命中 | 否(复用 ctx.algName) | 否(复用 ctx 的 thread/kernelHandle/cachedArgs) | `HcommCcuKernelLaunch` |
36+| ③ 回退 AICPU | 资源/协商失败 → `FallbackOp` | 是(ReSelector 降级重选) | **不再走 CCU**(改 AICPU 资源) | 无(转 AICPU 北向族) |
37+ 
38+---
39+ 
40+## 1. CCU 北向接口全景(调用时序图的「参与者」)
41+ 
42+### 1.1 接口分类与符号/实现映射
43+ 
44+| 类 | 北向符号(HCCL 侧声明文件) | HCOMM 侧实现 | 暴露时机 |
45+|---|---|---|---|
46+| **A. 通信域↔实例绑定** | `HcclCommQueryCcuIns` / `HcclCommQueryAssignedCcuIns` / `HcclCommAssignCcuIns`<br/>(`hccl_ccu_res_dl.h`) | `coll_comm_ccu_c_adpt.cc:67 / :109 / :148` | 资源申请期 |
47+| **B. 实例/资源族** | `HcommCcuInsResDescCreate` / `Destroy` / `SetNum` / `QueryNum`、`HcommCcuInsCreate` / `CreateDefault` / `Destroy` / `QueryResDesc`、`HcommCcuQueryRemainResDesc`、`HcommCcuKernelQueryResReq`<br/>(`ccu_res_dl.h`) | `ccu_res_c_adpt.cc` | 首算子资源申请期 |
48+| **B'. 实例/资源族(兼容旧包)** | `HcommCcuInsCreateLegacy`、`HcommCcuGetMemToken` | `ccu_res_c_adpt.cc:195`、`ccu_launch.cc:406` | 旧路径 / 每次下发 |
49+| **C. Kernel 生命周期(弱定义 W)** | `HcommCcuKernelRegisterStart` / `HcommCcuKernelRegister` / `HcommCcuKernelRegisterEnd` / `HcommCcuKernelLaunch`<br/>(`ccu_launch_dl.h`) | `ccu_launch.cc:47 / :77 / :120 / :293` | 注册期 / 每次下发 |
50+| **D. DSL 原语族(84~88 个)** | `CcuVariableAlloc` / `CcuLoadArg` / `CcuNotifyRecord` / `CcuNotifyWait` / `CcuWriteVariableWithNotify` / `CcuReadMemToMem` / `CcuLocalMemReduce` / `CcuLoopGroupCreate` / `CcuIf*` / `CcuWhile*` …<br/>(`ccu_primitives_impl_dl.h` ↔ `hcomm/include/ccu/ccu_primitives.hpp`) | `ccu_primitives_impl.cc` | **仅注册期**(kernelFunc 内) |
51+| **E. 线程/通道(既有桩 + CCU 分支)** | `HcclThreadAcquireWithStream` / `HcclChannelAcquire` / `HcclChannelQuery` / `HcclRankGraphGetEndpointInfo` | HCOMM base_comm thread/channel | 资源申请期(每次慢路径)/ 快速下发期(仅 thread) |
52+| **F. 辅助查询** | `HcommCcuGetTaskArgsNum`、`HcclGetCcuTaskInfo` | `ccu_launch.cc:138` | 可选 |
53+ 
54+### 1.2 关键不变量
55+ 
56+1. **注册期录 rep、发射期只换 args**:`HcommCcuKernelRegister` 内**同步回调** `kernelFunc`,函数体里逐条 `Ccu*` 原语不搬数、只把动作录成 rep 存进 `CcuKernel::res_`;`HcommCcuKernelRegisterEnd` 的 `Translate` 才把 rep 翻成微码并 `LoadInstruction`。
57+2. **原语作用于「当前注册 kernel」**:所有 `Ccu*` 实现 = `CcuKernelMgr::GetInstance(devId).GetCurrentKernel()->XXX()`,依赖 TLS 注册事务上下文。
58+3. **`HcommCcuKernelLaunch` 的 threadHandle 是 RTS Thread**:HCOMM 侧 `reinterpret_cast<hccl::Thread*>` 后 `GetStream()->ptr()` 取挂载的 `aclrtStream`。
59+ 
60+---
61+ 
62+## 2. 流程一:首次算子下发(慢路径)
63+ 
64+### 2.1 时序图
65+ 
66+```mermaid
67+sequenceDiagram
68+ autonumber
69+ participant APP as AI 框架 / 用户
70+ participant OPS as HCCL 编排层<br/>(op_common.cc)
71+ participant EXE as HCCL 执行器/模板<br/>(ins_v2_all_reduce_sole_executor.cc<br/>ccu_temp_all_reduce_mesh_1D_one_shot.cc)
72+ participant NA as HCCL 算法体<br/>(ccu_kernel_all_reduce_mesh1d_one_shot.cc)
73+ participant DL as dlsym 弱符号桥<br/>(hcomm_dlsym/*_dl.*)
74+ participant HC as HCOMM CCU<br/>(ccu_launch.cc / ccu_res_c_adpt.cc<br/>coll_comm_ccu_c_adpt.cc)
75+ participant HW as 南向 Runtime/Driver<br/>(rtCCULaunch / TLV / hrtMemcpy)
76+ 
77+ APP->>OPS: HcclAllReduce(...)
78+ OPS->>OPS: HcclGetOpExpansionMode → param.engine=CCU
79+ Note over OPS: ShouldGoCcuFastLaunch 未命中(首跑无 ctx)
80+ OPS->>OPS: Selector:选算法 CcuMSAllReduceSoleMeshOneShot 等
81+ OPS->>DL: CheckCcuParamAndFallbackC(跨 rank 协商 opExecuteConfig)
82+ DL->>HC: (子通信域 AllGather,AICPU 模式) / 命中缓存则跳过
83+ 
84+ rect rgb(225,240,255)
85+ Note over OPS,HW: P1 资源申请 HcclGetAlgRes → GetAlgResCcu → HcclAllocAlgResourceCcu
86+ OPS->>DL: HcclGetHcclBuffer(取 cclMem/scratch,通用)
87+ OPS->>DL: HcclThreadAcquireWithStream(comm, CCU, stream, notifyNum)
88+ DL->>HC: 申请 CCU 主流 Thread(Mission 载体)
89+ OPS->>DL: HcclChannelQuery / HcclChannelAcquire(comm, CCU, descs[], n)
90+ DL->>HC: 以 kernel 为粒度申请 channel
91+ OPS->>DL: HcclRankGraphGetEndpointInfo(ENDPOINT_ATTR_DIE_ID) → dieId
92+ end
93+ 
94+ rect rgb(235,250,235)
95+ Note over OPS,HW: P2 Kernel 注册 HcclGetCcuKernelDynamic(三件套)
96+ OPS->>DL: HcommCcuInsResDescCreate / SetNum(按 dieId 聚合资源需求)
97+ OPS->>DL: HcommCcuQueryRemainResDesc(IsDieEnabledForPadding 探测 die 使能)
98+ OPS->>DL: HcclCommQueryAssignedCcuIns → HCCL_E_UNAVAIL(首调未绑定)
99+ OPS->>DL: HcommCcuInsResDescCreate / QueryNum / SetNum(finalReqDesc)
100+ OPS->>DL: HcommCcuInsCreate → newInsHandle
101+ DL->>HC: CcuInstanceMgr::Create → CcuInstance::Init(建资源池)
102+ OPS->>DL: HcclCommAssignCcuIns(comm, insHandle)
103+ loop 每个 resGroup
104+ OPS->>DL: HcommCcuKernelRegisterStart(insHandle)
105+ DL->>HC: CcuInstance::BeginRegister + Reset
106+ loop 每个 kernel
107+ OPS->>DL: HcommCcuKernelRegister(ins, dieId, funcName, kernelFunc, args, 1)
108+ DL->>HC: CcuKernelMgr::Register → 同步回调 kernelFunc
109+ HC->>NA: ccuKernelFunc(kernelArg)(就地执行一次)
110+ loop kernelFunc 内每条原语
111+ NA->>DL: CcuVariableAlloc / CcuLoadArg / CcuNotifyRecord / CcuReadMemToMem / CcuLocalMemReduce / CcuLoopGroupCreate ...
112+ DL->>HC: CcuKernelMgr::GetCurrentKernel()->XXX() → Append(rep)
113+ end
114+ HC-->>OPS: kernelHandle
115+ end
116+ OPS->>DL: HcommCcuKernelRegisterEnd(insHandle)
117+ DL->>HC: EndRegister + CcuKernelMgr::Translate(rep→微码)
118+ HC->>HW: LoadInstruction → hrtMemcpy(指令空间)
119+ end
120+ end
121+ 
122+ rect rgb(255,245,230)
123+ Note over OPS,HW: P3 编排发射 exec->Orchestrate → template->KernelRun
124+ OPS->>EXE: executor->Orchestrate(param, resCtxHost)
125+ EXE->>EXE: OrchestrateLoop(按 maxDataCountPerLoop 切 loop)
126+ EXE->>EXE: template->KernelRun(param, tempAlgParams, templateAlgRes)
127+ EXE->>DL: HcommCcuGetMemToken(va, size) → token
128+ EXE->>DL: HcommCcuKernelLaunch(thread, kernelHandle, taskArgs[7], 7)
129+ DL->>HC: GeneTaskParams + LaunchCcuTasks
130+ HC->>HW: rtCCULaunch(&taskInfo, stream)(每个切片一次)
131+ end
132+ 
133+ rect rgb(250,235,250)
134+ Note over OPS: P4 首跑缓存(供流程二命中)
135+ EXE->>OPS: loopTimes==1 时 FastLaunchSaveCtx
136+ OPS->>OPS: HcclEngineCtxCreate(fastLaunchTag, COMM_ENGINE_CCU, size)<br/>存 algName / threadNum / notifyNum / kernelHandle / cachedArgs
137+ end
138+ OPS-->>APP: 返回
139+```
140+ 
141+### 2.2 关键步骤与北向接口清单
142+ 
143+| 阶段 | HCCL 调用点 | 北向接口(dlsym) | HCOMM 实现 | 产物 |
144+|---|---|---|---|---|
145+| 算法选择 | `Selector`→`CheckCcuParamAndFallback` | (子通信域协商,非 CCU 主链路) | `ccu_fallback.cc:482` | `algName` + 最终 `opExecuteConfig` |
146+| 线程 | `HcclAllocAlgResourceCcu`→`HcclGetThread` | `HcclThreadAcquireWithStream(CCU)` | base_comm thread | `resCtxHost->threads[0]`(主流) |
147+| 通道 | `HcclGetChannelForCcu`→`CcuAcquireKernelChannels` | `HcclChannelQuery`、`HcclChannelAcquire`、`HcclRankGraphGetEndpointInfo` | base_comm channel | `kernelArg->channels[i]` + `kernelInfo.dieId` |
148+| 需求聚合 | `BuildAggregatedResReq` | `HcommCcuInsResDescCreate` / `SetNum` / `Destroy`,`HcommCcuQueryRemainResDesc` | `ccu_res_c_adpt.cc` | `reqDescs`(按 dieId) |
149+| 查实例 | `HcclGetCcuKernelDynamic` | `HcclCommQueryAssignedCcuIns`(首调 UNAVAIL) | `coll_comm_ccu_c_adpt.cc:109` | 走新建路径 |
150+| 建实例 | `CreateAndAssignNewCcuIns` | `HcommCcuInsResDescCreate/QueryNum/SetNum`、`HcommCcuInsCreate`、`HcclCommAssignCcuIns` | `ccu_res_c_adpt.cc:208`、`coll_comm_ccu_c_adpt.cc:148` | `insHandle` 绑定到 comm |
151+| 注册 | `RegisterCcuKernels` | `HcommCcuKernelRegisterStart` / `HcommCcuKernelRegister` / `HcommCcuKernelRegisterEnd` | `ccu_launch.cc:47/:77/:120` | `kernelHandle` + 微码已装载 |
152+| 录制 | (HCOMM 回调 kernelFunc) | `CcuVariableAlloc` / `CcuLoadArg` / `CcuNotify*` / `CcuReadMemToMem` / `CcuLocalMemReduce` / `CcuLoopGroupCreate` … | `ccu_primitives_impl.cc` | `CcuKernel::res_`(rep 序列) |
153+| 发射 | `template->KernelRun` | `HcommCcuGetMemToken`、`HcommCcuKernelLaunch` | `ccu_launch.cc:406/:293` | `rtCCULaunch`(南向) |
154+| 缓存 | `FastLaunchSaveCtx` | (非跨仓,`HcclEngineCtxCreate`) | — | `fastLaunchCtx` |
155+ 
156+> **慢路径里的 CCU 资源回退点**:`HcclGetChannelForCcu` 的 `HcclChannelAcquire` 返回 `HCCL_E_UNAVAIL`,或 `HcclGetCcuKernelDynamic` 的容量判定/`HcommCcuInsCreate`/`HcommCcuKernelRegister` 返回 `CCU_E_UNAVAIL`,都会让 `HcclGetAlgRes` 返回 `HCCL_E_UNAVAIL` → 触发流程三。
157+ 
158+---
159+ 
160+## 3. 流程二:快速下发(快路径)
161+ 
162+### 3.1 时序图
163+ 
164+```mermaid
165+sequenceDiagram
166+ autonumber
167+ participant APP as AI 框架 / 用户
168+ participant OPS as HCCL 编排层<br/>(op_common.cc)
169+ participant EXE as HCCL 执行器/模板
170+ participant DL as dlsym 弱符号桥
171+ participant HC as HCOMM CCU<br/>(ccu_launch.cc)
172+ participant HW as 南向 Runtime<br/>(rtCCULaunch)
173+ 
174+ APP->>OPS: HcclAllReduce(...)(同 shape 第二次起)
175+ OPS->>OPS: HcclGetOpExpansionMode → engine=CCU
176+ 
177+ rect rgb(225,240,255)
178+ Note over OPS: ShouldGoCcuFastLaunch(op_common.cc:386)
179+ OPS->>OPS: 校验 opMode!=OFFLOAD 且 engine==CCU
180+ OPS->>OPS: SetOpParamFastLaunchTag(dataType/reduceOp/count/root 拼 tag)
181+ OPS->>OPS: HcclEngineCtxGet(comm, fastLaunchTag, COMM_ENGINE_CCU) → 命中 ✓
182+ end
183+ 
184+ OPS->>OPS: HcclExecOpCcuFastLaunch(op_common.cc:559)
185+ OPS->>OPS: CollAlgExecRegistryV2::GetAlgExec(opType, ctx->algName)
186+ OPS->>OPS: HcclGetHcclBuffer → param.hcclBuff(scratch)
187+ OPS->>DL: HcclThreadAcquireWithStream(comm, CCU, stream, ctx->notifyNumOnMainThread)
188+ DL->>HC: 覆盖主流(取一个 CCU Thread,写回 ctx->threads[0])
189+ OPS->>OPS: ConstructHcclDfxOpInfo + HcclDfxRegOpInfoByCommId
190+ opt 图捕获且多线程
191+ OPS->>OPS: CaptureSlaveStreams
192+ end
193+ 
194+ rect rgb(235,250,235)
195+ Note over OPS,HW: executor->FastLaunch → template->FastLaunch(无 Selector / 无 CalcRes / 无 Register)
196+ OPS->>EXE: executor->FastLaunch(param, ccuFastLaunchCtx)
197+ EXE->>EXE: 从 ctx 取 threads / submitInfos + 新 inputPtr/outputPtr
198+ EXE->>EXE: args[0]=inputPtr+args[7];args[1]=outputPtr+args[8](只改地址)
199+ EXE->>DL: HcommCcuKernelLaunch(threads[0], kernelHandle, args, argSize)
200+ DL->>HC: GeneTaskParams(校验 argsNum==LoadArg 集合)→ LaunchCcuTasks
201+ HC->>HW: rtCCULaunch(&taskInfo, stream)
202+ end
203+ OPS->>OPS: HcclProfilingReportOp
204+ OPS-->>APP: 返回
205+```
206+ 
207+### 3.2 与流程一的关键差异
208+ 
209+| 维度 | 首次下发 | 快速下发 |
210+|---|---|---|
211+| 判定 | 无 fastLaunchTag 命中 | `ShouldGoCcuFastLaunch` 命中 |
212+| 算法选择 | `Selector` + 跨 rank 协商 | 无(直接用 `CcuFastLaunchCtx::algName`) |
213+| 资源/注册 | `HcclGetAlgRes` 全量 + `HcommCcuKernelRegister*` | 无(复用 thread / kernelHandle / cachedArgs) |
214+| 北向接口 | 线程 + 通道 + 资源族 + 生命周期 + 原语 | **仅 `HcclThreadAcquireWithStream` + `HcommCcuKernelLaunch`** |
215+| 缓存写入 | `FastLaunchSaveCtx`(loopTimes==1 且非 OFFLOAD) | — |
216+| 缓存结构 | — | `CcuFastLaunchCtx{algName, threadNum, notifyNumOnMainThread, ccuKernelNum[], ThreadHandle[], CcuKernelSubmitInfo{handle, cachedArgs[48]}}`(`alg_param.h:407`) |
217+ 
218+> `cachedArgs` 布局约定(以 one-shot 为例):`[0]=inputAddr, [1]=outputAddr, [2]=token, [3..6]=goSize[0..3], [7]=inBuffBaseOff, [8]=outBuffBaseOff`。快路径只改 `[0]/[1]`,其余(token/goSize/offset)从缓存复用,这正是「同 shape 直发」的前提。
219+ 
220+---
221+ 
222+## 4. 流程三:CCU 回退 AICPU
223+ 
224+回退有 **4 个触发点**,最终都收敛到 `FallbackOp`(逐级 `CCU_MS → CCU_SCHED → AICPU_TS`)。
225+ 
226+### 4.1 触发点总览
227+ 
228+| # | 触发位置 | 条件 | 处理 |
229+|---|---|---|---|
230+| T1 | `HcclGetAlgRes`(`op_common.cc:863`)返回 `HCCL_E_UNAVAIL` | 通道申请/kernel 注册/实例创建资源不足 | `HcclExecOp` 调 `FallbackOp` |
231+| T2 | `Selector` 内 `CheckCcuParamAndFallback`(`ccu_fallback.cc:482`) | 跨 rank 交换 `opExecuteConfig`,取最低公共值 < 本地 | `ReSelector(lowestConfig)` 直接降级重选 |
232+| T3 | `GetAlgResWithEngine` CCU 分支 `CheckCcuResNegotiation`(`ccu_fallback.cc:337`) | 本端资源 OK 但对端有 rank 不足(AllReduce MIN 协商失败) | `ReleaseCcuAcquiredChannels` → 返回 `HCCL_E_UNAVAIL` |
233+| T4 | HCOMM `CreateCcuInsByFixedResNum`(`coll_comm_ccu_c_adpt.cc:21`) | 旧路径 CCU_MS 实例资源不足 | 内部降级 CCU_MS→CCU_SCHED 重试一次 |
234+ 
235+### 4.2 时序图(资源回退主链 T1 + 协商 T2/T3)
236+ 
237+```mermaid
238+sequenceDiagram
239+ autonumber
240+ participant OPS as HCCL 编排层<br/>(op_common.cc)
241+ participant NEG as 跨 rank 协商<br/>(ccu_fallback.cc)
242+ participant DL as dlsym 弱符号桥
243+ participant HC as HCOMM CCU
244+ participant AICPU as AICPU 执行路径<br/>(GetAlgResAICPU /<br/>HcclAicpuKernelEntranceLaunch)
245+ 
246+ rect rgb(255,235,235)
247+ Note over OPS,HC: 触发:资源不足(DIE 未使能 / 容量不足 / 通道不足)
248+ OPS->>DL: HcclGetCcuKernel → HcommCcuInsCreate / HcommCcuKernelRegister
249+ DL->>HC: 容量/资源校验
250+ HC-->>OPS: CCU_E_UNAVAIL
251+ Note over OPS: HcclAllocAlgResourceCcu 返回 HCCL_E_UNAVAIL
252+ end
253+ 
254+ rect rgb(255,245,225)
255+ Note over OPS,NEG: T3 多卡资源协商(本地成功也要确认对端)
256+ OPS->>NEG: CheckCcuResNegotiationC(comm, param, localResAvailable)
257+ NEG->>NEG: 取 commName+"_negotiation" 子通信域(AICPU 模式)
258+ NEG->>AICPU: HcclAllReduce(MIN, localVal=成功/失败标记) on subComm
259+ AICPU-->>NEG: result
260+ NEG-->>OPS: result==FAIL → HCCL_E_UNAVAIL(任一对端不足)
261+ OPS->>OPS: ReleaseCcuAcquiredChannels(释放已申请的 CCU 通道)
262+ end
263+ 
264+ rect rgb(225,240,255)
265+ Note over OPS,AICPU: T2 跨 rank 参数协商(Selector 内,CANN≥9.2.0)
266+ OPS->>NEG: CheckCcuParamAndFallbackC
267+ NEG->>NEG: 查 cacheTag=algName+config+"_ccuParamCache"(命中直接复用)
268+ NEG->>AICPU: HcclAllGather(CheckParamInfo) on subComm → 取 lowestConfig
269+ alt lowestConfig != 本地 config
270+ NEG->>OPS: ReSelector(comm, param, topoInfo, algName, lowestConfig)
271+ end
272+ end
273+ 
274+ rect rgb(240,240,240)
275+ Note over OPS,AICPU: FallbackOp 逐级降级(op_common.cc:652)
276+ OPS->>OPS: nextConfig: CCU_MS→CCU_SCHED;CCU_SCHED→AICPU_TS
277+ OPS->>OPS: HcclEngineCtxCreate(fallbackTag, COMM_ENGINE_CCU, FallbackCtxData)<br/>缓存 algName + opExecuteConfig
278+ OPS->>OPS: ReSelector(param.opExecuteConfig=nextConfig → 重选 algName)
279+ alt nextConfig == AICPU_TS
280+ OPS->>AICPU: LoadAICPUKernel()
281+ end
282+ OPS->>OPS: SetCommEngine() → param.engine=AICPU_TS;SetOpParamAlgTag()
283+ OPS->>OPS: HcclExecOp 递归(此时走 AICPU 分支)
284+ OPS->>AICPU: GetAlgResAICPU(HcclGetThread/HcclGetChannel,AICPU 族)
285+ OPS->>AICPU: executor->Orchestrate → HcclAicpuKernelEntranceLaunch
286+ end
287+ 
288+ Note over OPS: 下次同算法调用:HcclExecOp 入口查 fallbackTag 命中<br/>→ 直接应用缓存 config/algName → 递归执行(不再尝试 CCU)
289+```
290+ 
291+### 4.3 关键点
292+ 
293+1. **降级是「配置级」的,不是「本算子实例内」的**:`FallbackOp` 先 `ReSelector` 用更低 `opExecuteConfig` **重新选算法**,再从头 `HcclExecOp`。CCU_MS 与 CCU_SCHED 是两套不同资源阈值/算法(MS 模式 LOOP/CCU_BUF/EVENT 阈值更大)。
294+2. **回退结果被缓存两处**:
295+ - `fallbackTag = algName + "_fallback"`,`FallbackCtxData{algName, opExecuteConfig}`(`FallbackOp` 写,`HcclExecOp` 入口读)→ 下次直接复用降级结论;
296+ - `cacheTag = algName + config + "_ccuParamCache"`(`CheckCcuParamAndFallback` 写/读)→ 跳过跨 rank 协商。
297+3. **协商用「子通信域」**:`CheckCcuParamAndFallback` / `CheckCcuResNegotiation` 都会懒建一个 `commName+"_negotiation"` 子通信域(`hcclOpExpansionMode=AICPU`),在其上跑 `HcclAllGather`/`HcclAllReduce`。因此回退过程中的「通信」本身**不再经过 CCU 北向接口**,避免回退逻辑与 CCU 资源耦合。
298+4. **回退后无 CCU 北向调用**:`param.engine` 变为 `AICPU_TS` 后,`HcclGetAlgRes`→`GetAlgResWithEngine` 走 `GetAlgResAICPU`,执行走 `HcclAicpuKernelEntranceLaunch`;CCU 三件套/原语/发射接口在该次调用中全部不再出现。
299+5. **单 die 未使能不是回退,而是跳过补齐**:`IsDieEnabledForPadding` 用 `HcommCcuQueryRemainResDesc` 探测,未使能(`CCU_E_UNAVAIL`)只跳过该 die 的 padding,避免冗余申请;只有真正容量不足才回退。
300+ 
301+### 4.4 回退 AICPU 时逐项操作清单(按调用顺序)
302+ 
303+> 目标:回答「一次 CCU 回退 AICPU 到底做了哪些事」。按**触发 → 回滚 → 降级重选 → 递归执行 → 记忆**五段拆解,每项标注调用点与接口。
304+ 
305+#### 阶段 0:触发判定(回退的「因」)
306+ 
307+| # | 触发点 | 代码位置 | 触发条件 | 与本端/对端关系 | 后续去向 |
308+|---|---|---|---|---|---|
309+| T1 | `HcclExecOp` 捕获 `HcclGetAlgRes` 返回 `HCCL_E_UNAVAIL` | `op_common.cc:863` | 通道申请 / kernel 注册 / 实例创建资源不足 | 本端 | `FallbackOp` |
310+| T2 | `Selector` 内 `CheckCcuParamAndFallback` | `ccu_fallback.cc:482`(`op_common.cc:225`) | 跨 rank 交换 `opExecuteConfig`,取到比本地更低的值 | 跨 rank 取最低 | 直接 `ReSelector`(**不经 `FallbackOp`**) |
311+| T3 | `GetAlgResWithEngine` CCU 分支 `CheckCcuResNegotiation` | `op_common.cc:1578` / `ccu_fallback.cc:337` | 本端资源 OK,但 `HcclAllReduce(MIN)` 协商发现**任一 rank** 不足 | 对端 | 释放本端通道 → 返回 UNAVAIL → 再由 T1 进 `FallbackOp` |
312+| T4 | hcomm 旧路径 `CreateCcuInsByFixedResNum` | `coll_comm_ccu_c_adpt.cc:21` | 固定资源方式建 CCU_MS 实例时资源不足 | 本端 | 内部 `CCU_MS→CCU_SCHED` 重试一次(**仍在 CCU 内**) |
313+ 
314+> 注意 T2 与 T1/T3 的区别:**T2 是「选阶段降级」**(仅换 `opExecuteConfig` 与 `algName`,后面仍可能停留在 CCU),**T1/T3/T4 是「执行阶段回退」**。只有 `FallbackOp` 才可能一路降到 AICPU_TS。
315+ 
316+#### 阶段 1:本端资源回滚(回退前先还账)
317+ 
318+| 操作 | 接口/代码 | 说明 |
319+|---|---|---|
320+| 释放本次为 CCU kernel 新建的通道 | `ReleaseCcuAcquiredChannels`(`op_common.cc:1531`)→ `HcclChannelDestroy(comm, acquiredChannels[], n)` | 只释放 `resRequest.acquiredChannels`(`CcuAcquireKernelChannels` 记录的、本次 `HcclChannelAcquire` 新建的通道;已存在的复用通道不释放),释放后 `clear()` |
321+| 通道申请阶段即失败时的自动回滚 | `CcuAcquireKernelChannels` UNAVAIL 分支(`op_common.cc:2269-2273`) | 申请中失败当场 `ReleaseCcuAcquiredChannels`,不把脏状态带出去 |
322+| 协商失败时的回滚 | `GetAlgResWithEngine`(`op_common.cc:1581`) | `CheckCcuResNegotiation` 返回 UNAVAIL 后释放通道再返回 UNAVAIL |
323+| **不做的事** | — | 已创建的 `CcuInstance`、已注册的 `CcuKernel`/微码、主流 `Thread` 均**不主动销毁**(归 comm 持有,下次若再试 CCU 可复用;AICPU 路径不复用它们但也无需拆除) |
324+ 
325+#### 阶段 2:`FallbackOp` 主体(`op_common.cc:652`)
326+ 
327+| 步骤 | 操作 | 代码/接口 | 说明 |
328+|---|---|---|---|
329+| 1 | 计算 `nextConfig` | `FallbackOp:656-670` | `CCU_MS→CCU_SCHED`;`CCU_SCHED→AICPU_TS`;已在 AICPU_TS 或未知 → `HCCL_E_NOT_SUPPORT`(CANN<9.2.0 直接 `AICPU_TS`) |
330+| 2 | 申请回退结果缓存 | `HcclEngineCtxCreate(comm, fallbackTag, COMM_ENGINE_CCU, sizeof(FallbackCtxData))`(`:674`) | `fallbackTag = algName+"_fallback"`(`SetOpParamFallbackTag`,`:812`);**注意 ctx 挂在 CCU 引擎下**,但内容是回退结论 |
331+| 3 | 降级重选 | `ReSelector(comm, param, topoInfo, algName, nextConfig)`(`:676`) | 见阶段 3 |
332+| 4 | 写回退后算法名 | `sprintf_s(ctxData->algName, algName)`(`:677`) | `FallbackCtxData{algName, opExecuteConfig}`(`op_common.h:36`) |
333+| 5 | 写回退后配置 | `ctxData->opExecuteConfig = param.opExecuteConfig`(`:682`) | 供下次顶层调用命中 |
334+| 6 | 用新配置继续执行 | `HcclExecOp(comm, param, topoInfo, algName, resPack)`(`:683`) | 递归,见阶段 4 |
335+ 
336+#### 阶段 3:`ReSelector` 重选(`op_common.cc:687`)
337+ 
338+| 步骤 | 操作 | 说明 |
339+|---|---|---|
340+| 1 | `param.opExecuteConfig = executeConfig` | 覆写为 `nextConfig` |
341+| 2 | **不重算拓扑** | 复用已算好的 `topoInfo`(与首次 `Selector` 的差别) |
342+| 3 | 重新选算法 | `SelectorEngine::Global()->Run(...)` 或 `ExecuteSelector::Run(...)`;候选引擎优先级由 `SelectorEngine::GetEnginePriority` 给出:`CCU_MS→{CCU_MS,CCU_SCHED,AICPU_TS,HOSTCPU}`、`CCU_SCHED→{CCU_SCHED,AICPU_TS,HOSTCPU}` |
343+| 4 | 更新引擎 | `SetCommEngine(param)`(`op_common.cc:3288`):`AICPU_TS→COMM_ENGINE_AICPU_TS`、`CCU_MS/CCU_SCHED→COMM_ENGINE_CCU` |
344+| 5 | 按新引擎补加载物 | 落到 `AICPU_TS` → `LoadAICPUKernel()`(`load_kernel.cc:40`,内部防重复加载);落到 `AIV` → `RegisterKernel()` |
345+| 6 | 更新 algTag | `SetOpParamAlgTag(param, algName)` |
346+| 7 | 返回 | `checkValidAlgName` 校验非空 |
347+ 
348+#### 阶段 4:递归 `HcclExecOp` 走 AICPU 路径
349+ 
350+| 步骤 | 操作 | 代码/接口 | 说明 |
351+|---|---|---|---|
352+| 1 | 入口查回退缓存 | `HcclEngineCtxGet(comm, fallbackTag, param.engine, ...)`(`:813`) | 本次递归 algName 已变,通常不命中;下次顶层调用命中 |
353+| 2 | 资源申请(AICPU 族) | `GetAlgResWithEngine` → `GetAlgResAICPU` → `HcclAllocAlgResourceAICPU`(`:1751`) | `HcclGetHcclBuffer`(scratch)、`HcclGetThread`→`HcclGetAicpuThread`(`HcclThreadAcquireWithConfig(COMM_ENGINE_AICPU)` + 展开流 Thread)、`HcclGetChannel` |
354+| 3 | ctx 序列化下发 | `Serialize()` + `HcclMemcpyCtxHostToDevice`(`:1735`) | `HcclEngineCtxCreate(AICPU_TS)` + `HcclEngineCtxCopy` |
355+| 4 | 执行 | `executor->Orchestrate` → `HcclAicpuKernelEntranceLaunch`(`:902`) | **此处不再出现任何 CCU 北向接口** |
356+| 5 | 缓存检查(AICPU 侧) | `HcclAivCacheCheckAndReplay` / `aicpuCacheEnable` | 与回退无关,走各自缓存 |
357+ 
358+#### 阶段 5:记忆(避免下次再回退)
359+ 
360+| 缓存 | 键 | 写入点 | 命中效果 |
361+|---|---|---|---|
362+| 回退结论 | `fallbackTag = algName+"_fallback"`(COMM_ENGINE_CCU) | `FallbackOp:674` | 下次顶层 `HcclExecOp` 入口(`:813`)命中 → 直接 `param.opExecuteConfig=缓存 config` + `SetCommEngine`(→AICPU_TS)+ `SetOpParamAlgTag(缓存 algName)` → 递归执行(**不再尝试 CCU 的三件套/资源申请**) |
363+| 跨 rank 参数协商结论 | `cacheTag = algName+"_"+config+"_ccuParamCache"`(COMM_ENGINE_CCU) | `ccu_fallback.cc:553` | 下次 `CheckCcuParamAndFallback` 命中 → config 相同则跳过协商;config 不同则直接应用缓存结论(`SetCommEngine`+`SetOpParamAlgTag`) |
364+ 
365+#### 附:回退过程中「协商通信」本身走什么
366+ 
367+`CheckCcuParamAndFallback` / `CheckCcuResNegotiation` 都会懒建 `commName+"_negotiation"` **子通信域**(`hcclOpExpansionMode=AICPU`,`ccu_fallback.cc:199`),并准备:
368+ 
369+| 资源 | 操作 | 代码 |
370+|---|---|---|
371+| Stream | `aclrtCreateStream` | `ccu_fallback.cc:158` |
372+| Host/Device Buffer | `aclrtMallocHost` / `aclrtMalloc`(send/recv 各一) | `ccu_fallback.cc:162-181` |
373+| 子通信域 | `HcclCreateSubCommConfig`(rankIds 恒等映射) | `ccu_fallback.cc:213` |
374+| 常驻 worker | `CommWorkerMgr::GetInstance().Submit(comm, task)` 串行执行协商算子 | `ccu_fallback.cc:273` |
375+| 参数协商 | `HcclAllGather(CheckParamInfo)` → `CompareCcuParam` 取最低 config | `ccu_fallback.cc:408 / :433` |
376+| 资源协商 | `HcclAllReduce(MIN, 0x5a5a5a5a/0x0)` → `CompareNegotiationResult` | `ccu_fallback.cc:297 / :326` |
377+| 每次复用前清账 | `ClearNegotiationBuf`(memset host/device 收发 buffer) | `ccu_fallback.cc:136` |
378+| 生命周期 | `NegotiationCleanupCb`:`DESTROY_PRE` 释放(`Remove` worker → `CleanupNegotiationRes` → `HcclEngineCtxDestroy`),`RESUME_POST` 级联 `HcclCommResume` | `ccu_fallback.cc:96` |
379+ 
380+> 因此回退链上的「通信」全部在 AICPU 子通信域内完成,**不经过 CCU 北向接口**,保证回退判定与 CCU 资源解耦。
381+ 
382+#### 一句话总结
383+ 
384+一次「CCU 回退 AICPU」= **释放本端脏通道** → **`FallbackOp` 建回退缓存 + `ReSelector` 降级重选(CCU_MS→CCU_SCHED→AICPU_TS)** → **递归 `HcclExecOp` 用 AICPU 引擎重新申请 thread/channel 并执行** → **把结论写进 `fallbackTag`/`cacheTag`**,使后续同算法调用**直接从 AICPU 起步**,不再重走 CCU。
385+ 
386+---
387+ 
388+## 5. 三流程北向接口调用对比
389+ 
390+| 北向接口 | ① 首次下发 | ② 快速下发 | ③ 回退 AICPU |
391+|---|:---:|:---:|:---:|
392+| `HcclCommQueryAssignedCcuIns` | ✓ | — | ✓(失败即回退) |
393+| `HcclCommAssignCcuIns` | ✓ | — | —(回退后不走) |
394+| `HcommCcuInsResDescCreate/SetNum/QueryNum/Destroy` | ✓ | — | ✓(失败即回退) |
395+| `HcommCcuQueryRemainResDesc` | ✓(die 探测) | — | ✓(失败即回退) |
396+| `HcommCcuKernelQueryResReq` | (可选) | — | (可选) |
397+| `HcommCcuInsCreate` | ✓ | — | ✓(失败即回退) |
398+| `HcclThreadAcquireWithStream(CCU)` | ✓ | ✓ | — |
399+| `HcclChannelAcquire/HcclChannelQuery` | ✓ | — | — |
400+| `HcclRankGraphGetEndpointInfo` | ✓ | — | — |
401+| `HcommCcuKernelRegisterStart/Register/RegisterEnd` | ✓ | — | — |
402+| `Ccu*` DSL 原语(84~88) | ✓(回调录制) | — | — |
403+| `HcommCcuGetMemToken` | ✓ | —(复用 cachedArgs 的 token) | — |
404+| `HcommCcuKernelLaunch` | ✓ | ✓ | — |
405+| AICPU 北向族(`HcclThreadAcquire*`/`HcclGetChannel`/…) | — | — | ✓ |
406+ 
407+---
408+ 
409+## 6. 参考文件清单
410+ 
411+**HCCL 仓**
412+- `src/ops/all_reduce/all_reduce.cc`(算子入口 / 快路径分叉)
413+- `src/ops/op_common/op_common.cc`(`Selector` / `HcclExecOp` / `HcclGetAlgRes` / `HcclAllocAlgResourceCcu` / `HcclGetChannelForCcu` / `HcclGetCcuKernel` / `ShouldGoCcuFastLaunch` / `HcclExecOpCcuFastLaunch` / `FallbackOp` / `ReSelector` / `SetCommEngine`)
414+- `src/ops/op_common/ccu_fallback.{h,cc}`(`CheckCcuResNegotiation` / `CheckCcuParamAndFallback`)
415+- `src/ops/op_common/inc/alg_param.h`(`CcuKernelSubmitInfo` / `CcuFastLaunchCtx`)
416+- `src/ops/all_reduce/algorithm/executor/ins_v2_all_reduce_sole_executor.cc`(`Orchestrate` / `OrchestrateLoop` / `FastLaunchSaveCtx` / `FastLaunch`)
417+- `src/ops/all_reduce/algorithm/template/ccu/ccu_temp_all_reduce_mesh_1D_one_shot.cc`(`CalcRes` / `KernelRun` / `FastLaunch`)
418+- `src/ops/all_reduce/algorithm/template/ccu/kernel/ccu_kernel_all_reduce_mesh1d_one_shot.{h,cc}`(算法体,注册期录制)
419+- `src/common/hcomm_dlsym/`(`ccu_launch_dl.*`、`ccu_res_dl.*`、`hccl_ccu_res_dl.*`、`ccu_primitives_impl_dl.*`)
420+ 
421+**HCOMM 仓**
422+- `include/ccu/ccu_launch.h` / `ccu_primitives.hpp` / `ccu_res.h`(北向 CCU API)
423+- `src/base_comm/primitives/api_c_adpt/ccu/ccu_launch.cc`(`HcommCcuKernelRegister*` / `HcommCcuKernelLaunch` / `HcommCcuGetMemToken`)
424+- `src/base_comm/primitives/api_c_adpt/ccu/ccu_res_c_adpt.cc`(`HcommCcuInsCreate*`)
425+- `src/base_comm/primitives/api_c_adpt/ccu/ccu_primitives_impl.cc`(`Ccu*` 原语 C 适配)
426+- `src/coll_communicator_mgr/api_c_adpt/coll_comm_ccu_c_adpt.cc`(`HcclCommQuery/AssignCcuIns`)
427+- `src/base_comm/resources/ccu/ccu_instance/`、`ccu_kernel/`、`ccu_representation/`(实例 / Kernel / rep→微码翻译)
428+ 
429+**相关既有文档(CheckerL2)**
430+- `ccu_allreduce_call_flow.md`(AllReduce CCU 端到端流程)
431+- `ccu_dataplane_architecture.md`(控制面/数据面 SO 拆分)
432+- `docs/CCU北向劫持四方案对比与选型.md`(hccl→hcomm CCU 调用时序与打桩对象)
@@ -0,0 +1,432 @@
1+# CCU 模式北向接口调用时序(首次下发 / 快速下发 / 回退 AICPU)
2+ 
3+> 范围:以 HCCL 仓(`cann/hccl`)AllReduce 为样本算子,梳理 CCU 模式的三种主要流程下 **HCCL → HCOMM 的 CCU 北向接口**(dlsym C ABI)调用时序。
4+>
5+> 术语:
6+> - **北向接口** = HCCL 调 HCOMM 的 C ABI 边界(`hccl/src/common/hcomm_dlsym/` 中的弱符号 + `dlsym`,HCOMM 侧 `HCOMM_WEAK_SYMBOL` 导出)。南向 = HCOMM 之下的 Runtime/Driver 边界(`rtCCULaunch` / TLV / `hrtMemcpy`),本文只作终点标注。
7+> - **CCU 三段式**:注册期「就地执行 kernelFunc 录制 rep」→ 翻译期「rep 翻成微码并装载指令空间」→ 发射期「只换 taskArgs 下发」。
8+>
9+> 代码基线:`hccl/` 与 `hcomm/` 与 `CheckerL2/` 同层目录。
10+ 
11+---
12+ 
13+## 0. 三条流程的判定入口(一张图)
14+ 
15+```mermaid
16+flowchart TD
17+ A["HcclAllReduce<br/>(all_reduce.cc:AllReduceOutPlaceCommon)"] --> B["HcclGetOpExpansionMode<br/>param.engine = COMM_ENGINE_CCU"]
18+ B --> C{"ShouldGoCcuFastLaunch?<br/>(op_common.cc:386)"}
19+ C -->|"① engine==CCU 且非 OFFLOAD<br/>② engineCtx 命中 fastLaunchTag"| FAST["★ 流程二:快速下发<br/>HcclExecOpCcuFastLaunch<br/>(op_common.cc:559)"]
20+ C -->|"未命中"| SEL["Selector<br/>(op_common.cc:159)"]
21+ SEL --> SEL2["CheckCcuParamAndFallback<br/>(ccu_fallback.cc:482)<br/>跨 rank 协商 opExecuteConfig"]
22+ SEL2 --> EXEC["HcclExecOp<br/>(op_common.cc:787)<br/>★ 流程一:首次下发(慢路径)"]
23+ EXEC --> RES{"HcclGetAlgRes<br/>资源是否 UNAVAIL?"}
24+ RES -->|"可用"| REG["资源申请 + Kernel 注册 + Orchestrate<br/>→ HcommCcuKernelLaunch"]
25+ RES -->|"UNAVAIL"| FB["★ 流程三:回退<br/>FallbackOp (op_common.cc:652)<br/>CCU_MS→CCU_SCHED→AICPU_TS"]
26+ FB --> EXEC
27+ REG --> SAVE["FastLaunchSaveCtx<br/>写 engineCtx(供流程二命中)"]
28+```
29+ 
30+三条流程的本质区别只有「走到哪一段、跳过哪一段」:
31+ 
32+| 流程 | 入口 | 是否选算法 | 是否申请资源/注册 kernel | 运行期北向调用 |
33+|---|---|---|---|---|
34+| ① 首次下发 | `HcclExecOp` 慢路径 | 是(Selector) | 是(三件套 + 84 原语录制 + 翻译) | `HcommCcuKernelLaunch` |
35+| ② 快速下发 | `ShouldGoCcuFastLaunch` 命中 | 否(复用 ctx.algName) | 否(复用 ctx 的 thread/kernelHandle/cachedArgs) | `HcommCcuKernelLaunch` |
36+| ③ 回退 AICPU | 资源/协商失败 → `FallbackOp` | 是(ReSelector 降级重选) | **不再走 CCU**(改 AICPU 资源) | 无(转 AICPU 北向族) |
37+ 
38+---
39+ 
40+## 1. CCU 北向接口全景(调用时序图的「参与者」)
41+ 
42+### 1.1 接口分类与符号/实现映射
43+ 
44+| 类 | 北向符号(HCCL 侧声明文件) | HCOMM 侧实现 | 暴露时机 |
45+|---|---|---|---|
46+| **A. 通信域↔实例绑定** | `HcclCommQueryCcuIns` / `HcclCommQueryAssignedCcuIns` / `HcclCommAssignCcuIns`<br/>(`hccl_ccu_res_dl.h`) | `coll_comm_ccu_c_adpt.cc:67 / :109 / :148` | 资源申请期 |
47+| **B. 实例/资源族** | `HcommCcuInsResDescCreate` / `Destroy` / `SetNum` / `QueryNum`、`HcommCcuInsCreate` / `CreateDefault` / `Destroy` / `QueryResDesc`、`HcommCcuQueryRemainResDesc`、`HcommCcuKernelQueryResReq`<br/>(`ccu_res_dl.h`) | `ccu_res_c_adpt.cc` | 首算子资源申请期 |
48+| **B'. 实例/资源族(兼容旧包)** | `HcommCcuInsCreateLegacy`、`HcommCcuGetMemToken` | `ccu_res_c_adpt.cc:195`、`ccu_launch.cc:406` | 旧路径 / 每次下发 |
49+| **C. Kernel 生命周期(弱定义 W)** | `HcommCcuKernelRegisterStart` / `HcommCcuKernelRegister` / `HcommCcuKernelRegisterEnd` / `HcommCcuKernelLaunch`<br/>(`ccu_launch_dl.h`) | `ccu_launch.cc:47 / :77 / :120 / :293` | 注册期 / 每次下发 |
50+| **D. DSL 原语族(84~88 个)** | `CcuVariableAlloc` / `CcuLoadArg` / `CcuNotifyRecord` / `CcuNotifyWait` / `CcuWriteVariableWithNotify` / `CcuReadMemToMem` / `CcuLocalMemReduce` / `CcuLoopGroupCreate` / `CcuIf*` / `CcuWhile*` …<br/>(`ccu_primitives_impl_dl.h` ↔ `hcomm/include/ccu/ccu_primitives.hpp`) | `ccu_primitives_impl.cc` | **仅注册期**(kernelFunc 内) |
51+| **E. 线程/通道(既有桩 + CCU 分支)** | `HcclThreadAcquireWithStream` / `HcclChannelAcquire` / `HcclChannelQuery` / `HcclRankGraphGetEndpointInfo` | HCOMM base_comm thread/channel | 资源申请期(每次慢路径)/ 快速下发期(仅 thread) |
52+| **F. 辅助查询** | `HcommCcuGetTaskArgsNum`、`HcclGetCcuTaskInfo` | `ccu_launch.cc:138` | 可选 |
53+ 
54+### 1.2 关键不变量
55+ 
56+1. **注册期录 rep、发射期只换 args**:`HcommCcuKernelRegister` 内**同步回调** `kernelFunc`,函数体里逐条 `Ccu*` 原语不搬数、只把动作录成 rep 存进 `CcuKernel::res_`;`HcommCcuKernelRegisterEnd` 的 `Translate` 才把 rep 翻成微码并 `LoadInstruction`。
57+2. **原语作用于「当前注册 kernel」**:所有 `Ccu*` 实现 = `CcuKernelMgr::GetInstance(devId).GetCurrentKernel()->XXX()`,依赖 TLS 注册事务上下文。
58+3. **`HcommCcuKernelLaunch` 的 threadHandle 是 RTS Thread**:HCOMM 侧 `reinterpret_cast<hccl::Thread*>` 后 `GetStream()->ptr()` 取挂载的 `aclrtStream`。
59+ 
60+---
61+ 
62+## 2. 流程一:首次算子下发(慢路径)
63+ 
64+### 2.1 时序图
65+ 
66+```mermaid
67+sequenceDiagram
68+ autonumber
69+ participant APP as AI 框架 / 用户
70+ participant OPS as HCCL 编排层<br/>(op_common.cc)
71+ participant EXE as HCCL 执行器/模板<br/>(ins_v2_all_reduce_sole_executor.cc<br/>ccu_temp_all_reduce_mesh_1D_one_shot.cc)
72+ participant NA as HCCL 算法体<br/>(ccu_kernel_all_reduce_mesh1d_one_shot.cc)
73+ participant DL as dlsym 弱符号桥<br/>(hcomm_dlsym/*_dl.*)
74+ participant HC as HCOMM CCU<br/>(ccu_launch.cc / ccu_res_c_adpt.cc<br/>coll_comm_ccu_c_adpt.cc)
75+ participant HW as 南向 Runtime/Driver<br/>(rtCCULaunch / TLV / hrtMemcpy)
76+ 
77+ APP->>OPS: HcclAllReduce(...)
78+ OPS->>OPS: HcclGetOpExpansionMode → param.engine=CCU
79+ Note over OPS: ShouldGoCcuFastLaunch 未命中(首跑无 ctx)
80+ OPS->>OPS: Selector:选算法 CcuMSAllReduceSoleMeshOneShot 等
81+ OPS->>DL: CheckCcuParamAndFallbackC(跨 rank 协商 opExecuteConfig)
82+ DL->>HC: (子通信域 AllGather,AICPU 模式) / 命中缓存则跳过
83+ 
84+ rect rgb(225,240,255)
85+ Note over OPS,HW: P1 资源申请 HcclGetAlgRes → GetAlgResCcu → HcclAllocAlgResourceCcu
86+ OPS->>DL: HcclGetHcclBuffer(取 cclMem/scratch,通用)
87+ OPS->>DL: HcclThreadAcquireWithStream(comm, CCU, stream, notifyNum)
88+ DL->>HC: 申请 CCU 主流 Thread(Mission 载体)
89+ OPS->>DL: HcclChannelQuery / HcclChannelAcquire(comm, CCU, descs[], n)
90+ DL->>HC: 以 kernel 为粒度申请 channel
91+ OPS->>DL: HcclRankGraphGetEndpointInfo(ENDPOINT_ATTR_DIE_ID) → dieId
92+ end
93+ 
94+ rect rgb(235,250,235)
95+ Note over OPS,HW: P2 Kernel 注册 HcclGetCcuKernelDynamic(三件套)
96+ OPS->>DL: HcommCcuInsResDescCreate / SetNum(按 dieId 聚合资源需求)
97+ OPS->>DL: HcommCcuQueryRemainResDesc(IsDieEnabledForPadding 探测 die 使能)
98+ OPS->>DL: HcclCommQueryAssignedCcuIns → HCCL_E_UNAVAIL(首调未绑定)
99+ OPS->>DL: HcommCcuInsResDescCreate / QueryNum / SetNum(finalReqDesc)
100+ OPS->>DL: HcommCcuInsCreate → newInsHandle
101+ DL->>HC: CcuInstanceMgr::Create → CcuInstance::Init(建资源池)
102+ OPS->>DL: HcclCommAssignCcuIns(comm, insHandle)
103+ loop 每个 resGroup
104+ OPS->>DL: HcommCcuKernelRegisterStart(insHandle)
105+ DL->>HC: CcuInstance::BeginRegister + Reset
106+ loop 每个 kernel
107+ OPS->>DL: HcommCcuKernelRegister(ins, dieId, funcName, kernelFunc, args, 1)
108+ DL->>HC: CcuKernelMgr::Register → 同步回调 kernelFunc
109+ HC->>NA: ccuKernelFunc(kernelArg)(就地执行一次)
110+ loop kernelFunc 内每条原语
111+ NA->>DL: CcuVariableAlloc / CcuLoadArg / CcuNotifyRecord / CcuReadMemToMem / CcuLocalMemReduce / CcuLoopGroupCreate ...
112+ DL->>HC: CcuKernelMgr::GetCurrentKernel()->XXX() → Append(rep)
113+ end
114+ HC-->>OPS: kernelHandle
115+ end
116+ OPS->>DL: HcommCcuKernelRegisterEnd(insHandle)
117+ DL->>HC: EndRegister + CcuKernelMgr::Translate(rep→微码)
118+ HC->>HW: LoadInstruction → hrtMemcpy(指令空间)
119+ end
120+ end
121+ 
122+ rect rgb(255,245,230)
123+ Note over OPS,HW: P3 编排发射 exec->Orchestrate → template->KernelRun
124+ OPS->>EXE: executor->Orchestrate(param, resCtxHost)
125+ EXE->>EXE: OrchestrateLoop(按 maxDataCountPerLoop 切 loop)
126+ EXE->>EXE: template->KernelRun(param, tempAlgParams, templateAlgRes)
127+ EXE->>DL: HcommCcuGetMemToken(va, size) → token
128+ EXE->>DL: HcommCcuKernelLaunch(thread, kernelHandle, taskArgs[7], 7)
129+ DL->>HC: GeneTaskParams + LaunchCcuTasks
130+ HC->>HW: rtCCULaunch(&taskInfo, stream)(每个切片一次)
131+ end
132+ 
133+ rect rgb(250,235,250)
134+ Note over OPS: P4 首跑缓存(供流程二命中)
135+ EXE->>OPS: loopTimes==1 时 FastLaunchSaveCtx
136+ OPS->>OPS: HcclEngineCtxCreate(fastLaunchTag, COMM_ENGINE_CCU, size)<br/>存 algName / threadNum / notifyNum / kernelHandle / cachedArgs
137+ end
138+ OPS-->>APP: 返回
139+```
140+ 
141+### 2.2 关键步骤与北向接口清单
142+ 
143+| 阶段 | HCCL 调用点 | 北向接口(dlsym) | HCOMM 实现 | 产物 |
144+|---|---|---|---|---|
145+| 算法选择 | `Selector`→`CheckCcuParamAndFallback` | (子通信域协商,非 CCU 主链路) | `ccu_fallback.cc:482` | `algName` + 最终 `opExecuteConfig` |
146+| 线程 | `HcclAllocAlgResourceCcu`→`HcclGetThread` | `HcclThreadAcquireWithStream(CCU)` | base_comm thread | `resCtxHost->threads[0]`(主流) |
147+| 通道 | `HcclGetChannelForCcu`→`CcuAcquireKernelChannels` | `HcclChannelQuery`、`HcclChannelAcquire`、`HcclRankGraphGetEndpointInfo` | base_comm channel | `kernelArg->channels[i]` + `kernelInfo.dieId` |
148+| 需求聚合 | `BuildAggregatedResReq` | `HcommCcuInsResDescCreate` / `SetNum` / `Destroy`,`HcommCcuQueryRemainResDesc` | `ccu_res_c_adpt.cc` | `reqDescs`(按 dieId) |
149+| 查实例 | `HcclGetCcuKernelDynamic` | `HcclCommQueryAssignedCcuIns`(首调 UNAVAIL) | `coll_comm_ccu_c_adpt.cc:109` | 走新建路径 |
150+| 建实例 | `CreateAndAssignNewCcuIns` | `HcommCcuInsResDescCreate/QueryNum/SetNum`、`HcommCcuInsCreate`、`HcclCommAssignCcuIns` | `ccu_res_c_adpt.cc:208`、`coll_comm_ccu_c_adpt.cc:148` | `insHandle` 绑定到 comm |
151+| 注册 | `RegisterCcuKernels` | `HcommCcuKernelRegisterStart` / `HcommCcuKernelRegister` / `HcommCcuKernelRegisterEnd` | `ccu_launch.cc:47/:77/:120` | `kernelHandle` + 微码已装载 |
152+| 录制 | (HCOMM 回调 kernelFunc) | `CcuVariableAlloc` / `CcuLoadArg` / `CcuNotify*` / `CcuReadMemToMem` / `CcuLocalMemReduce` / `CcuLoopGroupCreate` … | `ccu_primitives_impl.cc` | `CcuKernel::res_`(rep 序列) |
153+| 发射 | `template->KernelRun` | `HcommCcuGetMemToken`、`HcommCcuKernelLaunch` | `ccu_launch.cc:406/:293` | `rtCCULaunch`(南向) |
154+| 缓存 | `FastLaunchSaveCtx` | (非跨仓,`HcclEngineCtxCreate`) | — | `fastLaunchCtx` |
155+ 
156+> **慢路径里的 CCU 资源回退点**:`HcclGetChannelForCcu` 的 `HcclChannelAcquire` 返回 `HCCL_E_UNAVAIL`,或 `HcclGetCcuKernelDynamic` 的容量判定/`HcommCcuInsCreate`/`HcommCcuKernelRegister` 返回 `CCU_E_UNAVAIL`,都会让 `HcclGetAlgRes` 返回 `HCCL_E_UNAVAIL` → 触发流程三。
157+ 
158+---
159+ 
160+## 3. 流程二:快速下发(快路径)
161+ 
162+### 3.1 时序图
163+ 
164+```mermaid
165+sequenceDiagram
166+ autonumber
167+ participant APP as AI 框架 / 用户
168+ participant OPS as HCCL 编排层<br/>(op_common.cc)
169+ participant EXE as HCCL 执行器/模板
170+ participant DL as dlsym 弱符号桥
171+ participant HC as HCOMM CCU<br/>(ccu_launch.cc)
172+ participant HW as 南向 Runtime<br/>(rtCCULaunch)
173+ 
174+ APP->>OPS: HcclAllReduce(...)(同 shape 第二次起)
175+ OPS->>OPS: HcclGetOpExpansionMode → engine=CCU
176+ 
177+ rect rgb(225,240,255)
178+ Note over OPS: ShouldGoCcuFastLaunch(op_common.cc:386)
179+ OPS->>OPS: 校验 opMode!=OFFLOAD 且 engine==CCU
180+ OPS->>OPS: SetOpParamFastLaunchTag(dataType/reduceOp/count/root 拼 tag)
181+ OPS->>OPS: HcclEngineCtxGet(comm, fastLaunchTag, COMM_ENGINE_CCU) → 命中 ✓
182+ end
183+ 
184+ OPS->>OPS: HcclExecOpCcuFastLaunch(op_common.cc:559)
185+ OPS->>OPS: CollAlgExecRegistryV2::GetAlgExec(opType, ctx->algName)
186+ OPS->>OPS: HcclGetHcclBuffer → param.hcclBuff(scratch)
187+ OPS->>DL: HcclThreadAcquireWithStream(comm, CCU, stream, ctx->notifyNumOnMainThread)
188+ DL->>HC: 覆盖主流(取一个 CCU Thread,写回 ctx->threads[0])
189+ OPS->>OPS: ConstructHcclDfxOpInfo + HcclDfxRegOpInfoByCommId
190+ opt 图捕获且多线程
191+ OPS->>OPS: CaptureSlaveStreams
192+ end
193+ 
194+ rect rgb(235,250,235)
195+ Note over OPS,HW: executor->FastLaunch → template->FastLaunch(无 Selector / 无 CalcRes / 无 Register)
196+ OPS->>EXE: executor->FastLaunch(param, ccuFastLaunchCtx)
197+ EXE->>EXE: 从 ctx 取 threads / submitInfos + 新 inputPtr/outputPtr
198+ EXE->>EXE: args[0]=inputPtr+args[7];args[1]=outputPtr+args[8](只改地址)
199+ EXE->>DL: HcommCcuKernelLaunch(threads[0], kernelHandle, args, argSize)
200+ DL->>HC: GeneTaskParams(校验 argsNum==LoadArg 集合)→ LaunchCcuTasks
201+ HC->>HW: rtCCULaunch(&taskInfo, stream)
202+ end
203+ OPS->>OPS: HcclProfilingReportOp
204+ OPS-->>APP: 返回
205+```
206+ 
207+### 3.2 与流程一的关键差异
208+ 
209+| 维度 | 首次下发 | 快速下发 |
210+|---|---|---|
211+| 判定 | 无 fastLaunchTag 命中 | `ShouldGoCcuFastLaunch` 命中 |
212+| 算法选择 | `Selector` + 跨 rank 协商 | 无(直接用 `CcuFastLaunchCtx::algName`) |
213+| 资源/注册 | `HcclGetAlgRes` 全量 + `HcommCcuKernelRegister*` | 无(复用 thread / kernelHandle / cachedArgs) |
214+| 北向接口 | 线程 + 通道 + 资源族 + 生命周期 + 原语 | **仅 `HcclThreadAcquireWithStream` + `HcommCcuKernelLaunch`** |
215+| 缓存写入 | `FastLaunchSaveCtx`(loopTimes==1 且非 OFFLOAD) | — |
216+| 缓存结构 | — | `CcuFastLaunchCtx{algName, threadNum, notifyNumOnMainThread, ccuKernelNum[], ThreadHandle[], CcuKernelSubmitInfo{handle, cachedArgs[48]}}`(`alg_param.h:407`) |
217+ 
218+> `cachedArgs` 布局约定(以 one-shot 为例):`[0]=inputAddr, [1]=outputAddr, [2]=token, [3..6]=goSize[0..3], [7]=inBuffBaseOff, [8]=outBuffBaseOff`。快路径只改 `[0]/[1]`,其余(token/goSize/offset)从缓存复用,这正是「同 shape 直发」的前提。
219+ 
220+---
221+ 
222+## 4. 流程三:CCU 回退 AICPU
223+ 
224+回退有 **4 个触发点**,最终都收敛到 `FallbackOp`(逐级 `CCU_MS → CCU_SCHED → AICPU_TS`)。
225+ 
226+### 4.1 触发点总览
227+ 
228+| # | 触发位置 | 条件 | 处理 |
229+|---|---|---|---|
230+| T1 | `HcclGetAlgRes`(`op_common.cc:863`)返回 `HCCL_E_UNAVAIL` | 通道申请/kernel 注册/实例创建资源不足 | `HcclExecOp` 调 `FallbackOp` |
231+| T2 | `Selector` 内 `CheckCcuParamAndFallback`(`ccu_fallback.cc:482`) | 跨 rank 交换 `opExecuteConfig`,取最低公共值 < 本地 | `ReSelector(lowestConfig)` 直接降级重选 |
232+| T3 | `GetAlgResWithEngine` CCU 分支 `CheckCcuResNegotiation`(`ccu_fallback.cc:337`) | 本端资源 OK 但对端有 rank 不足(AllReduce MIN 协商失败) | `ReleaseCcuAcquiredChannels` → 返回 `HCCL_E_UNAVAIL` |
233+| T4 | HCOMM `CreateCcuInsByFixedResNum`(`coll_comm_ccu_c_adpt.cc:21`) | 旧路径 CCU_MS 实例资源不足 | 内部降级 CCU_MS→CCU_SCHED 重试一次 |
234+ 
235+### 4.2 时序图(资源回退主链 T1 + 协商 T2/T3)
236+ 
237+```mermaid
238+sequenceDiagram
239+ autonumber
240+ participant OPS as HCCL 编排层<br/>(op_common.cc)
241+ participant NEG as 跨 rank 协商<br/>(ccu_fallback.cc)
242+ participant DL as dlsym 弱符号桥
243+ participant HC as HCOMM CCU
244+ participant AICPU as AICPU 执行路径<br/>(GetAlgResAICPU /<br/>HcclAicpuKernelEntranceLaunch)
245+ 
246+ rect rgb(255,235,235)
247+ Note over OPS,HC: 触发:资源不足(DIE 未使能 / 容量不足 / 通道不足)
248+ OPS->>DL: HcclGetCcuKernel → HcommCcuInsCreate / HcommCcuKernelRegister
249+ DL->>HC: 容量/资源校验
250+ HC-->>OPS: CCU_E_UNAVAIL
251+ Note over OPS: HcclAllocAlgResourceCcu 返回 HCCL_E_UNAVAIL
252+ end
253+ 
254+ rect rgb(255,245,225)
255+ Note over OPS,NEG: T3 多卡资源协商(本地成功也要确认对端)
256+ OPS->>NEG: CheckCcuResNegotiationC(comm, param, localResAvailable)
257+ NEG->>NEG: 取 commName+"_negotiation" 子通信域(AICPU 模式)
258+ NEG->>AICPU: HcclAllReduce(MIN, localVal=成功/失败标记) on subComm
259+ AICPU-->>NEG: result
260+ NEG-->>OPS: result==FAIL → HCCL_E_UNAVAIL(任一对端不足)
261+ OPS->>OPS: ReleaseCcuAcquiredChannels(释放已申请的 CCU 通道)
262+ end
263+ 
264+ rect rgb(225,240,255)
265+ Note over OPS,AICPU: T2 跨 rank 参数协商(Selector 内,CANN≥9.2.0)
266+ OPS->>NEG: CheckCcuParamAndFallbackC
267+ NEG->>NEG: 查 cacheTag=algName+config+"_ccuParamCache"(命中直接复用)
268+ NEG->>AICPU: HcclAllGather(CheckParamInfo) on subComm → 取 lowestConfig
269+ alt lowestConfig != 本地 config
270+ NEG->>OPS: ReSelector(comm, param, topoInfo, algName, lowestConfig)
271+ end
272+ end
273+ 
274+ rect rgb(240,240,240)
275+ Note over OPS,AICPU: FallbackOp 逐级降级(op_common.cc:652)
276+ OPS->>OPS: nextConfig: CCU_MS→CCU_SCHED;CCU_SCHED→AICPU_TS
277+ OPS->>OPS: HcclEngineCtxCreate(fallbackTag, COMM_ENGINE_CCU, FallbackCtxData)<br/>缓存 algName + opExecuteConfig
278+ OPS->>OPS: ReSelector(param.opExecuteConfig=nextConfig → 重选 algName)
279+ alt nextConfig == AICPU_TS
280+ OPS->>AICPU: LoadAICPUKernel()
281+ end
282+ OPS->>OPS: SetCommEngine() → param.engine=AICPU_TS;SetOpParamAlgTag()
283+ OPS->>OPS: HcclExecOp 递归(此时走 AICPU 分支)
284+ OPS->>AICPU: GetAlgResAICPU(HcclGetThread/HcclGetChannel,AICPU 族)
285+ OPS->>AICPU: executor->Orchestrate → HcclAicpuKernelEntranceLaunch
286+ end
287+ 
288+ Note over OPS: 下次同算法调用:HcclExecOp 入口查 fallbackTag 命中<br/>→ 直接应用缓存 config/algName → 递归执行(不再尝试 CCU)
289+```
290+ 
291+### 4.3 关键点
292+ 
293+1. **降级是「配置级」的,不是「本算子实例内」的**:`FallbackOp` 先 `ReSelector` 用更低 `opExecuteConfig` **重新选算法**,再从头 `HcclExecOp`。CCU_MS 与 CCU_SCHED 是两套不同资源阈值/算法(MS 模式 LOOP/CCU_BUF/EVENT 阈值更大)。
294+2. **回退结果被缓存两处**:
295+ - `fallbackTag = algName + "_fallback"`,`FallbackCtxData{algName, opExecuteConfig}`(`FallbackOp` 写,`HcclExecOp` 入口读)→ 下次直接复用降级结论;
296+ - `cacheTag = algName + config + "_ccuParamCache"`(`CheckCcuParamAndFallback` 写/读)→ 跳过跨 rank 协商。
297+3. **协商用「子通信域」**:`CheckCcuParamAndFallback` / `CheckCcuResNegotiation` 都会懒建一个 `commName+"_negotiation"` 子通信域(`hcclOpExpansionMode=AICPU`),在其上跑 `HcclAllGather`/`HcclAllReduce`。因此回退过程中的「通信」本身**不再经过 CCU 北向接口**,避免回退逻辑与 CCU 资源耦合。
298+4. **回退后无 CCU 北向调用**:`param.engine` 变为 `AICPU_TS` 后,`HcclGetAlgRes`→`GetAlgResWithEngine` 走 `GetAlgResAICPU`,执行走 `HcclAicpuKernelEntranceLaunch`;CCU 三件套/原语/发射接口在该次调用中全部不再出现。
299+5. **单 die 未使能不是回退,而是跳过补齐**:`IsDieEnabledForPadding` 用 `HcommCcuQueryRemainResDesc` 探测,未使能(`CCU_E_UNAVAIL`)只跳过该 die 的 padding,避免冗余申请;只有真正容量不足才回退。
300+ 
301+### 4.4 回退 AICPU 时逐项操作清单(按调用顺序)
302+ 
303+> 目标:回答「一次 CCU 回退 AICPU 到底做了哪些事」。按**触发 → 回滚 → 降级重选 → 递归执行 → 记忆**五段拆解,每项标注调用点与接口。
304+ 
305+#### 阶段 0:触发判定(回退的「因」)
306+ 
307+| # | 触发点 | 代码位置 | 触发条件 | 与本端/对端关系 | 后续去向 |
308+|---|---|---|---|---|---|
309+| T1 | `HcclExecOp` 捕获 `HcclGetAlgRes` 返回 `HCCL_E_UNAVAIL` | `op_common.cc:863` | 通道申请 / kernel 注册 / 实例创建资源不足 | 本端 | `FallbackOp` |
310+| T2 | `Selector` 内 `CheckCcuParamAndFallback` | `ccu_fallback.cc:482`(`op_common.cc:225`) | 跨 rank 交换 `opExecuteConfig`,取到比本地更低的值 | 跨 rank 取最低 | 直接 `ReSelector`(**不经 `FallbackOp`**) |
311+| T3 | `GetAlgResWithEngine` CCU 分支 `CheckCcuResNegotiation` | `op_common.cc:1578` / `ccu_fallback.cc:337` | 本端资源 OK,但 `HcclAllReduce(MIN)` 协商发现**任一 rank** 不足 | 对端 | 释放本端通道 → 返回 UNAVAIL → 再由 T1 进 `FallbackOp` |
312+| T4 | hcomm 旧路径 `CreateCcuInsByFixedResNum` | `coll_comm_ccu_c_adpt.cc:21` | 固定资源方式建 CCU_MS 实例时资源不足 | 本端 | 内部 `CCU_MS→CCU_SCHED` 重试一次(**仍在 CCU 内**) |
313+ 
314+> 注意 T2 与 T1/T3 的区别:**T2 是「选阶段降级」**(仅换 `opExecuteConfig` 与 `algName`,后面仍可能停留在 CCU),**T1/T3/T4 是「执行阶段回退」**。只有 `FallbackOp` 才可能一路降到 AICPU_TS。
315+ 
316+#### 阶段 1:本端资源回滚(回退前先还账)
317+ 
318+| 操作 | 接口/代码 | 说明 |
319+|---|---|---|
320+| 释放本次为 CCU kernel 新建的通道 | `ReleaseCcuAcquiredChannels`(`op_common.cc:1531`)→ `HcclChannelDestroy(comm, acquiredChannels[], n)` | 只释放 `resRequest.acquiredChannels`(`CcuAcquireKernelChannels` 记录的、本次 `HcclChannelAcquire` 新建的通道;已存在的复用通道不释放),释放后 `clear()` |
321+| 通道申请阶段即失败时的自动回滚 | `CcuAcquireKernelChannels` UNAVAIL 分支(`op_common.cc:2269-2273`) | 申请中失败当场 `ReleaseCcuAcquiredChannels`,不把脏状态带出去 |
322+| 协商失败时的回滚 | `GetAlgResWithEngine`(`op_common.cc:1581`) | `CheckCcuResNegotiation` 返回 UNAVAIL 后释放通道再返回 UNAVAIL |
323+| **不做的事** | — | 已创建的 `CcuInstance`、已注册的 `CcuKernel`/微码、主流 `Thread` 均**不主动销毁**(归 comm 持有,下次若再试 CCU 可复用;AICPU 路径不复用它们但也无需拆除) |
324+ 
325+#### 阶段 2:`FallbackOp` 主体(`op_common.cc:652`)
326+ 
327+| 步骤 | 操作 | 代码/接口 | 说明 |
328+|---|---|---|---|
329+| 1 | 计算 `nextConfig` | `FallbackOp:656-670` | `CCU_MS→CCU_SCHED`;`CCU_SCHED→AICPU_TS`;已在 AICPU_TS 或未知 → `HCCL_E_NOT_SUPPORT`(CANN<9.2.0 直接 `AICPU_TS`) |
330+| 2 | 申请回退结果缓存 | `HcclEngineCtxCreate(comm, fallbackTag, COMM_ENGINE_CCU, sizeof(FallbackCtxData))`(`:674`) | `fallbackTag = algName+"_fallback"`(`SetOpParamFallbackTag`,`:812`);**注意 ctx 挂在 CCU 引擎下**,但内容是回退结论 |
331+| 3 | 降级重选 | `ReSelector(comm, param, topoInfo, algName, nextConfig)`(`:676`) | 见阶段 3 |
332+| 4 | 写回退后算法名 | `sprintf_s(ctxData->algName, algName)`(`:677`) | `FallbackCtxData{algName, opExecuteConfig}`(`op_common.h:36`) |
333+| 5 | 写回退后配置 | `ctxData->opExecuteConfig = param.opExecuteConfig`(`:682`) | 供下次顶层调用命中 |
334+| 6 | 用新配置继续执行 | `HcclExecOp(comm, param, topoInfo, algName, resPack)`(`:683`) | 递归,见阶段 4 |
335+ 
336+#### 阶段 3:`ReSelector` 重选(`op_common.cc:687`)
337+ 
338+| 步骤 | 操作 | 说明 |
339+|---|---|---|
340+| 1 | `param.opExecuteConfig = executeConfig` | 覆写为 `nextConfig` |
341+| 2 | **不重算拓扑** | 复用已算好的 `topoInfo`(与首次 `Selector` 的差别) |
342+| 3 | 重新选算法 | `SelectorEngine::Global()->Run(...)` 或 `ExecuteSelector::Run(...)`;候选引擎优先级由 `SelectorEngine::GetEnginePriority` 给出:`CCU_MS→{CCU_MS,CCU_SCHED,AICPU_TS,HOSTCPU}`、`CCU_SCHED→{CCU_SCHED,AICPU_TS,HOSTCPU}` |
343+| 4 | 更新引擎 | `SetCommEngine(param)`(`op_common.cc:3288`):`AICPU_TS→COMM_ENGINE_AICPU_TS`、`CCU_MS/CCU_SCHED→COMM_ENGINE_CCU` |
344+| 5 | 按新引擎补加载物 | 落到 `AICPU_TS` → `LoadAICPUKernel()`(`load_kernel.cc:40`,内部防重复加载);落到 `AIV` → `RegisterKernel()` |
345+| 6 | 更新 algTag | `SetOpParamAlgTag(param, algName)` |
346+| 7 | 返回 | `checkValidAlgName` 校验非空 |
347+ 
348+#### 阶段 4:递归 `HcclExecOp` 走 AICPU 路径
349+ 
350+| 步骤 | 操作 | 代码/接口 | 说明 |
351+|---|---|---|---|
352+| 1 | 入口查回退缓存 | `HcclEngineCtxGet(comm, fallbackTag, param.engine, ...)`(`:813`) | 本次递归 algName 已变,通常不命中;下次顶层调用命中 |
353+| 2 | 资源申请(AICPU 族) | `GetAlgResWithEngine` → `GetAlgResAICPU` → `HcclAllocAlgResourceAICPU`(`:1751`) | `HcclGetHcclBuffer`(scratch)、`HcclGetThread`→`HcclGetAicpuThread`(`HcclThreadAcquireWithConfig(COMM_ENGINE_AICPU)` + 展开流 Thread)、`HcclGetChannel` |
354+| 3 | ctx 序列化下发 | `Serialize()` + `HcclMemcpyCtxHostToDevice`(`:1735`) | `HcclEngineCtxCreate(AICPU_TS)` + `HcclEngineCtxCopy` |
355+| 4 | 执行 | `executor->Orchestrate` → `HcclAicpuKernelEntranceLaunch`(`:902`) | **此处不再出现任何 CCU 北向接口** |
356+| 5 | 缓存检查(AICPU 侧) | `HcclAivCacheCheckAndReplay` / `aicpuCacheEnable` | 与回退无关,走各自缓存 |
357+ 
358+#### 阶段 5:记忆(避免下次再回退)
359+ 
360+| 缓存 | 键 | 写入点 | 命中效果 |
361+|---|---|---|---|
362+| 回退结论 | `fallbackTag = algName+"_fallback"`(COMM_ENGINE_CCU) | `FallbackOp:674` | 下次顶层 `HcclExecOp` 入口(`:813`)命中 → 直接 `param.opExecuteConfig=缓存 config` + `SetCommEngine`(→AICPU_TS)+ `SetOpParamAlgTag(缓存 algName)` → 递归执行(**不再尝试 CCU 的三件套/资源申请**) |
363+| 跨 rank 参数协商结论 | `cacheTag = algName+"_"+config+"_ccuParamCache"`(COMM_ENGINE_CCU) | `ccu_fallback.cc:553` | 下次 `CheckCcuParamAndFallback` 命中 → config 相同则跳过协商;config 不同则直接应用缓存结论(`SetCommEngine`+`SetOpParamAlgTag`) |
364+ 
365+#### 附:回退过程中「协商通信」本身走什么
366+ 
367+`CheckCcuParamAndFallback` / `CheckCcuResNegotiation` 都会懒建 `commName+"_negotiation"` **子通信域**(`hcclOpExpansionMode=AICPU`,`ccu_fallback.cc:199`),并准备:
368+ 
369+| 资源 | 操作 | 代码 |
370+|---|---|---|
371+| Stream | `aclrtCreateStream` | `ccu_fallback.cc:158` |
372+| Host/Device Buffer | `aclrtMallocHost` / `aclrtMalloc`(send/recv 各一) | `ccu_fallback.cc:162-181` |
373+| 子通信域 | `HcclCreateSubCommConfig`(rankIds 恒等映射) | `ccu_fallback.cc:213` |
374+| 常驻 worker | `CommWorkerMgr::GetInstance().Submit(comm, task)` 串行执行协商算子 | `ccu_fallback.cc:273` |
375+| 参数协商 | `HcclAllGather(CheckParamInfo)` → `CompareCcuParam` 取最低 config | `ccu_fallback.cc:408 / :433` |
376+| 资源协商 | `HcclAllReduce(MIN, 0x5a5a5a5a/0x0)` → `CompareNegotiationResult` | `ccu_fallback.cc:297 / :326` |
377+| 每次复用前清账 | `ClearNegotiationBuf`(memset host/device 收发 buffer) | `ccu_fallback.cc:136` |
378+| 生命周期 | `NegotiationCleanupCb`:`DESTROY_PRE` 释放(`Remove` worker → `CleanupNegotiationRes` → `HcclEngineCtxDestroy`),`RESUME_POST` 级联 `HcclCommResume` | `ccu_fallback.cc:96` |
379+ 
380+> 因此回退链上的「通信」全部在 AICPU 子通信域内完成,**不经过 CCU 北向接口**,保证回退判定与 CCU 资源解耦。
381+ 
382+#### 一句话总结
383+ 
384+一次「CCU 回退 AICPU」= **释放本端脏通道** → **`FallbackOp` 建回退缓存 + `ReSelector` 降级重选(CCU_MS→CCU_SCHED→AICPU_TS)** → **递归 `HcclExecOp` 用 AICPU 引擎重新申请 thread/channel 并执行** → **把结论写进 `fallbackTag`/`cacheTag`**,使后续同算法调用**直接从 AICPU 起步**,不再重走 CCU。
385+ 
386+---
387+ 
388+## 5. 三流程北向接口调用对比
389+ 
390+| 北向接口 | ① 首次下发 | ② 快速下发 | ③ 回退 AICPU |
391+|---|:---:|:---:|:---:|
392+| `HcclCommQueryAssignedCcuIns` | ✓ | — | ✓(失败即回退) |
393+| `HcclCommAssignCcuIns` | ✓ | — | —(回退后不走) |
394+| `HcommCcuInsResDescCreate/SetNum/QueryNum/Destroy` | ✓ | — | ✓(失败即回退) |
395+| `HcommCcuQueryRemainResDesc` | ✓(die 探测) | — | ✓(失败即回退) |
396+| `HcommCcuKernelQueryResReq` | (可选) | — | (可选) |
397+| `HcommCcuInsCreate` | ✓ | — | ✓(失败即回退) |
398+| `HcclThreadAcquireWithStream(CCU)` | ✓ | ✓ | — |
399+| `HcclChannelAcquire/HcclChannelQuery` | ✓ | — | — |
400+| `HcclRankGraphGetEndpointInfo` | ✓ | — | — |
401+| `HcommCcuKernelRegisterStart/Register/RegisterEnd` | ✓ | — | — |
402+| `Ccu*` DSL 原语(84~88) | ✓(回调录制) | — | — |
403+| `HcommCcuGetMemToken` | ✓ | —(复用 cachedArgs 的 token) | — |
404+| `HcommCcuKernelLaunch` | ✓ | ✓ | — |
405+| AICPU 北向族(`HcclThreadAcquire*`/`HcclGetChannel`/…) | — | — | ✓ |
406+ 
407+---
408+ 
409+## 6. 参考文件清单
410+ 
411+**HCCL 仓**
412+- `src/ops/all_reduce/all_reduce.cc`(算子入口 / 快路径分叉)
413+- `src/ops/op_common/op_common.cc`(`Selector` / `HcclExecOp` / `HcclGetAlgRes` / `HcclAllocAlgResourceCcu` / `HcclGetChannelForCcu` / `HcclGetCcuKernel` / `ShouldGoCcuFastLaunch` / `HcclExecOpCcuFastLaunch` / `FallbackOp` / `ReSelector` / `SetCommEngine`)
414+- `src/ops/op_common/ccu_fallback.{h,cc}`(`CheckCcuResNegotiation` / `CheckCcuParamAndFallback`)
415+- `src/ops/op_common/inc/alg_param.h`(`CcuKernelSubmitInfo` / `CcuFastLaunchCtx`)
416+- `src/ops/all_reduce/algorithm/executor/ins_v2_all_reduce_sole_executor.cc`(`Orchestrate` / `OrchestrateLoop` / `FastLaunchSaveCtx` / `FastLaunch`)
417+- `src/ops/all_reduce/algorithm/template/ccu/ccu_temp_all_reduce_mesh_1D_one_shot.cc`(`CalcRes` / `KernelRun` / `FastLaunch`)
418+- `src/ops/all_reduce/algorithm/template/ccu/kernel/ccu_kernel_all_reduce_mesh1d_one_shot.{h,cc}`(算法体,注册期录制)
419+- `src/common/hcomm_dlsym/`(`ccu_launch_dl.*`、`ccu_res_dl.*`、`hccl_ccu_res_dl.*`、`ccu_primitives_impl_dl.*`)
420+ 
421+**HCOMM 仓**
422+- `include/ccu/ccu_launch.h` / `ccu_primitives.hpp` / `ccu_res.h`(北向 CCU API)
423+- `src/base_comm/primitives/api_c_adpt/ccu/ccu_launch.cc`(`HcommCcuKernelRegister*` / `HcommCcuKernelLaunch` / `HcommCcuGetMemToken`)
424+- `src/base_comm/primitives/api_c_adpt/ccu/ccu_res_c_adpt.cc`(`HcommCcuInsCreate*`)
425+- `src/base_comm/primitives/api_c_adpt/ccu/ccu_primitives_impl.cc`(`Ccu*` 原语 C 适配)
426+- `src/coll_communicator_mgr/api_c_adpt/coll_comm_ccu_c_adpt.cc`(`HcclCommQuery/AssignCcuIns`)
427+- `src/base_comm/resources/ccu/ccu_instance/`、`ccu_kernel/`、`ccu_representation/`(实例 / Kernel / rep→微码翻译)
428+ 
429+**相关既有文档(CheckerL2)**
430+- `ccu_allreduce_call_flow.md`(AllReduce CCU 端到端流程)
431+- `ccu_dataplane_architecture.md`(控制面/数据面 SO 拆分)
432+- `docs/CCU北向劫持四方案对比与选型.md`(hccl→hcomm CCU 调用时序与打桩对象)
@@ -0,0 +1,3 @@
1+version https://git-lfs.github.com/spec/v1
2+oid sha256:72187772bdebc6709fd1724431ed82eaa23b9ac4918fd5f419d3c5589820786a
3+size 281402
@@ -0,0 +1,179 @@
1+#!/usr/bin/env python3
2+# -*- coding: UTF-8 -*-
3+# -----------------------------------------------------------------------------------------------------------
4+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
5+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
6+# CANN Open Software License Agreement Version 2.0 (the "License").
7+# Please refer to the License for details. You may not use this file except in compliance with the License.
8+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
9+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10+# See LICENSE in the root of the software repository for the full text of the License.
11+# -----------------------------------------------------------------------------------------------------------
12+ 
13+"""
14+Level1 CCU 函数度量扫描(超长/超大/过深)。
15+ 
16+口径(去注释/字符串 -> 花括号匹配取函数体):
17+ sloc = 函数体内非空、非注释代码行数;
18+ cc = 1 + if + for + while + case + catch + && + || + ?(含 case);
19+ depth = 函数体内相对函数起始的最大花括号嵌套深度;
20+ phys = 物理行数。
21+ 
22+用法:
23+ python3 docs/ccu_func_metrics.py [目标目录或文件...]
24+默认扫描 src/proxy/level1/ccu(相对本脚本所在仓库根)。
25+仅打印“违反指标(SLOC>50 或 CC>=20 或 depth>=5)”的函数;全部达标则无输出。
26+"""
27+import os
28+import re
29+import sys
30+import glob
31+ 
32+SLOC_LIMIT = 50
33+CC_LIMIT = 20
34+DEPTH_LIMIT = 5
35+ 
36+REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
37+DEFAULT_DIR = os.path.join(REPO_ROOT, "src", "proxy", "level1", "ccu")
38+ 
39+CTRL = {"if", "for", "while", "switch", "catch", "do", "else", "return",
40+ "sizeof", "throw", "typedef", "using"}
41+ 
42+ 
43+def strip_comments_strings(src):
44+ out = list(src)
45+ i, n = 0, len(src)
46+ while i < n:
47+ c = src[i]
48+ if c == '/' and i + 1 < n and src[i + 1] == '/':
49+ j = i
50+ while j < n and src[j] != '\n':
51+ out[j] = ' '
52+ j += 1
53+ i = j
54+ elif c == '/' and i + 1 < n and src[i + 1] == '*':
55+ j = i
56+ while j < n and not (src[j] == '*' and j + 1 < n and src[j + 1] == '/'):
57+ if src[j] != '\n':
58+ out[j] = ' '
59+ j += 1
60+ if j < n:
61+ out[j] = ' '
62+ if j + 1 < n:
63+ out[j + 1] = ' '
64+ i = j + 2
65+ elif c == '"' or c == "'":
66+ q = c
67+ j = i + 1
68+ while j < n and src[j] != q:
69+ if src[j] == '\\':
70+ j += 1
71+ if j < n and src[j] != '\n':
72+ out[j] = ' '
73+ j += 1
74+ if j < n:
75+ out[j] = ' '
76+ i = j + 1
77+ else:
78+ i += 1
79+ return "".join(out)
80+ 
81+ 
82+def first_ident(s):
83+ m = re.match(r"\s*([A-Za-z_]\w*)", s)
84+ return m.group(1) if m else ""
85+ 
86+ 
87+def sig_tail_ok(s):
88+ t = s.strip()
89+ if t == "" or t.startswith("#"):
90+ return False
91+ if first_ident(t) in CTRL:
92+ return False
93+ if t.endswith(";") or t.endswith("{"):
94+ return False
95+ return t.endswith(")") or t.endswith("const")
96+ 
97+ 
98+def analyze(path):
99+ with open(path, "r", encoding="utf-8", errors="replace") as f:
100+ src = f.read()
101+ cl = strip_comments_strings(src)
102+ cl_lines = cl.split("\n")
103+ rows = []
104+ i = 0
105+ while i < len(cl_lines):
106+ if cl_lines[i].strip() == "{":
107+ j = i - 1
108+ while j >= 0 and cl_lines[j].strip() == "":
109+ j -= 1
110+ if j >= 0 and sig_tail_ok(cl_lines[j]):
111+ s = j
112+ k = j - 1
113+ while k >= 0:
114+ t = cl_lines[k].strip()
115+ if (t == "" or t.endswith(";") or t.endswith("{") or t.endswith("}")
116+ or t.startswith("#") or t.endswith(":")
117+ or t.startswith(("public", "private", "protected"))):
118+ break
119+ s = k
120+ k -= 1
121+ depth = 0
122+ e = i
123+ while e < len(cl_lines):
124+ depth += cl_lines[e].count("{") - cl_lines[e].count("}")
125+ if depth <= 0:
126+ break
127+ e += 1
128+ body = cl_lines[s:e + 1]
129+ sloc = sum(1 for ln in body if ln.strip() != "")
130+ d = 0
131+ dep = 0
132+ for ln in body:
133+ d += ln.count("{") - ln.count("}")
134+ dep = max(dep, d)
135+ txt = "\n".join(body)
136+ cc = 1
137+ cc += len(re.findall(r"\bif\b", txt))
138+ cc += len(re.findall(r"\bfor\b", txt))
139+ cc += len(re.findall(r"\bwhile\b", txt))
140+ cc += len(re.findall(r"\bcase\b", txt))
141+ cc += len(re.findall(r"\bcatch\b", txt))
142+ cc += txt.count("&&") + txt.count("||") + txt.count("?")
143+ nm = first_ident(cl_lines[s])
144+ for ln in cl_lines[s:j + 1]:
145+ m = re.search(r"([A-Za-z_]\w*)\s*\(", ln)
146+ if m and m.group(1) not in CTRL:
147+ nm = m.group(1)
148+ break
149+ rows.append((os.path.basename(path), nm, s + 1, sloc, e - s + 1, cc, dep))
150+ i = e + 1
151+ continue
152+ i += 1
153+ return rows
154+ 
155+ 
156+def main():
157+ targets = sys.argv[1:] or [DEFAULT_DIR]
158+ files = []
159+ for t in targets:
160+ if os.path.isdir(t):
161+ files += sorted(glob.glob(os.path.join(t, "*.cc")) + glob.glob(os.path.join(t, "*.h")))
162+ else:
163+ files.append(t)
164+ total = 0
165+ bad = 0
166+ for f in files:
167+ rows = analyze(f)
168+ total += len(rows)
169+ for r in rows:
170+ if r[3] > SLOC_LIMIT or r[5] >= CC_LIMIT or r[6] >= DEPTH_LIMIT:
171+ bad += 1
172+ print(" %-22s %-40s L%-5d sloc=%-4d phys=%-4d cc=%-4d depth=%d"
173+ % (r[0], r[1], r[2], r[3], r[4], r[5], r[6]))
174+ print("总函数数:%d;违反(sloc>%d 或 cc>=%d 或 depth>=%d):%d"
175+ % (total, SLOC_LIMIT, CC_LIMIT, DEPTH_LIMIT, bad))
176+ 
177+ 
178+if __name__ == "__main__":
179+ main()
@@ -57,11 +57,11 @@ flowchart TD
57 57 
58| 任务类型 | 说明 | 核心字段 |58| 任务类型 | 说明 | 核心字段 |
59|---|---|---|59|---|---|---|
60-| `TRANS_MEM` | 内存数据搬运 | `srcRankId`, `srcOffset`<br>`dstRankId`, `dstOffset`<br>`len`, `type` |60+| `TRANS_MEM` | 内存数据搬运 | `srcDeviceId`, `srcOffset`<br>`dstDeviceId`, `dstOffset`<br>`len`, `type` |
61| `BATCH_TRANS_MEM` | 批量内存数据搬运,一个节点内包含多组 `(src -> dst)` 搬运关系 | `srcs[]`<br>`dsts[]` |61| `BATCH_TRANS_MEM` | 批量内存数据搬运,一个节点内包含多组 `(src -> dst)` 搬运关系 | `srcs[]`<br>`dsts[]` |
62-| `REDUCE` | 数据规约 | `srcRankId`, `srcOffset`<br>`dstRankId`, `dstOffset`<br>`type`, `dataCount`, `dataType`, `reduceOp` |62+| `REDUCE` | 数据规约 | `srcDeviceId`, `srcOffset`<br>`dstDeviceId`, `dstOffset`<br>`type`, `dataCount`, `dataType`, `reduceOp` |
63| `BATCH_REDUCE` | 批量数据规约,一个节点内包含多组 `(src -> dst)` 规约关系 | `srcs[][]`<br>`dsts[]`<br>`dataType`, `reduceOp` |63| `BATCH_REDUCE` | 批量数据规约,一个节点内包含多组 `(src -> dst)` 规约关系 | `srcs[][]`<br>`dsts[]`<br>`dataType`, `reduceOp` |
64-| `RECORD` / `WAIT` | 同步任务,分别表示发出同步信号和等待同步信号 | `srcRankId`(发出方)<br>`dstRankId`(等待方)<br>`notifyId` |64+| `RECORD` / `WAIT` | 同步任务,分别表示发出同步信号和等待同步信号 | `srcDeviceId`(发出方)<br>`dstDeviceId`(等待方)<br>`notifyId` |
65 65 
66除上述真实执行任务外,任务图中还会补充 `START` / `END` 两类虚拟边界节点。它们不对应实际的数据搬运或计算动作,主要用于表达主图、子图和 Loop 结构的边界。66除上述真实执行任务外,任务图中还会补充 `START` / `END` 两类虚拟边界节点。它们不对应实际的数据搬运或计算动作,主要用于表达主图、子图和 Loop 结构的边界。
67 67 
@@ -57,11 +57,11 @@ flowchart TD
57 57 
58| 任务类型 | 说明 | 核心字段 |58| 任务类型 | 说明 | 核心字段 |
59|---|---|---|59|---|---|---|
60-| `TRANS_MEM` | 内存数据搬运 | `srcRankId`, `srcOffset`<br>`dstRankId`, `dstOffset`<br>`len`, `type` |60+| `TRANS_MEM` | 内存数据搬运 | `srcDeviceId`, `srcOffset`<br>`dstDeviceId`, `dstOffset`<br>`len`, `type` |
61| `BATCH_TRANS_MEM` | 批量内存数据搬运,一个节点内包含多组 `(src -> dst)` 搬运关系 | `srcs[]`<br>`dsts[]` |61| `BATCH_TRANS_MEM` | 批量内存数据搬运,一个节点内包含多组 `(src -> dst)` 搬运关系 | `srcs[]`<br>`dsts[]` |
62-| `REDUCE` | 数据规约 | `srcRankId`, `srcOffset`<br>`dstRankId`, `dstOffset`<br>`type`, `dataCount`, `dataType`, `reduceOp` |62+| `REDUCE` | 数据规约 | `srcDeviceId`, `srcOffset`<br>`dstDeviceId`, `dstOffset`<br>`type`, `dataCount`, `dataType`, `reduceOp` |
63| `BATCH_REDUCE` | 批量数据规约,一个节点内包含多组 `(src -> dst)` 规约关系 | `srcs[][]`<br>`dsts[]`<br>`dataType`, `reduceOp` |63| `BATCH_REDUCE` | 批量数据规约,一个节点内包含多组 `(src -> dst)` 规约关系 | `srcs[][]`<br>`dsts[]`<br>`dataType`, `reduceOp` |
64-| `RECORD` / `WAIT` | 同步任务,分别表示发出同步信号和等待同步信号 | `srcRankId`(发出方)<br>`dstRankId`(等待方)<br>`notifyId` |64+| `RECORD` / `WAIT` | 同步任务,分别表示发出同步信号和等待同步信号 | `srcDeviceId`(发出方)<br>`dstDeviceId`(等待方)<br>`notifyId` |
65 65 
66除上述真实执行任务外,任务图中还会补充 `START` / `END` 两类虚拟边界节点。它们不对应实际的数据搬运或计算动作,主要用于表达主图、子图和 Loop 结构的边界。66除上述真实执行任务外,任务图中还会补充 `START` / `END` 两类虚拟边界节点。它们不对应实际的数据搬运或计算动作,主要用于表达主图、子图和 Loop 结构的边界。
67 67 
@@ -39,7 +39,7 @@ def parse_faq_markdown(md_content: str) -> List[Dict]:
39 current_submodule = ''39 current_submodule = ''
40 current_error_code_group = ''40 current_error_code_group = ''
41 41 
42- faq_blocks = re.split(r'\n#### FAQ-', md_content)42+ faq_blocks = re.split(r'(?m)^#### FAQ-', md_content)
43 43 
44 for i, block in enumerate(faq_blocks[1:]):44 for i, block in enumerate(faq_blocks[1:]):
45 faq_id_match = re.match(r'([A-Z]+\d+)', block)45 faq_id_match = re.match(r'([A-Z]+\d+)', block)
@@ -48,7 +48,7 @@ def parse_faq_markdown(md_content: str) -> List[Dict]:
48 48 
49 faq_id = faq_id_match.group(1)49 faq_id = faq_id_match.group(1)
50 50 
51- original_block = '\n#### FAQ-' + block51+ original_block = '#### FAQ-' + block
52 current_module, current_submodule, current_error_code_group = find_context(md_content, original_block)52 current_module, current_submodule, current_error_code_group = find_context(md_content, original_block)
53 53 
54 faq_item = parse_faq_block(faq_id, block)54 faq_item = parse_faq_block(faq_id, block)
@@ -215,19 +215,34 @@ def extract_diagram(block: str) -> Dict:
215 return {'content': '', 'type': ''}215 return {'content': '', 'type': ''}
216 216 
217 217 
218+def safe_json_dumps(obj, **kwargs):
219+ """JSON 序列化并转义 HTML/script 危险字符,防止模板注入和 script 提前结束"""
220+ result = json.dumps(obj, **kwargs)
221+ # 转义可能导致 HTML 解析器提前结束 script 的字符
222+ result = result.replace('<', '\\u003c')
223+ result = result.replace('>', '\\u003e')
224+ result = result.replace('&', '\\u0026')
225+ # 转义 JavaScript 的行/段落分隔符(在 JSON 字符串中合法,但在 JS 中不合法)
226+ result = result.replace('\u2028', '\\u2028')
227+ result = result.replace('\u2029', '\\u2029')
228+ return result
229+ 
230+ 
218def generate_html(faq_data: List[Dict], modules: List[str], submodules: Dict[str, List[str]], error_codes: List[str]) -> str:231def generate_html(faq_data: List[Dict], modules: List[str], submodules: Dict[str, List[str]], error_codes: List[str]) -> str:
219 """生成完整的HTML文件内容"""232 """生成完整的HTML文件内容"""
220 html_template = get_html_template()233 html_template = get_html_template()
221 234 
222- json_data = json.dumps(faq_data, ensure_ascii=False, indent=2)235+ # 序列化并转义所有槽位
223- modules_json = json.dumps(modules, ensure_ascii=False)236+ slots = {
224- submodules_json = json.dumps(submodules, ensure_ascii=False)237+ '{{FAQ_DATA}}': safe_json_dumps(faq_data, ensure_ascii=False, indent=2),
225- codes_json = json.dumps(error_codes, ensure_ascii=False)238+ '{{MODULES}}': safe_json_dumps(modules, ensure_ascii=False),
239+ '{{SUBMODULES}}': safe_json_dumps(submodules, ensure_ascii=False),
240+ '{{ERROR_CODES}}': safe_json_dumps(error_codes, ensure_ascii=False),
241+ }
226 242 
227- html_content = html_template.replace('{{FAQ_DATA}}', json_data)243+ # 单次替换:构建正则匹配所有占位符,避免插入值被后续替换再处理
228- html_content = html_content.replace('{{MODULES}}', modules_json)244+ pattern = re.compile('|'.join(re.escape(k) for k in slots.keys()))
229- html_content = html_content.replace('{{SUBMODULES}}', submodules_json)245+ html_content = pattern.sub(lambda m: slots[m.group(0)], html_template)
230- html_content = html_content.replace('{{ERROR_CODES}}', codes_json)
231 246 
232 return html_content247 return html_content
233 248 
@@ -55,7 +55,7 @@ def parse_faq_markdown(md_content: str, source_name: str = '') -> List[Dict]:
55 current_submodule = ''55 current_submodule = ''
56 current_error_code_group = ''56 current_error_code_group = ''
57 57 
58- faq_blocks = re.split(r'\n#### FAQ-', md_content)58+ faq_blocks = re.split(r'(?m)^#### FAQ-', md_content)
59 59 
60 for i, block in enumerate(faq_blocks[1:]):60 for i, block in enumerate(faq_blocks[1:]):
61 faq_id_match = re.match(r'([A-Z]+\d+)', block)61 faq_id_match = re.match(r'([A-Z]+\d+)', block)
@@ -64,7 +64,7 @@ def parse_faq_markdown(md_content: str, source_name: str = '') -> List[Dict]:
64 64 
65 faq_id = faq_id_match.group(1)65 faq_id = faq_id_match.group(1)
66 66 
67- original_block = '\n#### FAQ-' + block67+ original_block = '#### FAQ-' + block
68 current_module, current_submodule, current_error_code_group = find_context(md_content, original_block)68 current_module, current_submodule, current_error_code_group = find_context(md_content, original_block)
69 69 
70 faq_item = parse_faq_block(faq_id, block)70 faq_item = parse_faq_block(faq_id, block)
@@ -229,19 +229,34 @@ def extract_diagram(block: str) -> Dict:
229 return {'content': '', 'type': ''}229 return {'content': '', 'type': ''}
230 230 
231 231 
232+def safe_json_dumps(obj, **kwargs):
233+ """JSON 序列化并转义 HTML/script 危险字符,防止模板注入和 script 提前结束"""
234+ result = json.dumps(obj, **kwargs)
235+ # 转义可能导致 HTML 解析器提前结束 script 的字符
236+ result = result.replace('<', '\\u003c')
237+ result = result.replace('>', '\\u003e')
238+ result = result.replace('&', '\\u0026')
239+ # 转义 JavaScript 的行/段落分隔符(在 JSON 字符串中合法,但在 JS 中不合法)
240+ result = result.replace('\u2028', '\\u2028')
241+ result = result.replace('\u2029', '\\u2029')
242+ return result
243+ 
244+ 
232def generate_html(faq_data: List[Dict], modules: List[str], submodules: Dict[str, List[str]], error_codes: List[str]) -> str:245def generate_html(faq_data: List[Dict], modules: List[str], submodules: Dict[str, List[str]], error_codes: List[str]) -> str:
233 """生成完整的HTML文件内容"""246 """生成完整的HTML文件内容"""
234 html_template = get_html_template()247 html_template = get_html_template()
235 248 
236- json_data = json.dumps(faq_data, ensure_ascii=False, indent=2)249+ # 序列化并转义所有槽位
237- modules_json = json.dumps(modules, ensure_ascii=False)250+ slots = {
238- submodules_json = json.dumps(submodules, ensure_ascii=False)251+ '{{FAQ_DATA}}': safe_json_dumps(faq_data, ensure_ascii=False, indent=2),
239- codes_json = json.dumps(error_codes, ensure_ascii=False)252+ '{{MODULES}}': safe_json_dumps(modules, ensure_ascii=False),
253+ '{{SUBMODULES}}': safe_json_dumps(submodules, ensure_ascii=False),
254+ '{{ERROR_CODES}}': safe_json_dumps(error_codes, ensure_ascii=False),
255+ }
240 256 
241- html_content = html_template.replace('{{FAQ_DATA}}', json_data)257+ # 单次替换:构建正则匹配所有占位符,避免插入值被后续替换再处理
242- html_content = html_content.replace('{{MODULES}}', modules_json)258+ pattern = re.compile('|'.join(re.escape(k) for k in slots.keys()))
243- html_content = html_content.replace('{{SUBMODULES}}', submodules_json)259+ html_content = pattern.sub(lambda m: slots[m.group(0)], html_template)
244- html_content = html_content.replace('{{ERROR_CODES}}', codes_json)
245 260 
246 return html_content261 return html_content
247 262 
@@ -270,6 +285,17 @@ def parse_cli_args(argv: List[str]) -> argparse.Namespace:
270 return parser.parse_args(argv[1:])285 return parser.parse_args(argv[1:])
271 286 
272 287 
288+def extract_faq_ids(md_content: str) -> set:
289+ """从 Markdown 内容中提取所有 FAQ ID"""
290+ faq_ids = set()
291+ faq_blocks = re.split(r'(?m)^#### FAQ-', md_content)
292+ for block in faq_blocks[1:]:
293+ match = re.match(r'([A-Z]+\d+)', block)
294+ if match:
295+ faq_ids.add(f'FAQ-{match.group(1)}')
296+ return faq_ids
297+ 
298+ 
273def expand_input_paths(input_args: List[str]) -> List[Path]:299def expand_input_paths(input_args: List[str]) -> List[Path]:
274 """展开输入路径,支持 Markdown 文件和目录"""300 """展开输入路径,支持 Markdown 文件和目录"""
275 input_files: List[Path] = []301 input_files: List[Path] = []
@@ -288,11 +314,26 @@ def expand_input_paths(input_args: List[str]) -> List[Path]:
288 for child in sorted(path.glob('*.md')):314 for child in sorted(path.glob('*.md')):
289 if not child.is_file():315 if not child.is_file():
290 continue316 continue
317+
318+ # 检测 _en.md 镜像文件:如果对应的 canonical 文件存在且 FAQ ID 集合一致,跳过翻译副本
319+ if child.stem.endswith('_en'):
320+ canonical = child.with_name(child.stem[:-3] + '.md')
321+ if canonical.exists():
322+ try:
323+ canonical_content = canonical.read_text(encoding='utf-8')
324+ mirror_content = child.read_text(encoding='utf-8')
325+ canonical_ids = extract_faq_ids(canonical_content)
326+ mirror_ids = extract_faq_ids(mirror_content)
327+ if canonical_ids and canonical_ids == mirror_ids:
328+ continue # 跳过翻译副本
329+ except OSError:
330+ pass # 读取失败时保留文件,交给后续处理
331+
291 try:332 try:
292 md_content = child.read_text(encoding='utf-8')333 md_content = child.read_text(encoding='utf-8')
293 except OSError:334 except OSError:
294 continue335 continue
295- if '\n#### FAQ-' not in md_content:336+ if not re.search(r'(?m)^#### FAQ-', md_content):
296 continue337 continue
297 resolved = child.resolve()338 resolved = child.resolve()
298 if resolved in seen:339 if resolved in seen:
@@ -268,50 +268,81 @@ ChannelData(见 3.3)。本节保留仅作历史格式参考,读取方不
268 268 
269### 5.2 HcclTaskMetaData 结构269### 5.2 HcclTaskMetaData 结构
270 270 
271-**大小**:约 136 字节(含联合体)271+**大小**:188 字节(pack(1),含联合体;偏移 1~3 为 `HcclTaskProfInfo` 子结构,checker/runner 作为不透明整体透传)
272 272 
273-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |273+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
274-|:------:|:------:|-----------------|----------|------------------------|274+|:------:|:------:|:----------------|----------|--------------------------------------------|
275-| 0 | 1 | int8 | taskType | 任务类型(见枚举) |275+| 0 | 1 | int8 | taskType | 任务类型(见枚举) |
276-| 1 | 2 | uint16 | commId | 通信域 ID |276+| 1 | 3 | HcclTaskProfInfo| profInfo | profiling 对账信息子结构,见下表 |
277-| 3 | 4 | uint32 | rankId | Rank ID |277+| 4 | 8 | uint64 | commId | 通信域 ID |
278-| 7 | 8 | uint64 | streamId | Stream ID |278+| 12 | 4 | uint32 | rankId | 任务所属 Rank ID |
279-| 15 | 4 | uint32 | jettyId | Jetty ID |279+| 16 | 8 | uint64 | deviceId | 任务所属 Device ID |
280-| 19 | 变长 | union | taskData | 任务数据(根据类型解析)|280+| 24 | 8 | uint64 | streamId | Stream ID |
281+| 32 | 4 | uint32 | jettyId | Jetty ID |
282+| 36 | 16 | uint8[16] | rmEid | 对端 EID(WQE 原始字节序) |
283+| 52 | 16 | uint8[16] | lcEid | 本端 EID(WQE 字节序,见下方说明) |
284+| 68 | 120 | union | taskData | 任务数据(根据类型解析) |
285+ 
286+`HcclTaskProfInfo` 子结构(偏移 1~3,定义于 `include/sim_profiling_defs.h`,单源管理):
287+ 
288+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
289+|:------:|:------:|:-------------------|---------------|-----------------------------|
290+| 1 | 1 | uint8 | profTaskType | 对齐 hcomm TaskParamType |
291+| 2 | 1 | uint8 | linkType | 对齐 hcomm DfxLinkType |
292+| 3 | 1 | uint8 | transportType | 对齐 hcomm DfxTransportType |
293+ 
294+**EID 字段说明**:
295+ 
296+- `rmEid` 与 `lcEid` 统一采用 **ranktable.json 十六进制串字节序**(与 EndPoint.eid /
297+ RankEidMap 的入库序一致),可与 DB 表 / ranktable 的 EID 串直接比对,二者亦可直接互比。
298+- `rmEid` 来源:WQE 中的 `rmtEid` 为 `uint32[4]` 小端字存储(内存 16 字节与 ranktable
299+ 串整体相反),拷入任务时做整 16 字节翻转。
300+- `lcEid` 来源:由 `jettyId → RaJetty → RaContext → EndPoint.eid` 查询本端 EID 直拷,
301+ 天然为该序。
302+- `lcEid` 仅设备侧 SQE 解析(`device_sqe_parse_stub.cc`)生成的带 jettyId 的任务填充;
303+ 其余任务保持全 0。
304+- **rank 约定(estimate 采集)**:taskData 的 `srcDeviceId`/`dstDeviceId` 字段承载
305+ 通信域 rank(原 `srcRankId`/`dstRankId` 字段已回退删除,值合并入 deviceId 字段);
306+ 为 `UINT32_MAX`(0xFFFFFFFF)时表示未解析到对应 rank(如非 ranktable/EID 模式),
307+ 0 为合法 rank 值。normal 模式(checker 链路)下 deviceId 字段仍为真实 Device ID,
308+ 两种语义按运行模式隔离(estimate 模式禁用 checker)。
281 309 
282### 5.3 taskData 联合体310### 5.3 taskData 联合体
283 311 
312+联合体大小 120 字节(取最大成员 CcuTask)。
313+ 
284#### 5.3.1 TransMemTask314#### 5.3.1 TransMemTask
285 315 
286**适用任务类型**:`MEM_CPY (3)`。316**适用任务类型**:`MEM_CPY (3)`。
287 317 
288**大小**:33 字节。318**大小**:33 字节。
289 319 
290-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |320+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
291-|:------:|:------:|--------|-----------|--------------|321+|:------:|:------:|--------|-------------|---------------------------------------|
292-| 0 | 4 | uint32 | srcRankId | 源 Rank ID |322+| 0 | 4 | uint32 | srcDeviceId | 源端点(estimate: rank / normal: Device ID) |
293-| 4 | 8 | uint64 | srcOffset | 源偏移地址 |323+| 4 | 8 | uint64 | srcOffset | 源偏移地址 |
294-| 12 | 4 | uint32 | dstRankId | 目标 Rank ID |324+| 12 | 4 | uint32 | dstDeviceId | 目标端点(estimate: rank / normal: Device ID) |
295-| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |325+| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |
296-| 24 | 8 | uint64 | len | 数据长度 |326+| 24 | 8 | uint64 | len | 数据长度 |
297-| 32 | 1 | uint8 | protocol | 协议类型 |327+| 32 | 1 | uint8 | protocol | 协议类型 |
298 328 
299#### 5.3.2 ReduceTask329#### 5.3.2 ReduceTask
300 330 
301**适用任务类型**:`REDUCE (2)`。331**适用任务类型**:`REDUCE (2)`。
302 332 
303-**大小**:35 字节。333+**大小**:36 字节。
304 334 
305-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |335+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
306-|:------:|:------:|--------|-----------|--------------|336+|:------:|:------:|--------|-------------|---------------------------------------|
307-| 0 | 4 | uint32 | srcRankId | 源 Rank ID |337+| 0 | 4 | uint32 | srcDeviceId | 源端点(estimate: rank / normal: Device ID) |
308-| 4 | 8 | uint64 | srcOffset | 源偏移地址 |338+| 4 | 8 | uint64 | srcOffset | 源偏移地址 |
309-| 12 | 4 | uint32 | dstRankId | 目标 Rank ID |339+| 12 | 4 | uint32 | dstDeviceId | 目标端点(estimate: rank / normal: Device ID) |
310-| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |340+| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |
311-| 24 | 8 | uint64 | dataCount | 数据元素个数 |341+| 24 | 8 | uint64 | dataCount | 数据元素个数 |
312-| 32 | 1 | uint8 | dataType | 数据类型 |342+| 32 | 1 | uint8 | dataType | 数据类型 |
313-| 33 | 1 | uint8 | reduceOp | 归约操作类型 |343+| 33 | 1 | uint8 | reduceOp | 归约操作类型 |
314-| 34 | 1 | uint8 | protocol | 协议类型 |344+| 34 | 1 | uint8 | protocol | 协议类型 |
345+| 35 | 1 | uint8 | resv | 保留 |
315 346 
316#### 5.3.3 NotifyTask347#### 5.3.3 NotifyTask
317 348 
@@ -319,13 +350,13 @@ ChannelData(见 3.3)。本节保留仅作历史格式参考,读取方不
319 350 
320**大小**:18 字节。351**大小**:18 字节。
321 352 
322-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |353+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
323-|:------:|:------:|--------|-------------|------------|354+|:------:|:------:|--------|-------------|---------------------------------------------|
324-| 0 | 4 | uint32 | srcRankId | 源 Rank ID |355+| 0 | 4 | uint32 | srcDeviceId | 记录方端点(estimate: rank / normal: Device ID) |
325-| 4 | 8 | uint64 | notifyId | 通知 ID |356+| 4 | 8 | uint64 | notifyId | 通知 ID |
326-| 12 | 4 | uint32 | dstRankId | 目标 Rank ID |357+| 12 | 4 | uint32 | dstDeviceId | 等待方端点(estimate: rank / normal: Device ID) |
327-| 16 | 1 | uint8 | notifyCount | 通知计数 |358+| 16 | 1 | uint8 | notifyCount | 通知计数 |
328-| 17 | 1 | uint8 | protocol | 协议类型 |359+| 17 | 1 | uint8 | protocol | 协议类型 |
329 360 
330---361---
331 362 
@@ -461,60 +492,173 @@ struct MemLayoutData {
461// 任务类型枚举492// 任务类型枚举
462// ============================================================================493// ============================================================================
463enum class HccLTaskMetaType : int8_t {494enum class HccLTaskMetaType : int8_t {
464- NOTIFY_WAIT = 0,495+ NOTIFY_WAIT = 0,
465- NOTIFY_RECORD = 1,496+ NOTIFY_RECORD = 1,
466- REDUCE = 2,497+ REDUCE = 2,
467- MEM_CPY = 3,498+ MEM_CPY = 3,
468- CCU_GRAPH = 4,499+ CCU_GRAPH = 4,
469- AIV_GRAPH = 5,500+ AIV_GRAPH = 5,
470- EVENT_WAIT = 6,501+ SYNC_STREAM = 6,
471- EVENT_RECORD = 7502+ WRITE_WITH_NOTIFY = 7,
503+ INVALID = 8
472};504};
473 505 
474// ============================================================================506// ============================================================================
475-// 任务数据联合体507+// profiling 任务类型枚举值域与 hcomm TaskParamType 一一对齐
508+// ============================================================================
509+enum class ProfTaskParamType : uint8_t {
510+ TASK_SDMA = 0, // Memcpy
511+ TASK_RDMA = 1, // RDMASend
512+ TASK_REDUCE_INLINE = 2, // Reduce_Inline
513+ TASK_REDUCE_TBE = 3, // Reduce_TBE
514+ TASK_NOTIFY_RECORD = 4, // Notify_Record
515+ TASK_NOTIFY_WAIT = 5, // Notify_Wait
516+ TASK_SEND_NOTIFY = 6, // Send_Notify
517+ TASK_SEND_PAYLOAD = 7, // Send_Payload
518+ TASK_WRITE_WITH_NOTIFY = 8, // Write_With_Notify
519+ TASK_WRITE_REDUCE_WITH_NOTIFY = 9, // Reduce_With_Notify
520+ TASK_CCU = 10, // Ccu
521+ TASK_AICPU_KERNEL = 11, // AicpuKernel
522+ TASK_AICPU_REDUCE = 12, // Aicpu_Reduce
523+ TASK_AIV = 13, // AivKernel
524+ TASK_UB_INLINE_WRITE = 14, // Ub_Inline_Write
525+ TASK_UB_REDUCE_INLINE = 15, // Ub_Reduce_Inline
526+ TASK_UB = 16, // Ub_Write_Or_Read
527+ TASK_DPU_KERNEL = 17, // DpuKernel
528+ TASK_DPU_THREAD_FENCE = 18, // Dpu_ThreadFence
529+ TASK_DPU_CHANNEL_FENCE = 19, // Dpu_ChannelFence
530+ TASK_DPU_INLINE_WRITE = 20, // Dpu_Notify_Record
531+ TASK_DPU_NOTIFY_WAIT = 21, // Dpu_Notify_Wait
532+ TASK_DPU_WRITE_WITH_NOTIFY = 22, // Dpu_Write_With_Notify
533+ UNKNOWN = 0xFF
534+};
535+ 
536+// ============================================================================
537+// profiling 链路类型枚举值域与 hcomm DfxLinkType 一一对齐
538+// ============================================================================
539+enum class ProfLinkType : uint8_t {
540+ LINK_ONCHIP = 0, // 片上/本地
541+ LINK_HCCS = 1, // HCCS
542+ LINK_PCIE = 2, // PCIe(跨片 SDMA 通道)
543+ LINK_ROCE = 3, // RoCE
544+ LINK_SIO = 4, // SIO
545+ LINK_HCCS_SW = 5, // HCCS_SW
546+ LINK_STANDARD_ROCE = 6, // 标准RoCE
547+ LINK_UB = 7, // UB
548+ LINK_UBoE = 8, // UB over Ethernet
549+ LINK_RESERVED = 9, // 预留
550+ UNKNOWN = 0xFF
551+};
552+ 
553+// ============================================================================
554+// profiling 传输类型枚举值域与 hcomm DfxTransportType/SimpleTaskType 一一对齐
555+// ============================================================================
556+enum class ProfTransportType : uint8_t {
557+ TRANSPORT_SDMA = 0, // 跨片 SDMA 通道搬运
558+ TRANSPORT_RDMA = 1, // RDMA
559+ TRANSPORT_LOCAL = 2, // 本地搬运/本地算子
560+ TRANSPORT_UB = 3, // UB 传输
561+ TRANSPORT_ROCE = 4, // RoCE 传输
562+ UNKNOWN = 0xFF
563+};
564+ 
565+// ============================================================================
566+// 任务数据联合体 (联合体大小 120 字节, 取最大成员 CcuTask)
476// ============================================================================567// ============================================================================
477struct TransMemTask {568struct TransMemTask {
478- uint32_t srcRankId;569+ uint32_t srcDeviceId;
479 uint64_t srcOffset;570 uint64_t srcOffset;
480- uint32_t dstRankId;571+ uint32_t dstDeviceId;
481 uint64_t dstOffset;572 uint64_t dstOffset;
482 uint64_t len;573 uint64_t len;
483 uint8_t protocol;574 uint8_t protocol;
484};575};
485 576 
486struct ReduceTask {577struct ReduceTask {
487- uint32_t srcRankId;578+ uint32_t srcDeviceId;
488 uint64_t srcOffset;579 uint64_t srcOffset;
489- uint32_t dstRankId;580+ uint32_t dstDeviceId;
490 uint64_t dstOffset;581 uint64_t dstOffset;
491 uint64_t dataCount;582 uint64_t dataCount;
492 uint8_t dataType;583 uint8_t dataType;
493 uint8_t reduceOp;584 uint8_t reduceOp;
494 uint8_t protocol;585 uint8_t protocol;
586+ uint8_t resv;
495};587};
496 588 
497struct NotifyTask {589struct NotifyTask {
498- uint32_t srcRankId;590+ uint32_t srcDeviceId;
499 uint64_t notifyId;591 uint64_t notifyId;
500- uint32_t dstRankId;592+ uint32_t dstDeviceId;
501 uint8_t notifyCount;593 uint8_t notifyCount;
502 uint8_t protocol;594 uint8_t protocol;
503};595};
504 596 
597+struct CcuTask {
598+ uint8_t dieId;
599+ uint8_t missionId;
600+ uint16_t timeout;
601+ uint16_t instStartId;
602+ uint16_t instCnt;
603+ uint32_t key;
604+ uint32_t argSize;
605+ uint64_t args[13];
606+};
607+ 
608+struct AivTask {
609+ uint64_t launchIdx;
610+};
611+ 
612+struct SyncStreamTask {
613+ uint64_t syncIdx;
614+};
615+ 
616+struct WriteWithNotifyTask {
617+ uint32_t srcDeviceId;
618+ uint64_t srcOffset;
619+ uint32_t dstDeviceId;
620+ uint64_t dstOffset;
621+ uint64_t len; // MEM_CPY: 传输长度; REDUCE: dataCount
622+ uint64_t notifyId;
623+ uint8_t isReduce; // 0: 写部分为MEM_CPY; 1: 写部分为REDUCE
624+ uint8_t dataType;
625+ uint8_t reduceOp;
626+ uint8_t protocol;
627+ uint8_t notifyCount;
628+};
629+ 
505// ============================================================================630// ============================================================================
506-// 任务元数据631+// 任务 profiling 对账信息子结构 (3 字节, checker/runner 作为不透明整体透传)
632+// 值域对齐 hcomm TaskParamType/DfxLinkType/DfxTransportType
633+// ============================================================================
634+struct HcclTaskProfInfo {
635+ ProfTaskParamType profTaskType; // 对应 msprof timeline op 名
636+ ProfLinkType linkType; // 物理链路类型
637+ ProfTransportType transportType; // 数据面传输方式
638+};
639+ 
640+// ============================================================================
641+// 任务元数据 (taskType 后含 HcclTaskProfInfo 子结构, sizeof 189 字节)
507// ============================================================================642// ============================================================================
508struct HcclTaskMetaData {643struct HcclTaskMetaData {
509 HccLTaskMetaType taskType;644 HccLTaskMetaType taskType;
510- uint16_t commId;645+ HcclTaskProfInfo profInfo; // profiling 对账信息(整体 3 字节)
646+ uint64_t commId;
511 uint32_t rankId;647 uint32_t rankId;
648+ uint64_t deviceId;
512 uint64_t streamId;649 uint64_t streamId;
513 uint32_t jettyId;650 uint32_t jettyId;
651+ uint8_t sqeGroupId; // UDMA SQE批分组标记, 环形递增1~255
652+ uint8_t rmEid[16];
653+ uint8_t lcEid[16];
514 union {654 union {
515- TransMemTask transMem;655+ TransMemTask transMem;
516- ReduceTask reduce;656+ ReduceTask reduce;
517- NotifyTask notify;657+ NotifyTask notify;
658+ CcuTask ccu;
659+ AivTask aiv;
660+ SyncStreamTask syncStreamTask;
661+ WriteWithNotifyTask writeWithNotify;
518 } taskData;662 } taskData;
519};663};
520 664 
@@ -674,15 +818,15 @@ bool ReadTaskMetaData(const char* filename) {
674 switch (task.taskType) {818 switch (task.taskType) {
675 case HccLTaskMetaType::MEM_CPY:819 case HccLTaskMetaType::MEM_CPY:
676 std::cout << "MEM_CPY: "820 std::cout << "MEM_CPY: "
677- << "src=" << task.taskData.transMem.srcRankId821+ << "src=" << task.taskData.transMem.srcDeviceId
678- << ", dst=" << task.taskData.transMem.dstRankId822+ << ", dst=" << task.taskData.transMem.dstDeviceId
679 << ", len=" << task.taskData.transMem.len;823 << ", len=" << task.taskData.transMem.len;
680 break;824 break;
681 825
682 case HccLTaskMetaType::REDUCE:826 case HccLTaskMetaType::REDUCE:
683 std::cout << "REDUCE: "827 std::cout << "REDUCE: "
684- << "src=" << task.taskData.reduce.srcRankId828+ << "src=" << task.taskData.reduce.srcDeviceId
685- << ", dst=" << task.taskData.reduce.dstRankId829+ << ", dst=" << task.taskData.reduce.dstDeviceId
686 << ", count=" << task.taskData.reduce.dataCount;830 << ", count=" << task.taskData.reduce.dataCount;
687 break;831 break;
688 832
@@ -268,50 +268,81 @@ ChannelData(见 3.3)。本节保留仅作历史格式参考,读取方不
268 268 
269### 5.2 HcclTaskMetaData 结构269### 5.2 HcclTaskMetaData 结构
270 270 
271-**大小**:约 136 字节(含联合体)271+**大小**:188 字节(pack(1),含联合体;偏移 1~3 为 `HcclTaskProfInfo` 子结构,checker/runner 作为不透明整体透传)
272 272 
273-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |273+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
274-|:------:|:------:|-----------------|----------|------------------------|274+|:------:|:------:|:----------------|----------|--------------------------------------------|
275-| 0 | 1 | int8 | taskType | 任务类型(见枚举) |275+| 0 | 1 | int8 | taskType | 任务类型(见枚举) |
276-| 1 | 2 | uint16 | commId | 通信域 ID |276+| 1 | 3 | HcclTaskProfInfo| profInfo | profiling 对账信息子结构,见下表 |
277-| 3 | 4 | uint32 | rankId | Rank ID |277+| 4 | 8 | uint64 | commId | 通信域 ID |
278-| 7 | 8 | uint64 | streamId | Stream ID |278+| 12 | 4 | uint32 | rankId | 任务所属 Rank ID |
279-| 15 | 4 | uint32 | jettyId | Jetty ID |279+| 16 | 8 | uint64 | deviceId | 任务所属 Device ID |
280-| 19 | 变长 | union | taskData | 任务数据(根据类型解析)|280+| 24 | 8 | uint64 | streamId | Stream ID |
281+| 32 | 4 | uint32 | jettyId | Jetty ID |
282+| 36 | 16 | uint8[16] | rmEid | 对端 EID(WQE 原始字节序) |
283+| 52 | 16 | uint8[16] | lcEid | 本端 EID(WQE 字节序,见下方说明) |
284+| 68 | 120 | union | taskData | 任务数据(根据类型解析) |
285+ 
286+`HcclTaskProfInfo` 子结构(偏移 1~3,定义于 `include/sim_profiling_defs.h`,单源管理):
287+ 
288+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
289+|:------:|:------:|:-------------------|---------------|-----------------------------|
290+| 1 | 1 | uint8 | profTaskType | 对齐 hcomm TaskParamType |
291+| 2 | 1 | uint8 | linkType | 对齐 hcomm DfxLinkType |
292+| 3 | 1 | uint8 | transportType | 对齐 hcomm DfxTransportType |
293+ 
294+**EID 字段说明**:
295+ 
296+- `rmEid` 与 `lcEid` 统一采用 **ranktable.json 十六进制串字节序**(与 EndPoint.eid /
297+ RankEidMap 的入库序一致),可与 DB 表 / ranktable 的 EID 串直接比对,二者亦可直接互比。
298+- `rmEid` 来源:WQE 中的 `rmtEid` 为 `uint32[4]` 小端字存储(内存 16 字节与 ranktable
299+ 串整体相反),拷入任务时做整 16 字节翻转。
300+- `lcEid` 来源:由 `jettyId → RaJetty → RaContext → EndPoint.eid` 查询本端 EID 直拷,
301+ 天然为该序。
302+- `lcEid` 仅设备侧 SQE 解析(`device_sqe_parse_stub.cc`)生成的带 jettyId 的任务填充;
303+ 其余任务保持全 0。
304+- **rank 约定(estimate 采集)**:taskData 的 `srcDeviceId`/`dstDeviceId` 字段承载
305+ 通信域 rank(原 `srcRankId`/`dstRankId` 字段已回退删除,值合并入 deviceId 字段);
306+ 为 `UINT32_MAX`(0xFFFFFFFF)时表示未解析到对应 rank(如非 ranktable/EID 模式),
307+ 0 为合法 rank 值。normal 模式(checker 链路)下 deviceId 字段仍为真实 Device ID,
308+ 两种语义按运行模式隔离(estimate 模式禁用 checker)。
281 309 
282### 5.3 taskData 联合体310### 5.3 taskData 联合体
283 311 
312+联合体大小 120 字节(取最大成员 CcuTask)。
313+ 
284#### 5.3.1 TransMemTask314#### 5.3.1 TransMemTask
285 315 
286**适用任务类型**:`MEM_CPY (3)`。316**适用任务类型**:`MEM_CPY (3)`。
287 317 
288**大小**:33 字节。318**大小**:33 字节。
289 319 
290-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |320+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
291-|:------:|:------:|--------|-----------|--------------|321+|:------:|:------:|--------|-------------|---------------------------------------|
292-| 0 | 4 | uint32 | srcRankId | 源 Rank ID |322+| 0 | 4 | uint32 | srcDeviceId | 源端点(estimate: rank / normal: Device ID) |
293-| 4 | 8 | uint64 | srcOffset | 源偏移地址 |323+| 4 | 8 | uint64 | srcOffset | 源偏移地址 |
294-| 12 | 4 | uint32 | dstRankId | 目标 Rank ID |324+| 12 | 4 | uint32 | dstDeviceId | 目标端点(estimate: rank / normal: Device ID) |
295-| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |325+| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |
296-| 24 | 8 | uint64 | len | 数据长度 |326+| 24 | 8 | uint64 | len | 数据长度 |
297-| 32 | 1 | uint8 | protocol | 协议类型 |327+| 32 | 1 | uint8 | protocol | 协议类型 |
298 328 
299#### 5.3.2 ReduceTask329#### 5.3.2 ReduceTask
300 330 
301**适用任务类型**:`REDUCE (2)`。331**适用任务类型**:`REDUCE (2)`。
302 332 
303-**大小**:35 字节。333+**大小**:36 字节。
304 334 
305-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |335+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
306-|:------:|:------:|--------|-----------|--------------|336+|:------:|:------:|--------|-------------|---------------------------------------|
307-| 0 | 4 | uint32 | srcRankId | 源 Rank ID |337+| 0 | 4 | uint32 | srcDeviceId | 源端点(estimate: rank / normal: Device ID) |
308-| 4 | 8 | uint64 | srcOffset | 源偏移地址 |338+| 4 | 8 | uint64 | srcOffset | 源偏移地址 |
309-| 12 | 4 | uint32 | dstRankId | 目标 Rank ID |339+| 12 | 4 | uint32 | dstDeviceId | 目标端点(estimate: rank / normal: Device ID) |
310-| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |340+| 16 | 8 | uint64 | dstOffset | 目标偏移地址 |
311-| 24 | 8 | uint64 | dataCount | 数据元素个数 |341+| 24 | 8 | uint64 | dataCount | 数据元素个数 |
312-| 32 | 1 | uint8 | dataType | 数据类型 |342+| 32 | 1 | uint8 | dataType | 数据类型 |
313-| 33 | 1 | uint8 | reduceOp | 归约操作类型 |343+| 33 | 1 | uint8 | reduceOp | 归约操作类型 |
314-| 34 | 1 | uint8 | protocol | 协议类型 |344+| 34 | 1 | uint8 | protocol | 协议类型 |
345+| 35 | 1 | uint8 | resv | 保留 |
315 346 
316#### 5.3.3 NotifyTask347#### 5.3.3 NotifyTask
317 348 
@@ -319,13 +350,13 @@ ChannelData(见 3.3)。本节保留仅作历史格式参考,读取方不
319 350 
320**大小**:18 字节。351**大小**:18 字节。
321 352 
322-| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |353+| 偏移量 | 字节数 | 类型 | 字段名 | 说明 |
323-|:------:|:------:|--------|-------------|------------|354+|:------:|:------:|--------|-------------|---------------------------------------------|
324-| 0 | 4 | uint32 | srcRankId | 源 Rank ID |355+| 0 | 4 | uint32 | srcDeviceId | 记录方端点(estimate: rank / normal: Device ID) |
325-| 4 | 8 | uint64 | notifyId | 通知 ID |356+| 4 | 8 | uint64 | notifyId | 通知 ID |
326-| 12 | 4 | uint32 | dstRankId | 目标 Rank ID |357+| 12 | 4 | uint32 | dstDeviceId | 等待方端点(estimate: rank / normal: Device ID) |
327-| 16 | 1 | uint8 | notifyCount | 通知计数 |358+| 16 | 1 | uint8 | notifyCount | 通知计数 |
328-| 17 | 1 | uint8 | protocol | 协议类型 |359+| 17 | 1 | uint8 | protocol | 协议类型 |
329 360 
330---361---
331 362 
@@ -461,60 +492,173 @@ struct MemLayoutData {
461// 任务类型枚举492// 任务类型枚举
462// ============================================================================493// ============================================================================
463enum class HccLTaskMetaType : int8_t {494enum class HccLTaskMetaType : int8_t {
464- NOTIFY_WAIT = 0,495+ NOTIFY_WAIT = 0,
465- NOTIFY_RECORD = 1,496+ NOTIFY_RECORD = 1,
466- REDUCE = 2,497+ REDUCE = 2,
467- MEM_CPY = 3,498+ MEM_CPY = 3,
468- CCU_GRAPH = 4,499+ CCU_GRAPH = 4,
469- AIV_GRAPH = 5,500+ AIV_GRAPH = 5,
470- EVENT_WAIT = 6,501+ SYNC_STREAM = 6,
471- EVENT_RECORD = 7502+ WRITE_WITH_NOTIFY = 7,
503+ INVALID = 8
472};504};
473 505 
474// ============================================================================506// ============================================================================
475-// 任务数据联合体507+// profiling 任务类型枚举值域与 hcomm TaskParamType 一一对齐
508+// ============================================================================
509+enum class ProfTaskParamType : uint8_t {
510+ TASK_SDMA = 0, // Memcpy
511+ TASK_RDMA = 1, // RDMASend
512+ TASK_REDUCE_INLINE = 2, // Reduce_Inline
513+ TASK_REDUCE_TBE = 3, // Reduce_TBE
514+ TASK_NOTIFY_RECORD = 4, // Notify_Record
515+ TASK_NOTIFY_WAIT = 5, // Notify_Wait
516+ TASK_SEND_NOTIFY = 6, // Send_Notify
517+ TASK_SEND_PAYLOAD = 7, // Send_Payload
518+ TASK_WRITE_WITH_NOTIFY = 8, // Write_With_Notify
519+ TASK_WRITE_REDUCE_WITH_NOTIFY = 9, // Reduce_With_Notify
520+ TASK_CCU = 10, // Ccu
521+ TASK_AICPU_KERNEL = 11, // AicpuKernel
522+ TASK_AICPU_REDUCE = 12, // Aicpu_Reduce
523+ TASK_AIV = 13, // AivKernel
524+ TASK_UB_INLINE_WRITE = 14, // Ub_Inline_Write
525+ TASK_UB_REDUCE_INLINE = 15, // Ub_Reduce_Inline
526+ TASK_UB = 16, // Ub_Write_Or_Read
527+ TASK_DPU_KERNEL = 17, // DpuKernel
528+ TASK_DPU_THREAD_FENCE = 18, // Dpu_ThreadFence
529+ TASK_DPU_CHANNEL_FENCE = 19, // Dpu_ChannelFence
530+ TASK_DPU_INLINE_WRITE = 20, // Dpu_Notify_Record
531+ TASK_DPU_NOTIFY_WAIT = 21, // Dpu_Notify_Wait
532+ TASK_DPU_WRITE_WITH_NOTIFY = 22, // Dpu_Write_With_Notify
533+ UNKNOWN = 0xFF
534+};
535+ 
536+// ============================================================================
537+// profiling 链路类型枚举值域与 hcomm DfxLinkType 一一对齐
538+// ============================================================================
539+enum class ProfLinkType : uint8_t {
540+ LINK_ONCHIP = 0, // 片上/本地
541+ LINK_HCCS = 1, // HCCS
542+ LINK_PCIE = 2, // PCIe(跨片 SDMA 通道)
543+ LINK_ROCE = 3, // RoCE
544+ LINK_SIO = 4, // SIO
545+ LINK_HCCS_SW = 5, // HCCS_SW
546+ LINK_STANDARD_ROCE = 6, // 标准RoCE
547+ LINK_UB = 7, // UB
548+ LINK_UBoE = 8, // UB over Ethernet
549+ LINK_RESERVED = 9, // 预留
550+ UNKNOWN = 0xFF
551+};
552+ 
553+// ============================================================================
554+// profiling 传输类型枚举值域与 hcomm DfxTransportType/SimpleTaskType 一一对齐
555+// ============================================================================
556+enum class ProfTransportType : uint8_t {
557+ TRANSPORT_SDMA = 0, // 跨片 SDMA 通道搬运
558+ TRANSPORT_RDMA = 1, // RDMA
559+ TRANSPORT_LOCAL = 2, // 本地搬运/本地算子
560+ TRANSPORT_UB = 3, // UB 传输
561+ TRANSPORT_ROCE = 4, // RoCE 传输
562+ UNKNOWN = 0xFF
563+};
564+ 
565+// ============================================================================
566+// 任务数据联合体 (联合体大小 120 字节, 取最大成员 CcuTask)
476// ============================================================================567// ============================================================================
477struct TransMemTask {568struct TransMemTask {
478- uint32_t srcRankId;569+ uint32_t srcDeviceId;
479 uint64_t srcOffset;570 uint64_t srcOffset;
480- uint32_t dstRankId;571+ uint32_t dstDeviceId;
481 uint64_t dstOffset;572 uint64_t dstOffset;
482 uint64_t len;573 uint64_t len;
483 uint8_t protocol;574 uint8_t protocol;
484};575};
485 576 
486struct ReduceTask {577struct ReduceTask {
487- uint32_t srcRankId;578+ uint32_t srcDeviceId;
488 uint64_t srcOffset;579 uint64_t srcOffset;
489- uint32_t dstRankId;580+ uint32_t dstDeviceId;
490 uint64_t dstOffset;581 uint64_t dstOffset;
491 uint64_t dataCount;582 uint64_t dataCount;
492 uint8_t dataType;583 uint8_t dataType;
493 uint8_t reduceOp;584 uint8_t reduceOp;
494 uint8_t protocol;585 uint8_t protocol;
586+ uint8_t resv;
495};587};
496 588 
497struct NotifyTask {589struct NotifyTask {
498- uint32_t srcRankId;590+ uint32_t srcDeviceId;
499 uint64_t notifyId;591 uint64_t notifyId;
500- uint32_t dstRankId;592+ uint32_t dstDeviceId;
501 uint8_t notifyCount;593 uint8_t notifyCount;
502 uint8_t protocol;594 uint8_t protocol;
503};595};
504 596 
597+struct CcuTask {
598+ uint8_t dieId;
599+ uint8_t missionId;
600+ uint16_t timeout;
601+ uint16_t instStartId;
602+ uint16_t instCnt;
603+ uint32_t key;
604+ uint32_t argSize;
605+ uint64_t args[13];
606+};
607+ 
608+struct AivTask {
609+ uint64_t launchIdx;
610+};
611+ 
612+struct SyncStreamTask {
613+ uint64_t syncIdx;
614+};
615+ 
616+struct WriteWithNotifyTask {
617+ uint32_t srcDeviceId;
618+ uint64_t srcOffset;
619+ uint32_t dstDeviceId;
620+ uint64_t dstOffset;
621+ uint64_t len; // MEM_CPY: 传输长度; REDUCE: dataCount
622+ uint64_t notifyId;
623+ uint8_t isReduce; // 0: 写部分为MEM_CPY; 1: 写部分为REDUCE
624+ uint8_t dataType;
625+ uint8_t reduceOp;
626+ uint8_t protocol;
627+ uint8_t notifyCount;
628+};
629+ 
505// ============================================================================630// ============================================================================
506-// 任务元数据631+// 任务 profiling 对账信息子结构 (3 字节, checker/runner 作为不透明整体透传)
632+// 值域对齐 hcomm TaskParamType/DfxLinkType/DfxTransportType
633+// ============================================================================
634+struct HcclTaskProfInfo {
635+ ProfTaskParamType profTaskType; // 对应 msprof timeline op 名
636+ ProfLinkType linkType; // 物理链路类型
637+ ProfTransportType transportType; // 数据面传输方式
638+};
639+ 
640+// ============================================================================
641+// 任务元数据 (taskType 后含 HcclTaskProfInfo 子结构, sizeof 189 字节)
507// ============================================================================642// ============================================================================
508struct HcclTaskMetaData {643struct HcclTaskMetaData {
509 HccLTaskMetaType taskType;644 HccLTaskMetaType taskType;
510- uint16_t commId;645+ HcclTaskProfInfo profInfo; // profiling 对账信息(整体 3 字节)
646+ uint64_t commId;
511 uint32_t rankId;647 uint32_t rankId;
648+ uint64_t deviceId;
512 uint64_t streamId;649 uint64_t streamId;
513 uint32_t jettyId;650 uint32_t jettyId;
651+ uint8_t sqeGroupId; // UDMA SQE批分组标记, 环形递增1~255
652+ uint8_t rmEid[16];
653+ uint8_t lcEid[16];
514 union {654 union {
515- TransMemTask transMem;655+ TransMemTask transMem;
516- ReduceTask reduce;656+ ReduceTask reduce;
517- NotifyTask notify;657+ NotifyTask notify;
658+ CcuTask ccu;
659+ AivTask aiv;
660+ SyncStreamTask syncStreamTask;
661+ WriteWithNotifyTask writeWithNotify;
518 } taskData;662 } taskData;
519};663};
520 664 
@@ -674,15 +818,15 @@ bool ReadTaskMetaData(const char* filename) {
674 switch (task.taskType) {818 switch (task.taskType) {
675 case HccLTaskMetaType::MEM_CPY:819 case HccLTaskMetaType::MEM_CPY:
676 std::cout << "MEM_CPY: "820 std::cout << "MEM_CPY: "
677- << "src=" << task.taskData.transMem.srcRankId821+ << "src=" << task.taskData.transMem.srcDeviceId
678- << ", dst=" << task.taskData.transMem.dstRankId822+ << ", dst=" << task.taskData.transMem.dstDeviceId
679 << ", len=" << task.taskData.transMem.len;823 << ", len=" << task.taskData.transMem.len;
680 break;824 break;
681 825
682 case HccLTaskMetaType::REDUCE:826 case HccLTaskMetaType::REDUCE:
683 std::cout << "REDUCE: "827 std::cout << "REDUCE: "
684- << "src=" << task.taskData.reduce.srcRankId828+ << "src=" << task.taskData.reduce.srcDeviceId
685- << ", dst=" << task.taskData.reduce.dstRankId829+ << ", dst=" << task.taskData.reduce.dstDeviceId
686 << ", count=" << task.taskData.reduce.dataCount;830 << ", count=" << task.taskData.reduce.dataCount;
687 break;831 break;
688 832
@@ -0,0 +1,111 @@
1+# PyTorch 模式运行指南
2+ 
3+HCCL-VM 现可运行 PyTorch 的 `hccl` 集合通信脚本。脚本使用 `torch.multiprocessing.spawn` 启动各设备进程。多 server 示例在同一宿主机上启动多个 Python 主进程,分别模拟各 server。
4+ 
5+## 1. 准备环境
6+ 
7+先按 [README](../README.md) 完成 HCCL-VM 构建安装和 CANN 环境配置,准备已安装兼容版本 `torch`、`torch_npu` 的 Python 虚拟环境。
8+ 
9+```bash
10+cd /path/to/CheckerL2/hccl_vm_install/bin
11+ 
12+# 按需选择通信域配置文件,PyTorch暂时仅支持 Ascend950 系列。
13+./hccl-vm start ascend950_cluster_32_server_normal.yaml
14+```
15+ 
16+进入 `(hvm)$>` 终端后,执行:
17+ 
18+```bash
19+# 启动 PyTorch 模式
20+export HCCL_VM_ENABLE_PYTORCH=1
21+# 激活虚拟环境(如有)
22+source /path/to/torch_test/bin/activate
23+ 
24+# 需要模拟执行时安装 Runner
25+hccl-vm plugin install @runner
26+```
27+ 
28+后续通信域配置、环境变量设置和 Python 启动均在该 HCCL-VM 终端内执行,使 Python 进程继承模拟环境。
29+ 
30+## 2. 单 server 运行
31+ 
32+以 `118` 配置为 1 个 server、8 个设备为例:
33+ 
34+```bash
35+hccl-vm mock-comm 118
36+ 
37+# 直接运行用例即可
38+python -u /path/to/torch/pytorch_test.py \
39+ --master_ip 127.0.0.1 \
40+ --master_port 50001 \
41+ --dev_num 8 \
42+ --server_num 1 \
43+ --server_index 0 \
44+ --data_list 1024 \
45+ --dtype int32 \
46+ --optype sum > server0.log 2>&1
47+```
48+ 
49+## 3. 多 server 运行
50+ 
51+以 `128` 配置为 2 个 server、每个 server 8 个设备,共 16 个 rank为例。两个 server 需要并发启动,使用相同的 master 地址和端口。
52+ 
53+```bash
54+hccl-vm mock-comm 128
55+export HCCL_VM_ENABLE_PYTORCH=1
56+# 激活虚拟环境(如有)
57+source /path/to/torch_test/bin/activate
58+ 
59+# 启动 server 0
60+(
61+ export HCCL_VM_SERVER_INDEX=0
62+ python -u /path/to/torch/pytorch_test.py \
63+ --master_ip 127.0.0.1 \
64+ --master_port 50001 \
65+ --dev_num 8 \
66+ --server_num 2 \
67+ --server_index 0 \
68+ --data_list 1024 \
69+ --dtype int32 \
70+ --optype sum
71+) > server0.log 2>&1 &
72+ 
73+# 启动 server 1
74+(
75+ export HCCL_VM_SERVER_INDEX=1
76+ python -u /path/to/torch/pytorch_test.py \
77+ --master_ip 127.0.0.1 \
78+ --master_port 50001 \
79+ --dev_num 8 \
80+ --server_num 2 \
81+ --server_index 1 \
82+ --data_list 1024 \
83+ --dtype int32 \
84+ --optype sum
85+) > server1.log 2>&1 &
86+ 
87+# 分别等待两个 server 运行结束
88+```
89+ 
90+| 配置项 | 说明 |
91+| --- | --- |
92+| `HCCL_VM_ENABLE_PYTORCH=1` | 启用 PyTorch 适配;设置为 `1`时 `HCCL_VM_SERVER_INDEX` 才生效 |
93+| `HCCL_VM_SERVER_INDEX` | 当前通信域配置中从 0 开始的 server 序号;每个 server 的子进程分别设置 |
94+| `--server_index` | 测试脚本的 server 序号,须与该进程的 `HCCL_VM_SERVER_INDEX` 一致 |
95+| `--dev_num` / `--server_num` | 每个 server 的设备数和 server 总数,须与 `mock-comm` 配置一致 |
96+| `--master_ip` / `--master_port` | 所有 server 使用相同的 rendezvous 地址;本例进程在同一宿主机上,使用 `127.0.0.1:50001`,可自行设置 |
97+| `--data_list` / `--dtype` / `--optype` | 本例执行 1024 个 int32 元素的 AllReduce SUM |
98+ 
99+每个 server 的本地逻辑设备号均为 `0–7`;本例 server 0 对应全局 rank `0–7`,server 1 对应全局 rank `8–15`。括号内设置环境变量可避免两个 server 的索引互相覆盖。脚本按每个 server 相同设备数计算全局 rank,因此其他规模应选择设备数一致的通信域配置。
100+ 
101+## 4. 查看结果
102+ 
103+等待全部进程结束后查看 `server0.log`、`server1.log`,关注退出状态、异常和相关日志输出。
104+ 
105+随后可使用 Checker 进行结果校验:
106+ 
107+```bash
108+hccl-vm plugin run @checker
109+```
110+ 
111+全部用例和校验结束后,执行 `exit` 退出 HCCL-VM 终端。
@@ -0,0 +1,111 @@
1+# PyTorch 模式运行指南
2+ 
3+HCCL-VM 现可运行 PyTorch 的 `hccl` 集合通信脚本。脚本使用 `torch.multiprocessing.spawn` 启动各设备进程。多 server 示例在同一宿主机上启动多个 Python 主进程,分别模拟各 server。
4+ 
5+## 1. 准备环境
6+ 
7+先按 [README](../README.md) 完成 HCCL-VM 构建安装和 CANN 环境配置,准备已安装兼容版本 `torch`、`torch_npu` 的 Python 虚拟环境。
8+ 
9+```bash
10+cd /path/to/CheckerL2/hccl_vm_install/bin
11+ 
12+# 按需选择通信域配置文件,PyTorch暂时仅支持 Ascend950 系列。
13+./hccl-vm start ascend950_cluster_32_server_normal.yaml
14+```
15+ 
16+进入 `(hvm)$>` 终端后,执行:
17+ 
18+```bash
19+# 启动 PyTorch 模式
20+export HCCL_VM_ENABLE_PYTORCH=1
21+# 激活虚拟环境(如有)
22+source /path/to/torch_test/bin/activate
23+ 
24+# 需要模拟执行时安装 Runner
25+hccl-vm plugin install @runner
26+```
27+ 
28+后续通信域配置、环境变量设置和 Python 启动均在该 HCCL-VM 终端内执行,使 Python 进程继承模拟环境。
29+ 
30+## 2. 单 server 运行
31+ 
32+以 `118` 配置为 1 个 server、8 个设备为例:
33+ 
34+```bash
35+hccl-vm mock-comm 118
36+ 
37+# 直接运行用例即可
38+python -u /path/to/torch/pytorch_test.py \
39+ --master_ip 127.0.0.1 \
40+ --master_port 50001 \
41+ --dev_num 8 \
42+ --server_num 1 \
43+ --server_index 0 \
44+ --data_list 1024 \
45+ --dtype int32 \
46+ --optype sum > server0.log 2>&1
47+```
48+ 
49+## 3. 多 server 运行
50+ 
51+以 `128` 配置为 2 个 server、每个 server 8 个设备,共 16 个 rank为例。两个 server 需要并发启动,使用相同的 master 地址和端口。
52+ 
53+```bash
54+hccl-vm mock-comm 128
55+export HCCL_VM_ENABLE_PYTORCH=1
56+# 激活虚拟环境(如有)
57+source /path/to/torch_test/bin/activate
58+ 
59+# 启动 server 0
60+(
61+ export HCCL_VM_SERVER_INDEX=0
62+ python -u /path/to/torch/pytorch_test.py \
63+ --master_ip 127.0.0.1 \
64+ --master_port 50001 \
65+ --dev_num 8 \
66+ --server_num 2 \
67+ --server_index 0 \
68+ --data_list 1024 \
69+ --dtype int32 \
70+ --optype sum
71+) > server0.log 2>&1 &
72+ 
73+# 启动 server 1
74+(
75+ export HCCL_VM_SERVER_INDEX=1
76+ python -u /path/to/torch/pytorch_test.py \
77+ --master_ip 127.0.0.1 \
78+ --master_port 50001 \
79+ --dev_num 8 \
80+ --server_num 2 \
81+ --server_index 1 \
82+ --data_list 1024 \
83+ --dtype int32 \
84+ --optype sum
85+) > server1.log 2>&1 &
86+ 
87+# 分别等待两个 server 运行结束
88+```
89+ 
90+| 配置项 | 说明 |
91+| --- | --- |
92+| `HCCL_VM_ENABLE_PYTORCH=1` | 启用 PyTorch 适配;设置为 `1`时 `HCCL_VM_SERVER_INDEX` 才生效 |
93+| `HCCL_VM_SERVER_INDEX` | 当前通信域配置中从 0 开始的 server 序号;每个 server 的子进程分别设置 |
94+| `--server_index` | 测试脚本的 server 序号,须与该进程的 `HCCL_VM_SERVER_INDEX` 一致 |
95+| `--dev_num` / `--server_num` | 每个 server 的设备数和 server 总数,须与 `mock-comm` 配置一致 |
96+| `--master_ip` / `--master_port` | 所有 server 使用相同的 rendezvous 地址;本例进程在同一宿主机上,使用 `127.0.0.1:50001`,可自行设置 |
97+| `--data_list` / `--dtype` / `--optype` | 本例执行 1024 个 int32 元素的 AllReduce SUM |
98+ 
99+每个 server 的本地逻辑设备号均为 `0–7`;本例 server 0 对应全局 rank `0–7`,server 1 对应全局 rank `8–15`。括号内设置环境变量可避免两个 server 的索引互相覆盖。脚本按每个 server 相同设备数计算全局 rank,因此其他规模应选择设备数一致的通信域配置。
100+ 
101+## 4. 查看结果
102+ 
103+等待全部进程结束后查看 `server0.log`、`server1.log`,关注退出状态、异常和相关日志输出。
104+ 
105+随后可使用 Checker 进行结果校验:
106+ 
107+```bash
108+hccl-vm plugin run @checker
109+```
110+ 
111+全部用例和校验结束后,执行 `exit` 退出 HCCL-VM 终端。
@@ -1868,7 +1868,7 @@ HCCP Network API
1868 1868 
1869##### 落库必要性分类(进程私有候选)1869##### 落库必要性分类(进程私有候选)
1870 1870 
1871-判定依据是**有没有别的进程/组件在运行期真调用库 API**(`Add`/`Get*`/`Update*`/`Delete*`\<sim::X\>);某实体的名字在别的目录出现不算数——原判据把 `cmd` 的 `PrintTable` 转储、以及同名结构体的局部变量误算成了运行期使用,本节按此修正。1871+判定依据是**有没有别的进程/组件在运行期真调用库 API**(`Add`/`Get*`/`Update*`/`Delete*` `<sim::X>`);某实体的名字在别的目录出现不算数——原判据把 `cmd` 的 `PrintTable` 转储、以及同名结构体的局部变量误算成了运行期使用,本节按此修正。
1872 1872 
1873- **C1 跨进程共享**:`src/device_arm`(独立 aarch64 `device` 可执行,单独链接 `db_sim_sqlite_db.cc`)、`src/plugin/runner`、`src/plugin/checker`、`src/store`(shm 通道)、`src/plugin/hccl_plugin_manager.cc` 中存在真库调用 ⇒ 必须落库。1873- **C1 跨进程共享**:`src/device_arm`(独立 aarch64 `device` 可执行,单独链接 `db_sim_sqlite_db.cc`)、`src/plugin/runner`、`src/plugin/checker`、`src/store`(shm 通道)、`src/plugin/hccl_plugin_manager.cc` 中存在真库调用 ⇒ 必须落库。
1874- **C2 拓扑/硬件事实**:由 `src/topo/topo_ascend_cluster_parser.cc` 写入、多进程共读同一份 ⇒ 必须落库。1874- **C2 拓扑/硬件事实**:由 `src/topo/topo_ascend_cluster_parser.cc` 写入、多进程共读同一份 ⇒ 必须落库。
@@ -1868,7 +1868,7 @@ HCCP Network API
1868 1868 
1869##### 落库必要性分类(进程私有候选)1869##### 落库必要性分类(进程私有候选)
1870 1870 
1871-判定依据是**有没有别的进程/组件在运行期真调用库 API**(`Add`/`Get*`/`Update*`/`Delete*`\<sim::X\>);某实体的名字在别的目录出现不算数——原判据把 `cmd` 的 `PrintTable` 转储、以及同名结构体的局部变量误算成了运行期使用,本节按此修正。1871+判定依据是**有没有别的进程/组件在运行期真调用库 API**(`Add`/`Get*`/`Update*`/`Delete*` `<sim::X>`);某实体的名字在别的目录出现不算数——原判据把 `cmd` 的 `PrintTable` 转储、以及同名结构体的局部变量误算成了运行期使用,本节按此修正。
1872 1872 
1873- **C1 跨进程共享**:`src/device_arm`(独立 aarch64 `device` 可执行,单独链接 `db_sim_sqlite_db.cc`)、`src/plugin/runner`、`src/plugin/checker`、`src/store`(shm 通道)、`src/plugin/hccl_plugin_manager.cc` 中存在真库调用 ⇒ 必须落库。1873- **C1 跨进程共享**:`src/device_arm`(独立 aarch64 `device` 可执行,单独链接 `db_sim_sqlite_db.cc`)、`src/plugin/runner`、`src/plugin/checker`、`src/store`(shm 通道)、`src/plugin/hccl_plugin_manager.cc` 中存在真库调用 ⇒ 必须落库。
1874- **C2 拓扑/硬件事实**:由 `src/topo/topo_ascend_cluster_parser.cc` 写入、多进程共读同一份 ⇒ 必须落库。1874- **C2 拓扑/硬件事实**:由 `src/topo/topo_ascend_cluster_parser.cc` 写入、多进程共读同一份 ⇒ 必须落库。
@@ -0,0 +1,135 @@
1+#!/usr/bin/env python3
2+# -*- coding: UTF-8 -*-
3+# -----------------------------------------------------------------------------------------------------------
4+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
5+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
6+# CANN Open Software License Agreement Version 2.0 (the "License").
7+# Please refer to the License for details. You may not use this file except in compliance with the License.
8+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
9+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10+# See LICENSE in the root of the software repository for the full text of the License.
11+# -----------------------------------------------------------------------------------------------------------
12+ 
13+"""light_performance 一键 dump 入口: db → 任务图 → DOT + JSON。
14+ 
15+用法 (仓库根目录执行):
16+ python3 dump_graph.py hccl_vm_install/data/hccl_vm_data.db
17+ python3 dump_graph.py <db> --device 1 --iter 0 --out graph_dump --no-sim
18+ python3 dump_graph.py <db> --html # 额外输出单文件 HTML
19+ 
20+输出 (默认 graph_dump/ 目录):
21+ graph_comm{X}_iter{Y}_dev{Z}.dot graphviz 任务图 (VSCode Graphviz 插件直接预览)
22+ graph_comm{X}_iter{Y}_dev{Z}.json 固定格式任务图 (nodes/streams/matches)
23+"""
24+ 
25+import argparse
26+import os
27+import sys
28+ 
29+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
30+ "src", "plugin"))
31+ 
32+from light_performance.__main__ import _find_ranktable
33+from light_performance.db_reader import load_op_executions
34+from light_performance.graph_builder import GraphBuilder
35+from light_performance.graph_dumper import dump_group
36+from light_performance.sqe_group_merge import merge_sqe_group_tasks, merge_dpu_write_sequences
37+from light_performance.simulator.config import SimConfig
38+from light_performance.simulator.simulator import HcclSimulator
39+from light_performance.simulator.task_model import TRANSFER_TYPES
40+from light_performance.simulator.topo_resolver import TopoResolver
41+ 
42+ 
43+def main():
44+ parser = argparse.ArgumentParser(
45+ description="读取 hccl_vm_data.db, 生成任务依赖图 dump (JSON + HTML)")
46+ parser.add_argument("db", help="hccl_vm_data.db 路径")
47+ parser.add_argument("--device", type=int, default=None,
48+ help="目标 deviceId (默认取 opDetails 首个设备)")
49+ parser.add_argument("--iter", type=int, default=None,
50+ help="仅处理指定 opIter (默认全部)")
51+ parser.add_argument("--ranktable",
52+ help="ranktable.json (eid→端口解析; 默认取 db 同目录)")
53+ parser.add_argument("--out", default="graph_dump",
54+ help="dump 输出目录 (默认 graph_dump)")
55+ parser.add_argument("--no-sim", action="store_true",
56+ help="不执行仿真 (dump 中不含任务时刻信息)")
57+ parser.add_argument("--html", action="store_true",
58+ help="额外输出单文件 HTML 视图")
59+ args = parser.parse_args()
60+ 
61+ if not os.path.isfile(args.db):
62+ print(f"错误: db 文件不存在: {args.db}")
63+ return 1
64+ 
65+ groups = load_op_executions(args.db, target_device=args.device)
66+ if not groups:
67+ print("错误: db 中未读取到算子执行数据")
68+ return 1
69+ if args.iter is not None:
70+ groups = [g for g in groups if g.op_iter == args.iter]
71+ if not groups:
72+ print(f"错误: 未找到 opIter={args.iter}")
73+ return 1
74+ 
75+ os.makedirs(args.out, exist_ok=True)
76+ config = SimConfig()
77+ topo = None
78+ ranktable = _find_ranktable(args.db, args.ranktable)
79+ if ranktable:
80+ topo = TopoResolver(ranktable_path=ranktable)
81+ outputs = []
82+ 
83+ for group in groups:
84+ # SQE 批合并: 同批同键 UDMA 任务并成 1 个 (见 sqe_group_merge), 与 pipeline 入口口径一致
85+ group.tasks, merged = merge_sqe_group_tasks(group.tasks)
86+ if merged:
87+ print(f"[MERGE] comm{group.comm_id}/iter{group.op_iter}: "
88+ f"{merged} 个 UDMA 数据任务并入同组 (剩余 {len(group.tasks)})")
89+ # DPU 序列合并: 大消息前块并入 WRITE_WITH_NOTIFY, 与 pipeline 入口口径一致
90+ group.tasks, merged = merge_dpu_write_sequences(group.tasks)
91+ if merged:
92+ print(f"[MERGE-DPU] comm{group.comm_id}/iter{group.op_iter}: "
93+ f"{merged} 个前块 MEM_CPY 并入 WRITE_WITH_NOTIFY "
94+ f"(剩余 {len(group.tasks)})")
95+ builder = GraphBuilder(group, config)
96+ _, dep = builder.build()
97+ if dep.task_count == 0:
98+ print(f"comm{group.comm_id}/iter{group.op_iter}: 依赖图为空, 跳过")
99+ continue
100+ 
101+ meta = {"op_desc": f"comm{group.comm_id}/iter{group.op_iter}"
102+ f"/dev{group.device_id}",
103+ "op_type": group.op_type, "rank_size": group.rank_size}
104+ if not args.no_sim:
105+ has_transfer = any(t.task_type in TRANSFER_TYPES
106+ for t in dep.tasks.values())
107+ if has_transfer and topo is None:
108+ print(f"comm{group.comm_id}/iter{group.op_iter}: 存在走网任务"
109+ "但无 ranktable, 跳过仿真")
110+ else:
111+ sim = HcclSimulator(config, dep, topo)
112+ result = sim.run()
113+ meta["makespan_us"] = result["makespan"] * 1e6
114+ 
115+ prefix = os.path.join(
116+ args.out,
117+ f"graph_comm{group.comm_id}_iter{group.op_iter}"
118+ f"_dev{group.device_id}")
119+ paths = dump_group(dep, prefix, meta, stats=builder.stats,
120+ stream_labels=builder.stream_labels,
121+ stream_meta=builder.stream_meta,
122+ html=args.html)
123+ outputs.extend(paths)
124+ print(f"[OK] comm{group.comm_id}/iter{group.op_iter}: "
125+ f"{builder.stats.summary()}")
126+ 
127+ print("\n输出文件:")
128+ for path in outputs:
129+ tag = " <- VSCode Graphviz 插件预览" if path.endswith(".dot") else ""
130+ print(f" {path}{tag}")
131+ return 0
132+ 
133+ 
134+if __name__ == "__main__":
135+ sys.exit(main())
@@ -221,10 +221,8 @@ profile_cann_channel() { profile_row "$1" | cut -d'|' -f5; } # CANN 下载通
221show_help() {221show_help() {
222 echo "HCCL-VM 一键安装脚本 $(version_line)"222 echo "HCCL-VM 一键安装脚本 $(version_line)"
223 echo ""223 echo ""
224- echo "新手直接运行,无需任何参数(依赖自动安装;需确认的操作有终端时提示、超时按默认继续):"224+ echo "取得完整 CheckerL2 源码后,在仓库根目录直接运行:"
225- echo " curl -fsSL https://raw.gitcode.com/cann/hcomm/raw/master/test/hccl_vm/hccl_vm_installer | bash"225+ echo " bash ./hccl_vm_installer"
226- echo " curl -fsSL <URL> | bash -s -- --workspace /root/hvm # 一键并指定工作目录"
227- echo " (或下载后本地运行: bash hccl_vm_installer)"
228 echo ""226 echo ""
229 echo "脚本将自动完成以下 9 步:"227 echo "脚本将自动完成以下 9 步:"
230 echo " 1-3. 检查环境、磁盘、安装依赖"228 echo " 1-3. 检查环境、磁盘、安装依赖"
@@ -383,7 +381,7 @@ apply_defaults() {
383 ASCEND_PATH=${ASCEND_PATH:-/usr/local/Ascend}381 ASCEND_PATH=${ASCEND_PATH:-/usr/local/Ascend}
384 HCOMM_PATH=${HCOMM_PATH:-${WORKSPACE}/hcomm}382 HCOMM_PATH=${HCOMM_PATH:-${WORKSPACE}/hcomm}
385 HCCL_PATH=${HCCL_PATH:-${WORKSPACE}/hccl}383 HCCL_PATH=${HCCL_PATH:-${WORKSPACE}/hccl}
386- CHECKER_PATH=${CHECKER_PATH:-${HCOMM_PATH}/test/hccl_vm}384+ CHECKER_PATH=${CHECKER_PATH:-$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)}
387 # 路径统一绝对化:相对路径会在后续 cd 与 precheck_cann_path 的 dirname 回溯中出错385 # 路径统一绝对化:相对路径会在后续 cd 与 precheck_cann_path 的 dirname 回溯中出错
388 WORKSPACE="$(to_abs "${WORKSPACE}")"386 WORKSPACE="$(to_abs "${WORKSPACE}")"
389 ASCEND_PATH="$(to_abs "${ASCEND_PATH}")"387 ASCEND_PATH="$(to_abs "${ASCEND_PATH}")"
@@ -1330,10 +1328,10 @@ build_hcomm_hccl_pkg() {
1330 info "编译日志: ${pkg_log}"1328 info "编译日志: ${pkg_log}"
1331 local rc=01329 local rc=0
1332 if [ "${VERBOSE}" = true ]; then1330 if [ "${VERBOSE}" = true ]; then
1333- bash "${pkg_script}" --tool_path "${CHECKER_PATH}" 2>&1 | tee "${pkg_log}" || rc=${PIPESTATUS[0]}1331+ HCCL_VM_PATH="${CHECKER_PATH}" bash "${pkg_script}" --tool_path "${CHECKER_PATH}" 2>&1 | tee "${pkg_log}" || rc=${PIPESTATUS[0]}
1334 else1332 else
1335 info "开始执行 build_pkg.sh。实时日志: tail -f ${pkg_log}"1333 info "开始执行 build_pkg.sh。实时日志: tail -f ${pkg_log}"
1336- bash "${pkg_script}" --tool_path "${CHECKER_PATH}" > "${pkg_log}" 2>&1 &1334+ HCCL_VM_PATH="${CHECKER_PATH}" bash "${pkg_script}" --tool_path "${CHECKER_PATH}" > "${pkg_log}" 2>&1 &
1337 local pkg_pid=$!1335 local pkg_pid=$!
1338 spin_on_pid "${pkg_pid}" "编译子包中"1336 spin_on_pid "${pkg_pid}" "编译子包中"
1339 wait "${pkg_pid}" || rc=$?1337 wait "${pkg_pid}" || rc=$?
@@ -46,7 +46,8 @@
46 (Version(1), Scope::Static, Field(id, AutoIncrement), Field(pid), Field(deviceId), Field(rankId), \46 (Version(1), Scope::Static, Field(id, AutoIncrement), Field(pid), Field(deviceId), Field(rankId), \
47 Field(commId), Field(opIter), Field(syncIter), Field(streamId), Field(root), Field(opExpansionMode), \47 Field(commId), Field(opIter), Field(syncIter), Field(streamId), Field(root), Field(opExpansionMode), \
48 Field(devType), Field(rankSize), Field(srcRank), Field(dstRank), Field(opDetail), Field(opExtInfo), \48 Field(devType), Field(rankSize), Field(srcRank), Field(dstRank), Field(opDetail), Field(opExtInfo), \
49- PrimaryKey(id), Index(pid, syncIter), Index(commId, deviceId, id), Index(syncIter), Index(deviceId, id))) \49+ Field(algorithmName, Text), PrimaryKey(id), Index(pid, syncIter), Index(commId, deviceId, id), \
50+ Index(syncIter), Index(deviceId, id))) \
50 Table( \51 Table( \
51 sim::operation::OpMemInfoTab, \52 sim::operation::OpMemInfoTab, \
52 (Version(1), Scope::Static, Field(id, AutoIncrement), Field(opDetailId), Field(inputAddr), \53 (Version(1), Scope::Static, Field(id, AutoIncrement), Field(opDetailId), Field(inputAddr), \
@@ -158,6 +159,8 @@ int InsertOpDetail(OpDetailTab& rec);
158int InsertOpMem(OpMemInfoTab& rec);159int InsertOpMem(OpMemInfoTab& rec);
159// OpDetail 与 OpMem 同事务原子提交(多表流程)。160// OpDetail 与 OpMem 同事务原子提交(多表流程)。
160int InsertOpDetailAndMem(OpDetailTab& detail, OpMemInfoTab& mem);161int InsertOpDetailAndMem(OpDetailTab& detail, OpMemInfoTab& mem);
162+// 算法选择结果回填(日志截取): 同一算子多次匹配时后写覆盖 (last-wins),与最终生效算法一致
163+int UpdateOpDetailAlgName(const std::string& algName);
161int QueryNewestOpDeatailIdByPid(uint64_t pid, uint32_t& OpDetailId);164int QueryNewestOpDeatailIdByPid(uint64_t pid, uint32_t& OpDetailId);
162// 同 syncIter 下目标 rank 的最新算子内存信息(组合查询)。165// 同 syncIter 下目标 rank 的最新算子内存信息(组合查询)。
163int QueryCurrentOpMemInfoByRank(uint32_t rankId, OpMemInfoTab& out);166int QueryCurrentOpMemInfoByRank(uint32_t rankId, OpMemInfoTab& out);
@@ -48,6 +48,7 @@ struct OpDetailTab {
48 uint32_t dstRank; // dstRank48 uint32_t dstRank; // dstRank
49 std::vector<uint8_t> opDetail; // BLOB49 std::vector<uint8_t> opDetail; // BLOB
50 std::vector<uint8_t> opExtInfo; // BLOB50 std::vector<uint8_t> opExtInfo; // BLOB
51+ char algorithmName[128]; // 算法选择结果(日志截取回填, last-wins)
51};52};
52 53 
53struct OpMemInfoTab {54struct OpMemInfoTab {
@@ -77,6 +77,8 @@ aclError GetEndPointByEid(const IpAddress& addr, EndPoint& endPoint);
77// EID精确匹配失败时, 若为v4映射EID(高12字节全0+低4字节IPv4, UBOE IPv4链路地址派生),77// EID精确匹配失败时, 若为v4映射EID(高12字节全0+低4字节IPv4, UBOE IPv4链路地址派生),
78// 按低32位IPv4回退匹配EndPoint.ip_addr(与真实驱动v4->EID解析语义一致)78// 按低32位IPv4回退匹配EndPoint.ip_addr(与真实驱动v4->EID解析语义一致)
79aclError GetEndPointByEidOrIpV4(const IpAddress& addr, EndPoint& endPoint);79aclError GetEndPointByEidOrIpV4(const IpAddress& addr, EndPoint& endPoint);
80+// 按EID查ranktable.json记录的rankId(RankEidMap表); estimate模式Communicator表无对端行, 对端rank以此为准
81+bool GetRankIdByEid(const IpAddress& addr, uint32_t& rankId);
80aclError GetPortById(uint64_t portId, Port& port);82aclError GetPortById(uint64_t portId, Port& port);
81 83 
82uint32_t GetAICpuCount(uint64_t deviceId);84uint32_t GetAICpuCount(uint64_t deviceId);
@@ -25,6 +25,15 @@ typedef struct {
25 char file_name[128]; // topo_meta yaml文件名(不含.yaml后缀); "ranktable"表示ranktable.json模式25 char file_name[128]; // topo_meta yaml文件名(不含.yaml后缀); "ranktable"表示ranktable.json模式
26} TopoMetaConfig;26} TopoMetaConfig;
27 27 
28+// ranktable.json的rank_id与EID映射: 一个rank在每个net_layer/net_instance各有一个EID, 故一rank多行;
29+// eid按十六进制串字节序存储(与EndPoint.eid一致), mock-comm时随通信域初始化整体重写。
30+// estimate模式Communicator表只有本rank一行, 对端rankId以此表为准。
31+typedef struct {
32+ uint64_t id; // PK
33+ uint32_t rank_id; // rank_list[].rank_id(文件显式值)
34+ uint8_t eid[URMA_EID_LEN]; // rank_addr_list[].addr
35+} RankEidMap;
36+ 
28typedef struct {37typedef struct {
29 uint64_t id; // PK38 uint64_t id; // PK
30 uint64_t pod_id;39 uint64_t pod_id;
@@ -36,7 +45,7 @@ typedef struct {
36 45 
37typedef struct {46typedef struct {
38 uint64_t id; // PK47 uint64_t id; // PK
39- uint8_t mode; // 0=normal,1=check-only48+ uint8_t mode; // 0=normal,1=check-only,2=estimate (互斥三态)
40} RunModeConfig;49} RunModeConfig;
41 50 
42typedef struct {51typedef struct {
@@ -81,7 +90,9 @@ typedef struct {
81 uint64_t sym_win_addr;90 uint64_t sym_win_addr;
82 uint64_t sym_win_size;91 uint64_t sym_win_size;
83 uint8_t sym_win_registered;92 uint8_t sym_win_registered;
84- uint8_t status; // CommStatus: 销毁同步状态93+ uint8_t status; // CommStatus: 销毁同步状态
94+ uint64_t dpu_mem_addr; // DPU(DPUTAG)共享内存的 host 侧地址(观测用,HostDPU level1 登记)
95+ uint64_t dpu_mem_size; // DPU(DPUTAG)共享内存实际分配尺寸(观测用)
85} Communicator;96} Communicator;
86 97 
87// level 1 专用通信域清理同步机制98// level 1 专用通信域清理同步机制
@@ -103,7 +114,7 @@ typedef struct {
103 uint32_t overflow_mode;114 uint32_t overflow_mode;
104 // 完整SoC型号名(如"Ascend950DT_95A1",16字符)需16+1字节,32对齐hal侧MAX_CHIP_NAME115 // 完整SoC型号名(如"Ascend950DT_95A1",16字符)需16+1字节,32对齐hal侧MAX_CHIP_NAME
105 char soc_version[32];116 char soc_version[32];
106- uint32_t status; // 0 可用, 1不可用117+ uint32_t status; // 设备编域状态:0 未编入通信域, 1 已编入通信域/在线(runner 在线计数、dump 等消费方均按 1 过滤)
107} Device;118} Device;
108 119 
109enum TsDevType { TS_DEV_TYPE_SCALAR = 0, TS_DEV_TYPE_CPU = 1, TS_DEV_TYPE_CCU = 2 };120enum TsDevType { TS_DEV_TYPE_SCALAR = 0, TS_DEV_TYPE_CPU = 1, TS_DEV_TYPE_CCU = 2 };
@@ -19,6 +19,8 @@
19#include <string>19#include <string>
20#include <vector>20#include <vector>
21 21 
22+#include "sim_profiling_defs.h"
23+ 
22#define RT_CCU_SQE_ARGS_LEN (13U)24#define RT_CCU_SQE_ARGS_LEN (13U)
23 25 
24namespace HcclSim {26namespace HcclSim {
@@ -183,9 +185,15 @@ enum class HccLTaskMetaType : char {
183 AIV_GRAPH,185 AIV_GRAPH,
184 SYNC_STREAM,186 SYNC_STREAM,
185 MODEL_EXEC,187 MODEL_EXEC,
188+ WRITE_WITH_NOTIFY,
186 INVALID189 INVALID
187};190};
188 191 
192+typedef enum {
193+ TASK_SRC_DEFAULT = 0,
194+ TASK_SRC_DPU = 1,
195+} HcclTaskSrc;
196+ 
189typedef enum {197typedef enum {
190 SUCCESS = 0,198 SUCCESS = 0,
191 FAILURE = 1,199 FAILURE = 1,
@@ -307,6 +315,29 @@ typedef struct {
307 }315 }
308} NotifyTask;316} NotifyTask;
309 317 
318+typedef struct {
319+ uint32_t srcDeviceId;
320+ uint64_t srcOffset;
321+ uint32_t dstDeviceId;
322+ uint64_t dstOffset;
323+ uint64_t len; // MEM_CPY/REDUCE: 传输长度
324+ uint64_t notifyId;
325+ uint8_t isReduce; // 0: 写部分为MEM_CPY; 1: 写部分为REDUCE
326+ uint8_t dataType; // REDUCE 载荷: HcclDataType
327+ uint8_t reduceOp; // REDUCE 载荷: HcclReduceOp
328+ uint8_t protocol;
329+ uint8_t notifyCount;
330+ 
331+ std::string Describe() const
332+ {
333+ std::ostringstream oss;
334+ oss << "srcDeviceId=" << srcDeviceId << " srcOffset=" << srcOffset << " dstDeviceId=" << dstDeviceId
335+ << " dstOffset=" << dstOffset << " len=" << len << " notifyId=" << notifyId
336+ << " isReduce=" << static_cast<uint32_t>(isReduce);
337+ return oss.str();
338+ }
339+} WriteWithNotifyTask;
340+ 
310typedef struct {341typedef struct {
311 uint8_t dieId;342 uint8_t dieId;
312 uint8_t missionId;343 uint8_t missionId;
@@ -340,12 +371,16 @@ typedef struct {
340 371 
341typedef struct HcclTaskMetaData {372typedef struct HcclTaskMetaData {
342 HccLTaskMetaType taskType;373 HccLTaskMetaType taskType;
374+ HcclTaskProfInfo profInfo; // 整体3字节, checker/runner不使用
343 uint64_t commId;375 uint64_t commId;
344 uint32_t rankId;376 uint32_t rankId;
345 uint64_t deviceId;377 uint64_t deviceId;
346 uint64_t streamId;378 uint64_t streamId;
347 uint32_t jettyId;379 uint32_t jettyId;
380+ uint8_t sqeGroupId; // 多wqe分组标记,环形递增1~255(0=未打标)
381+ uint8_t taskSrc;
348 uint8_t rmEid[16];382 uint8_t rmEid[16];
383+ uint8_t lcEid[16];
349 union {384 union {
350 TransMemTask transMem;385 TransMemTask transMem;
351 ReduceTask reduce;386 ReduceTask reduce;
@@ -354,27 +389,37 @@ typedef struct HcclTaskMetaData {
354 AivTask aiv;389 AivTask aiv;
355 SyncStreamTask syncStreamTask;390 SyncStreamTask syncStreamTask;
356 ModelExecTask modelExec;391 ModelExecTask modelExec;
392+ WriteWithNotifyTask writeWithNotify;
357 } taskData;393 } taskData;
358 394 
359 HcclTaskMetaData()395 HcclTaskMetaData()
360 {396 {
361 taskType = HccLTaskMetaType::INVALID;397 taskType = HccLTaskMetaType::INVALID;
398+ profInfo = HcclTaskProfInfo();
362 commId = 0;399 commId = 0;
363 rankId = UINT32_MAX;400 rankId = UINT32_MAX;
364 deviceId = UINT64_MAX;401 deviceId = UINT64_MAX;
365 streamId = UINT64_MAX;402 streamId = UINT64_MAX;
366 jettyId = UINT32_MAX;403 jettyId = UINT32_MAX;
404+ sqeGroupId = 0;
405+ taskSrc = TASK_SRC_DEFAULT;
367 memset(rmEid, 0, sizeof(rmEid));406 memset(rmEid, 0, sizeof(rmEid));
407+ memset(lcEid, 0, sizeof(lcEid));
368 memset(&taskData, 0, sizeof(taskData));408 memset(&taskData, 0, sizeof(taskData));
369 }409 }
370 410 
371 std::string TaskTypeName() const411 std::string TaskTypeName() const
372 {412 {
373 static const std::map<HccLTaskMetaType, std::string> TASK_NAMES{413 static const std::map<HccLTaskMetaType, std::string> TASK_NAMES{
374- {HccLTaskMetaType::NOTIFY_WAIT, "NOTIFY_WAIT"}, {HccLTaskMetaType::NOTIFY_RECORD, "NOTIFY_RECORD"},414+ {HccLTaskMetaType::NOTIFY_WAIT, "NOTIFY_WAIT"},
375- {HccLTaskMetaType::REDUCE, "REDUCE"}, {HccLTaskMetaType::MEM_CPY, "MEM_CPY"},415+ {HccLTaskMetaType::NOTIFY_RECORD, "NOTIFY_RECORD"},
376- {HccLTaskMetaType::CCU_GRAPH, "CCU_GRAPH"}, {HccLTaskMetaType::AIV_GRAPH, "AIV_GRAPH"},416+ {HccLTaskMetaType::REDUCE, "REDUCE"},
377- {HccLTaskMetaType::SYNC_STREAM, "SYNC_STREAM"}, {HccLTaskMetaType::MODEL_EXEC, "MODEL_EXEC"},417+ {HccLTaskMetaType::MEM_CPY, "MEM_CPY"},
418+ {HccLTaskMetaType::CCU_GRAPH, "CCU_GRAPH"},
419+ {HccLTaskMetaType::AIV_GRAPH, "AIV_GRAPH"},
420+ {HccLTaskMetaType::SYNC_STREAM, "SYNC_STREAM"},
421+ {HccLTaskMetaType::MODEL_EXEC, "MODEL_EXEC"},
422+ {HccLTaskMetaType::WRITE_WITH_NOTIFY, "WRITE_WITH_NOTIFY"},
378 };423 };
379 auto it = TASK_NAMES.find(taskType);424 auto it = TASK_NAMES.find(taskType);
380 return it != TASK_NAMES.end() ? it->second : "INVALID";425 return it != TASK_NAMES.end() ? it->second : "INVALID";
@@ -383,8 +428,8 @@ typedef struct HcclTaskMetaData {
383 std::string Describe() const428 std::string Describe() const
384 {429 {
385 std::ostringstream oss;430 std::ostringstream oss;
386- oss << "taskType=" << TaskTypeName() << " commId=" << commId << " rankId=" << rankId << " deviceId=" << deviceId431+ oss << "taskType=" << TaskTypeName() << " " << profInfo.Describe() << " commId=" << commId
387- << " streamId=" << streamId << " jettyId=" << jettyId;432+ << " rankId=" << rankId << " deviceId=" << deviceId << " streamId=" << streamId << " jettyId=" << jettyId;
388 switch (taskType) {433 switch (taskType) {
389 case HccLTaskMetaType::NOTIFY_WAIT:434 case HccLTaskMetaType::NOTIFY_WAIT:
390 case HccLTaskMetaType::NOTIFY_RECORD:435 case HccLTaskMetaType::NOTIFY_RECORD:
@@ -407,6 +452,8 @@ typedef struct HcclTaskMetaData {
407 break;452 break;
408 case HccLTaskMetaType::MODEL_EXEC:453 case HccLTaskMetaType::MODEL_EXEC:
409 oss << " taskData={" << taskData.modelExec.Describe() << "}";454 oss << " taskData={" << taskData.modelExec.Describe() << "}";
455+ case HccLTaskMetaType::WRITE_WITH_NOTIFY:
456+ oss << " taskData={" << taskData.writeWithNotify.Describe() << "}";
410 break;457 break;
411 default:458 default:
412 break;459 break;
@@ -427,6 +474,40 @@ typedef struct {
427 474 
428#pragma pack(pop)475#pragma pack(pop)
429 476 
477+// WRITE_WITH_NOTIFY 复合任务展开: 拆为 [写子任务(MEM_CPY/REDUCE), NOTIFY_RECORD] 两个子任务,
478+inline void SplitWriteWithNotify(const HcclTaskMetaData& task, HcclTaskMetaData& outWrite, HcclTaskMetaData& outNotify)
479+{
480+ const WriteWithNotifyTask& wn = task.taskData.writeWithNotify;
481+ outWrite = task;
482+ outNotify = task;
483+ if (wn.isReduce == 1) {
484+ outWrite.taskType = HccLTaskMetaType::REDUCE;
485+ outWrite.taskData.reduce.srcDeviceId = wn.srcDeviceId;
486+ outWrite.taskData.reduce.srcOffset = wn.srcOffset;
487+ outWrite.taskData.reduce.dstDeviceId = wn.dstDeviceId;
488+ outWrite.taskData.reduce.dstOffset = wn.dstOffset;
489+ outWrite.taskData.reduce.dataCount = wn.len;
490+ outWrite.taskData.reduce.dataType = wn.dataType;
491+ outWrite.taskData.reduce.reduceOp = wn.reduceOp;
492+ outWrite.taskData.reduce.protocol = wn.protocol;
493+ outWrite.taskData.reduce.resv = 0;
494+ } else {
495+ outWrite.taskType = HccLTaskMetaType::MEM_CPY;
496+ outWrite.taskData.transMem.srcDeviceId = wn.srcDeviceId;
497+ outWrite.taskData.transMem.srcOffset = wn.srcOffset;
498+ outWrite.taskData.transMem.dstDeviceId = wn.dstDeviceId;
499+ outWrite.taskData.transMem.dstOffset = wn.dstOffset;
500+ outWrite.taskData.transMem.len = wn.len;
501+ outWrite.taskData.transMem.protocol = wn.protocol;
502+ }
503+ outNotify.taskType = HccLTaskMetaType::NOTIFY_RECORD;
504+ outNotify.taskData.notify.srcDeviceId = wn.srcDeviceId;
505+ outNotify.taskData.notify.notifyId = wn.notifyId;
506+ outNotify.taskData.notify.dstDeviceId = wn.dstDeviceId;
507+ outNotify.taskData.notify.notifyCount = wn.notifyCount;
508+ outNotify.taskData.notify.protocol = wn.protocol;
509+}
510+ 
430enum BufferType { INPUT = 0, OUTPUT, CCL, RESERVED };511enum BufferType { INPUT = 0, OUTPUT, CCL, RESERVED };
431 512 
432class DataSlice {513class DataSlice {
@@ -0,0 +1,167 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/**
12+ * AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
13+ * for the full text of the License.
14+ */
15+ 
16+#ifndef SIM_PROFILING_DEFS_H
17+#define SIM_PROFILING_DEFS_H
18+ 
19+#include <cstdint>
20+#include <map>
21+#include <sstream>
22+#include <string>
23+ 
24+// profiling 任务类型: 与 hcomm TaskParamType(值域 0~22)
25+enum class ProfTaskParamType : uint8_t {
26+ TASK_SDMA = 0, // profiling op 名: Memcpy
27+ TASK_RDMA, // RDMASend
28+ TASK_REDUCE_INLINE, // Reduce_Inline
29+ TASK_REDUCE_TBE, // Reduce_TBE
30+ TASK_NOTIFY_RECORD, // Notify_Record
31+ TASK_NOTIFY_WAIT, // Notify_Wait
32+ TASK_SEND_NOTIFY, // Send_Notify
33+ TASK_SEND_PAYLOAD, // Send_Payload
34+ TASK_WRITE_WITH_NOTIFY, // Write_With_Notify
35+ TASK_WRITE_REDUCE_WITH_NOTIFY, // Reduce_With_Notify
36+ TASK_CCU, // Ccu
37+ TASK_AICPU_KERNEL, // AicpuKernel
38+ TASK_AICPU_REDUCE, // Aicpu_Reduce
39+ TASK_AIV, // AivKernel
40+ TASK_UB_INLINE_WRITE, // Ub_Inline_Write
41+ TASK_UB_REDUCE_INLINE, // Ub_Reduce_Inline
42+ TASK_UB, // Ub_Write_Or_Read
43+ TASK_DPU_KERNEL, // DpuKernel
44+ TASK_DPU_THREAD_FENCE, // Dpu_ThreadFence
45+ TASK_DPU_CHANNEL_FENCE, // Dpu_ChannelFence
46+ TASK_DPU_INLINE_WRITE, // Dpu_Notify_Record
47+ TASK_DPU_NOTIFY_WAIT, // Dpu_Notify_Wait
48+ TASK_DPU_WRITE_WITH_NOTIFY, // Dpu_Write_With_Notify
49+ UNKNOWN = 0xFF
50+};
51+ 
52+// profiling 链路类型: 与 hcomm DfxLinkType(值域 0~9)
53+enum class ProfLinkType : uint8_t {
54+ LINK_ONCHIP = 0, // 片上/本地
55+ LINK_HCCS = 1, // HCCS
56+ LINK_PCIE = 2, // PCIe(跨片 SDMA 通道)
57+ LINK_ROCE = 3, // RoCE
58+ LINK_SIO = 4, // SIO
59+ LINK_HCCS_SW = 5, // HCCS_SW
60+ LINK_STANDARD_ROCE = 6, // 标准RoCE
61+ LINK_UB = 7, // UB
62+ LINK_UBoE = 8, // UB over Ethernet
63+ LINK_RESERVED = 9, // 预留
64+ UNKNOWN = 0xFF
65+};
66+ 
67+// profiling 传输类型: 与 hcomm DfxTransportType/SimpleTaskType(值域 0~4)
68+enum class ProfTransportType : uint8_t {
69+ TRANSPORT_SDMA = 0, // 跨片 SDMA 通道搬运
70+ TRANSPORT_RDMA = 1, // RDMA
71+ TRANSPORT_LOCAL = 2, // 本地搬运/本地算子
72+ TRANSPORT_UB = 3, // UB 传输
73+ TRANSPORT_ROCE = 4, // RoCE 传输
74+ UNKNOWN = 0xFF
75+};
76+ 
77+// 名称与 hcomm PROF_TASK_OP_NAME_V2(profiling_common.h)一致
78+inline std::string ProfTaskParamTypeName(ProfTaskParamType type)
79+{
80+ static const std::map<ProfTaskParamType, std::string> PROF_TASK_NAMES{
81+ {ProfTaskParamType::TASK_SDMA, "Memcpy"},
82+ {ProfTaskParamType::TASK_RDMA, "RDMASend"},
83+ {ProfTaskParamType::TASK_REDUCE_INLINE, "Reduce_Inline"},
84+ {ProfTaskParamType::TASK_REDUCE_TBE, "Reduce_TBE"},
85+ {ProfTaskParamType::TASK_NOTIFY_RECORD, "Notify_Record"},
86+ {ProfTaskParamType::TASK_NOTIFY_WAIT, "Notify_Wait"},
87+ {ProfTaskParamType::TASK_SEND_NOTIFY, "Send_Notify"},
88+ {ProfTaskParamType::TASK_SEND_PAYLOAD, "Send_Payload"},
89+ {ProfTaskParamType::TASK_WRITE_WITH_NOTIFY, "Write_With_Notify"},
90+ {ProfTaskParamType::TASK_WRITE_REDUCE_WITH_NOTIFY, "Reduce_With_Notify"},
91+ {ProfTaskParamType::TASK_CCU, "Ccu"},
92+ {ProfTaskParamType::TASK_AICPU_KERNEL, "AicpuKernel"},
93+ {ProfTaskParamType::TASK_AICPU_REDUCE, "Aicpu_Reduce"},
94+ {ProfTaskParamType::TASK_AIV, "AivKernel"},
95+ {ProfTaskParamType::TASK_UB_INLINE_WRITE, "Ub_Inline_Write"},
96+ {ProfTaskParamType::TASK_UB_REDUCE_INLINE, "Ub_Reduce_Inline"},
97+ {ProfTaskParamType::TASK_UB, "Ub_Write_Or_Read"},
98+ {ProfTaskParamType::TASK_DPU_KERNEL, "DpuKernel"},
99+ {ProfTaskParamType::TASK_DPU_THREAD_FENCE, "Dpu_ThreadFence"},
100+ {ProfTaskParamType::TASK_DPU_CHANNEL_FENCE, "Dpu_ChannelFence"},
101+ {ProfTaskParamType::TASK_DPU_INLINE_WRITE, "Dpu_Notify_Record"},
102+ {ProfTaskParamType::TASK_DPU_NOTIFY_WAIT, "Dpu_Notify_Wait"},
103+ {ProfTaskParamType::TASK_DPU_WRITE_WITH_NOTIFY, "Dpu_Write_With_Notify"},
104+ };
105+ auto it = PROF_TASK_NAMES.find(type);
106+ return it != PROF_TASK_NAMES.end() ? it->second : "Unknown";
107+}
108+ 
109+// 名称对应 hcomm DfxLinkType 枚举名
110+inline std::string ProfLinkTypeName(ProfLinkType type)
111+{
112+ static const std::map<ProfLinkType, std::string> PROF_LINK_NAMES{
113+ {ProfLinkType::LINK_ONCHIP, "ONCHIP"},
114+ {ProfLinkType::LINK_HCCS, "HCCS"},
115+ {ProfLinkType::LINK_PCIE, "PCIE"},
116+ {ProfLinkType::LINK_ROCE, "ROCE"},
117+ {ProfLinkType::LINK_SIO, "SIO"},
118+ {ProfLinkType::LINK_HCCS_SW, "HCCS_SW"},
119+ {ProfLinkType::LINK_STANDARD_ROCE, "STANDARD_ROCE"},
120+ {ProfLinkType::LINK_UB, "UB"},
121+ {ProfLinkType::LINK_UBoE, "UBoE"},
122+ {ProfLinkType::LINK_RESERVED, "RESERVED"},
123+ };
124+ auto it = PROF_LINK_NAMES.find(type);
125+ return it != PROF_LINK_NAMES.end() ? it->second : "Unknown";
126+}
127+ 
128+// 名称对应 hcomm DfxTransportType/SimpleTaskType 枚举名
129+inline std::string ProfTransportTypeName(ProfTransportType type)
130+{
131+ static const std::map<ProfTransportType, std::string> PROF_TRANSPORT_NAMES{
132+ {ProfTransportType::TRANSPORT_SDMA, "SDMA"}, {ProfTransportType::TRANSPORT_RDMA, "RDMA"},
133+ {ProfTransportType::TRANSPORT_LOCAL, "LOCAL"}, {ProfTransportType::TRANSPORT_UB, "UB"},
134+ {ProfTransportType::TRANSPORT_ROCE, "ROCE"},
135+ };
136+ auto it = PROF_TRANSPORT_NAMES.find(type);
137+ return it != PROF_TRANSPORT_NAMES.end() ? it->second : "Unknown";
138+}
139+ 
140+// 任务 profiling 信息: 值域对齐 hcomm TaskParamType/DfxLinkType/DfxTransportType
141+struct HcclTaskProfInfo {
142+ ProfTaskParamType profTaskType; // profiling 类型
143+ ProfLinkType linkType; // 物理链路类型
144+ ProfTransportType transportType; // 数据面传输方式
145+ 
146+ HcclTaskProfInfo()
147+ : profTaskType(ProfTaskParamType::UNKNOWN),
148+ linkType(ProfLinkType::UNKNOWN),
149+ transportType(ProfTransportType::UNKNOWN)
150+ {}
151+ 
152+ HcclTaskProfInfo(ProfTaskParamType taskType, ProfLinkType link, ProfTransportType transport)
153+ : profTaskType(taskType),
154+ linkType(link),
155+ transportType(transport)
156+ {}
157+ 
158+ std::string Describe() const
159+ {
160+ std::ostringstream oss;
161+ oss << "profTaskType=" << ProfTaskParamTypeName(profTaskType) << " linkType=" << ProfLinkTypeName(linkType)
162+ << " transportType=" << ProfTransportTypeName(transportType);
163+ return oss.str();
164+ }
165+};
166+ 
167+#endif // SIM_PROFILING_DEFS_H
@@ -109,7 +109,6 @@ private:
109 109 
110 std::mutex m_mutex;110 std::mutex m_mutex;
111 std::vector<void*> m_pages;111 std::vector<void*> m_pages;
112- BatchCache m_batchCache;
113};112};
114 113 
115} // namespace sim114} // namespace sim
@@ -11,12 +11,42 @@
11#ifndef STORE_SIM_RUN_MODE_H11#ifndef STORE_SIM_RUN_MODE_H
12#define STORE_SIM_RUN_MODE_H12#define STORE_SIM_RUN_MODE_H
13 13 
14+#include <cstdint>
15+#include <string>
16+ 
14namespace sim {17namespace sim {
18+// RunModeConfig.mode 的互斥三态取值
19+enum RunModeValue : uint8_t {
20+ RUN_MODE_NORMAL = 0,
21+ RUN_MODE_CHECK_ONLY = 1,
22+ RUN_MODE_ESTIMATE = 2,
23+};
24+ 
15// 读 DB 的 RunModeConfig,返回是否仅校验模式,不缓存。表为空返回 false。25// 读 DB 的 RunModeConfig,返回是否仅校验模式,不缓存。表为空返回 false。
16bool ProbeCheckOnlyMode();26bool ProbeCheckOnlyMode();
17 27 
18// 进程内只读一次并缓存结果。28// 进程内只读一次并缓存结果。
19bool IsCheckOnlyMode();29bool IsCheckOnlyMode();
30+ 
31+// 读 DB 的 RunModeConfig,返回是否评估模式,不缓存。表为空返回 false。
32+bool ProbeEstimateMode();
33+ 
34+// 进程内只读一次并缓存结果。惰性求值:首次调用发生在算子执行期,
35+// 此时 cmd 层已写入 RunModeConfig,避免了 .so 加载期读空表。
36+bool IsEstimateMode();
37+ 
38+// 重置模式缓存,供 mode 命令切换后刷新。
39+void ResetRunModeCache();
40+ 
41+// mode 值到日志可读名的映射:normal / check-only / estimate。
42+const char* ModeName(uint8_t mode);
43+ 
44+// mode 值到子 bash 提示符的单一映射,保证各进程显示一致。
45+// 0 -> "(hvm)$> ",1 -> "(chk-only)$> ",2 -> "(estimate)$> ",未知值回退 "(hvm)$> "。
46+std::string GetRunModePrompt(uint8_t mode);
47+ 
48+// 读 DB 的 RunModeConfig 后映射提示符。供 checker 等无法访问 cmd 层全局的进程使用。
49+std::string GetRunModePrompt();
20} // namespace sim50} // namespace sim
21 51 
22#endif // STORE_SIM_RUN_MODE_H52#endif // STORE_SIM_RUN_MODE_H
@@ -78,13 +78,13 @@ pre-commit run --files path/to/file1.cc path/to/file2.h
78 78 
79```bash79```bash
80# 检查指定文件80# 检查指定文件
81-./pre-commit_check.sh path/to/file1.cc path/to/file2.h81+bash ./pre-commit_check.sh path/to/file1.cc path/to/file2.h
82 82 
83# 检查 git 中已修改的文件(最常用,--modified 或 -modified 均可)83# 检查 git 中已修改的文件(最常用,--modified 或 -modified 均可)
84-./pre-commit_check.sh --modified84+bash ./pre-commit_check.sh --modified
85 85 
86# 检查仓库所有 C/C++ 文件(--all 或 -all 均可)86# 检查仓库所有 C/C++ 文件(--all 或 -all 均可)
87-./pre-commit_check.sh --all87+bash ./pre-commit_check.sh --all
88```88```
89 89 
90**输出示例:**90**输出示例:**
@@ -78,13 +78,13 @@ pre-commit run --files path/to/file1.cc path/to/file2.h
78 78 
79```bash79```bash
80# 检查指定文件80# 检查指定文件
81-./pre-commit_check.sh path/to/file1.cc path/to/file2.h81+bash ./pre-commit_check.sh path/to/file1.cc path/to/file2.h
82 82 
83# 检查 git 中已修改的文件(最常用,--modified 或 -modified 均可)83# 检查 git 中已修改的文件(最常用,--modified 或 -modified 均可)
84-./pre-commit_check.sh --modified84+bash ./pre-commit_check.sh --modified
85 85 
86# 检查仓库所有 C/C++ 文件(--all 或 -all 均可)86# 检查仓库所有 C/C++ 文件(--all 或 -all 均可)
87-./pre-commit_check.sh --all87+bash ./pre-commit_check.sh --all
88```88```
89 89 
90**输出示例:**90**输出示例:**
@@ -0,0 +1,77 @@
1+#!/usr/bin/env python3
2+# -*- coding: UTF-8 -*-
3+# -----------------------------------------------------------------------------------------------------------
4+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
5+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
6+# CANN Open Software License Agreement Version 2.0 (the "License").
7+# Please refer to the License for details. You may not use this file except in compliance with the License.
8+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
9+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10+# See LICENSE in the root of the software repository for the full text of the License.
11+# -----------------------------------------------------------------------------------------------------------
12+ 
13+"""light_performance 一键性能仿真入口: db → 任务图 → 仿真 → perf_profiling.json。
14+ 
15+pipeline 实现收编于 light_performance/pipeline.py, 与安装树 @estimate 插件入口
16+(light_performance/main.py, 由 `hccl-vm plugin run @estimate` 触发) 共用同一
17+实现 (设计文档 3.1 节); 本脚本仅为源码树手动调试的 CLI 包装。
18+ 
19+用法 (仓库根目录执行):
20+ python3 run_perf_sim.py hccl_vm_install/data/hccl_vm_data.db
21+ python3 run_perf_sim.py <db> -o perf.json --config src/plugin/light_performance/sim_config.json
22+ python3 run_perf_sim.py <db> --device 1 --iter 0 --trace-dir trace/ --dump-dir graph_dump/
23+ 
24+说明:
25+ - ranktable.json 缺省取 db 同目录 (eid→端口解析, 走网任务必需);
26+ 缺失时该算子跳过仿真 (不产生 trace 事件), 仅输出任务图 dump。
27+ - --dump-dir 额外输出任务图 (DOT/JSON/HTML); --trace-dir 额外输出单算子
28+ Chrome tracing 文件 (每算子一个, 格式同 perf_profiling.json)。
29+"""
30+ 
31+from __future__ import annotations
32+ 
33+import argparse
34+import os
35+import sys
36+ 
37+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
38+ "src", "plugin"))
39+ 
40+from light_performance.pipeline import run_perf_pipeline
41+ 
42+ 
43+def main():
44+ parser = argparse.ArgumentParser(
45+ description="light_performance 一键仿真: db → 任务图 → 仿真 → "
46+ "perf_profiling.json (Chrome tracing 格式, 设计文档 1.1 节)")
47+ parser.add_argument("db", help="hccl_vm_data.db 路径")
48+ parser.add_argument("-o", "--out", default="perf_profiling.json",
49+ help="输出 json 路径 (默认 perf_profiling.json)")
50+ parser.add_argument("--config", help="时延/带宽配置 JSON (单位 us/GBps)")
51+ parser.add_argument("--bw-profile", help="带宽利用率配置 JSON")
52+ parser.add_argument("--ranktable",
53+ help="ranktable.json (默认取 db 同目录)")
54+ parser.add_argument("--device", type=int, default=None,
55+ help="目标 deviceId (默认取 opDetails 首个设备)")
56+ parser.add_argument("--iter", type=int, default=None,
57+ help="仅仿真指定 opIter (默认全部)")
58+ parser.add_argument("--trace-dir", metavar="DIR",
59+ help="额外输出单算子 Chrome tracing (每算子一个文件)")
60+ parser.add_argument("--dump-dir", metavar="DIR",
61+ help="额外输出任务图 dump (DOT/JSON, 每算子)")
62+ args = parser.parse_args()
63+ 
64+ return run_perf_pipeline(
65+ args.db, args.out,
66+ config_path=args.config,
67+ bw_profile_path=args.bw_profile,
68+ ranktable_path=args.ranktable,
69+ device=args.device,
70+ iter_filter=args.iter,
71+ trace_dir=args.trace_dir,
72+ dump_dir=args.dump_dir,
73+ )
74+ 
75+ 
76+if __name__ == "__main__":
77+ sys.exit(main())
Rtest/hccl_vm/test/test.txt→test/hccl_vm/test/test.md+1-1