已合并
同步 CheckerL2 最新代码到 hccl_vm #4305
git_qk创建于 7月31日
同步 CheckerL2 最新代码到 hccl_vm #4305
已合并
git_qk创建于 7月31日
105 个文件变更+4603-975
@@ -41,6 +41,13 @@ if(NOT DEFINED ASCEND_CANN_PACKAGE_PATH)
41endif()41endif()
42message(STATUS "ASCEND_CANN_PACKAGE_PATH: ${ASCEND_CANN_PACKAGE_PATH}")42message(STATUS "ASCEND_CANN_PACKAGE_PATH: ${ASCEND_CANN_PACKAGE_PATH}")
43 43 
44+if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)")
45+ set(CANN_ARCH_DIR "aarch64-linux")
46+else()
47+ set(CANN_ARCH_DIR "x86_64-linux")
48+endif()
49+message(STATUS "CANN_ARCH_DIR: ${CANN_ARCH_DIR} (processor: ${CMAKE_SYSTEM_PROCESSOR})")
50+ 
44if(BUILD_DEVICE_ARM)51if(BUILD_DEVICE_ARM)
45 if(NOT DEFINED HCCL_CODE_ROOT)52 if(NOT DEFINED HCCL_CODE_ROOT)
46 if(NOT DEFINED ENV{HCCL_CODE_HOME})53 if(NOT DEFINED ENV{HCCL_CODE_HOME})
@@ -155,6 +162,7 @@ if(BUILD_DEVICE_ARM)
155 -DTHRID_PARTY_DIR=${THRID_PARTY_DIR}162 -DTHRID_PARTY_DIR=${THRID_PARTY_DIR}
156 -DHCCL_VM_INCLUDE=${HCCL_VM_INCLUDE}163 -DHCCL_VM_INCLUDE=${HCCL_VM_INCLUDE}
157 -DASCEND_CANN_PACKAGE_PATH=${ASCEND_CANN_PACKAGE_PATH}164 -DASCEND_CANN_PACKAGE_PATH=${ASCEND_CANN_PACKAGE_PATH}
165+ -DCANN_ARCH_DIR=${CANN_ARCH_DIR}
158 -DHCOMM_CODE_ROOT=${HCOMM_CODE_ROOT}166 -DHCOMM_CODE_ROOT=${HCOMM_CODE_ROOT}
159 -DHCCL_CODE_ROOT=${HCCL_CODE_ROOT}167 -DHCCL_CODE_ROOT=${HCCL_CODE_ROOT}
160 168
@@ -677,7 +677,7 @@ Runner插件支持通过 `hccl-vm plugin install/uninstall` 命令进行安装
677Checker插件,即算法分析器插件:功能是将hccl生成的所有task形成一个DAG图,并且通过分析DAG图,判断是否存在内存冲突;通过模拟执行DAG图,判断是否存在语义错误等问题。677Checker插件,即算法分析器插件:功能是将hccl生成的所有task形成一个DAG图,并且通过分析DAG图,判断是否存在内存冲突;通过模拟执行DAG图,判断是否存在语义错误等问题。
678算法分析器插件,是由用户自行通过命令启动执行。678算法分析器插件,是由用户自行通过命令启动执行。
679 679 
680-Checker插件正处于新旧交替阶段,Checker V3为原Checker的重构版,主要提高了校验性能,在默认情况下将会运行新Checker(Checker V3),可以通过修改Checker的`manifest.json`文件中的配置参数进行调整。680+Checker插件正处于新旧交替阶段,Checker V3为原Checker的重构版,主要提高了校验性能,在默认情况下将会运行新Checker(Checker V3)。Checker V3大图校验默认开启:每个sync window内的多个算子会合并成一张大图执行跨算子同步资源冲突校验。大图校验与老Checker、新Checker的开关相互独立,可以通过修改Checker的`manifest.json`文件中的配置参数进行调整。
681 681 
682```bash682```bash
683 683 
@@ -693,6 +693,7 @@ Checker插件正处于新旧交替阶段,Checker V3为原Checker的重构版
693 "setting": { // Checker插件配置项693 "setting": { // Checker插件配置项
694 "enable_new_checker": true, // 是否启用新Checker(Checker V3,默认开启)694 "enable_new_checker": true, // 是否启用新Checker(Checker V3,默认开启)
695 "enable_old_checker": false, // 是否启用老Checker(默认关闭)695 "enable_old_checker": false, // 是否启用老Checker(默认关闭)
696+ "enable_big_graph_checker": true, // 是否启用Checker V3大图校验(默认开启,与old/new checker独立)
696 "enable_insight_dump": false, // 是否启用可视化数据输出(默认关闭,仅支持老Checker)697 "enable_insight_dump": false, // 是否启用可视化数据输出(默认关闭,仅支持老Checker)
697 "enable_memory_snapshot_dump": false // 是否启用可视化内存快照数据输出(默认关闭,仅支持老Checker,需要先开启可视化数据输出"enable_insight_dump")698 "enable_memory_snapshot_dump": false // 是否启用可视化内存快照数据输出(默认关闭,仅支持老Checker,需要先开启可视化数据输出"enable_insight_dump")
698 }699 }
@@ -767,6 +768,8 @@ data_size(Bytes): | aveg_time(us): | alg_bandwidth(GB/s): | check_result:
767 768 
768在hccl-vm终端内执行hccl-vm plugin run @checker后,Checker校验流程及结果会打印在终端内,用于需关注是否存在[error]级别日志和最终校验结果:769在hccl-vm终端内执行hccl-vm plugin run @checker后,Checker校验流程及结果会打印在终端内,用于需关注是否存在[error]级别日志和最终校验结果:
769 770 
771+大图校验按每个sync window执行一次。大图校验失败不会阻断其他校验流程,需通过日志中的`BigGraphCheckerV3 failed``Big graph sync-conflict check failed``error`级别日志识别。
772+ 
770```bash773```bash
771[info][PID:144373][TID:144880][main.cc][RunChecker] [RunChecker] op[0] Checker Success.774[info][PID:144373][TID:144880][main.cc][RunChecker] [RunChecker] op[0] Checker Success.
772```775```
@@ -102,6 +102,16 @@ fi
102# 5.获得CANN安装目录: ASCEND_INSTALL_PATH102# 5.获得CANN安装目录: ASCEND_INSTALL_PATH
103ASCEND_INSTALL_PATH=$(dirname "$ASCEND_HOME_PATH")103ASCEND_INSTALL_PATH=$(dirname "$ASCEND_HOME_PATH")
104 104 
105+MACHINE_ARCH=$(uname -m)
106+if [ "$MACHINE_ARCH" = "aarch64" ] || [ "$MACHINE_ARCH" = "arm64" ]; then
107+ CANN_ARCH_DIR="aarch64-linux"
108+else
109+ CANN_ARCH_DIR="x86_64-linux"
110+fi
111+ 
112+echo "CANN_ARCH_DIR: $CANN_ARCH_DIR (processor: $MACHINE_ARCH)"
113+ 
114+ 
105echo "--- 环境变量解析成功 ---"115echo "--- 环境变量解析成功 ---"
106echo "HCCL_VM_PATH: $HCCL_VM_PATH"116echo "HCCL_VM_PATH: $HCCL_VM_PATH"
107echo "ASCEND_INSTALL_PATH: $ASCEND_INSTALL_PATH"117echo "ASCEND_INSTALL_PATH: $ASCEND_INSTALL_PATH"
@@ -132,7 +142,7 @@ if [ "$BUILD_HCOMM" = true ]; then
132 if [ $? -eq 0 ]; then142 if [ $? -eq 0 ]; then
133 echo "HCOMM 构建成功,准备安装..."143 echo "HCOMM 构建成功,准备安装..."
134 # 自动匹配版本号run包144 # 自动匹配版本号run包
135- CANN_HCOMM_PACKAGE=$(ls -t "$HCOMM_CODE_HOME"/build_out/cann-hcomm_*_linux-x86_64.run | head -n 1)145+ CANN_HCOMM_PACKAGE=$(ls -t "$HCOMM_CODE_HOME"/build_out/cann-hcomm_*_linux-${MACHINE_ARCH}.run | head -n 1)
136 146
137 # 检查是否找到安装包147 # 检查是否找到安装包
138 if [ ! -f "$CANN_HCOMM_PACKAGE" ]; then148 if [ ! -f "$CANN_HCOMM_PACKAGE" ]; then
@@ -161,7 +171,7 @@ if [ "$BUILD_HCCL" = true ]; then
161 if [ $? -eq 0 ]; then171 if [ $? -eq 0 ]; then
162 echo "HCCL 构建成功,准备安装..."172 echo "HCCL 构建成功,准备安装..."
163 # 自动匹配版本号run包173 # 自动匹配版本号run包
164- CANN_HCCL_PACKAGE=$(ls -t "$HCCL_CODE_HOME"/build_out/cann-hccl_*_linux-x86_64.run | head -n 1)174+ CANN_HCCL_PACKAGE=$(ls -t "$HCCL_CODE_HOME"/build_out/cann-hccl_*_linux-${MACHINE_ARCH}.run | head -n 1)
165 175
166 # 检查是否找到安装包176 # 检查是否找到安装包
167 if [ ! -f "$CANN_HCCL_PACKAGE" ]; then177 if [ ! -f "$CANN_HCCL_PACKAGE" ]; then
@@ -8,6 +8,7 @@
8# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
9 9 
10# HCCL-VM 一键安装:装依赖 -> 检测 CANN -> 拉取公开源码(hcomm/hccl) -> 编译。10# HCCL-VM 一键安装:装依赖 -> 检测 CANN -> 拉取公开源码(hcomm/hccl) -> 编译。
11+# 支持架构:x86_64 / aarch64
11#12#
12# ============================ 依赖关系说明 ============================13# ============================ 依赖关系说明 ============================
13# 组件角色:14# 组件角色:
@@ -67,6 +68,7 @@ CANN_RUN_FILE="" # 实际下载到的 .run 文件全路径(收尾
67CANN_CHANNEL="master" # CANN 镜像下载通道,apply_defaults 按 profile 落定(campus=legacy / main=master)68CANN_CHANNEL="master" # CANN 镜像下载通道,apply_defaults 按 profile 落定(campus=legacy / main=master)
68HCCL_TEST_RESULT="" # build_hccl_test 写入:built | skipped | failed:<原因>69HCCL_TEST_RESULT="" # build_hccl_test 写入:built | skipped | failed:<原因>
69HCCL_TEST_BIN_DIR="" # build_hccl_test 写入:hccl_test 可执行文件所在目录(原地编译)70HCCL_TEST_BIN_DIR="" # build_hccl_test 写入:hccl_test 可执行文件所在目录(原地编译)
71+PKG_MGR="" # detect_pkg_mgr 写入:apt(Ubuntu/Debian)或 dnf(HCE/openEuler/EulerOS)
70SUDO_PREFIX="" # setup_sudo 解析:root 为空;非 root 有 sudo 为 "sudo"72SUDO_PREFIX="" # setup_sudo 解析:root 为空;非 root 有 sudo 为 "sudo"
71SUDO_KEEPALIVE_PID="" # sudo 授权保活后台进程 PID(cleanup_sudo 负责回收)73SUDO_KEEPALIVE_PID="" # sudo 授权保活后台进程 PID(cleanup_sudo 负责回收)
72STEP_TOTAL=9 # 编译 HCCL-VM(7) → 编译安装子包(8) → 编译 hccl_test(9)74STEP_TOTAL=9 # 编译 HCCL-VM(7) → 编译安装子包(8) → 编译 hccl_test(9)
@@ -129,13 +131,17 @@ success_summary() {
129 [ -n "${CANN_RUN_FILE}" ] && info "CANN 安装包(已保留): ${CANN_RUN_FILE}"131 [ -n "${CANN_RUN_FILE}" ] && info "CANN 安装包(已保留): ${CANN_RUN_FILE}"
130 local inst="${CHECKER_PATH}/hccl_vm_install"132 local inst="${CHECKER_PATH}/hccl_vm_install"
131 local setenv="${ASCEND_HOME_PATH:-<CANN>/ascend-toolkit}/set_env.sh"133 local setenv="${ASCEND_HOME_PATH:-<CANN>/ascend-toolkit}/set_env.sh"
134+ local mpirun_extra=""
135+ if [ "$(normalize_arch "$(uname -m)" 2>/dev/null)" = "x86_64" ]; then
136+ mpirun_extra="--allow-run-as-root --oversubscribe"
137+ fi
132 if [ "${HCCL_TEST_RESULT}" = built ]; then138 if [ "${HCCL_TEST_RESULT}" = built ]; then
133 info "后续步骤(可直接复制,运行一个 hccl_test 用例并由 checker 校验):"139 info "后续步骤(可直接复制,运行一个 hccl_test 用例并由 checker 校验):"
134 echo " source ${setenv}" >&2140 echo " source ${setenv}" >&2
135 echo " source ${inst}/script/hccl_config.sh # 设 RANK_TABLE_FILE 等运行变量" >&2141 echo " source ${inst}/script/hccl_config.sh # 设 RANK_TABLE_FILE 等运行变量" >&2
136 echo " cd ${inst}/bin && ./hccl-vm start ascend950_cluster_32_server_normal.yaml" >&2142 echo " cd ${inst}/bin && ./hccl-vm start ascend950_cluster_32_server_normal.yaml" >&2
137 echo " (hvm)\$> hccl-vm mock-comm 112" >&2143 echo " (hvm)\$> hccl-vm mock-comm 112" >&2
138- echo " (hvm)\$> mpirun --allow-run-as-root --oversubscribe -np 2 ${HCCL_TEST_BIN_DIR:-${WORKSPACE}/hccl_test/bin}/alltoall_test -b 64 -e 64 -d int32 -o sum -w 0 -n 1 -c 1" >&2144+ echo " (hvm)\$> mpirun ${mpirun_extra} -np 2 ${HCCL_TEST_BIN_DIR:-${WORKSPACE}/hccl_test/bin}/alltoall_test -b 64 -e 64 -d int32 -o sum -w 0 -n 1 -c 1" >&2
139 echo " (hvm)\$> hccl-vm plugin run @checker" >&2145 echo " (hvm)\$> hccl-vm plugin run @checker" >&2
140 echo " (hvm)\$> exit" >&2146 echo " (hvm)\$> exit" >&2
141 else147 else
@@ -149,11 +155,29 @@ success_summary() {
149 fi155 fi
150}156}
151 157 
152-# 检查 apt 包是否已安装(dpkg-query 精确查询,无管道,避免 dpkg -l|grep 在 pipefail 下被 SIGPIPE 误判)158+# 检查系统包是否已安装:apt 系Ubuntu/Debian)用 dpkg-query 精确查询
159+# dnf 系(HCE/openEuler/EulerOS/CentOS)用 rpm -q 查询。需在 check_env 中调用 detect_pkg_mgr 后使用。
153check_package() {160check_package() {
154- local status161+ if [ "${PKG_MGR:-}" = "apt" ]; then
155- status="$(dpkg-query -W -f='${Status}' "$1" 2>/dev/null)" || return 1162+ local status
156- [ "$status" = "install ok installed" ]163+ status="$(dpkg-query -W -f='${Status}' "$1" 2>/dev/null)" || return 1
164+ [ "$status" = "install ok installed" ]
165+ elif [ "${PKG_MGR:-}" = "dnf" ]; then
166+ rpm -q "$1" &>/dev/null
167+ else
168+ return 1
169+ fi
170+}
171+ 
172+# 检测包管理器:apt(Ubuntu/Debian)或 dnf(HCE/openEuler/EulerOS/CentOS/RHEL);均未找到留空
173+detect_pkg_mgr() {
174+ if command -v apt-get &>/dev/null; then
175+ PKG_MGR="apt"
176+ elif command -v dnf &>/dev/null; then
177+ PKG_MGR="dnf"
178+ else
179+ PKG_MGR=""
180+ fi
157}181}
158 182 
159# 判断操作系统是否受支持(仅 Linux)183# 判断操作系统是否受支持(仅 Linux)
@@ -427,30 +451,31 @@ cann_phase1_decide() {
427 return 0451 return 0
428}452}
429 453 
430-# 运行环境自检:必须 Linux + 具备 apt + 受支持架构454+# 运行环境自检:必须 Linux + 具备 apt 或 dnf + 受支持架构(x86_64 / aarch64)
431check_env() {455check_env() {
432 if ! is_supported_os "$(uname -s)"; then456 if ! is_supported_os "$(uname -s)"; then
433 error "本工具仅支持 Linux。Windows 请在 WSL2 或远端 Linux 中运行。"457 error "本工具仅支持 Linux。Windows 请在 WSL2 或远端 Linux 中运行。"
434 fi458 fi
435- if ! command -v apt-get &> /dev/null; then459+ # 检测包管理器:apt(Ubuntu/Debian)或 dnf(HCE/openEuler/EulerOS);均未找到则报错
436- error "未检测到 apt-get。本工具按 checker 官方要求支持 x86_64 Ubuntu 22.04 及以上(apt)。460+ detect_pkg_mgr
437- apt 系统请在 Ubuntu 22.04+ 上运行,或手动安装等价依赖后用 --hcomm-path/--hccl-path 复用已备源码:461+ if [ -z "${PKG_MGR}" ]; then
462+ error "未检测到 apt-get 或 dnf。本工具支持 Ubuntu 22.04+(apt)或 Huawei Cloud EulerOS(dnf)。
463+ 其他发行版请手动安装等价依赖后用 --hcomm-path/--hccl-path 复用已备源码:
438 $(dependency_list | tr '\n' ' ')"464 $(dependency_list | tr '\n' ' ')"
439 fi465 fi
440 if ! normalize_arch "$(uname -m)" &> /dev/null; then466 if ! normalize_arch "$(uname -m)" &> /dev/null; then
441- error "不支持的架构: $(uname -m)(仅 x86_64 / aarch64)。请换用 x86_64 环境。"467+ error "不支持的架构: $(uname -m)(仅 x86_64 / aarch64)。请换用 x86_64 或 aarch64 环境。"
442 fi468 fi
443- # 非官方验证环境软警告(不阻断):官方验证 x86_64 Ubuntu 22.04+469+ # 非受支持架构软警告(不阻断):仅 x86_64 / aarch64 为受支持架构,其他架构报错已在上面处理
444- if [ "$(uname -m)" != "x86_64" ]; then470+ # Ubuntu 版本检查仅对 apt 系有意义;dnf 系(HCE/openEuler)无 Ubuntu 版本号,跳过
445- warn "当前架构 $(uname -m) 非官方验证环境(官方仅验证 x86_64);可继续,但编译失败概率较高,出问题请优先换 x86_64。"471+ if [ "${PKG_MGR}" = "apt" ] && ! ubuntu_version_ok; then
446- fi472+ warn "当前系统非 Ubuntu 22.04+(官方验证 x86_64 / aarch64 Ubuntu 22.04+);可继续,但遇到编译问题请优先换官方环境。"
447- if ! ubuntu_version_ok; then
448- warn "当前系统非 Ubuntu 22.04+(官方仅验证该版本);可继续,但遇到编译问题请优先换官方环境。"
449 fi473 fi
450 # gcc 版本软警告(不阻断,与架构/OS 警告同档):hcomm build.md 前置依赖要求 gcc 7.3.0–13.3.x。474 # gcc 版本软警告(不阻断,与架构/OS 警告同档):hcomm build.md 前置依赖要求 gcc 7.3.0–13.3.x。
451- # 该约束同时管宿主与 aarch64 交叉编译器(device_arm 用系统交叉 gcc 编)。超范围(如 Ubuntu 25.04475+ # x86_64 宿主该约束同时管宿主 gcc 与 aarch64 交叉编译器(device_arm 用系统交叉 gcc 编)
452- # gcc14 / 26.04 gcc15)可能因新 gcc 移除头文件间接包含、第三方(yaml-cpp 0.8.0 等)未适配而编译失败——476+ # aarch64 本机构筑仅管系统 gcc。超范围(如 Ubuntu 25.04 gcc14 / 26.04 gcc15)可能因新 gcc 移除
453- # 属超出官方工具链范围,非本脚本缺陷。此处仅告警并继续尝试(编译器会在真不兼容时报真错)。477+ # 头文件间接包含、第三方(yaml-cpp 0.8.0 等)未适配而编译失败——属超出官方工具链范围,非本脚本缺陷。
478+ # 此处仅告警并继续尝试(编译器会在真不兼容时报真错)。
454 local _gcc_major479 local _gcc_major
455 _gcc_major="$(gcc -dumpversion 2>/dev/null | cut -d. -f1 || true)"480 _gcc_major="$(gcc -dumpversion 2>/dev/null | cut -d. -f1 || true)"
456 if [ -n "${_gcc_major}" ] && [ "${_gcc_major}" -ge 15 ] 2>/dev/null; then481 if [ -n "${_gcc_major}" ] && [ "${_gcc_major}" -ge 15 ] 2>/dev/null; then
@@ -488,12 +513,12 @@ check_env() {
488 fi513 fi
489 # 管道模式(curl|bash)下 stdin 非终端:明确非交互514 # 管道模式(curl|bash)下 stdin 非终端:明确非交互
490 if [ ! -t 0 ]; then515 if [ ! -t 0 ]; then
491- info "检测到管道模式(curl|bash):apt 依赖自动安装;需确认的操作会在检测到终端时提示(超时按默认值继续),无终端时按默认值自动执行。"516+ info "检测到管道模式(curl|bash):系统依赖自动安装(${PKG_MGR});需确认的操作会在检测到终端时提示(超时按默认值继续),无终端时按默认值自动执行。"
492 fi517 fi
493 cann_phase1_decide518 cann_phase1_decide
494}519}
495 520 
496-# 判断是否 Ubuntu 22.04 及以上(读 /etc/os-release,非 Ubuntu 或版本低返回非零)521+# 判断是否 Ubuntu 22.04 及以上(读 /etc/os-release,非 Ubuntu 或版本低返回非零);仅 apt 系(x86_64 / aarch64)调用
497ubuntu_version_ok() {522ubuntu_version_ok() {
498 local id ver_major523 local id ver_major
499 [ -r /etc/os-release ] || return 1524 [ -r /etc/os-release ] || return 1
@@ -556,23 +581,38 @@ pick_qemu_pkg() {
556 fi581 fi
557}582}
558 583 
559-# 依赖清单:编译基础包 + 运行时 python-yaml(hccl-vm start 生成组网拓扑需) + 仅 x86_64 宿主需要的 device(arm) 交叉编译工具链584+# 依赖清单:编译基础包 + 运行时 python-yaml(hccl-vm start 生成组网拓扑需);按 PKG_MGR 输出对应包名。
560-# sudobuild_pkg.sh 内部用 sudo pip 保护锁并 chmod CANN 目录;标准 Ubuntu 自带,极简 root 环境需补装585+# apt 系(Ubuntu)build-essential / -dev 后缀;dnf 系(HCE/openEuler):gcc gcc-c++ make / -devel 后缀。
586+# x86_64 宿主额外装 device(arm) 交叉编译工具链(仅 apt 有此包);aarch64 本机直接编译用系统 gcc 无需交叉链。
587+# sudo:build_pkg.sh 内部用 sudo 关 pip 保护锁并 chmod CANN 目录;标准 Ubuntu/HCE 自带,极简 root 环境需补装。
561dependency_list() {588dependency_list() {
562- local deps=("git" "sudo" "build-essential" "cmake" "libsqlite3-dev" "libboost-all-dev" "rdma-core" "libibverbs-dev" "pkg-config" "python3" "python3-yaml")589+ local deps=()
563- [ "${SKIP_HCCL_TEST}" = false ] && deps+=("openmpi-bin" "libopenmpi-dev")590+ if [ "${PKG_MGR}" = "apt" ]; then
564- # curl 列举镜像/取头、wget 下载 .run;仅下载 CANN 时需要(keep 从不下载)。极简 Ubuntu 可能不自带591+ deps=("git" "sudo" "build-essential" "cmake" "libsqlite3-dev" "libboost-all-dev" "rdma-core" "libibverbs-dev" "pkg-config" "python3" "python3-yaml")
565- [ "${CANN_MODE}" != keep ] && deps+=("curl" "wget" "python3-pip")592+ [ "${SKIP_HCCL_TEST}" = false ] && deps+=("openmpi-bin" "libopenmpi-dev")
566- if [ "$(uname -m)" = "x86_64" ]; then593+ # curl 列举镜像/取头、wget 下载 .run;仅下载 CANN 时需要(keep 从不下载)
567- deps+=("gcc-aarch64-linux-gnu" "g++-aarch64-linux-gnu" "$(pick_qemu_pkg)" "binfmt-support")594+ [ "${CANN_MODE}" != keep ] && deps+=("curl" "wget" "python3-pip")
595+ # x86_64 宿主编译 device 侧(ARM)代码需交叉编译工具链 + qemu 模拟执行 binfmt;
596+ # aarch64 本机直接编译,用系统 gcc 即可,无需交叉链和 qemu。
597+ if [ "$(uname -m)" = "x86_64" ]; then
598+ deps+=("gcc-aarch64-linux-gnu" "g++-aarch64-linux-gnu" "$(pick_qemu_pkg)" "binfmt-support")
599+ fi
600+ elif [ "${PKG_MGR}" = "dnf" ]; then
601+ # HCE/openEuler/EulerOS:gcc gcc-c++ make 替代 build-essential;-devel 替代 -dev
602+ deps=("git" "sudo" "gcc" "gcc-c++" "make" "cmake" "sqlite-devel" "boost-devel" "rdma-core" "libibverbs-devel" "pkgconf-pkg-config" "python3" "python3-pyyaml")
603+ [ "${SKIP_HCCL_TEST}" = false ] && deps+=("mpich" "mpich-devel")
604+ [ "${CANN_MODE}" != keep ] && deps+=("curl" "wget" "python3-pip")
605+ # aarch64 在 HCE 上本机编译,无需交叉链;x86_64 在 HCE 上的交叉链包名暂不内置
568 fi606 fi
569 printf '%s\n' "${deps[@]}"607 printf '%s\n' "${deps[@]}"
570}608}
571 609 
572-# 确保 universe 源已启用:精简/被裁过的 Ubuntu 只留 main 时,libboost-all-dev、openmpi-bin、610+# 确保 universe 源已启用(仅 apt 系):精简/被裁过的 Ubuntu 只留 main 时,libboost-all-dev、openmpi-bin、
573# libopenmpi-dev、qemu-user-static 等(均在 universe 组件)会报 "Unable to locate package"。611# libopenmpi-dev、qemu-user-static 等(均在 universe 组件)会报 "Unable to locate package"。
612+# dnf 系(HCE/openEuler)所有包均在官方源,无需额外启用;调用时自动跳过。
574# 装依赖前调用;启用后不在此 apt-get update,交由 install_deps 紧接着的 update 统一刷新。613# 装依赖前调用;启用后不在此 apt-get update,交由 install_deps 紧接着的 update 统一刷新。
575ensure_universe_enabled() {614ensure_universe_enabled() {
615+ [ "${PKG_MGR:-}" = "apt" ] || return 0 # dnf 系无需处理,直接返回
576 local apt_prefix="$1" apt_log="$2" cand base_line616 local apt_prefix="$1" apt_log="$2" cand base_line
577 # 命令替换取值 + || true + 判空;不在 pipefail 管道里用 grep -q(-q 早退致上游 SIGPIPE 会误判失败)617 # 命令替换取值 + || true + 判空;不在 pipefail 管道里用 grep -q(-q 早退致上游 SIGPIPE 会误判失败)
578 cand="$(apt-cache policy libboost-all-dev 2>/dev/null | grep -E 'Candidate: [0-9]' || true)"618 cand="$(apt-cache policy libboost-all-dev 2>/dev/null | grep -E 'Candidate: [0-9]' || true)"
@@ -595,7 +635,7 @@ ensure_universe_enabled() {
595 fi635 fi
596}636}
597 637 
598-# 安装第三方依赖638+# 安装第三方依赖:按 PKG_MGR 走 apt 或 dnf 分支
599install_deps() {639install_deps() {
600 info "检查第三方依赖..."640 info "检查第三方依赖..."
601 local dependencies=() dep_line641 local dependencies=() dep_line
@@ -615,41 +655,61 @@ install_deps() {
615 655 
616 info "安装缺失的依赖: ${missing_deps[*]}"656 info "安装缺失的依赖: ${missing_deps[*]}"
617 # 提权前缀由 setup_sudo 已提前解析并认证(root 为空、非 root 为 sudo);curl|bash 的密码经 /dev/tty 输入,不再误判657 # 提权前缀由 setup_sudo 已提前解析并认证(root 为空、非 root 为 sudo);curl|bash 的密码经 /dev/tty 输入,不再误判
618- local apt_prefix="${SUDO_PREFIX}"658+ local pkg_prefix="${SUDO_PREFIX}"
619- if [ "$(id -u)" -ne 0 ] && [ -z "${apt_prefix}" ]; then659+ if [ "$(id -u)" -ne 0 ] && [ -z "${pkg_prefix}" ]; then
620 warn "缺少系统依赖,但当前非 root 且无 sudo,无法自动安装:"660 warn "缺少系统依赖,但当前非 root 且无 sudo,无法自动安装:"
621 echo " ${missing_deps[*]}" >&2661 echo " ${missing_deps[*]}" >&2
622 echo " 请让管理员安装后重试,或改用 root 运行,或手动执行:" >&2662 echo " 请让管理员安装后重试,或改用 root 运行,或手动执行:" >&2
623- echo " sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}" >&2663+ if [ "${PKG_MGR}" = "apt" ]; then
664+ echo " sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}" >&2
665+ else
666+ echo " sudo dnf install -y ${missing_deps[*]}" >&2
667+ fi
624 exit 1668 exit 1
625 fi669 fi
626 # 输出留存到日志文件(不再 >/dev/null 吞掉);--verbose 时同时回显到终端,失败时回显便于定位670 # 输出留存到日志文件(不再 >/dev/null 吞掉);--verbose 时同时回显到终端,失败时回显便于定位
627 mkdir -p "${LOG_DIR}"671 mkdir -p "${LOG_DIR}"
628- local apt_log="${LOG_DIR}/apt-install-${RUN_TS}.log"672+ local pkg_log="${LOG_DIR}/${PKG_MGR}-install-${RUN_TS}.log"
629- info "apt 安装日志: ${apt_log}"673+ info "安装日志: ${pkg_log}"
630- # 精简/被裁过的 Ubuntu 可能未启用 universe 源(libboost-all-dev、openmpi 等在该组件中);674+ # apt 系:精简/被裁过的 Ubuntu 可能未启用 universe 源(libboost-all-dev、openmpi 等在该组件中);
631- # 装依赖前先确保 universe 可用,避免 "Unable to locate package"。675+ # 装依赖前先确保 universe 可用,避免 "Unable to locate package"。dnf 系所有包均在官方源,跳过。
632- ensure_universe_enabled "${apt_prefix}" "${apt_log}"676+ ensure_universe_enabled "${pkg_prefix}" "${pkg_log}"
633 local rc=0677 local rc=0
634- if [ "${VERBOSE}" = true ]; then678+ if [ "${PKG_MGR}" = "apt" ]; then
635- if { ${apt_prefix} apt-get update -y \679+ if [ "${VERBOSE}" = true ]; then
636- && ${apt_prefix} env DEBIAN_FRONTEND=noninteractive apt-get install -y "${missing_deps[@]}"; } 2>&1 | tee "${apt_log}"; then680+ if { ${pkg_prefix} apt-get update -y \
637- rc=0681+ && ${pkg_prefix} env DEBIAN_FRONTEND=noninteractive apt-get install -y "${missing_deps[@]}"; } 2>&1 | tee "${pkg_log}"; then
682+ rc=0
683+ else
684+ rc=${PIPESTATUS[0]}
685+ fi
638 else686 else
639- rc=${PIPESTATUS[0]}687+ { ${pkg_prefix} apt-get update -y \
688+ && ${pkg_prefix} env DEBIAN_FRONTEND=noninteractive apt-get install -y "${missing_deps[@]}"; } > "${pkg_log}" 2>&1 &
689+ local install_pid=$!
690+ spin_on_pid "${install_pid}" "安装依赖中"
691+ wait "${install_pid}" || rc=$?
640 fi692 fi
641 else693 else
642- { ${apt_prefix} apt-get update -y \694+ # dnf 系(HCE/openEuler/EulerOS):直接 dnf install -y,无需 update
643- && ${apt_prefix} env DEBIAN_FRONTEND=noninteractive apt-get install -y "${missing_deps[@]}"; } > "${apt_log}" 2>&1 &695+ if [ "${VERBOSE}" = true ]; then
644- local apt_pid=$!696+ if ${pkg_prefix} dnf install -y "${missing_deps[@]}" 2>&1 | tee "${pkg_log}"; then
645- spin_on_pid "${apt_pid}" "安装依赖中"697+ rc=0
646- wait "${apt_pid}" || rc=$?698+ else
699+ rc=${PIPESTATUS[0]}
700+ fi
701+ else
702+ ${pkg_prefix} dnf install -y "${missing_deps[@]}" > "${pkg_log}" 2>&1 &
703+ local install_pid=$!
704+ spin_on_pid "${install_pid}" "安装依赖中"
705+ wait "${install_pid}" || rc=$?
706+ fi
647 fi707 fi
648 if [ "${rc}" -ne 0 ]; then708 if [ "${rc}" -ne 0 ]; then
649 warn "依赖安装失败,末尾日志:"709 warn "依赖安装失败,末尾日志:"
650- tail -n 20 "${apt_log}" >&2710+ tail -n 20 "${pkg_log}" >&2
651 echo " 仍无法解决可带完整日志到 https://gitcode.com/cann/hcomm/issues 反馈。" >&2711 echo " 仍无法解决可带完整日志到 https://gitcode.com/cann/hcomm/issues 反馈。" >&2
652- error "apt 安装依赖失败,请检查网络 / apt 源 / 磁盘 / apt 锁后重试(完整日志: ${apt_log})。"712+ error "${PKG_MGR} 安装依赖失败,请检查网络 / 源 / 磁盘 / 锁后重试(完整日志: ${pkg_log})。"
653 fi713 fi
654}714}
655 715 
@@ -761,16 +821,17 @@ pick_cann_snapshot() {
761 821 
762# $1=快照号 $2=是否允许 weekly(true=主线 profile;否则只取正式发布版)822# $1=快照号 $2=是否允许 weekly(true=主线 profile;否则只取正式发布版)
763pick_toolkit_file() {823pick_toolkit_file() {
764- local snap="$1" allow_weekly="${2:-false}" base all file824+ local snap="$1" allow_weekly="${2:-false}" base all file arch
825+ arch="$(normalize_arch "$(uname -m)" 2>/dev/null || echo x86_64)"
765 base="https://ascend.devcloud.huaweicloud.com/artifactory/cann-run-mirror/software/${CANN_CHANNEL}/${snap}"826 base="https://ascend.devcloud.huaweicloud.com/artifactory/cann-run-mirror/software/${CANN_CHANNEL}/${snap}"
766- all="$(curl -fsSL "${base}/" 2>/dev/null | grep -oE 'Ascend-cann-toolkit_[^"< ]*linux-x86_64\.run' | sort -u)" || true827+ all="$(curl -fsSL "${base}/" 2>/dev/null | grep -oE "Ascend-cann-toolkit_[^\"< ]*linux-${arch}\\.run" | sort -u)" || true
767 if [ "${allow_weekly}" = true ]; then828 if [ "${allow_weekly}" = true ]; then
768 # 主线 profile(随官方更新):允许 weekly,优先 weekly(最新),无则退回正式版。829 # 主线 profile(随官方更新):允许 weekly,优先 weekly(最新),无则退回正式版。
769 file="$(printf '%s\n' "${all}" | grep -i weekly | sort -V | tail -1)"830 file="$(printf '%s\n' "${all}" | grep -i weekly | sort -V | tail -1)"
770 [ -n "${file}" ] || file="$(printf '%s\n' "${all}" | sort -V | tail -1)"831 [ -n "${file}" ] || file="$(printf '%s\n' "${all}" | sort -V | tail -1)"
771 else832 else
772 # 固定配套 profile(如竞赛):只取正式发布版(版本号纯数字点分,如 9.1.0),排除 weekly 等未测构建;取最高版本。833 # 固定配套 profile(如竞赛):只取正式发布版(版本号纯数字点分,如 9.1.0),排除 weekly 等未测构建;取最高版本。
773- file="$(printf '%s\n' "${all}" | grep -E '^Ascend-cann-toolkit_[0-9]+(\.[0-9]+)*_linux-x86_64\.run$' | sort -V | tail -1)"834+ file="$(printf '%s\n' "${all}" | grep -E "^Ascend-cann-toolkit_[0-9]+(\\.[0-9]+)*_linux-${arch}\\.run$" | sort -V | tail -1)"
774 fi835 fi
775 [ -n "${file}" ] || return 1836 [ -n "${file}" ] || return 1
776 echo "${file}"837 echo "${file}"
@@ -1000,7 +1061,9 @@ download_and_install_cann() {
1000 # 3. 文件(是否允许 weekly 由 profile 决定:主线可用 weekly,竞赛等固定配套只取正式发布版)1061 # 3. 文件(是否允许 weekly 由 profile 决定:主线可用 weekly,竞赛等固定配套只取正式发布版)
1001 local aw; aw="$(profile_allow_weekly "${PROFILE}")"1062 local aw; aw="$(profile_allow_weekly "${PROFILE}")"
1002 local file; file="$(pick_toolkit_file "${snap}" "${aw}")" || true1063 local file; file="$(pick_toolkit_file "${snap}" "${aw}")" || true
1003- [ -n "${file}" ] || { warn "快照目录 ${snap} 未找到可用的 x86_64 Toolkit 包(当前 profile=${PROFILE}$([ "${aw}" = true ] || echo ',仅取正式发布版、不取 weekly'))。"; print_cann_guidance; exit 1; }1064+ local _arch_for_msg
1065+ _arch_for_msg="$(normalize_arch "$(uname -m)" 2>/dev/null || echo x86_64)"
1066+ [ -n "${file}" ] || { warn "快照目录 ${snap} 未找到可用的 ${_arch_for_msg} Toolkit 包(当前 profile=${PROFILE}$([ "${aw}" = true ] || echo ',仅取正式发布版、不取 weekly'))。"; print_cann_guidance; exit 1; }
1004 # 4. 下载1067 # 4. 下载
1005 local base="https://ascend.devcloud.huaweicloud.com/artifactory/cann-run-mirror/software/${CANN_CHANNEL}/${snap}"1068 local base="https://ascend.devcloud.huaweicloud.com/artifactory/cann-run-mirror/software/${CANN_CHANNEL}/${snap}"
1006 local url="${base}/${file}" total1069 local url="${base}/${file}" total
@@ -1134,6 +1197,7 @@ build_hccl_vm() {
1134 echo " ① 第三方库下载失败(网络/SSL):已清理下载缓存,重跑本脚本即可重新下载;" >&21197 echo " ① 第三方库下载失败(网络/SSL):已清理下载缓存,重跑本脚本即可重新下载;" >&2
1135 echo " ② gcc 超出 build.md 前置依赖范围(7.3.0–13.3.x,管宿主+交叉):Ubuntu 25.04/26.04 的 gcc14/15 会使 yaml-cpp 等第三方编译失败,请在满足该范围的环境(如 22.04/24.04)运行;" >&21198 echo " ② gcc 超出 build.md 前置依赖范围(7.3.0–13.3.x,管宿主+交叉):Ubuntu 25.04/26.04 的 gcc14/15 会使 yaml-cpp 等第三方编译失败,请在满足该范围的环境(如 22.04/24.04)运行;" >&2
1136 echo " ③ CANN 与 hccl 不配套(device 侧报 ThreadType 未声明等):换配套 CANN,见 https://gitcode.com/cann/release-management/ ;" >&21199 echo " ③ CANN 与 hccl 不配套(device 侧报 ThreadType 未声明等):换配套 CANN,见 https://gitcode.com/cann/release-management/ ;" >&2
1200+ echo " ④ 架构适配问题(aarch64):确认 CANN 安装包与当前架构一致(linux-aarch64),交叉编译工具链已正确安装(x86_64 宿主需 gcc-aarch64-linux-gnu);" >&2
1137 echo " 仍无法解决可带完整日志到 https://gitcode.com/cann/hcomm/issues 反馈。" >&21201 echo " 仍无法解决可带完整日志到 https://gitcode.com/cann/hcomm/issues 反馈。" >&2
1138 clean_thirdparty_dl_cache1202 clean_thirdparty_dl_cache
1139 error "编译未通过(完整日志: ${build_log})。"1203 error "编译未通过(完整日志: ${build_log})。"
@@ -1230,17 +1294,81 @@ build_hccl_test() {
1230 fi1294 fi
1231 chmod -R u+w "${work}" 2>/dev/null || true1295 chmod -R u+w "${work}" 2>/dev/null || true
1232 [ -n "${CANN_SETENV}" ] && source_cann_env "${CANN_SETENV}"1296 [ -n "${CANN_SETENV}" ] && source_cann_env "${CANN_SETENV}"
1233- # 临时修改 Makefile,补 -lmpi_cxx(照 README §4.2.1 官方步骤,逐字一致)1297+ # ── Makefile 幂等保护 ──────────────────────────────────────────────
1234- if ! grep -q '\-lmpi_cxx' "${work}/Makefile" 2>/dev/null; then1298+ # 首次运行:把已污染的 Makefile 清理为干净状态(-lmpi_cxxcxx / -lmpicxxcxx 等所有历史残留均消除),
1235- sed -i 's/-lmpi/-lmpi -lmpi_cxx/g' "${work}/Makefile" 2>/dev/null || true1299+ # 保存为 Makefile.orig;重跑:从干净 Makefile.orig 恢复(任何旧污染都被覆盖)。
1300+ # 清理链(6 步,覆盖所有已知污染模式):
1301+ # 1) -lmpi_cxxcxx → -lmpi(消除级联替换产生的畸形标志)
1302+ # 2) -lmpi_cxx → -lmpi(消除历史 -lmpi_cxx 残留)
1303+ # 3) -lmpicxxcxx → -lmpi(消除级联替换产生的畸形标志)
1304+ # 4) -lmpicxx → -lmpi(消除历史 -lmpicxx 残留)
1305+ # 5) -lmpi -lmpi → -lmpi(消除重复追加,跑两次以覆盖 2+、3+ 连续重复)
1306+ if [ ! -f "${work}/Makefile.orig" ]; then
1307+ { sed -e 's/-lmpi_cxxcxx/-lmpi/g' \
1308+ -e 's/-lmpi_cxx/-lmpi/g' \
1309+ -e 's/-lmpicxxcxx/-lmpi/g' \
1310+ -e 's/-lmpicxx/-lmpi/g' \
1311+ -e 's/ -lmpi -lmpi/ -lmpi/g' \
1312+ -e 's/ -lmpi -lmpi/ -lmpi/g' "${work}/Makefile" > "${work}/Makefile.cl" \
1313+ && mv -- "${work}/Makefile.cl" "${work}/Makefile"; } 2>/dev/null || true
1314+ cp -- "${work}/Makefile" "${work}/Makefile.orig"
1315+ else
1316+ cp -- "${work}/Makefile.orig" "${work}/Makefile"
1236 fi1317 fi
1237 mkdir -p "${LOG_DIR}"1318 mkdir -p "${LOG_DIR}"
1238 local ht_log="${LOG_DIR}/hccl_test-build-${RUN_TS}.log" rc=01319 local ht_log="${LOG_DIR}/hccl_test-build-${RUN_TS}.log" rc=0
1239- # OpenMPI 按架构安装在 /usr/lib/<triplet>/openmpi(x86_64-linux-gnu / aarch64-linux-gnu);1320+ local arch
1240- # 取当前架构 triplet,避免在 aarch64 上写死 x86_64 路径导致必编译失败。目录不存在则回退传统 x86_64 路径。1321+ arch="$(normalize_arch "$(uname -m)" 2>/dev/null || echo x86_64)"
1241- local mpi_home="/usr/lib/$(gcc -dumpmachine 2>/dev/null)/openmpi"1322+ 
1242- [ -d "${mpi_home}" ] || mpi_home="/usr/lib/x86_64-linux-gnu/openmpi"1323+ if [ "${arch}" = "x86_64" ]; then
1243- ( cd "${work}" && MPI_HOME="${mpi_home}" make ASCEND_DIR="${ASCEND_HOME_PATH}" ) > "${ht_log}" 2>&1 &1324+ # ── x86_64:OpenMPI ──────────────────────────────────────────────
1325+ # Ubuntu:/usr/lib/<triplet>/openmpi/{lib,include}
1326+ # HCE/openEuler:/usr/lib64/openmpi-<arch>/{lib,include} 或 /usr/lib/<triplet>/openmpi/
1327+ # 优先用 ompi_info 探测真实路径(所有发行版通用),不可用时回退到已知候选路径列表。
1328+ local mpi_home="" _mpi_lib _mpi_inc
1329+ if command -v ompi_info &>/dev/null; then
1330+ _mpi_lib="$(ompi_info --path libs 2>/dev/null | grep -v '^libs:' | head -1 | tr -d ' ')" || true
1331+ _mpi_inc="$(ompi_info --path headers 2>/dev/null | grep -v '^headers:' | head -1 | tr -d ' ')" || true
1332+ if [ -n "${_mpi_lib}" ] && [ -n "${_mpi_inc}" ]; then
1333+ mpi_home="${_mpi_lib%/lib}"
1334+ [ -d "${mpi_home}/lib" ] && [ -d "${mpi_home}/include" ] || mpi_home=""
1335+ fi
1336+ fi
1337+ if [ -z "${mpi_home}" ]; then
1338+ local _probe_path
1339+ for _probe_path in \
1340+ "/usr/lib/x86_64-linux-gnu/openmpi" \
1341+ "/usr/lib64/openmpi" \
1342+ "/usr/lib/openmpi"; do
1343+ if [ -d "${_probe_path}/lib" ] && [ -d "${_probe_path}/include" ]; then
1344+ mpi_home="${_probe_path}"
1345+ break
1346+ fi
1347+ done
1348+ fi
1349+ if [ -z "${mpi_home}" ]; then
1350+ HCCL_TEST_RESULT="failed:找不到 OpenMPI 安装路径"
1351+ warn "找不到 OpenMPI 安装路径(ompi_info 不可用,且已知候选路径均不存在)。"
1352+ echo " 请手动安装 openmpi 或确认安装路径后用 MPI_HOME 环境变量指定。" >&2
1353+ return 0
1354+ fi
1355+ # 补 -lmpi_cxx
1356+ perl -pi -e 's/(?<!\w)(-lmpi)(?!_cxx)/${1} -lmpi_cxx/g' "${work}/Makefile" 2>/dev/null || true
1357+ ( cd "${work}" && MPI_HOME="${mpi_home}" make ASCEND_DIR="${ASCEND_HOME_PATH}" ) > "${ht_log}" 2>&1 &
1358+ else
1359+ # ── aarch64: mpich ──────────────────────────────────────────────
1360+ local mpi_home="/usr/local/mpich"
1361+ if [ ! -d "${mpi_home}" ]; then
1362+ HCCL_TEST_RESULT="failed:找不到 mpich 安装路径"
1363+ warn "找不到 mpich 安装路径:${mpi_home} 不存在。"
1364+ echo " 请手动安装 mpich 或确认安装路径后用 MPI_HOME 环境变量指定。" >&2
1365+ return 0
1366+ fi
1367+ # 补 -lmpicxx
1368+ perl -pi -e 's/(?<!\w)(-lmpi)(?!cxx)/${1} -lmpicxx/g' "${work}/Makefile" 2>/dev/null || true
1369+ local ld_path="/usr/lib/mpich/lib/:${ASCEND_HOME_PATH}/lib64/:${ASCEND_HOME_PATH}/aarch64-linux/devlib"
1370+ ( cd "${work}" && export LD_LIBRARY_PATH="${ld_path}:${LD_LIBRARY_PATH:-}" && MPI_HOME="${mpi_home}" make ASCEND_DIR="${ASCEND_HOME_PATH}" ) > "${ht_log}" 2>&1 &
1371+ fi
1244 local bpid=$!1372 local bpid=$!
1245 spin_on_pid "${bpid}" "编译 hccl_test 中"1373 spin_on_pid "${bpid}" "编译 hccl_test 中"
1246 wait "${bpid}" || rc=$?1374 wait "${bpid}" || rc=$?
@@ -36,5 +36,6 @@ uint32_t GetVectorCoreCount(uint64_t deviceId);
36int GetRankIdByDeviceId(uint32_t deviceId);36int GetRankIdByDeviceId(uint32_t deviceId);
37bool ResetAllDeviceLogicId();37bool ResetAllDeviceLogicId();
38bool GetRankIdByMPI(uint32_t &rankId, uint64_t &serverId);38bool GetRankIdByMPI(uint32_t &rankId, uint64_t &serverId);
39+uint64_t GetCurServerId();
39}40}
40#endif // _SIM_RUNNER_COMMOM_H_41#endif // _SIM_RUNNER_COMMOM_H_
@@ -271,14 +271,18 @@ enum VirMemType {
271 271 
272typedef struct {272typedef struct {
273 uint64_t id;273 uint64_t id;
274- uint64_t start_ptr;274+ uint64_t start_ptr; // 按照卡分配的虚拟编址的地址
275+ uint64_t dev_mapped_ptr; // device进程打开共享内存后的地址
276+ uint8_t is_dev_access; // 0: dev不可直接访问, 1: dev可以直接访问
275 uint64_t size;277 uint64_t size;
276 uint64_t ctx_id;278 uint64_t ctx_id;
279+ uint64_t device_id; // Device表主键
280+ uint64_t rank_id; // 通信域RankId
277 uint64_t phy_mem_id;281 uint64_t phy_mem_id;
278- uint64_t owner_pid;282+ uint64_t owner_pid; // host查找根据pid
279- uint8_t src_type;//0: host 1: device283+ uint8_t src_type; // 0: host, 1: device
280 uint8_t policy;284 uint8_t policy;
281- uint8_t is_freed; // 0: using, 1: freed285+ uint8_t is_freed; // 0: using, 1: freed
282} VirtualMemBlock;286} VirtualMemBlock;
283 287 
284typedef struct {288typedef struct {
@@ -491,6 +495,7 @@ typedef struct {
491 uint64_t send_cq_handle;495 uint64_t send_cq_handle;
492 uint64_t recv_cq_handle;496 uint64_t recv_cq_handle;
493 uint32_t sqDepth;497 uint32_t sqDepth;
498+ uint64_t sqBuffer; // jetty下发wqe对应的buffer地址
494 uint32_t rqDepth;499 uint32_t rqDepth;
495 uint8_t type;500 uint8_t type;
496 uint32_t jetty_id;501 uint32_t jetty_id;
@@ -0,0 +1,73 @@
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+#ifndef SIM_AICPU_PIPE_MSG_H
12+#define SIM_AICPU_PIPE_MSG_H
13+ 
14+#include <cstdint>
15+#include <cstring>
16+ 
17+constexpr uint16_t KERNEL_NAME_LEN_MAX = 64;
18+constexpr uint16_t KERNEL_SO_NAME_LEN_MAX = 64;
19+constexpr uint16_t DEVICE_MEMORY_NAME_LEN_MAX = 100;
20+ 
21+// Host-Device管道通信消息定义
22+constexpr uint8_t PIPE_CMD_SHUTDOWN = 0x00;
23+constexpr uint8_t PIPE_CMD_EXEC_KERNEL = 0x01;
24+constexpr uint8_t PIPE_CMD_GET_DEV_PTR = 0x02;
25+constexpr uint8_t PIPE_CMD_SET_DEV_ID = 0x03;
26+constexpr uint8_t PIPE_CMD_FREE_DEV_PTR = 0x04;
27+constexpr uint8_t PIPE_RSP_SHUTDOWN_ACK = 0x80;
28+constexpr uint8_t PIPE_RSP_EXEC_KERNEL = 0x81;
29+constexpr uint8_t PIPE_RSP_GET_DEV_PTR = 0x82;
30+constexpr uint8_t PIPE_RSP_SET_DEV_ID = 0x83;
31+constexpr uint8_t PIPE_RSP_FREE_DEV_PTR = 0x84;
32+constexpr uint8_t PIPE_RSP_READY = 0x85;
33+constexpr uint8_t PIPE_RSP_ERROR = 0xFF;
34+constexpr uint8_t PAYLOAD_LEN_MAX = 253;
35+ 
36+#pragma pack(push, 1)
37+ 
38+struct PipeMessage {
39+ uint8_t cmd;
40+ uint16_t bufLen;
41+ uint8_t payload[PAYLOAD_LEN_MAX];
42+};
43+ 
44+typedef struct {
45+ char kernelName[KERNEL_NAME_LEN_MAX];
46+ char soName[KERNEL_SO_NAME_LEN_MAX];
47+ uint64_t args;
48+} ExecKernelPayload;
49+ 
50+typedef struct {
51+ int32_t status;
52+} RspExecKernelPayload;
53+ 
54+typedef struct {
55+ char memName[DEVICE_MEMORY_NAME_LEN_MAX];
56+} DevMemOpPayload;
57+ 
58+typedef struct {
59+ uint64_t ptr;
60+} RspGetDevPtrPayload;
61+ 
62+typedef struct {
63+ int32_t status;
64+} RspFreeDevPtrPayload;
65+ 
66+typedef struct {
67+ uint64_t rankId;
68+ uint64_t deviceKey;
69+} SetDevIdPayload;
70+ 
71+#pragma pack(pop)
72+ 
73+#endif
@@ -327,22 +327,6 @@ typedef struct {
327 uint16_t status;327 uint16_t status;
328} HcclTaskRsp;328} HcclTaskRsp;
329 329 
330-typedef struct {
331- char kernelName[64];
332- uint64_t args;
333- uint8_t devState;
334-} HcclAicpuTask;
335- 
336-typedef struct {
337- uint32_t jettyIdGen;
338- uint64_t jettyId2WqeBufMap[HcclSim::AICPU_JETTY_NUM_MAX];
339-} HcclAicpuCommon;
340- 
341-typedef struct {
342- HcclAicpuCommon common;
343- HcclAicpuTask task[512]; // 最大512卡
344-} HcclAicpuData;
345- 
346#pragma pack(pop)330#pragma pack(pop)
347 331 
348enum BufferType {332enum BufferType {
@@ -263,7 +263,7 @@ build_hccl_test() {
263 if ! grep -q '\-lmpi_cxx' Makefile; then263 if ! grep -q '\-lmpi_cxx' Makefile; then
264 sed -i 's/-lmpi/-lmpi -lmpi_cxx/g' Makefile264 sed -i 's/-lmpi/-lmpi -lmpi_cxx/g' Makefile
265 fi265 fi
266- MPI_HOME=/usr/lib/x86_64-linux-gnu/openmpi make ASCEND_DIR=${ASCEND_HOME_PATH}266+ MPI_HOME=/usr/lib/$(uname -m)-linux-gnu/openmpi make ASCEND_DIR=${ASCEND_HOME_PATH}
267}267}
268 268 
269# 编译HCCL-VM工具269# 编译HCCL-VM工具
@@ -42,7 +42,7 @@ target_include_directories(hccl-vm PUBLIC
42 ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc42 ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc
43 ${ASCEND_CANN_PACKAGE_PATH}/include43 ${ASCEND_CANN_PACKAGE_PATH}/include
44 ${ASCEND_CANN_PACKAGE_PATH}/include/hccl44 ${ASCEND_CANN_PACKAGE_PATH}/include/hccl
45- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/toolchain45+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/toolchain
46 46 
47 # cann包头文件47 # cann包头文件
48 ${ASCEND_CANN_PACKAGE_PATH}/include/driver48 ${ASCEND_CANN_PACKAGE_PATH}/include/driver
@@ -374,11 +374,6 @@ HcclVmResult InitHvmEnv(const std::string& configClusterDir, uint32_t level, boo
374 return HcclVmResult::HCCL_SIM_HOST_ERROR_CMD;374 return HcclVmResult::HCCL_SIM_HOST_ERROR_CMD;
375 }375 }
376 }376 }
377- void *shmptr =sim::MemoryManager::GetInstance().AllocMemByName("HcclAicpuData", sizeof(HcclAicpuData));
378- if (shmptr == nullptr) {
379- HCCL_VM_ERROR("Alloc Shared Memory fail ");
380- return HcclVmResult::HCCL_SIM_HOST_ERROR_CMD;
381- }
382 377 
383 // 解析集群拓扑,并初始化静态数据模型数据 378 // 解析集群拓扑,并初始化静态数据模型数据
384 HCCL_VM_INFO("Initializing: Cluster Topo"); 379 HCCL_VM_INFO("Initializing: Cluster Topo");
@@ -572,7 +567,7 @@ HcclVmResult StartHvmCmd() {
572 // Child Process(Bash) 567 // Child Process(Bash)
573 // 劫持库存在性判断 568 // 劫持库存在性判断
574 std::string hcclVmbin = InstallPath::ResolveToInstallRoot("bin/hccl-vm");569 std::string hcclVmbin = InstallPath::ResolveToInstallRoot("bin/hccl-vm");
575- std::string proxyPath = InstallPath::ResolveToInstallRoot("lib/x86_64/libhccl_proxy_level" + std::to_string(g_hcclVmLevel) + ".so");570+ std::string proxyPath = InstallPath::ResolveToInstallRoot("lib/" + GetArchStr() + "/libhccl_proxy_level" + std::to_string(g_hcclVmLevel) + ".so");
576 if (!fs::exists(proxyPath)) { 571 if (!fs::exists(proxyPath)) {
577 HCCL_VM_ERROR("proxy hacking .so not found {}, please check your proxy hacking .so:" 572 HCCL_VM_ERROR("proxy hacking .so not found {}, please check your proxy hacking .so:"
578 "1. Whether the hook library has been successfully built and installed. 2. Whether the simulation level matches the proxy hook library version. Current simulation level: {}, Default simulation level: 2" 573 "1. Whether the hook library has been successfully built and installed. 2. Whether the simulation level matches the proxy hook library version. Current simulation level: {}, Default simulation level: 2"
@@ -39,7 +39,7 @@ target_include_directories(common PRIVATE
39 ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc39 ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc
40 ${ASCEND_CANN_PACKAGE_PATH}/include40 ${ASCEND_CANN_PACKAGE_PATH}/include
41 ${ASCEND_CANN_PACKAGE_PATH}/include/hccl41 ${ASCEND_CANN_PACKAGE_PATH}/include/hccl
42- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/toolchain42+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/toolchain
43 43 
44 ${ASCEND_CANN_PACKAGE_PATH}/include/driver44 ${ASCEND_CANN_PACKAGE_PATH}/include/driver
45 ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/trace45 ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/trace
@@ -0,0 +1,155 @@
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+#include "sim_pipe_io.h"
12+ 
13+#include <cerrno>
14+#include <cstdint>
15+#include <cstring>
16+#include <fcntl.h>
17+#include <unistd.h>
18+ 
19+#include "sim_log.h"
20+ 
21+namespace sim {
22+ 
23+int PipeBlockRead(int fd, void *buf, size_t len)
24+{
25+ uint8_t *ptr = static_cast<uint8_t *>(buf);
26+ size_t remaining = len;
27+ while (remaining > 0) {
28+ ssize_t n = read(fd, ptr, remaining);
29+ if (n > 0) {
30+ ptr += n;
31+ remaining -= n;
32+ } else if (n == 0) {
33+ HCCL_VM_INFO("read EOF, peer closed.");
34+ return -1;
35+ } else if (errno == EINTR) {
36+ continue;
37+ } else {
38+ HCCL_VM_ERROR("read failed: {} (errno={}).", strerror(errno), errno);
39+ return -1;
40+ }
41+ }
42+ 
43+ return 0;
44+}
45+ 
46+int PipeBlockWrite(int fd, const void *buf, size_t len)
47+{
48+ const uint8_t *ptr = static_cast<const uint8_t *>(buf);
49+ size_t remaining = len;
50+ while (remaining > 0) {
51+ ssize_t n = write(fd, ptr, remaining);
52+ if (n > 0) {
53+ ptr += n;
54+ remaining -= n;
55+ } else if (n == 0) {
56+ HCCL_VM_INFO("write returned 0.");
57+ return -1;
58+ } else if (errno == EINTR) {
59+ continue;
60+ } else if (errno == EPIPE || errno == EAGAIN) {
61+ HCCL_VM_INFO("peer closed (errno={}).", errno);
62+ return -1;
63+ } else {
64+ HCCL_VM_ERROR("write failed: {} (errno={}).", strerror(errno), errno);
65+ return -1;
66+ }
67+ }
68+ 
69+ return 0;
70+}
71+ 
72+int PipeSendMsg(int fd, uint8_t cmd, const void *data, uint32_t len)
73+{
74+ PipeMessage msg{};
75+ msg.cmd = cmd;
76+ msg.bufLen = static_cast<uint16_t>(len);
77+ if (len > 0 && data != nullptr) {
78+ std::memcpy(msg.payload, data, len);
79+ }
80+ 
81+ return PipeBlockWrite(fd, &msg, sizeof(msg));
82+}
83+ 
84+int PipeRecvMsg(int fd, uint8_t &outCmd, void *outData, uint32_t maxLen, uint32_t &outLen)
85+{
86+ PipeMessage msg{};
87+ if (PipeBlockRead(fd, &msg, sizeof(msg)) != 0) {
88+ outCmd = 0;
89+ outLen = 0;
90+ return -1;
91+ }
92+ 
93+ outCmd = msg.cmd;
94+ outLen = msg.bufLen;
95+ 
96+ if (msg.bufLen > maxLen) {
97+ HCCL_VM_ERROR("payload too large: {} > {}", msg.bufLen, maxLen);
98+ outLen = 0;
99+ return -1;
100+ }
101+ 
102+ if (msg.bufLen > 0 && outData != nullptr) {
103+ std::memcpy(outData, msg.payload, msg.bufLen);
104+ }
105+ 
106+ return 0;
107+}
108+ 
109+int PipeCreate(PipePair &pair)
110+{
111+ int fds[2] = {-1, -1};
112+ if (pipe2(fds, O_CLOEXEC) == -1) {
113+ HCCL_VM_ERROR("pipe2() failed: {}", strerror(errno));
114+ return -1;
115+ }
116+ 
117+ pair.readFd = fds[0];
118+ pair.writeFd = fds[1];
119+ return 0;
120+}
121+ 
122+void PipeClose(int &fd)
123+{
124+ if (fd >= 0) {
125+ close(fd);
126+ fd = -1;
127+ }
128+}
129+ 
130+int PipeChildSetup(PipePair &h2d, PipePair &d2h, int targetReadFd, int targetWriteFd)
131+{
132+ // 子进程不写 h2d,不读 d2h
133+ close(h2d.writeFd);
134+ close(d2h.readFd);
135+ 
136+ // 重定向到固定 fd
137+ dup2(h2d.readFd, targetReadFd);
138+ dup2(d2h.writeFd, targetWriteFd);
139+ 
140+ // 清除 CLOEXEC 标记(execvp 后保留)
141+ fcntl(targetReadFd, F_SETFD, 0);
142+ fcntl(targetWriteFd, F_SETFD, 0);
143+ 
144+ // 关闭原始 fd(如果与目标 fd 不同)
145+ if (h2d.readFd != targetReadFd) {
146+ close(h2d.readFd);
147+ }
148+ if (d2h.writeFd != targetWriteFd) {
149+ close(d2h.writeFd);
150+ }
151+ 
152+ return 0;
153+}
154+ 
155+} // namespace sim
@@ -0,0 +1,41 @@
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+#ifndef SIM_PIPE_IO_H
12+#define SIM_PIPE_IO_H
13+ 
14+#include <cstddef>
15+#include <cstdint>
16+#include "sim_aicpu_pipe_msg.h"
17+ 
18+namespace sim {
19+ 
20+struct PipePair {
21+ int readFd;
22+ int writeFd;
23+};
24+ 
25+int PipeBlockRead(int fd, void *buf, size_t len);
26+ 
27+int PipeBlockWrite(int fd, const void *buf, size_t len);
28+ 
29+int PipeSendMsg(int fd, uint8_t cmd, const void *data, uint32_t len);
30+ 
31+int PipeRecvMsg(int fd, uint8_t &outCmd, void *outData, uint32_t maxLen, uint32_t &outLen);
32+ 
33+int PipeCreate(PipePair &pair);
34+ 
35+void PipeClose(int &fd);
36+ 
37+int PipeChildSetup(PipePair &h2d, PipePair &d2h, int targetReadFd, int targetWriteFd);
38+ 
39+} // namespace sim
40+ 
41+#endif // SIM_PIPE_IO_H
@@ -0,0 +1,268 @@
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+#include "sim_sub_process_manager.h"
12+#include <sys/wait.h>
13+#include <sys/utsname.h>
14+#include <unistd.h>
15+ 
16+#include <cerrno>
17+#include <chrono>
18+#include <cstring>
19+#include <thread>
20+#include "sim_log.h"
21+#include "sim_common_defs.h"
22+#include "sim_common_api.h"
23+#include "sim_pipe_io.h"
24+ 
25+namespace sim {
26+ 
27+thread_local static sim::SubProcessManager g_aiCpuProcMgr;
28+ 
29+SubProcessManager &GetAicpuProcMgr()
30+{
31+ return g_aiCpuProcMgr;
32+}
33+ 
34+SubProcessManager::~SubProcessManager()
35+{
36+ if (m_pid > 0) {
37+ DestroyProcess();
38+ }
39+}
40+ 
41+int SubProcessManager::CreateProcess(const SubProcessConfig& config)
42+{
43+ std::lock_guard<std::mutex> lock(m_forkLock);
44+ 
45+ if (m_pid > 0) {
46+ HCCL_VM_INFO("Process {} already exists, skip.", m_pid);
47+ return 0;
48+ }
49+ 
50+ sim::PipePair h2dPipe{}, d2hPipe{};
51+ if (sim::PipeCreate(h2dPipe) != 0) {
52+ HCCL_VM_ERROR("Failed to create h2d pipe");
53+ return -1;
54+ }
55+ if (sim::PipeCreate(d2hPipe) != 0) {
56+ HCCL_VM_ERROR("Failed to create d2h pipe");
57+ sim::PipeClose(h2dPipe.readFd);
58+ sim::PipeClose(h2dPipe.writeFd);
59+ return -1;
60+ }
61+ 
62+ pid_t pid = fork();
63+ if (pid == -1) {
64+ HCCL_VM_ERROR("fork() failed: {}", strerror(errno));
65+ sim::PipeClose(h2dPipe.readFd);
66+ sim::PipeClose(h2dPipe.writeFd);
67+ sim::PipeClose(d2hPipe.readFd);
68+ sim::PipeClose(d2hPipe.writeFd);
69+ return -1;
70+ }
71+ 
72+ // device进程执行参数拼接
73+ std::vector<char*> argv;
74+ for (const auto& arg : config.args) {
75+ argv.push_back(const_cast<char *>(arg.c_str()));
76+ }
77+ 
78+ std::string h2dReadFdStr = std::to_string(kH2dReadFd);
79+ std::string d2hWriteFdStr = std::to_string(kD2hWriteFd);
80+ argv.push_back(const_cast<char *>(h2dReadFdStr.c_str()));
81+ argv.push_back(const_cast<char *>(d2hWriteFdStr.c_str()));
82+ argv.push_back(nullptr);
83+ 
84+ if (pid == 0) {
85+ g_logger = nullptr;
86+ sim::PipeChildSetup(h2dPipe, d2hPipe, kH2dReadFd, kD2hWriteFd);
87+ 
88+ for (const auto& env : config.envVars) {
89+ setenv(env.first.c_str(), env.second.c_str(), 1);
90+ }
91+ 
92+ execvp(config.executable.c_str(), argv.data());
93+ _exit(127);
94+ }
95+ 
96+ m_pid = pid;
97+ sim::PipeClose(h2dPipe.readFd); // 主进程不读 h2dPipe
98+ sim::PipeClose(d2hPipe.writeFd); // 主进程不写 d2hPipe
99+ m_h2dWriteFd = h2dPipe.writeFd;
100+ m_d2hReadFd = d2hPipe.readFd;
101+ 
102+ HCCL_VM_INFO("Child process {} created (m_h2dWriteFd={}, m_d2hReadFd={}).", m_pid, m_h2dWriteFd, m_d2hReadFd);
103+ 
104+ // 等待device进程管道准备就绪进入Ready状态
105+ if (WaitForReady() != 0) {
106+ HCCL_VM_ERROR("Child process {} failed to become READY, aborting.", m_pid);
107+ DestroyProcess();
108+ return -1;
109+ }
110+ 
111+ return 0;
112+}
113+ 
114+int SubProcessManager::WaitForReady()
115+{
116+ if (m_d2hReadFd < 0 || m_pid < 0) {
117+ HCCL_VM_ERROR("WaitForReady: child not running.");
118+ return -1;
119+ }
120+ 
121+ uint8_t rspCmd = 0;
122+ uint8_t buf[16] = {0};
123+ uint32_t rspLen = 0;
124+ if (HostRecvMsg(rspCmd, buf, sizeof(buf), rspLen) != 0) {
125+ HCCL_VM_ERROR("WaitForReady: child pid={} exited or read failed.", m_pid);
126+ return -1;
127+ }
128+ if (rspCmd != PIPE_RSP_READY) {
129+ HCCL_VM_ERROR("WaitForReady: unexpected msg cmd=0x{:02x}.", rspCmd);
130+ return -1;
131+ }
132+ HCCL_VM_INFO("Child process {} is READY.", m_pid);
133+ return 0;
134+}
135+ 
136+int SubProcessManager::DestroyProcess(int timeoutMs)
137+{
138+ if (m_pid < 0) {
139+ HCCL_VM_INFO("Process already stopped.");
140+ return 0;
141+ }
142+ 
143+ HCCL_VM_INFO("Sending SHUTDOWN to process {}.", m_pid);
144+ {
145+ std::lock_guard<std::mutex> lock(m_rpcLock);
146+ HostSendMsg(PIPE_CMD_SHUTDOWN, nullptr, 0);
147+ }
148+ 
149+ sim::PipeClose(m_h2dWriteFd);
150+ 
151+ auto startTime = std::chrono::steady_clock::now();
152+ while (true) {
153+ int status;
154+ pid_t wPid = waitpid(m_pid, &status, WNOHANG);
155+ if (wPid == m_pid) {
156+ HCCL_VM_INFO("Child process {} exited with status {}.", m_pid, status);
157+ break;
158+ } else if (wPid == -1 && errno == ECHILD) {
159+ break;
160+ }
161+ 
162+ auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
163+ std::chrono::steady_clock::now() - startTime).count();
164+ if (elapsed >= timeoutMs) {
165+ HCCL_VM_WARN("Child process {} did not exit within {} ms, SIGKILL.", m_pid, timeoutMs);
166+ kill(m_pid, SIGKILL);
167+ waitpid(m_pid, &status, 0);
168+ break;
169+ }
170+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
171+ }
172+ 
173+ sim::PipeClose(m_d2hReadFd);
174+ 
175+ m_pid = -1;
176+ return 0;
177+}
178+ 
179+bool SubProcessManager::IsAlive() const
180+{
181+ if (m_pid < 0) {
182+ return false;
183+ }
184+ 
185+ int status = 0;
186+ pid_t wPid = waitpid(m_pid, &status, WNOHANG);
187+ return wPid == 0;
188+}
189+ 
190+int SubProcessManager::Request(uint8_t reqCmd, const void* reqData, uint32_t reqLen,
191+ uint8_t& rspCmd, void* rspData, uint32_t rspMaxLen, uint32_t& rspLen)
192+{
193+ std::lock_guard<std::mutex> lock(m_rpcLock);
194+ if (HostSendMsg(reqCmd, reqData, reqLen) != 0) {
195+ return -1;
196+ }
197+ 
198+ if (HostRecvMsg(rspCmd, rspData, rspMaxLen, rspLen) != 0) {
199+ return -1;
200+ }
201+ 
202+ return 0;
203+}
204+ 
205+int SubProcessManager::HostSendMsg(uint8_t cmd, const void* data, uint32_t len)
206+{
207+ if (m_h2dWriteFd < 0) {
208+ HCCL_VM_ERROR("HostSendMsg: h2d pipe not open.");
209+ return -1;
210+ }
211+ 
212+ return PipeSendMsg(m_h2dWriteFd, cmd, data, len);
213+}
214+ 
215+int SubProcessManager::HostRecvMsg(uint8_t& outCmd, void* outData, uint32_t maxLen, uint32_t& outLen)
216+{
217+ if (m_d2hReadFd < 0) {
218+ HCCL_VM_ERROR("HostRecvMsg: d2h pipe not open.");
219+ return -1;
220+ }
221+ 
222+ return PipeRecvMsg(m_d2hReadFd, outCmd, outData, maxLen, outLen);
223+}
224+ 
225+bool IsAarch64Host()
226+{
227+ utsname utsBuf;
228+ uname(&utsBuf);
229+ return (std::strstr(utsBuf.machine, "aarch64") != nullptr ||
230+ std::strstr(utsBuf.machine, "arm") != nullptr);
231+}
232+ 
233+SubProcessConfig CreateAicpuDeviceConfig(uint32_t rankId, uint32_t deviceKey)
234+{
235+ SubProcessConfig config;
236+ std::string rankIdStr = std::to_string(rankId);
237+ std::string devKeyStr = std::to_string(deviceKey);
238+ std::string devBinPath = InstallPath::ResolveToInstallRoot("bin/device");
239+ 
240+ if (IsAarch64Host()) {
241+ config.executable = devBinPath;
242+ config.args.push_back(devBinPath);
243+ } else {
244+ config.executable = "qemu-aarch64-static";
245+ config.args.push_back("qemu-aarch64-static");
246+ config.args.push_back(devBinPath);
247+ config.envVars["QEMU_LD_PREFIX"] = "/usr/aarch64-linux-gnu";
248+ }
249+ 
250+ config.args.push_back(rankIdStr);
251+ config.args.push_back(devKeyStr);
252+ 
253+ std::string preloadPath = InstallPath::ResolveToInstallRoot("lib/aarch64/libhccl_device_proxy.so");
254+ std::string libPath = InstallPath::ResolveToInstallRoot("lib/aarch64");
255+ const char* ascendHomePath = std::getenv("ASCEND_HOME_PATH");
256+ if (ascendHomePath != nullptr) {
257+ libPath += ":";
258+ libPath += ascendHomePath;
259+ libPath += "/" + GetArchStr() + "-linux/devlib/device";
260+ }
261+ 
262+ config.envVars["LD_PRELOAD"] = preloadPath;
263+ config.envVars["LD_LIBRARY_PATH"] = libPath;
264+ 
265+ return config;
266+}
267+ 
268+}
@@ -0,0 +1,69 @@
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+#ifndef SIM_SUB_PROCESS_MANAGER_H
12+#define SIM_SUB_PROCESS_MANAGER_H
13+ 
14+#include <sys/types.h>
15+#include <cstdint>
16+#include <mutex>
17+#include <map>
18+#include <string>
19+#include <vector>
20+#include "sim_aicpu_pipe_msg.h"
21+ 
22+namespace sim {
23+ 
24+struct SubProcessConfig {
25+ std::string executable;
26+ std::vector<std::string> args;
27+ std::map<std::string, std::string> envVars;
28+ std::string workDir;
29+};
30+ 
31+class SubProcessManager {
32+public:
33+ SubProcessManager() = default;
34+ ~SubProcessManager();
35+ 
36+ SubProcessManager(const SubProcessManager&) = delete;
37+ SubProcessManager& operator=(const SubProcessManager&) = delete;
38+ 
39+ int CreateProcess(const SubProcessConfig& config);
40+ int DestroyProcess(int timeoutMs = 3000);
41+ 
42+ bool IsAlive() const;
43+ pid_t GetPid() const { return m_pid; }
44+ 
45+ int Request(uint8_t reqCmd, const void* reqData, uint32_t reqLen,
46+ uint8_t& rspCmd, void* rspData, uint32_t rspMaxLen, uint32_t& rspLen);
47+ 
48+private:
49+ static constexpr int kH2dReadFd = 200;
50+ static constexpr int kD2hWriteFd = 201;
51+ 
52+ int m_h2dWriteFd = -1;
53+ int m_d2hReadFd = -1;
54+ pid_t m_pid = -1;
55+ 
56+ mutable std::mutex m_rpcLock;
57+ mutable std::mutex m_forkLock;
58+ 
59+ int WaitForReady();
60+ 
61+ int HostSendMsg(uint8_t cmd, const void* data, uint32_t len);
62+ int HostRecvMsg(uint8_t& outCmd, void* outData, uint32_t maxLen, uint32_t& outLen);
63+};
64+ 
65+SubProcessConfig CreateAicpuDeviceConfig(uint32_t rankId, uint32_t deviceKey = 0);
66+SubProcessManager &GetAicpuProcMgr();
67+}
68+ 
69+#endif
@@ -52,7 +52,8 @@ add_executable(device
52 main.cc52 main.cc
53 hccl_device_pub.cc53 hccl_device_pub.cc
54 hccl_task_collection.cc54 hccl_task_collection.cc
55- hccl_kernel_executor.cc55+ sim_aicpu_pipe_handler.cc
56+ sim_kernel_lib_mgr.cc
56 ${HCCL_VM_SRC}/store/store_sim_memory_manager.cc57 ${HCCL_VM_SRC}/store/store_sim_memory_manager.cc
57 ${HCCL_VM_SRC}/store/store_sim_shm_ops.cc58 ${HCCL_VM_SRC}/store/store_sim_shm_ops.cc
58 ${HCCL_VM_SRC}/runnerdb/tracedb/db_sim_sqlite_db.cc59 ${HCCL_VM_SRC}/runnerdb/tracedb/db_sim_sqlite_db.cc
@@ -64,6 +65,7 @@ add_executable(device
64 ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_op_db_ops.cc65 ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_op_db_ops.cc
65 ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_factory.cc66 ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_factory.cc
66 ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_sqlite.cc67 ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_sqlite.cc
68+ ${HCCL_VM_SRC}/common/sim_pipe_io.cc
67)69)
68 70 
69target_link_libraries(device PRIVATE71target_link_libraries(device PRIVATE
@@ -79,22 +81,24 @@ target_include_directories(device PRIVATE
79 ${HCCL_CODE_ROOT}/src/common81 ${HCCL_CODE_ROOT}/src/common
80 ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym82 ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym
81 ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym/ccu83 ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym/ccu
82- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc84+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc
83- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl85+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl
84- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include86+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include
85- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/hccl87+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/hccl
86- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/base88+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/base
87- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/hcomm/ccu89+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/hcomm/ccu
88 90 
89 ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode91 ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode
90 92 
91 ${HCCL_VM_INCLUDE}93 ${HCCL_VM_INCLUDE}
94+ ${HCCL_VM_INCLUDE}/include
92 ${HCCL_VM_INCLUDE}/store95 ${HCCL_VM_INCLUDE}/store
93 ${HCCL_VM_INCLUDE}/runnerdb96 ${HCCL_VM_INCLUDE}/runnerdb
94 97 
95 ${HCCL_VM_SRC}/utils98 ${HCCL_VM_SRC}/utils
96 ${HCCL_VM_SRC}/device_arm99 ${HCCL_VM_SRC}/device_arm
97 ${HCCL_VM_SRC}/runnerdb/modeldb100 ${HCCL_VM_SRC}/runnerdb/modeldb
101+ ${HCCL_VM_SRC}/common
98 ${THRID_PARTY_DIR}102 ${THRID_PARTY_DIR}
99 ${THRID_PARTY_DIR}/spdlog103 ${THRID_PARTY_DIR}/spdlog
100)104)
@@ -122,7 +126,6 @@ endif()
122target_compile_options(device PRIVATE126target_compile_options(device PRIVATE
123 -O0127 -O0
124 -g128 -g
125- -rdynamic
126 -D_GLIBCXX_USE_CXX11_ABI=0129 -D_GLIBCXX_USE_CXX11_ABI=0
127 -DCANN_VERSION_NUM=${HCCL_CANN_VERSION_NUM}130 -DCANN_VERSION_NUM=${HCCL_CANN_VERSION_NUM}
128 -DNO_YAML_CONFIG131 -DNO_YAML_CONFIG
@@ -12,13 +12,7 @@
12#define AICPU_ARGS_STUB_H12#define AICPU_ARGS_STUB_H
13 13 
14#include <cstdint>14#include <cstdint>
15-constexpr uint32_t UNIQUEID_HEADER_OFFSET = 152;15+ 
16-constexpr uint32_t UNIQUEID_HEADER_SIZE = 20;
17-constexpr uint32_t COMMON_DATA_SIZE = 8;
18-constexpr uint32_t NOTIFY_ID_SIZE = 8;
19-constexpr uint32_t NOTIFY_BUFFER_SIZE = 28;
20-constexpr uint32_t LOCAL_BUFFER_SIZE = 28;
21-constexpr uint32_t REMOTE_BUFFER_SIZE = 28;
22constexpr uint32_t HCOMID_MAX_SIZE = 128;16constexpr uint32_t HCOMID_MAX_SIZE = 128;
23 17 
24constexpr uint32_t P2P_MAX_ARG_SIZE_STUB = 8192;18constexpr uint32_t P2P_MAX_ARG_SIZE_STUB = 8192;
@@ -51,6 +45,7 @@ struct HDCommunicateParams {
51 45 
52struct DevAicpuCommConfig {46struct DevAicpuCommConfig {
53 bool taskExceptionEnable{true};47 bool taskExceptionEnable{true};
48+ uint32_t notifyWaitTimeout{1836};
54 // 如要新增配置类字段,在此处添加49 // 如要新增配置类字段,在此处添加
55};50};
56struct CommAicpuParam {51struct CommAicpuParam {
@@ -65,80 +60,4 @@ struct CommAicpuParam {
65 DevAicpuCommConfig commConfig; // 收编通信域配置类变量60 DevAicpuCommConfig commConfig; // 收编通信域配置类变量
66};61};
67 62 
68-struct DevAicpuThreadConfig {
69- // 如要新增配置类字段,在此处添加
70-};
71- 
72-struct ThreadMgrAicpuParam {
73- uint32_t threadNum;
74- char hcomId[128];
75- char threadParam[200][6000]; // 含序列化后thread信息,约40KB
76- void* deviceHandle;
77- uint32_t rsv1;
78- int32_t deviceLogicId{-1}; // 基础通信使用
79- uint32_t deviceType{0}; // 基础通信使用
80- DevAicpuThreadConfig threadConfig; // 收编thread配置类变量
81-};
82- 
83-struct InitTask {
84- uint64_t context;
85- bool isCustom;
86-};
87- 
88-struct DevAicpuChannelConfig {
89- // 如要新增配置类字段,在此处添加
90-};
91- 
92-struct HcclChannelUrmaRes {
93- char hcomId[256]; // 通信域ID 最大长度待修改
94- void* channelList; // 反序列后返回给host侧的device侧handle地址
95- uint32_t listNum = 0; // 建链channel的总数量
96- void* uniqueIdAddr; // 序列化后device侧地址
97- uint32_t uniqueIdSize{0}; // 序列化后总地址长度
98- void* channelSizeAddr{nullptr}; // 存放序列化后device channel size的指针
99- uint32_t* remoteRankList; // 序列化后返回给host侧的device侧rankList地址
100- uint32_t* remoteRankId; // 记录每个channel的对端rank
101- int32_t deviceLogicId{0}; // 基础通信使用
102- uint32_t deviceType{0}; // 基础通信使用
103- DevAicpuChannelConfig channelConfig; // 收编channel配置类变量
104-};
105- 
106-#pragma pack(push, 1)
107- 
108-struct UniqueIdV2Header {
109- uint32_t type;
110- uint32_t notifyNum;
111- uint32_t bufferNum;
112- uint32_t rmtBufferNum;
113- uint32_t connNum;
114-};
115- 
116-struct ConnUniqueIds {
117- uint32_t dieId;
118- uint32_t funcId;
119- uint32_t jettyId;
120- uint32_t jfcPollMode;
121- uint8_t dwqeCacheLocked;
122- uint64_t dbAddr;
123- uint64_t sqCiAddr;
124- uint64_t sqBuffVa;
125- uint32_t sqDepth;
126- uint32_t tpn;
127- uint8_t rmtEidRaw[16U];
128- uint8_t locEidRaw[16U];
129-};
130- 
131-struct ConnUniqueBlock {
132- uint64_t size;
133- ConnUniqueIds conn[0];
134-};
135- 
136-struct AicpuTsThread {
137- uint32_t streamType;
138- uint32_t notifyLoadType;
139- uint32_t devId;
140-};
141- 
142-#pragma pack(pop)
143- 
144#endif63#endif
@@ -10,10 +10,12 @@
10 10 
11#include "hccl_device_pub.h"11#include "hccl_device_pub.h"
12 12 
13+#include <cerrno>
13#include <csignal>14#include <csignal>
14#include <cstdint>15#include <cstdint>
15#include <cstdio>16#include <cstdio>
16#include <cstdlib>17#include <cstdlib>
18+#include <cstring>
17#include <dlfcn.h>19#include <dlfcn.h>
18#include <execinfo.h>20#include <execinfo.h>
19#include <fcntl.h>21#include <fcntl.h>
@@ -26,17 +28,20 @@
26#include "sim_log.h"28#include "sim_log.h"
27#include "store_sim_memory_manager.h"29#include "store_sim_memory_manager.h"
28#include "db_sim_runner_db.h"30#include "db_sim_runner_db.h"
31+#include "sim_pipe_io.h"
29 32 
30#ifdef __cplusplus33#ifdef __cplusplus
31extern "C" {34extern "C" {
32#endif // __cplusplus35#endif // __cplusplus
33 36 
34uint32_t g_rankId = 0;37uint32_t g_rankId = 0;
38+uint32_t g_deviceKey = 0;
35 39 
36char g_crash_file_name[64] = "crash_default.log";40char g_crash_file_name[64] = "crash_default.log";
37 41 
38HcclVmResult SetCurRankId(uint32_t rankId)42HcclVmResult SetCurRankId(uint32_t rankId)
39{43{
44+ HCCL_VM_INFO("SetCurRankId, old rankId: {}, new rankId: {}", g_rankId, rankId);
40 g_rankId = rankId;45 g_rankId = rankId;
41 return HcclVmResult::HCCL_SIM_SUCCESS;46 return HcclVmResult::HCCL_SIM_SUCCESS;
42}47}
@@ -47,6 +52,17 @@ HcclVmResult GetCurRankId(uint32_t *rankId)
47 return HcclVmResult::HCCL_SIM_SUCCESS;52 return HcclVmResult::HCCL_SIM_SUCCESS;
48}53}
49 54 
55+void SetCurDeviceKey(uint32_t deviceKey)
56+{
57+ HCCL_VM_INFO("SetCurDeviceKey, old deviceKey: {}, new deviceKey: {}", g_deviceKey, deviceKey);
58+ g_deviceKey = deviceKey;
59+}
60+ 
61+uint32_t GetCurDeviceKey()
62+{
63+ return g_deviceKey;
64+}
65+ 
50uint8_t sqBuffer[HCCL_SQE_SIZE * HCCL_SQE_MAX_CNT];66uint8_t sqBuffer[HCCL_SQE_SIZE * HCCL_SQE_MAX_CNT];
51HcclVmResult GetSqBufferAddr(uint8_t **sqBuff)67HcclVmResult GetSqBufferAddr(uint8_t **sqBuff)
52{68{
@@ -78,31 +94,87 @@ void UpdateSqTail(uint32_t sqId, uint32_t newTail)
78 sqTailMap[sqId] = newTail;94 sqTailMap[sqId] = newTail;
79}95}
80 96 
81-void *GetRealPtrByDevPtrImpl(void *devPtr, const char *file, int line)97+// AICPU构造Task时任务转换,将本端设备地址(本rank对应host进程申请的)转换为虚拟地址
98+uint64_t TransLocalAddrToVirtual(uint64_t devAddr)
82{99{
83- uint64_t devAddr = reinterpret_cast<uint64_t>(devPtr);100+ uint64_t deviceKey = GetCurDeviceKey();
84- auto virMemRes = RunnerDB::GetOneByPred<sim::VirtualMemBlock>(101+ auto virMemRes = RunnerDB::GetOneByPred<sim::VirtualMemBlock> (
85- [devAddr](const sim::VirtualMemBlock &virMem)102+ [devAddr, deviceKey](const sim::VirtualMemBlock &virMem) {
86- { return ((virMem.start_ptr <= devAddr) &&103+ return ((virMem.dev_mapped_ptr <= devAddr) &&
87- (devAddr < (virMem.start_ptr + virMem.size)) &&104+ (devAddr < (virMem.dev_mapped_ptr + virMem.size)) &&
88- (virMem.src_type == (uint8_t)sim::VIR_MEM_TYPE_DEV)); });105+ (virMem.src_type == (uint8_t)sim::VIR_MEM_TYPE_DEV)) &&
106+ (virMem.device_id == deviceKey);
107+ }
108+ );
89 if (!virMemRes.second) {109 if (!virMemRes.second) {
90- HCCL_VM_ERROR("cannot find virMemRes by devAddr[{}], called from {}:{}]", devAddr, file, line);110+ HCCL_VM_ERROR("cannot find virMemRes by devAddr[{}]", devAddr);
91- return nullptr;111+ return 0;
112+ }
113+ 
114+ uint64_t diff = devAddr - virMemRes.first.dev_mapped_ptr;
115+ return virMemRes.first.start_ptr + diff;
116+}
117+ 
118+// AICPU构造Task时任务转换,将对端设备地址(rankId对应host进程申请的)转换为虚拟地址
119+uint64_t TransRemoteAddrToVirtualByRank(uint64_t devAddr, uint32_t rankId)
120+{
121+ auto virMemRes = RunnerDB::GetOneByPred<sim::VirtualMemBlock> (
122+ [devAddr, rankId](const sim::VirtualMemBlock &virMem) {
123+ return ((virMem.dev_mapped_ptr <= devAddr) &&
124+ (devAddr < (virMem.dev_mapped_ptr + virMem.size)) &&
125+ (virMem.src_type == (uint8_t)sim::VIR_MEM_TYPE_DEV)) &&
126+ (virMem.rank_id == rankId);
127+ }
128+ );
129+ if (!virMemRes.second) {
130+ HCCL_VM_ERROR("cannot find virMemRes by devAddr[{}]", devAddr);
131+ return 0;
132+ }
133+ 
134+ uint64_t diff = devAddr - virMemRes.first.dev_mapped_ptr;
135+ return virMemRes.first.start_ptr + diff;
136+}
137+ 
138+uint64_t GetDevMapperAddrByDevAddrImpl(uint64_t devAddr, const char *file, int line)
139+{
140+ uint64_t deviceKey = GetCurDeviceKey();
141+ auto virMemRes = RunnerDB::GetOneByPred<sim::VirtualMemBlock>(
142+ [devAddr, deviceKey](const sim::VirtualMemBlock &virMem) {
143+ return (virMem.dev_mapped_ptr <= devAddr) &&
144+ (devAddr < virMem.dev_mapped_ptr + virMem.size) &&
145+ (virMem.src_type == static_cast<uint8_t>(sim::VIR_MEM_TYPE_DEV)) &&
146+ (virMem.device_id == deviceKey);
147+ });
148+ if (!virMemRes.second) {
149+ HCCL_VM_ERROR("cannot find virMemRes by devAddr[0x{:x}], called from {}:{}", devAddr, file, line);
150+ return 0;
151+ }
152+ 
153+ // 已经映射过的这里直接取值
154+ if (virMemRes.first.is_dev_access == 1) {
155+ HCCL_VM_INFO("device cann access this devAddr[0x{:x}], called from {}:{}", devAddr, file, line);
156+ return devAddr;
92 }157 }
93 158 
94 auto phyMemId = virMemRes.first.phy_mem_id;159 auto phyMemId = virMemRes.first.phy_mem_id;
95 auto phyMemRes = RunnerDB::GetById<sim::PhyMemBlock>(phyMemId);160 auto phyMemRes = RunnerDB::GetById<sim::PhyMemBlock>(phyMemId);
96 if (!phyMemRes.has_value()) {161 if (!phyMemRes.has_value()) {
97- HCCL_VM_ERROR("cannot find phyMemRes by phyMemId[{}], called from {}:{}]", phyMemId, file, line);162+ HCCL_VM_ERROR("cannot find phyMemRes by phyMemId[{}], called from {}:{}", phyMemId, file, line);
98- return nullptr;163+ return 0;
99- };164+ }
100 165 
101 std::string memName(phyMemRes->name);166 std::string memName(phyMemRes->name);
102- void *realPtr = sim::MemoryManager::GetInstance().AcquireMemByName(memName.c_str());167+ void *devMappedPtr = sim::MemoryManager::GetInstance().AcquireMemByName(memName.c_str());
103- HCCL_VM_INFO("devAddr[{}] realPtr[{}] memName[{}]", devAddr, reinterpret_cast<uint64_t>(realPtr), memName);168+ if (devMappedPtr == nullptr) {
169+ HCCL_VM_ERROR("acquire device shm for memName[{}] failed, called from {}:{}", memName, file, line);
170+ return 0;
171+ }
104 172 
105- return realPtr;173+ uint64_t offset = devAddr - virMemRes.first.dev_mapped_ptr;
174+ uint64_t result = reinterpret_cast<uint64_t>(devMappedPtr) + offset;
175+ HCCL_VM_INFO("devAddr[0x{:x}] offset[{}] devMappedPtr[0x{:x}] memName[{}]",
176+ devAddr, offset, reinterpret_cast<uint64_t>(devMappedPtr), memName);
177+ return result;
106}178}
107 179 
108uint32_t GetRankIdByDevAddr(uint64_t devAddr)180uint32_t GetRankIdByDevAddr(uint64_t devAddr)
@@ -134,17 +206,6 @@ uint32_t GetRankIdByDevAddr(uint64_t devAddr)
134 return rank.first.rank_id;206 return rank.first.rank_id;
135}207}
136 208 
137-HcclAicpuData *GetHcclAicpuDataShmPtr()
138-{
139- void *shmptr = sim::MemoryManager::GetInstance().AcquireMemByName("HcclAicpuData");
140- if (shmptr == nullptr) {
141- HCCL_VM_ERROR("acquire HcclAicpuData shm failed.");
142- return nullptr;
143- }
144- 
145- return reinterpret_cast<HcclAicpuData *>(shmptr);
146-}
147- 
148uint32_t GetRankIdByIpAddr(std::string ipAddr)209uint32_t GetRankIdByIpAddr(std::string ipAddr)
149{210{
150 auto ret = RunnerDB::GetOneByPred<sim::EndPoint>([ipAddr](const sim::EndPoint &p) { return strcmp(p.ip_addr, ipAddr.c_str()) == 0; });211 auto ret = RunnerDB::GetOneByPred<sim::EndPoint>([ipAddr](const sim::EndPoint &p) { return strcmp(p.ip_addr, ipAddr.c_str()) == 0; });
@@ -289,6 +350,47 @@ void RegisterSignalHandler()
289 signal(SIGILL, SignalHandler); // 非法指令350 signal(SIGILL, SignalHandler); // 非法指令
290}351}
291 352 
353+bool GetWqebufferByJettyId(uint64_t jettyId, uint64_t &wqeBuffer)
354+{
355+ auto raJetty = RunnerDB::GetById<sim::RaJetty>(jettyId);
356+ if (!raJetty.has_value()) {
357+ HCCL_VM_ERROR("RaJetty id:{:d} not found", jettyId);
358+ return false;
359+ }
360+ 
361+ wqeBuffer = raJetty->sqBuffer;
362+ return true;
363+}
364+ 
365+static int g_h2dReadFd = -1;
366+static int g_d2hWriteFd = -1;
367+ 
368+void InitPipeFds(int h2dReadFd, int d2hWriteFd)
369+{
370+ g_h2dReadFd = h2dReadFd;
371+ g_d2hWriteFd = d2hWriteFd;
372+}
373+ 
374+int DeviceSendMsg(uint8_t cmd, const void *data, uint32_t dataLen)
375+{
376+ if (g_d2hWriteFd < 0) {
377+ HCCL_VM_ERROR("pipe d2h write fd not initialized.");
378+ return -1;
379+ }
380+ 
381+ return sim::PipeSendMsg(g_d2hWriteFd, cmd, data, dataLen);
382+}
383+ 
384+int DeviceRecvMsg(uint8_t &outCmd, void *outData, uint32_t maxLen, uint32_t &outLen)
385+{
386+ if (g_h2dReadFd < 0) {
387+ HCCL_VM_ERROR("pipe h2d read fd not initialized.");
388+ return -1;
389+ }
390+ 
391+ return sim::PipeRecvMsg(g_h2dReadFd, outCmd, outData, maxLen, outLen);
392+}
393+ 
292#ifdef __cplusplus394#ifdef __cplusplus
293}395}
294#endif396#endif
@@ -25,22 +25,28 @@ HcclSim::HcclVmResult SetCurRankId(uint32_t rankId);
25 25 
26HcclSim::HcclVmResult GetCurRankId(uint32_t *rankId);26HcclSim::HcclVmResult GetCurRankId(uint32_t *rankId);
27 27 
28+void SetCurDeviceKey(uint32_t deviceKey);
29+ 
30+uint32_t GetCurDeviceKey();
31+ 
28HcclSim::HcclVmResult GetSqBufferAddr(uint8_t **sqBuff);32HcclSim::HcclVmResult GetSqBufferAddr(uint8_t **sqBuff);
29 33 
30HcclSim::HcclVmResult GetPiValByJettyId(uint32_t jettyId, uint32_t *piValue);34HcclSim::HcclVmResult GetPiValByJettyId(uint32_t jettyId, uint32_t *piValue);
31 35 
32HcclSim::HcclVmResult UpdatePiValByJettyId(uint32_t jettyId, uint32_t piValue);36HcclSim::HcclVmResult UpdatePiValByJettyId(uint32_t jettyId, uint32_t piValue);
33 37 
34-void *GetRealPtrByDevPtrImpl(void *devPtr, const char *file, int line);38+uint64_t TransLocalAddrToVirtual(uint64_t devAddr);
35 39 
36-#define GetRealPtrByDevPtr(devPtr) GetRealPtrByDevPtrImpl(devPtr, __FILE__, __LINE__)40+uint64_t TransRemoteAddrToVirtualByRank(uint64_t devAddr, uint32_t rankId);
37 41 
38uint32_t GetRankIdByDevAddr(uint64_t devAddr);42uint32_t GetRankIdByDevAddr(uint64_t devAddr);
39 43 
40-HcclAicpuData *GetHcclAicpuDataShmPtr();
41- 
42uint32_t GetRankIdByIpAddr(std::string ipAddr);44uint32_t GetRankIdByIpAddr(std::string ipAddr);
43 45 
46+uint64_t GetDevMapperAddrByDevAddrImpl(uint64_t devAddr, const char *file, int line);
47+ 
48+#define GetDevMapperAddrByDevAddr(devAddr) GetDevMapperAddrByDevAddrImpl(devAddr, __FILE__, __LINE__)
49+ 
44void UpdataKfcStatus(uint64_t d2hAddr);50void UpdataKfcStatus(uint64_t d2hAddr);
45 51 
46void RegisterSignalHandler();52void RegisterSignalHandler();
@@ -49,6 +55,14 @@ uint32_t GetSqTail(uint32_t sqId);
49 55 
50void UpdateSqTail(uint32_t sqId, uint32_t newTail);56void UpdateSqTail(uint32_t sqId, uint32_t newTail);
51 57 
58+bool GetWqebufferByJettyId(uint64_t jettyId, uint64_t &wqeBuffer);
59+ 
60+void InitPipeFds(int h2dReadFd, int d2hWriteFd);
61+ 
62+int DeviceSendMsg(uint8_t cmd, const void *data, uint32_t dataLen);
63+ 
64+int DeviceRecvMsg(uint8_t &outCmd, void *outData, uint32_t maxLen, uint32_t &outDataLen);
65+ 
52#ifdef __cplusplus66#ifdef __cplusplus
53}67}
54#endif68#endif
@@ -9,20 +9,18 @@
9 */9 */
10 10 
11#include <atomic>11#include <atomic>
12-#include <cstdint>12+#include <cstdlib>
13#include <cstring>13#include <cstring>
14-#include <iostream>14+#include <string>
15+#include <unistd.h>
15 16 
16#include "hccl_device_pub.h"17#include "hccl_device_pub.h"
17-#include "hccl_kernel_executor.h"
18-#include "sim_log.h"
19#include "db_sim_op_db_ops.h"18#include "db_sim_op_db_ops.h"
20- 19+#include "sim_log.h"
21-using namespace HcclSim;20+#include "sim_aicpu_pipe_msg.h"
22- 21+#include "sim_pipe_io.h"
23-namespace sim {22+#include "sim_aicpu_pipe_handler.h"
24- extern uint32_t g_currOpDetailId;23+#include "sim_kernel_lib_mgr.h"
25-}
26 24 
27int main(int argc, char *argv[])25int main(int argc, char *argv[])
28{26{
@@ -31,40 +29,64 @@ int main(int argc, char *argv[])
31 29 
32 RegisterSignalHandler();30 RegisterSignalHandler();
33 setvbuf(stdout, nullptr, _IOLBF, 0);31 setvbuf(stdout, nullptr, _IOLBF, 0);
34- HCCL_VM_INFO("main process start.");32+ HCCL_VM_INFO("[device] main process start.");
35 33
36- uint32_t rankId = static_cast<uint32_t>(std::stoi(argv[1]));34+ if (argc < 4) {
37- SetCurRankId(rankId);35+ HCCL_VM_ERROR("[device] Usage: {} <rankId> <h2d_read_fd> <d2h_write_fd>", argv[0]);
38- HCCL_VM_INFO("rankId[{}] process start...", rankId);
39- 
40- HcclAicpuData *aicpuData = GetHcclAicpuDataShmPtr();
41- if (aicpuData == nullptr) {
42- HCCL_VM_ERROR("get HcclAicpuData shm ptr failed.");
43 return -1;36 return -1;
44 }37 }
45 38 
46- aicpuData->task[rankId].devState = DEVICE_WAIT;39+ uint32_t rankId = static_cast<uint32_t>(std::atoi(argv[1]));
40+ uint32_t devKey = static_cast<uint32_t>(std::atoi(argv[2]));
41+ int h2dReadFd = std::atoi(argv[3]);
42+ int d2hWriteFd = std::atoi(argv[4]);
43+ HCCL_VM_INFO("[device] parse input args: rankId={} devKey={} h2dReadFd={} d2hWriteFd={}", rankId, devKey, h2dReadFd, d2hWriteFd);
44+ 
45+ SetCurRankId(rankId);
46+ SetCurDeviceKey(devKey);
47+ InitPipeFds(h2dReadFd, d2hWriteFd);
48+ DeviceSendMsg(PIPE_RSP_READY, nullptr, 0);
49+ 
50+ uint8_t cmd = 0;
51+ uint8_t payload[PAYLOAD_LEN_MAX] = {0};
52+ uint32_t payloadLen = 0;
53+ 
47 while (true) {54 while (true) {
48- if (aicpuData->task[rankId].devState == DEVICE_WAIT) {55+ int rc = DeviceRecvMsg(cmd, payload, sizeof(payload), payloadLen);
49- sleep(1);56+ if (rc != 0) {
50- continue;57+ HCCL_VM_INFO("[device] DeviceRecvMsg failed (EOF or error), exiting loop.");
58+ break;
51 }59 }
52 60 
53- std::atomic_thread_fence(std::memory_order_acquire);61+ switch (cmd) {
54- std::string kernelName(aicpuData->task[rankId].kernelName);62+ case PIPE_CMD_SHUTDOWN:
55- if (kernelName == "HcclLaunchAicpuKernel" || kernelName == "RunAicpuNotifyWait" ||63+ HCCL_VM_INFO("[device] Received PIPE_CMD_SHUTDOWN, exiting gracefully.");
56- kernelName == "HcclLaunchP2pAicpuKernel" || kernelName == "RunAicpuNotifyRecord") {64+ goto done;
57- uint32_t opDetailId = 0;65+ case PIPE_CMD_SET_DEV_ID:
58- int ret = sim::QueryNewestOpDeatailIdByPid(getppid(), opDetailId);66+ sim::HandlePipeCmdSetDevId(payload, payloadLen);
59- if (ret != 0) {67+ break;
60- HCCL_VM_ERROR("rankId[{}] kernel[{}] QueryNewestOpDeatailIdByPid failed.", rankId, kernelName);68+ case PIPE_CMD_GET_DEV_PTR:
61- }69+ sim::HandlePipeCmdGetDevPtr(payload, payloadLen);
62- sim::g_currOpDetailId = opDetailId;70+ break;
71+ case PIPE_CMD_EXEC_KERNEL:
72+ sim::HandlePipeCmdExecKernel(payload, payloadLen);
73+ break;
74+ case PIPE_CMD_FREE_DEV_PTR:
75+ sim::HandlePipeCmdFreeDevPtr(payload, payloadLen);
76+ break;
77+ default:
78+ HCCL_VM_ERROR("[device] Unknown command: 0x{:02x}", cmd);
79+ break;
63 }80 }
64- 
65- ExecuteAicpuKernel(rankId, kernelName, aicpuData->task[rankId].args);
66- aicpuData->task[rankId].devState = DEVICE_WAIT;
67 }81 }
68 82 
83+done:
84+ uint32_t curRankId = 0;
85+ GetCurRankId(&curRankId);
86+ sim::KernelLibManager::GetInstance().Cleanup();
87+ HCCL_VM_INFO("[device] rankId[{}] exiting.", curRankId);
88+ 
89+ sim::PipeClose(h2dReadFd);
90+ sim::PipeClose(d2hWriteFd);
69 _exit(0);91 _exit(0);
70}92}
@@ -31,14 +31,14 @@ target_include_directories(hccl_device_proxy PRIVATE
31 ${THRID_PARTY_DIR}/spdlog31 ${THRID_PARTY_DIR}/spdlog
32 ${HCCL_VM_SRC}/device_arm32 ${HCCL_VM_SRC}/device_arm
33 33 
34- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc34+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc
35- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl35+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl
36- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include36+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include
37- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/hccl37+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/hccl
38- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/driver38+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/driver
39- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/runtime39+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/runtime
40- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/toolchain40+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/toolchain
41- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/profiling41+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/profiling
42)42)
43 43 
44install(TARGETS hccl_device_proxy44install(TARGETS hccl_device_proxy
@@ -10,7 +10,7 @@
10 10 
11#include <cstdint>11#include <cstdint>
12#include <mutex>12#include <mutex>
13- 13+#include <thread>
14namespace aicpu {14namespace aicpu {
15std::mutex g_sqeIdMtx;15std::mutex g_sqeIdMtx;
16constexpr uint32_t INITAL_SQE_ID = 0x80000000U;16constexpr uint32_t INITAL_SQE_ID = 0x80000000U;
@@ -33,3 +33,26 @@ void GetSqeId(const uint32_t num, uint32_t &start, uint32_t &end)
33 return;33 return;
34}34}
35} // aicpu35} // aicpu
36+ 
37+extern "C" {
38+ 
39+// 打桩支持AICPU上背景线程,用于销毁通信域等场景
40+int32_t StartMC2MaintenanceThread(void (*f1)(void*), void *p1,
41+ void (*f2)(void*), void *p2)
42+{
43+ // 创建一个真正运行的后台线程(非 MC2 固件,而是 std::thread)
44+ // AicpuDaemonService::ServiceRun 会无限循环直到 command == Stop
45+ // 守护线程 detach:进程退出时自然死亡
46+ std::thread(f1, p1).detach();
47+ return 0;
48+}
49+ 
50+int32_t AicpuCreateCtrlThread(int32_t type,
51+ void (*f1)(void*), void *p1,
52+ void (*f2)(void*), void *p2)
53+{
54+ std::thread(f1, p1).detach();
55+ return 0;
56+}
57+ 
58+} // extern "C"
@@ -30,7 +30,8 @@ uint32_t curRankId = 0;
30 30 
31void ParseA5SqeFromSqBuffer(uint32_t devId, struct halSqCqConfigInfo *info)31void ParseA5SqeFromSqBuffer(uint32_t devId, struct halSqCqConfigInfo *info)
32{32{
33- curRankId = devId;33+ // devId会在不同Server内重复,此处使用Device进程维护的rankId
34+ GetCurRankId(&curRankId);
34 uint32_t streamId = info->sqId;35 uint32_t streamId = info->sqId;
35 int tail = info->value[0];36 int tail = info->value[0];
36 int head = GetSqTail(streamId);37 int head = GetSqTail(streamId);
@@ -92,8 +93,8 @@ void ParseDavidSDMASqe(uint32_t streamId, void *sqeBuf)
92 taskMeta.jettyId = UINT32_MAX;93 taskMeta.jettyId = UINT32_MAX;
93 94 
94 uint64_t length = sqe->u.strideMode0.lengthMove;95 uint64_t length = sqe->u.strideMode0.lengthMove;
95- uint64_t srcOffset = GetFull64BitAddr(sqe->u.strideMode0.srcAddrLow, sqe->u.strideMode0.srcAddrHigh);96+ uint64_t srcOffset = TransLocalAddrToVirtual(GetFull64BitAddr(sqe->u.strideMode0.srcAddrLow, sqe->u.strideMode0.srcAddrHigh));
96- uint64_t dstOffset = GetFull64BitAddr(sqe->u.strideMode0.dstAddrLow, sqe->u.strideMode0.dstAddrHigh);97+ uint64_t dstOffset = TransLocalAddrToVirtual(GetFull64BitAddr(sqe->u.strideMode0.dstAddrLow, sqe->u.strideMode0.dstAddrHigh));
97 uint64_t srcRankId = GetRankIdByDevAddr(srcOffset);98 uint64_t srcRankId = GetRankIdByDevAddr(srcOffset);
98 uint64_t dstRankId = GetRankIdByDevAddr(dstOffset);99 uint64_t dstRankId = GetRankIdByDevAddr(dstOffset);
99 100 
@@ -182,22 +183,9 @@ void ParseDavidUDMASqe(uint32_t streamId, void *sqeBuf)
182{183{
183 Rt91095StarsUbdmaDBmodeSqe *ubSqe = reinterpret_cast<Rt91095StarsUbdmaDBmodeSqe *>(sqeBuf);184 Rt91095StarsUbdmaDBmodeSqe *ubSqe = reinterpret_cast<Rt91095StarsUbdmaDBmodeSqe *>(sqeBuf);
184 uint32_t jettyId = ubSqe->jettyId1;185 uint32_t jettyId = ubSqe->jettyId1;
185- 186+ uint64_t wqeBuffer = 0;
186- HcclAicpuData *aicpuData = GetHcclAicpuDataShmPtr();187+ if (!GetWqebufferByJettyId(jettyId, wqeBuffer)) {
187- if (aicpuData == nullptr) {188+ HCCL_VM_ERROR("GetWqebufferByJettyId failed, jettyId[{}].", jettyId);
188- HCCL_VM_ERROR("aicpuData is nullptr.");
189- return;
190- }
191- 
192- if (jettyId >= HcclSim::AICPU_JETTY_NUM_MAX) {
193- HCCL_VM_ERROR("jettyId[{}] >= AICPU_JETTY_NUM_MAX[{}]", jettyId, HcclSim::AICPU_JETTY_NUM_MAX);
194- return;
195- }
196- 
197- uint64_t wqeAddrDev = aicpuData->common.jettyId2WqeBufMap[jettyId];
198- uint64_t wqeBuffer = reinterpret_cast<uint64_t>(GetRealPtrByDevPtr(reinterpret_cast<void *>(wqeAddrDev)));
199- if (wqeBuffer == 0) {
200- HCCL_VM_ERROR("wqeBuffer is nullptr, wqeAddrDev[{}].", wqeAddrDev);
201 return;189 return;
202 }190 }
203 191 
@@ -243,13 +231,14 @@ void ParseDavidUBReadWriteSqe(uint64_t wqeAddr, uint16_t streamId, uint32_t jett
243 taskMeta.jettyId = jettyId;231 taskMeta.jettyId = jettyId;
244 memcpy(taskMeta.rmEid, ubWqe->comm.rmtEid, 16);232 memcpy(taskMeta.rmEid, ubWqe->comm.rmtEid, 16);
245 233 
234+ uint32_t rmtRankId = GetRmtRankIdByEid(ubWqe->comm.rmtEid[0]);
246 // case1:UbConnLite::InlineWrite 写Notify235 // case1:UbConnLite::InlineWrite 写Notify
247 if (ubWqe->comm.inlineEn == 1) {236 if (ubWqe->comm.inlineEn == 1) {
248 uint64_t notifyAddr = GetFull64BitAddr(ubWqe->comm.rmtAddrLow, ubWqe->comm.rmtAddrHigh);237 uint64_t notifyAddr = GetFull64BitAddr(ubWqe->comm.rmtAddrLow, ubWqe->comm.rmtAddrHigh);
249 taskMeta.taskType = HccLTaskMetaType::NOTIFY_RECORD;238 taskMeta.taskType = HccLTaskMetaType::NOTIFY_RECORD;
250 taskMeta.taskData.notify.notifyId = notifyAddr;239 taskMeta.taskData.notify.notifyId = notifyAddr;
251 taskMeta.taskData.notify.srcRankId = curRankId;240 taskMeta.taskData.notify.srcRankId = curRankId;
252- taskMeta.taskData.notify.dstRankId = GetRmtRankIdByEid(ubWqe->comm.rmtEid[0]);241+ taskMeta.taskData.notify.dstRankId = rmtRankId;
253 PrintTaskMetaData(taskMeta);242 PrintTaskMetaData(taskMeta);
254 InsertTaskToCollectionDev(&taskMeta);243 InsertTaskToCollectionDev(&taskMeta);
255 return;244 return;
@@ -259,10 +248,12 @@ void ParseDavidUBReadWriteSqe(uint64_t wqeAddr, uint16_t streamId, uint32_t jett
259 uint64_t length = static_cast<uint64_t>(ubWqe->u.sge.length);248 uint64_t length = static_cast<uint64_t>(ubWqe->u.sge.length);
260 uint64_t locAddr = GetFull64BitAddr(ubWqe->u.sge.dataAddrLow, ubWqe->u.sge.dataAddrHigh);249 uint64_t locAddr = GetFull64BitAddr(ubWqe->u.sge.dataAddrLow, ubWqe->u.sge.dataAddrHigh);
261 uint64_t rmtAddr = GetFull64BitAddr(ubWqe->comm.rmtAddrLow, ubWqe->comm.rmtAddrHigh);250 uint64_t rmtAddr = GetFull64BitAddr(ubWqe->comm.rmtAddrLow, ubWqe->comm.rmtAddrHigh);
251+ locAddr = TransLocalAddrToVirtual(locAddr);
252+ rmtAddr = TransRemoteAddrToVirtualByRank(rmtAddr, rmtRankId);
262 uint64_t srcOffset = isRead ? rmtAddr : locAddr;253 uint64_t srcOffset = isRead ? rmtAddr : locAddr;
263 uint64_t dstOffset = isRead ? locAddr : rmtAddr;254 uint64_t dstOffset = isRead ? locAddr : rmtAddr;
264- uint32_t srcRankId = GetRankIdByDevAddr(srcOffset);255+ uint32_t srcRankId = isRead ? rmtRankId : curRankId;
265- uint32_t dstRankId = GetRankIdByDevAddr(dstOffset);256+ uint32_t dstRankId = isRead ? curRankId : rmtRankId;
266 taskMeta.taskType = HccLTaskMetaType::MEM_CPY;257 taskMeta.taskType = HccLTaskMetaType::MEM_CPY;
267 taskMeta.taskData.transMem.srcOffset = srcOffset;258 taskMeta.taskData.transMem.srcOffset = srcOffset;
268 taskMeta.taskData.transMem.dstOffset = dstOffset;259 taskMeta.taskData.transMem.dstOffset = dstOffset;
@@ -294,10 +285,11 @@ void ParseDavidUBWriteWithNotifySqe(uint64_t wqeAddr, uint16_t streamId, uint32_
294 taskMeta1.rankId = curRankId;285 taskMeta1.rankId = curRankId;
295 taskMeta1.jettyId = jettyId;286 taskMeta1.jettyId = jettyId;
296 memcpy(taskMeta1.rmEid, ubWqe->comm.rmtEid, 16);287 memcpy(taskMeta1.rmEid, ubWqe->comm.rmtEid, 16);
288+ uint32_t rmtRankId = GetRmtRankIdByEid(ubWqe->comm.rmtEid[0]);
297 289 
298 // 1.先构造MEM_CPY(或SDMA_REDUCE)所需参数290 // 1.先构造MEM_CPY(或SDMA_REDUCE)所需参数
299- uint64_t dstOffset = GetFull64BitAddr(ubWqe->comm.rmtAddrLow, ubWqe->comm.rmtAddrHigh);291+ uint64_t dstOffset = TransRemoteAddrToVirtualByRank(GetFull64BitAddr(ubWqe->comm.rmtAddrLow, ubWqe->comm.rmtAddrHigh), rmtRankId);
300- uint64_t srcOffset = GetFull64BitAddr(ubWqe->localU.sge.dataAddrLow, ubWqe->localU.sge.dataAddrHigh);292+ uint64_t srcOffset = TransLocalAddrToVirtual(GetFull64BitAddr(ubWqe->localU.sge.dataAddrLow, ubWqe->localU.sge.dataAddrHigh));
301 uint64_t length = static_cast<uint64_t>(ubWqe->localU.sge.length);293 uint64_t length = static_cast<uint64_t>(ubWqe->localU.sge.length);
302 uint32_t srcRankId = GetRankIdByDevAddr(srcOffset);294 uint32_t srcRankId = GetRankIdByDevAddr(srcOffset);
303 uint32_t dstRankId = GetRankIdByDevAddr(dstOffset);295 uint32_t dstRankId = GetRankIdByDevAddr(dstOffset);
@@ -331,7 +323,7 @@ void ParseDavidUBWriteWithNotifySqe(uint64_t wqeAddr, uint16_t streamId, uint32_
331 taskMeta2.taskType = HccLTaskMetaType::NOTIFY_RECORD;323 taskMeta2.taskType = HccLTaskMetaType::NOTIFY_RECORD;
332 taskMeta2.taskData.notify.notifyId = notifyAddr;324 taskMeta2.taskData.notify.notifyId = notifyAddr;
333 taskMeta2.taskData.notify.srcRankId = curRankId;325 taskMeta2.taskData.notify.srcRankId = curRankId;
334- taskMeta2.taskData.notify.dstRankId = GetRmtRankIdByEid(ubWqe->comm.rmtEid[0]);326+ taskMeta2.taskData.notify.dstRankId = rmtRankId;
335 PrintTaskMetaData(taskMeta2);327 PrintTaskMetaData(taskMeta2);
336 InsertTaskToCollectionDev(&taskMeta2);328 InsertTaskToCollectionDev(&taskMeta2);
337}329}
@@ -0,0 +1,131 @@
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+#include "sim_aicpu_pipe_handler.h"
12+#include "sim_aicpu_pipe_msg.h"
13+#include <unistd.h>
14+#include <string>
15+#include <dlfcn.h>
16+#include "sim_log.h"
17+#include "sim_common_api.h"
18+#include "db_sim_op_db_ops.h"
19+#include "hccl_device_pub.h"
20+#include "store_sim_memory_manager.h"
21+#include "sim_kernel_lib_mgr.h"
22+#include "aicpu_args_stub.h"
23+ 
24+namespace sim {
25+ 
26+extern uint64_t g_currOpDetailId;
27+ 
28+int HandlePipeCmdSetDevId(uint8_t* payload, uint16_t payloadLen)
29+{
30+ SetDevIdPayload *req = reinterpret_cast<SetDevIdPayload *>(payload);
31+ uint32_t curRankId = static_cast<uint32_t>(req->rankId);
32+ uint64_t curDeviceKey = req->deviceKey;
33+ SetCurRankId(curRankId);
34+ SetCurDeviceKey(curDeviceKey);
35+ HCCL_VM_INFO("Process[{}] PIPE_RSP_SET_DEV_ID, set rankId = [{}], deviceKey = [{}]", getpid(), curRankId, curDeviceKey);
36+ uint64_t donePayload = 0;
37+ DeviceSendMsg(PIPE_RSP_SET_DEV_ID, &donePayload, sizeof(donePayload));
38+ return 0;
39+}
40+ 
41+int HandlePipeCmdGetDevPtr(uint8_t* payload, uint16_t payloadLen)
42+{
43+ DevMemOpPayload *req = reinterpret_cast<DevMemOpPayload *>(payload);
44+ RspGetDevPtrPayload donePayload{};
45+ void *shmptr = sim::MemoryManager::GetInstance().AcquireMemByName(req->memName);
46+ if (shmptr == nullptr) {
47+ donePayload.ptr = 0;
48+ HCCL_VM_ERROR("acquire {} shm failed.", req->memName);
49+ } else {
50+ donePayload.ptr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(shmptr));
51+ }
52+ HCCL_VM_INFO("[device] acquire {} shm ptr:{:p}", req->memName, shmptr);
53+ DeviceSendMsg(PIPE_RSP_GET_DEV_PTR, &donePayload, sizeof(donePayload));
54+ return 0;
55+}
56+ 
57+static void ExecuteAicpuKernel(uint32_t rankId, ExecKernelPayload *kernelReq)
58+{
59+ uint64_t args = kernelReq->args;
60+ std::string kernelSo = kernelReq->soName;
61+ std::string kernelName = kernelReq->kernelName;
62+ 
63+ HCCL_VM_INFO("rankId[{}] kernel[{}] start run...", rankId, kernelName);
64+ std::string libDir = InstallPath::ResolveToInstallRoot("lib/" + GetArchStr()) + "/" + kernelSo;
65+ KernelFn fn = sim::KernelLibManager::GetInstance().GetOrLoadFunc(libDir, kernelName);
66+ if (!fn) {
67+ HCCL_VM_ERROR("failed to resolve function");
68+ return;
69+ }
70+ 
71+ void *ptr = reinterpret_cast<void *>(args);
72+ if (ptr == nullptr) {
73+ HCCL_VM_ERROR("[device] rankId[{}] init func handle failed null ptr.", rankId);
74+ return;
75+ }
76+ 
77+ // CCU退化AICPU场景此处使用的内存先于device进程启动前分配,使用前需转换
78+ if (kernelName == "RunAicpuIndOpCommInit") {
79+ CommAicpuParam *param = reinterpret_cast<CommAicpuParam *>(ptr);
80+ param->kfcControlTransferH2DParams.deviceAddr = GetDevMapperAddrByDevAddr(param->kfcControlTransferH2DParams.deviceAddr);
81+ param->kfcControlTransferH2DParams.readCacheAddr = GetDevMapperAddrByDevAddr(param->kfcControlTransferH2DParams.readCacheAddr);
82+ param->kfcStatusTransferD2HParams.deviceAddr = GetDevMapperAddrByDevAddr(param->kfcStatusTransferD2HParams.deviceAddr);
83+ }
84+ 
85+ fn(ptr);
86+ 
87+ HCCL_VM_INFO("rankId[{}] kernel[{}] finish run...", rankId, kernelName);
88+}
89+ 
90+int HandlePipeCmdExecKernel(uint8_t* payload, uint16_t payloadLen)
91+{
92+ if (payloadLen < sizeof(ExecKernelPayload)) {
93+ HCCL_VM_ERROR("[device] EXEC_KERNEL payload too small: {} < {}",
94+ payloadLen, sizeof(ExecKernelPayload));
95+ return -1;
96+ }
97+ 
98+ ExecKernelPayload *kernelReq = reinterpret_cast<ExecKernelPayload *>(payload);
99+ uint32_t rankId = 0;
100+ GetCurRankId(&rankId);
101+ std::string kernelName(kernelReq->kernelName);
102+ HCCL_VM_INFO("[device] rankId[{}] executing kernel:{}", rankId, kernelName);
103+ 
104+ // device进程查询并使用host进程记录的opDetailId
105+ uint32_t opDetailId = 0;
106+ int ret = sim::QueryNewestOpDeatailIdByPid(getppid(), opDetailId);
107+ if (ret != 0) {
108+ HCCL_VM_ERROR("[device] QueryNewestOpDeatailIdByPid failed.");
109+ }
110+ 
111+ sim::g_currOpDetailId = opDetailId;
112+ 
113+ ExecuteAicpuKernel(rankId, kernelReq);
114+ RspExecKernelPayload donePayload{};
115+ donePayload.status = 0;
116+ DeviceSendMsg(PIPE_RSP_EXEC_KERNEL, &donePayload, sizeof(donePayload));
117+ return 0;
118+}
119+ 
120+int HandlePipeCmdFreeDevPtr(uint8_t* payload, uint16_t payloadLen)
121+{
122+ DevMemOpPayload *req = reinterpret_cast<DevMemOpPayload *>(payload);
123+ sim::MemoryManager::GetInstance().ReleaseMemByName(req->memName);
124+ HCCL_VM_INFO("[device] release memName:{} shm", req->memName);
125+ RspFreeDevPtrPayload donePayload{};
126+ donePayload.status = 0;
127+ DeviceSendMsg(PIPE_RSP_FREE_DEV_PTR, &donePayload, sizeof(donePayload));
128+ return 0;
129+}
130+ 
131+}
Rtest/hccl_vm/src/device_arm/hccl_kernel_executor.htest/hccl_vm/src/device_arm/sim_aicpu_pipe_handler.h+13-7
@@ -8,15 +8,21 @@
8 * See LICENSE in the root of the software repository for the full text of the License.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
10 10 
11-#ifndef HCCL_KERNEL_EXECUTOR_H11+#ifndef SIM_AICPU_PIPE_HANDLER_H
12-#define HCCL_KERNEL_EXECUTOR_H12+#define SIM_AICPU_PIPE_HANDLER_H
13+ 
13#include <cstdint>14#include <cstdint>
14-#include <iostream>
15-#include <string>
16 15 
17-void ExecuteAicpuKernel(uint32_t rankId, const std::string &kernelName, uint64_t args);16+namespace sim {
18 17 
19-void* LoadLibrary(const std::string &libDir, const std::string &libName);18+int HandlePipeCmdSetDevId(uint8_t* payload, uint16_t payloadLen);
19+ 
20+int HandlePipeCmdGetDevPtr(uint8_t* payload, uint16_t payloadLen);
21+ 
22+int HandlePipeCmdExecKernel(uint8_t* payload, uint16_t payloadLen);
23+ 
24+int HandlePipeCmdFreeDevPtr(uint8_t* payload, uint16_t payloadLen);
25+ 
26+}
20 27 
21-bool InitKernelFuncHandle();
22#endif28#endif
@@ -0,0 +1,105 @@
1+#include "sim_kernel_lib_mgr.h"
2+#include <dlfcn.h>
3+#include "sim_log.h"
4+#include "sim_common_defs.h"
5+#include "sim_common_api.h"
6+ 
7+namespace sim {
8+ 
9+KernelLibManager::KernelLibManager()
10+{
11+ LoadBaseLibs();
12+}
13+ 
14+KernelLibManager& KernelLibManager::GetInstance()
15+{
16+ static KernelLibManager instance;
17+ return instance;
18+}
19+ 
20+void* KernelLibManager::LoadKernelSo(const std::string& libName)
21+{
22+ auto it = m_soHandles.find(libName);
23+ if (it != m_soHandles.end()) {
24+ return it->second;
25+ }
26+ 
27+ void* handle = dlopen(libName.c_str(), RTLD_NOW | RTLD_GLOBAL);
28+ if (!handle) {
29+ HCCL_VM_ERROR("dlopen({}) failed:{}", libName, dlerror());
30+ return nullptr;
31+ }
32+ 
33+ m_soHandles[libName] = handle;
34+ HCCL_VM_INFO("loaded so:{} finished", libName);
35+ return handle;
36+}
37+ 
38+KernelFn KernelLibManager::GetOrLoadFunc(const std::string& libName, const std::string& symbolName)
39+{
40+ std::lock_guard<std::mutex> lock(m_mutex);
41+ void* handle = LoadKernelSo(libName);
42+ if (!handle) {
43+ return nullptr;
44+ }
45+ 
46+ std::string key = libName + "::" + symbolName;
47+ auto it = m_symbolCache.find(key);
48+ if (it != m_symbolCache.end()) {
49+ return it->second;
50+ }
51+ 
52+ void* fn = dlsym(handle, symbolName.c_str());
53+ if (!fn) {
54+ HCCL_VM_ERROR("dlsym({}) in {} failed: {}", symbolName, libName, dlerror());
55+ return nullptr;
56+ }
57+ 
58+ KernelFn func = reinterpret_cast<KernelFn>(fn);
59+ m_symbolCache[key] = func;
60+ HCCL_VM_INFO("dlsym({}) in {}", symbolName, libName);
61+ return func;
62+}
63+ 
64+void KernelLibManager::Cleanup()
65+{
66+ HCCL_VM_INFO("cleanup: {} SOs, {} symbols", m_soHandles.size(), m_symbolCache.size());
67+ 
68+ m_symbolCache.clear();
69+ 
70+ for (auto& [name, handle] : m_soHandles) {
71+ if (handle) {
72+ dlclose(handle);
73+ HCCL_VM_INFO("dlclose({})", name);
74+ }
75+ }
76+ m_soHandles.clear();
77+}
78+ 
79+void KernelLibManager::LoadBaseLibs()
80+{
81+ if (m_baseLoaded) {
82+ return;
83+ }
84+ 
85+ std::string libName = "libslog.so";
86+ std::string archStr = GetArchStr();
87+ std::string libPath = InstallPath::ResolveToInstallRoot("lib/" + archStr + "/" + libName);
88+ 
89+ void* handle = LoadKernelSo(libPath);
90+ if (handle == nullptr) {
91+ HCCL_VM_ERROR("Load base library {} failed, path:{}", libName, libPath);
92+ return;
93+ }
94+ 
95+ HCCL_VM_INFO("Base library {} loaded successfully", libName);
96+ m_baseLoaded = true;
97+ return;
98+}
99+ 
100+KernelLibManager::~KernelLibManager()
101+{
102+ Cleanup();
103+}
104+ 
105+} // namespace sim
@@ -0,0 +1,42 @@
1+#ifndef SIM_KERNEL_LIB_MGR_H
2+#define SIM_KERNEL_LIB_MGR_H
3+ 
4+#include <cstdint>
5+#include <map>
6+#include <string>
7+#include <mutex>
8+ 
9+// 函数原型:入参void*,返回uint32_t
10+using KernelFn = uint32_t(*)(void*);
11+ 
12+namespace sim {
13+ 
14+class KernelLibManager
15+{
16+public:
17+ static KernelLibManager& GetInstance();
18+ 
19+ KernelFn GetOrLoadFunc(const std::string& libName, const std::string& symbolName);
20+ 
21+ void Cleanup();
22+ 
23+private:
24+ KernelLibManager();
25+ ~KernelLibManager();
26+ 
27+ void* LoadKernelSo(const std::string& libName);
28+ 
29+ KernelLibManager(const KernelLibManager&) = delete;
30+ KernelLibManager& operator=(const KernelLibManager&) = delete;
31+ 
32+ void LoadBaseLibs();
33+ 
34+ std::mutex m_mutex;
35+ bool m_baseLoaded{false};
36+ std::map<std::string, void*> m_soHandles; // libName -> dlopen handle
37+ std::map<std::string, KernelFn> m_symbolCache; // "funcName" -> func ptr
38+};
39+ 
40+} // namespace sim
41+ 
42+#endif
@@ -23,9 +23,9 @@ add_subdirectory(src)
23 23 
24# 如果需要暴露头文件目录24# 如果需要暴露头文件目录
25target_include_directories(checker PUBLIC25target_include_directories(checker PUBLIC
26- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include26+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include
27- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc27+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc
28- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl28+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl
29 29
30 ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode30 ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode
31 31 
@@ -62,7 +62,7 @@ target_link_libraries(checker PRIVATE
62 modeldb62 modeldb
63 store63 store
64 common64 common
65- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.so65+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/lib64/libc_sec.so
66 pthread66 pthread
67 yaml-cpp::yaml-cpp67 yaml-cpp::yaml-cpp
68 sqlite368 sqlite3
@@ -15,19 +15,22 @@
15 15 
16class DataSlice {16class DataSlice {
17public:17public:
18- DataSlice() : type_(BufferType::INPUT), offset_(0), size_(0) {}18+ DataSlice() : type_(BufferType::INPUT), offset_(0), size_(0), rawAddr_(0) {}
19- DataSlice(BufferType type, uint64_t offset, uint64_t size) : type_(type), offset_(offset), size_(size) {}19+ DataSlice(BufferType type, uint64_t offset, uint64_t size) : type_(type), offset_(offset), size_(size), rawAddr_(0) {}
20 std::string Describe() const { return StringFormat("DataSlice[type=%d, offset=0x%llX, size=0x%llX]", type_, offset_, size_); }20 std::string Describe() const { return StringFormat("DataSlice[type=%d, offset=0x%llX, size=0x%llX]", type_, offset_, size_); }
21 inline BufferType GetType() const { return type_; }21 inline BufferType GetType() const { return type_; }
22 inline uint64_t GetOffset() const { return offset_; }22 inline uint64_t GetOffset() const { return offset_; }
23 inline uint64_t GetSize() const { return size_; }23 inline uint64_t GetSize() const { return size_; }
24+ inline uint64_t GetRawAddr() const { return rawAddr_; }
24 void SetBufferType(const BufferType type) { type_ = type; }25 void SetBufferType(const BufferType type) { type_ = type; }
25 void SetOffset(uint64_t offset) { offset_ = offset; }26 void SetOffset(uint64_t offset) { offset_ = offset; }
26 void SetSize(uint64_t size) { size_ = size; }27 void SetSize(uint64_t size) { size_ = size; }
28+ void SetRawAddr(uint64_t rawAddr) { rawAddr_ = rawAddr; }
27private:29private:
28 BufferType type_;30 BufferType type_;
29 uint64_t offset_;31 uint64_t offset_;
30 uint64_t size_;32 uint64_t size_;
33+ uint64_t rawAddr_;
31};34};
32 35 
33#endif36#endif
@@ -9,12 +9,16 @@
9 */9 */
10 10 
11#include <algorithm>11#include <algorithm>
12+#include <array>
13+#include <cstdint>
14+#include <iomanip>
12#include <iostream>15#include <iostream>
13#include <string>16#include <string>
14#include <thread>17#include <thread>
15#include <atomic>18#include <atomic>
16#include <mutex>19#include <mutex>
17#include <cstring>20#include <cstring>
21+#include <sstream>
18#include <utility>22#include <utility>
19#include <nlohmann_json/json.hpp>23#include <nlohmann_json/json.hpp>
20#include "dump/dump_manager.h"24#include "dump/dump_manager.h"
@@ -25,6 +29,7 @@
25#include "storage_manager.h"29#include "storage_manager.h"
26#include "task_utils.h"30#include "task_utils.h"
27#include "checker.h"31#include "checker.h"
32+#include "framework/big_graph_check/big_graph_checker.h"
28#include "hccl_verifier.h"33#include "hccl_verifier.h"
29#include "sim_log.h"34#include "sim_log.h"
30#include "ccu_all_rank_param_recorder.h"35#include "ccu_all_rank_param_recorder.h"
@@ -44,6 +49,12 @@ std::mutex g_run_checker_mutex;
44std::mutex g_worker_mutex;49std::mutex g_worker_mutex;
45std::thread g_worker_thread;50std::thread g_worker_thread;
46 51 
52+enum class CheckerStatus : uint8_t { SUCCESS, FAILED, DISABLE };
53+using CheckerResult = std::array<CheckerStatus, 2>;
54+static constexpr size_t OLD_CHECKER_RESULT = 0;
55+static constexpr size_t NEW_CHECKER_RESULT = 1;
56+static constexpr const char *CHECKER_STATUS_TEXT[] = {"success", "failed", "disable"};
57+ 
47static std::vector<std::map<uint32_t, sim::CompositeOpDetail>> TransposeCompositeOpMap(58static std::vector<std::map<uint32_t, sim::CompositeOpDetail>> TransposeCompositeOpMap(
48 const std::map<uint32_t, std::vector<sim::CompositeOpDetail>>& compositeDataMap)59 const std::map<uint32_t, std::vector<sim::CompositeOpDetail>>& compositeDataMap)
49{60{
@@ -286,7 +297,8 @@ static HcclResult ProcessOneOpGroup(
286 std::vector<sim::CcuChannelTab> &channels,297 std::vector<sim::CcuChannelTab> &channels,
287 std::vector<sim::CcuInstrResTab> &instrRes,298 std::vector<sim::CcuInstrResTab> &instrRes,
288 uint32_t opIdx,299 uint32_t opIdx,
289- std::map<uint32_t, sim::CompositeOpDetail> &opGroup)300+ std::map<uint32_t, sim::CompositeOpDetail> &opGroup,
301+ CheckerResult &checkerResult)
290{302{
291 HcclSim::ValidationIssueRecorder::GetInstance().Reset();303 HcclSim::ValidationIssueRecorder::GetInstance().Reset();
292 HcclSim::AllRankParamRecorder::Global()->Reset();304 HcclSim::AllRankParamRecorder::Global()->Reset();
@@ -297,6 +309,8 @@ static HcclResult ProcessOneOpGroup(
297 bool enableNewChecker = settingManager.IsNewCheckerEnabled();309 bool enableNewChecker = settingManager.IsNewCheckerEnabled();
298 bool enableOldChecker = settingManager.IsOldCheckerEnabled();310 bool enableOldChecker = settingManager.IsOldCheckerEnabled();
299 bool usesAivExpansionMode = false;311 bool usesAivExpansionMode = false;
312+ checkerResult[OLD_CHECKER_RESULT] = enableOldChecker ? CheckerStatus::FAILED : CheckerStatus::DISABLE;
313+ checkerResult[NEW_CHECKER_RESULT] = enableNewChecker ? CheckerStatus::FAILED : CheckerStatus::DISABLE;
300 314 
301 HCCL_VM_INFO("Start checking one op group, opGroupSize={}", opGroup.size());315 HCCL_VM_INFO("Start checking one op group, opGroupSize={}", opGroup.size());
302 storage.BeginOpGroup();316 storage.BeginOpGroup();
@@ -356,6 +370,7 @@ static HcclResult ProcessOneOpGroup(
356 HCCL_VM_WARN("AIV op detected, the old checker is skipped and only CheckerV3 will run, "370 HCCL_VM_WARN("AIV op detected, the old checker is skipped and only CheckerV3 will run, "
357 "opIndex={}, oldCheckerEnabled={}", opIdx, enableOldChecker);371 "opIndex={}, oldCheckerEnabled={}", opIdx, enableOldChecker);
358 enableOldChecker = false;372 enableOldChecker = false;
373+ checkerResult[OLD_CHECKER_RESULT] = CheckerStatus::DISABLE;
359 }374 }
360 enableNewChecker = true;375 enableNewChecker = true;
361 }376 }
@@ -382,6 +397,8 @@ static HcclResult ProcessOneOpGroup(
382 newCheckerRet = HcclSim::GenAndCheckGraphV3();397 newCheckerRet = HcclSim::GenAndCheckGraphV3();
383 HCCL_VM_INFO("----------[CheckerV3 Finished]----------");398 HCCL_VM_INFO("----------[CheckerV3 Finished]----------");
384 HCCL_VM_INFO("CheckerV3 finished for this op, opIndex={}", opIdx);399 HCCL_VM_INFO("CheckerV3 finished for this op, opIndex={}", opIdx);
400+ checkerResult[NEW_CHECKER_RESULT] = newCheckerRet == HcclResult::HCCL_SUCCESS ?
401+ CheckerStatus::SUCCESS : CheckerStatus::FAILED;
385 } else {402 } else {
386 HCCL_VM_INFO("CheckerV3 is disabled by configuration");403 HCCL_VM_INFO("CheckerV3 is disabled by configuration");
387 }404 }
@@ -401,6 +418,8 @@ static HcclResult ProcessOneOpGroup(
401 auto checkerParam = storage.GetCheckerParam();418 auto checkerParam = storage.GetCheckerParam();
402 oldCheckerRet = DispatchCheckByCmdType(taskQueues, checkerParam);419 oldCheckerRet = DispatchCheckByCmdType(taskQueues, checkerParam);
403 }420 }
421+ checkerResult[OLD_CHECKER_RESULT] = oldCheckerRet == HcclResult::HCCL_SUCCESS ?
422+ CheckerStatus::SUCCESS : CheckerStatus::FAILED;
404 HCCL_VM_INFO("----------[Old Checker Finished]----------");423 HCCL_VM_INFO("----------[Old Checker Finished]----------");
405 HCCL_VM_INFO("Old checker finished for this op, opIndex={}", opIdx);424 HCCL_VM_INFO("Old checker finished for this op, opIndex={}", opIdx);
406 } else {425 } else {
@@ -417,6 +436,56 @@ static HcclResult ProcessOneOpGroup(
417 return oldCheckerRet;436 return oldCheckerRet;
418}437}
419 438 
439+static HcclResult ProcessOneBigGraphSyncIter(loader::Loader &loader, uint32_t syncIter,
440+ HcclSim::BigGraphCheckV3::BigGraphCheckerV3 &bigGraphChecker)
441+{
442+ HCCL_VM_INFO("----------[Start BigGraphCheckerV3]----------");
443+ HCCL_VM_INFO("Start building the big graph for one sync iteration, syncIter={}", syncIter);
444+ 
445+ // Each sync window owns an independent CCU register state. Keep this reset at
446+ // the window boundary; the V3 CCU expansion must remain continuous within the window.
447+ HcclSim::TaskGraphGeneratorV3::AllRankParamRecorder::Global()->Reset();
448+ HcclResult ret = bigGraphChecker.LoadOpData(loader, syncIter);
449+ if (ret != HcclResult::HCCL_SUCCESS) {
450+ HCCL_VM_ERROR("{} Failed to load multi-operator data for big graph, syncIter={}, ret={}",
451+ HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::CHECKER_RUNTIME_ERROR), syncIter,
452+ static_cast<uint32_t>(ret));
453+ return ret;
454+ }
455+ 
456+ ret = bigGraphChecker.TranslateTask();
457+ if (ret != HcclResult::HCCL_SUCCESS) {
458+ HCCL_VM_ERROR("{} Failed to translate multi-operator tasks for big graph, syncIter={}, ret={}",
459+ HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::CHECKER_RUNTIME_ERROR), syncIter,
460+ static_cast<uint32_t>(ret));
461+ return ret;
462+ }
463+ 
464+ ret = bigGraphChecker.GenerateBigGraph();
465+ if (ret != HcclResult::HCCL_SUCCESS) {
466+ HCCL_VM_ERROR("{} Failed to generate big graph, syncIter={}, ret={}",
467+ HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::CHECKER_RUNTIME_ERROR), syncIter,
468+ static_cast<uint32_t>(ret));
469+ return ret;
470+ }
471+ 
472+ ret = bigGraphChecker.SyncCheck();
473+ if (ret != HcclResult::HCCL_SUCCESS) {
474+ HCCL_VM_ERROR("{} Big graph sync-conflict check failed, syncIter={}, ret={}",
475+ HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::CHECKER_RUNTIME_ERROR), syncIter,
476+ static_cast<uint32_t>(ret));
477+ return ret;
478+ }
479+ 
480+ const auto *graph = bigGraphChecker.GetGraph();
481+ const size_t nodeCount = graph == nullptr ? 0 : graph->GetNodes().size();
482+ const size_t rankCount = graph == nullptr ? 0 : graph->GetTaskQueues().size();
483+ HCCL_VM_INFO("BigGraphCheckerV3 generated graph successfully, syncIter={}, operatorCount={}, "
484+ "nodeCount={}, rankCount={}", syncIter, bigGraphChecker.GetOpParams().size(), nodeCount, rankCount);
485+ HCCL_VM_INFO("----------[BigGraphCheckerV3 Finished]----------");
486+ return HcclResult::HCCL_SUCCESS;
487+}
488+ 
420json BuildOpParamSummaryJson(const HcclSim::CheckerParam &param)489json BuildOpParamSummaryJson(const HcclSim::CheckerParam &param)
421{490{
422 json opParamJson = json::object();491 json opParamJson = json::object();
@@ -520,39 +589,112 @@ void RunChecker(const std::string& data_id) {
520 }589 }
521 590 
522 HCCL_VM_INFO("Start checker run, syncRecordCount={}", syncRecords.size());591 HCCL_VM_INFO("Start checker run, syncRecordCount={}", syncRecords.size());
523- uint32_t opIdx = 0;592+ const HcclSim::CheckerSettings checkerSettings = HcclSim::SettingManager::GetInstance().GetSettings();
524- do {593+ const bool enableBigGraphChecker = checkerSettings.enableBigGraphChecker;
525- for (uint32_t syncIter = 0; syncIter <= syncIterMaxNum; syncIter++) {594+ const bool enableSingleOpChecker = checkerSettings.enableNewChecker || checkerSettings.enableOldChecker;
526- std::map<uint32_t, std::vector<sim::CompositeOpDetail>> compositeDataMap;595+ std::vector<uint32_t> bigGraphSyncIters;
527- g_loader.LoadCompositeOpDetailBySyncIter(syncIter, compositeDataMap);596+ bigGraphSyncIters.reserve(syncRecords.size());
528- auto opGroups = TransposeCompositeOpMap(compositeDataMap);597+ for (const auto &syncRecord : syncRecords) {
529- HCCL_VM_INFO("Start one sync iteration, syncIter={}, opGroupCount={}", syncIter, opGroups.size());598+ if (bigGraphSyncIters.empty() || bigGraphSyncIters.back() != syncRecord.syncIter) {
530- for (auto& opGroup : opGroups) {599+ bigGraphSyncIters.push_back(syncRecord.syncIter);
531- HCCL_VM_INFO("Check one op group in this sync iteration, opGroupSize={}", opGroup.size());600+ }
532- ret = ProcessOneOpGroup(storage, channels, instrRes, opIdx, opGroup);601+ }
533- if (dumpManager.IsEnabled()) {602+ std::vector<CheckerStatus> multiOpCheckerResults(bigGraphSyncIters.size(),
534- HcclSim::DumpRunManifest::GetInstance().SetCheckResult(ret);603+ enableBigGraphChecker ? CheckerStatus::SUCCESS : CheckerStatus::DISABLE);
535- const HcclResult flushRet = HcclSim::ValidationIssueRecorder::GetInstance().Flush();604+ std::vector<CheckerResult> checkerResults;
536- if (flushRet != HcclResult::HCCL_SUCCESS) {605+ HcclSim::BigGraphCheckV3::BigGraphCheckerV3 bigGraphChecker;
537- HCCL_VM_WARN("{} Failed to flush the validation issue dump, dataId={}, opIndex={}, "606+ 
538- "dumpType=validation_issues", HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::DUMP_FAILED),607+ if (enableBigGraphChecker) {
539- data_id, opIdx);608+ for (size_t iterIndex = 0; iterIndex < bigGraphSyncIters.size(); ++iterIndex) {
540- }609+ const uint32_t syncIter = bigGraphSyncIters[iterIndex];
541- const HcclResult manifestRet = HcclSim::DumpRunManifest::GetInstance().Flush();610+ const HcclResult bigGraphRet = ProcessOneBigGraphSyncIter(g_loader, syncIter, bigGraphChecker);
542- if (manifestRet != HcclResult::HCCL_SUCCESS) {611+ if (bigGraphRet != HcclResult::HCCL_SUCCESS) {
543- HCCL_VM_WARN("{} Failed to flush the dump manifest, dataId={}, opIndex={}",612+ multiOpCheckerResults[iterIndex] = CheckerStatus::FAILED;
544- HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::DUMP_FAILED), data_id, opIdx);613+ HCCL_VM_ERROR("BigGraphCheckerV3 failed, syncIter={}, ret={}", syncIter,
545- }614+ static_cast<uint32_t>(bigGraphRet));
546- }
547- if (ret != HcclResult::HCCL_SUCCESS) {
548- HCCL_VM_ERROR("op[{}] Checker failed", opIdx);
549- break;
550- }
551- HCCL_VM_INFO("op[{}] Checker Success", opIdx);
552- opIdx++;
553 }615 }
554 }616 }
555- } while (false);617+ }
618+ 
619+ if (!enableSingleOpChecker) {
620+ HCCL_VM_INFO("Single-op checkers are disabled by configuration, skip sync iteration checks");
621+ } else {
622+ uint32_t opIdx = 0;
623+ do {
624+ for (uint32_t syncIter = 0; syncIter <= syncIterMaxNum; syncIter++) {
625+ std::map<uint32_t, std::vector<sim::CompositeOpDetail>> compositeDataMap;
626+ g_loader.LoadCompositeOpDetailBySyncIter(syncIter, compositeDataMap);
627+ auto opGroups = TransposeCompositeOpMap(compositeDataMap);
628+ HCCL_VM_INFO("Start one sync iteration, syncIter={}, opGroupCount={}", syncIter, opGroups.size());
629+ for (auto& opGroup : opGroups) {
630+ HCCL_VM_INFO("Check one op group in this sync iteration, opGroupSize={}", opGroup.size());
631+ const uint32_t currentOpIdx = opIdx++;
632+ CheckerResult checkerResult = {CheckerStatus::DISABLE, CheckerStatus::DISABLE};
633+ ret = ProcessOneOpGroup(storage, channels, instrRes, currentOpIdx, opGroup, checkerResult);
634+ checkerResults.push_back(checkerResult);
635+ if (dumpManager.IsEnabled()) {
636+ HcclSim::DumpRunManifest::GetInstance().SetCheckResult(ret);
637+ const HcclResult flushRet = HcclSim::ValidationIssueRecorder::GetInstance().Flush();
638+ if (flushRet != HcclResult::HCCL_SUCCESS) {
639+ HCCL_VM_WARN("{} Failed to flush the validation issue dump, dataId={}, opIndex={}, "
640+ "dumpType=validation_issues", HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::DUMP_FAILED),
641+ data_id, currentOpIdx);
642+ }
643+ const HcclResult manifestRet = HcclSim::DumpRunManifest::GetInstance().Flush();
644+ if (manifestRet != HcclResult::HCCL_SUCCESS) {
645+ HCCL_VM_WARN("{} Failed to flush the dump manifest, dataId={}, opIndex={}",
646+ HcclSim::MakeErrorCodeText(HcclSim::ErrorCode::DUMP_FAILED), data_id, currentOpIdx);
647+ }
648+ }
649+ if (ret != HcclResult::HCCL_SUCCESS) {
650+ HCCL_VM_ERROR("op[{}] Checker failed", currentOpIdx);
651+ break;
652+ }
653+ HCCL_VM_INFO("op[{}] Checker Success", currentOpIdx);
654+ }
655+ }
656+ } while (false);
657+ }
658+ if (!checkerResults.empty()) {
659+ constexpr int OP_COLUMN_WIDTH = 8;
660+ constexpr int CHECKER_COLUMN_WIDTH = 13;
661+ HCCL_VM_INFO("Checker execution result (success/failed/disable):");
662+ HCCL_VM_INFO("Single-op checker result:");
663+ std::ostringstream header;
664+ header << "| " << std::left << std::setw(OP_COLUMN_WIDTH) << "op[id]"
665+ << " | " << std::setw(CHECKER_COLUMN_WIDTH) << "old checker"
666+ << " | " << std::setw(CHECKER_COLUMN_WIDTH) << "new checker" << " |";
667+ HCCL_VM_INFO("{}", header.str());
668+ for (size_t opIdx = 0; opIdx < checkerResults.size(); ++opIdx) {
669+ const CheckerResult &checkerResult = checkerResults[opIdx];
670+ std::ostringstream row;
671+ row << "| " << std::left << std::setw(OP_COLUMN_WIDTH)
672+ << opIdx
673+ << " | " << std::setw(CHECKER_COLUMN_WIDTH)
674+ << CHECKER_STATUS_TEXT[static_cast<size_t>(checkerResult[OLD_CHECKER_RESULT])]
675+ << " | " << std::setw(CHECKER_COLUMN_WIDTH)
676+ << CHECKER_STATUS_TEXT[static_cast<size_t>(checkerResult[NEW_CHECKER_RESULT])] << " |";
677+ HCCL_VM_INFO("{}", row.str());
678+ }
679+ } else {
680+ HCCL_VM_WARN("Checker execution result is unavailable because no single-op checker was executed");
681+ }
682+ if (!multiOpCheckerResults.empty()) {
683+ constexpr int SYNC_ITER_COLUMN_WIDTH = 10;
684+ constexpr int MULTI_OP_COLUMN_WIDTH = 17;
685+ HCCL_VM_INFO("Multi-op checker result:");
686+ std::ostringstream header;
687+ header << "| " << std::left << std::setw(SYNC_ITER_COLUMN_WIDTH) << "syncIter"
688+ << " | " << std::setw(MULTI_OP_COLUMN_WIDTH) << "multi op checker" << " |";
689+ HCCL_VM_INFO("{}", header.str());
690+ for (size_t iterIndex = 0; iterIndex < multiOpCheckerResults.size(); ++iterIndex) {
691+ std::ostringstream row;
692+ row << "| " << std::left << std::setw(SYNC_ITER_COLUMN_WIDTH) << bigGraphSyncIters[iterIndex]
693+ << " | " << std::setw(MULTI_OP_COLUMN_WIDTH)
694+ << CHECKER_STATUS_TEXT[static_cast<size_t>(multiOpCheckerResults[iterIndex])] << " |";
695+ HCCL_VM_INFO("{}", row.str());
696+ }
697+ }
556 std::cout << "(hvm)$> " << std::flush;698 std::cout << "(hvm)$> " << std::flush;
557 FlushLog(); // 将本轮完整日志落盘699 FlushLog(); // 将本轮完整日志落盘
558}700}
@@ -8,6 +8,7 @@
8 "setting": {8 "setting": {
9 "enable_new_checker": true,9 "enable_new_checker": true,
10 "enable_old_checker": false,10 "enable_old_checker": false,
11+ "enable_big_graph_checker": true,
11 "enable_insight_dump": false,12 "enable_insight_dump": false,
12 "enable_memory_snapshot_dump": false13 "enable_memory_snapshot_dump": false
13 }14 }
@@ -173,7 +173,7 @@ std::unique_ptr<TaskGraphGeneratorV3::TaskGraphGeneratorV3> GenGraphV3FromTaskMe
173 // 1. 先把 task meta 翻译成中间节点;173 // 1. 先把 task meta 翻译成中间节点;
174 // 2. 做一次从流合法性检查;174 // 2. 做一次从流合法性检查;
175 // 3. 再生成 V3 图并在日志里记录成图/CCU 展开耗时。175 // 3. 再生成 V3 图并在日志里记录成图/CCU 展开耗时。
176- HcclResult ret = taskMetaTranslatorV3.Translate(storage);176+ HcclResult ret = taskMetaTranslatorV3.Translate(storage, TaskGraphGeneratorV3::INVALID_OPERATOR_ID);
177 if (ret != HCCL_SUCCESS) {177 if (ret != HCCL_SUCCESS) {
178 HCCL_VM_WARN("Failed to translate one task into the V3 internal format, V3 graph generation is "178 HCCL_VM_WARN("Failed to translate one task into the V3 internal format, V3 graph generation is "
179 "stopped, ret={}", static_cast<uint32_t>(ret));179 "stopped, ret={}", static_cast<uint32_t>(ret));
@@ -13,3 +13,4 @@ add_subdirectory(semantics_check)
13add_subdirectory(singletask_check)13add_subdirectory(singletask_check)
14add_subdirectory(task_graph_generator)14add_subdirectory(task_graph_generator)
15add_subdirectory(task_graph_generator_v3)15add_subdirectory(task_graph_generator_v3)
16+add_subdirectory(big_graph_check)
@@ -0,0 +1,14 @@
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+target_sources(checker PRIVATE
12+ ${CMAKE_CURRENT_SOURCE_DIR}/big_graph_checker.cc
13+ ${CMAKE_CURRENT_SOURCE_DIR}/big_graph_data_loader.cc
14+)
@@ -0,0 +1,217 @@
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+#include "big_graph_checker.h"
12+ 
13+#include <cstring>
14+#include <limits>
15+#include <utility>
16+ 
17+#include "sim_log.h"
18+#include "task_graph_generator_v3/task_graph_single_task_check_v3.h"
19+#include "task_graph_generator_v3/task_graph_sync_conflict_v3.h"
20+#include "task_graph_generator_v3/task_meta_translator_v3.h"
21+#include "utils/error_codes.h"
22+ 
23+namespace HcclSim {
24+namespace BigGraphCheckV3 {
25+ 
26+namespace {
27+using V3Graph = TaskGraphGeneratorV3::TaskGraphGeneratorV3;
28+using V3Node = TaskGraphGeneratorV3::TaskNode;
29+using V3NodeId = TaskGraphGeneratorV3::NodeId;
30+using V3RankNodeQueues = TaskGraphGeneratorV3::RankNodeQueues;
31+ 
32+HcclResult DecodeOpDetails(const sim::OpDetailTab &detailTab, OpDetails &details)
33+{
34+ if (detailTab.opDetail.size() < sizeof(OpDetails)) {
35+ HCCL_VM_ERROR("Operator detail payload is too small, rankId={}, actualSize={}, expectedSize={}",
36+ detailTab.rankId, detailTab.opDetail.size(), sizeof(OpDetails));
37+ return HCCL_E_PARA;
38+ }
39+ std::memcpy(&details, detailTab.opDetail.data(), sizeof(OpDetails));
40+ return HCCL_SUCCESS;
41+}
42+ 
43+HcclResult AppendTranslatedOperator(TaskGraphGeneratorV3::TaskMetaTranslatorV3 &translator,
44+ std::vector<std::unique_ptr<V3Node>> &nodes, TaskGraphGeneratorV3::AllRankNodeQueues &queues)
45+{
46+ std::vector<std::unique_ptr<V3Node>> localNodes = translator.TakeNodes();
47+ TaskGraphGeneratorV3::AllRankNodeQueues localQueues = translator.TakeTaskQueues();
48+ const size_t nodeOffset = nodes.size();
49+ if (nodeOffset > static_cast<size_t>(std::numeric_limits<V3NodeId>::max()) ||
50+ localNodes.size() > static_cast<size_t>(std::numeric_limits<V3NodeId>::max()) - nodeOffset) {
51+ return HCCL_E_MEMORY;
52+ }
53+ for (const auto &node : localNodes) {
54+ if (node == nullptr) {
55+ return HCCL_E_PTR;
56+ }
57+ }
58+ 
59+ for (auto &node : localNodes) {
60+ node->SetNodeId(static_cast<V3NodeId>(nodeOffset + static_cast<size_t>(node->GetNodeId())));
61+ nodes.emplace_back(std::move(node));
62+ }
63+ 
64+ for (const auto &rankEntry : localQueues) {
65+ V3RankNodeQueues &target = queues[rankEntry.first];
66+ if (target.size() < rankEntry.second.size()) {
67+ target.resize(rankEntry.second.size());
68+ }
69+ for (size_t streamIndex = 0; streamIndex < rankEntry.second.size(); ++streamIndex) {
70+ auto &targetStream = target[streamIndex];
71+ for (V3NodeId nodeId : rankEntry.second[streamIndex]) {
72+ if (nodeId < 0 || static_cast<size_t>(nodeId) >= localNodes.size()) {
73+ return HCCL_E_PARA;
74+ }
75+ targetStream.push_back(static_cast<V3NodeId>(nodeOffset + static_cast<size_t>(nodeId)));
76+ }
77+ }
78+ }
79+ return HCCL_SUCCESS;
80+}
81+} // namespace
82+ 
83+HcclResult BigGraphCheckerV3::LoadOpData(loader::Loader &loader, uint32_t syncIter)
84+{
85+ return dataLoader_.Load(loader, syncIter, data_);
86+}
87+ 
88+HcclResult BigGraphCheckerV3::TranslateTask()
89+{
90+ if (data_.operators.empty()) {
91+ return HCCL_E_PARA;
92+ }
93+ 
94+ storage_.Reset(false);
95+ translatedNodes_.clear();
96+ translatedTaskQueues_.clear();
97+ graph_.reset();
98+ 
99+ for (const OpParam &opParam : data_.operators) {
100+ for (const OperatorRankData &rankData : opParam.ranks) {
101+ HcclResult ret = storage_.LoadHcclVmSynthesisData(rankData.rankId, rankData.op.memInfo,
102+ data_.channels);
103+ if (ret != HCCL_SUCCESS) {
104+ return ret;
105+ }
106+ }
107+ }
108+ HcclResult ret = storage_.LoadHcclVmInstrData(data_.instrRes);
109+ if (ret != HCCL_SUCCESS) {
110+ return ret;
111+ }
112+ 
113+ for (const OpParam &opParam : data_.operators) {
114+ storage_.BeginOpGroup();
115+ for (const OperatorRankData &rankData : opParam.ranks) {
116+ OpDetails details{};
117+ ret = DecodeOpDetails(rankData.op.detail, details);
118+ if (ret != HCCL_SUCCESS) {
119+ return ret;
120+ }
121+ sim::OpDetailTab detailTab = rankData.op.detail;
122+ ret = storage_.Trans2CheckerParam(detailTab, details);
123+ if (ret != HCCL_SUCCESS) {
124+ return ret;
125+ }
126+ }
127+ ret = storage_.FinalizeOpGroup();
128+ if (ret != HCCL_SUCCESS) {
129+ return ret;
130+ }
131+ storage_.MergeAll2AllVSendCountMatrix();
132+ storage_.SaveCheckerParam(opParam.operatorId);
133+ 
134+ std::vector<std::vector<HcclTaskMetaData>> allTaskMetas;
135+ allTaskMetas.reserve(opParam.ranks.size());
136+ for (const OperatorRankData &rankData : opParam.ranks) {
137+ allTaskMetas.push_back(rankData.taskMetas);
138+ }
139+ ret = storage_.LoadDecodedHcclVmTaskMetaData(allTaskMetas);
140+ if (ret != HCCL_SUCCESS) {
141+ return ret;
142+ }
143+ 
144+ TaskGraphGeneratorV3::TaskMetaTranslatorV3 translator;
145+ ret = translator.Translate(storage_, opParam.operatorId);
146+ if (ret != HCCL_SUCCESS) {
147+ return ret;
148+ }
149+ ret = AppendTranslatedOperator(translator, translatedNodes_, translatedTaskQueues_);
150+ if (ret != HCCL_SUCCESS) {
151+ return ret;
152+ }
153+ }
154+ 
155+ HCCL_VM_INFO("Translated big graph tasks, operatorCount={}, nodeCount={}, rankCount={}",
156+ data_.operators.size(), translatedNodes_.size(), translatedTaskQueues_.size());
157+ return HCCL_SUCCESS;
158+}
159+ 
160+HcclResult BigGraphCheckerV3::GenerateBigGraph()
161+{
162+ if (translatedNodes_.empty() || translatedTaskQueues_.empty()) {
163+ return HCCL_E_PARA;
164+ }
165+ 
166+ HcclResult ret = TaskGraphGeneratorV3::CheckSlaveTaskQueue(translatedNodes_, translatedTaskQueues_);
167+ if (ret != HCCL_SUCCESS) {
168+ return ret;
169+ }
170+ 
171+ auto graph = std::make_unique<V3Graph>();
172+ graph->SetStorageManager(&storage_);
173+ ret = graph->GenGraph(std::move(translatedNodes_), std::move(translatedTaskQueues_));
174+ if (ret != HCCL_SUCCESS) {
175+ return ret;
176+ }
177+ graph_ = std::move(graph);
178+ HCCL_VM_INFO("Generated big graph, nodeCount={}, rankCount={}", graph_->GetNodes().size(),
179+ graph_->GetTaskQueues().size());
180+ return HCCL_SUCCESS;
181+}
182+ 
183+HcclResult BigGraphCheckerV3::SingleTaskCheck()
184+{
185+ return HCCL_E_NOT_SUPPORT;
186+}
187+ 
188+HcclResult BigGraphCheckerV3::SyncCheck()
189+{
190+ if (graph_ == nullptr || graph_->GetMainStartNode() == nullptr) {
191+ HCCL_VM_ERROR("{} Cannot run big graph sync-conflict check before the graph is generated",
192+ MakeErrorCodeText(ErrorCode::CHECKER_RUNTIME_ERROR));
193+ return HCCL_E_PARA;
194+ }
195+ 
196+ TaskGraphGeneratorV3::SyncConflictCheckStats stats;
197+ const HcclResult ret = TaskGraphGeneratorV3::CheckSyncResourceConflict(graph_->GetMainStartNode(), &stats);
198+ HCCL_VM_INFO("Big graph sync-conflict check finished, status={}, originalNodeCount={}, copiedNodeCount={}, "
199+ "copiedEdgeCount={}, resourceBucketCount={}, pairCount={}, checkedBucketCount={}, conflictCount={}",
200+ ret == HCCL_SUCCESS ? "success" : "failed", stats.originalNodeCount, stats.copiedNodeCount,
201+ stats.copiedEdgeCount, stats.resourceBucketCount, stats.pairCount, stats.checkedBucketCount,
202+ stats.conflictCount);
203+ return ret;
204+}
205+ 
206+HcclResult BigGraphCheckerV3::MemConflictCheck()
207+{
208+ return HCCL_E_NOT_SUPPORT;
209+}
210+ 
211+HcclResult BigGraphCheckerV3::SemanticCheck()
212+{
213+ return HCCL_E_NOT_SUPPORT;
214+}
215+ 
216+} // namespace BigGraphCheckV3
217+} // namespace HcclSim
@@ -0,0 +1,56 @@
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+#ifndef CHECKER_BIG_GRAPH_CHECKER_H
12+#define CHECKER_BIG_GRAPH_CHECKER_H
13+ 
14+#include <cstdint>
15+#include <map>
16+#include <memory>
17+#include <vector>
18+ 
19+#include "big_graph_data_loader.h"
20+#include "storage_manager.h"
21+#include "task_graph_generator_v3/task_graph_generator_v3.h"
22+ 
23+namespace HcclSim {
24+namespace BigGraphCheckV3 {
25+ 
26+class BigGraphCheckerV3 {
27+public:
28+ BigGraphCheckerV3() = default;
29+ ~BigGraphCheckerV3() = default;
30+ 
31+ HcclResult LoadOpData(loader::Loader &loader, uint32_t syncIter);
32+ const BigGraphData &GetData() const { return data_; }
33+ const std::vector<OpParam> &GetOpParams() const { return data_.operators; }
34+ const TaskGraphGeneratorV3::TaskGraphGeneratorV3 *GetGraph() const { return graph_.get(); }
35+ 
36+ // Future stages intentionally remain separate from the existing V3 path.
37+ HcclResult TranslateTask();
38+ HcclResult GenerateBigGraph();
39+ HcclResult SingleTaskCheck();
40+ HcclResult SyncCheck();
41+ HcclResult MemConflictCheck();
42+ HcclResult SemanticCheck();
43+ 
44+private:
45+ BigGraphData data_;
46+ BigGraphDataLoader dataLoader_;
47+ StorageManager storage_;
48+ std::vector<std::unique_ptr<TaskGraphGeneratorV3::TaskNode>> translatedNodes_;
49+ TaskGraphGeneratorV3::AllRankNodeQueues translatedTaskQueues_;
50+ std::unique_ptr<TaskGraphGeneratorV3::TaskGraphGeneratorV3> graph_;
51+};
52+ 
53+} // namespace BigGraphCheckV3
54+} // namespace HcclSim
55+ 
56+#endif // CHECKER_BIG_GRAPH_CHECKER_H
@@ -0,0 +1,114 @@
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+#include "big_graph_data_loader.h"
12+ 
13+#include <algorithm>
14+#include <cstring>
15+ 
16+#include "sim_log.h"
17+ 
18+namespace HcclSim {
19+namespace BigGraphCheckV3 {
20+ 
21+HcclResult BigGraphDataLoader::DecodeTaskMeta(const sim::OpTaskTab &task, HcclTaskMetaData &taskMeta)
22+{
23+ if (task.optaskMeta.size() < sizeof(HcclTaskMetaData)) {
24+ HCCL_VM_ERROR("Cannot load operator task metadata because the payload is too small, taskSeq={}, "
25+ "actualSize={}, expectedSize={}", task.taskSeq, task.optaskMeta.size(), sizeof(HcclTaskMetaData));
26+ return HCCL_E_PARA;
27+ }
28+ std::memcpy(&taskMeta, task.optaskMeta.data(), sizeof(HcclTaskMetaData));
29+ return HCCL_SUCCESS;
30+}
31+ 
32+HcclResult BigGraphDataLoader::Load(loader::Loader &loader, uint32_t syncIter, BigGraphData &data) const
33+{
34+ data.Clear();
35+ data.syncIter = syncIter;
36+ 
37+ HcclResult ret = loader.GetCcuChannelInfo(data.channels);
38+ if (ret != HCCL_SUCCESS) {
39+ data.Clear();
40+ return ret;
41+ }
42+ ret = loader.GetInstrResInfo(data.instrRes);
43+ if (ret != HCCL_SUCCESS) {
44+ data.Clear();
45+ return ret;
46+ }
47+ 
48+ std::map<uint32_t, std::vector<sim::CompositeOpDetail>> compositeData;
49+ ret = loader.LoadCompositeOpDetailBySyncIter(syncIter, compositeData);
50+ if (ret != HCCL_SUCCESS) {
51+ HCCL_VM_ERROR("Failed to load operator data for a sync window, syncIter={}, ret={}", syncIter,
52+ static_cast<uint32_t>(ret));
53+ data.Clear();
54+ return ret;
55+ }
56+ 
57+ size_t operatorCount = 0;
58+ for (const auto &rankEntry : compositeData) {
59+ operatorCount = std::max(operatorCount, rankEntry.second.size());
60+ }
61+ if (operatorCount > static_cast<size_t>(TaskGraphGeneratorV3::INVALID_OPERATOR_ID)) {
62+ HCCL_VM_ERROR("Too many operators in one sync window, syncIter={}, operatorCount={}", syncIter,
63+ operatorCount);
64+ data.Clear();
65+ return HCCL_E_PARA;
66+ }
67+ 
68+ data.operators.resize(operatorCount);
69+ for (size_t operatorIndex = 0; operatorIndex < operatorCount; ++operatorIndex) {
70+ OpParam &opParam = data.operators[operatorIndex];
71+ opParam.operatorId = static_cast<TaskGraphGeneratorV3::OperatorId>(operatorIndex);
72+ opParam.syncIter = syncIter;
73+ 
74+ bool hasOp = false;
75+ for (const auto &rankEntry : compositeData) {
76+ if (operatorIndex >= rankEntry.second.size()) {
77+ continue;
78+ }
79+ 
80+ const sim::CompositeOpDetail &compositeOp = rankEntry.second[operatorIndex];
81+ if (!hasOp) {
82+ opParam.opIter = compositeOp.detail.opIter;
83+ hasOp = true;
84+ }
85+ 
86+ OperatorRankData rankData;
87+ rankData.rankId = rankEntry.first;
88+ rankData.op = compositeOp;
89+ rankData.taskMetas.reserve(compositeOp.tasks.size());
90+ for (const sim::OpTaskTab &task : compositeOp.tasks) {
91+ HcclTaskMetaData taskMeta;
92+ const HcclResult decodeRet = DecodeTaskMeta(task, taskMeta);
93+ if (decodeRet != HCCL_SUCCESS) {
94+ data.Clear();
95+ return decodeRet;
96+ }
97+ rankData.taskMetas.push_back(taskMeta);
98+ }
99+ opParam.ranks.push_back(std::move(rankData));
100+ }
101+ 
102+ if (!hasOp) {
103+ data.operators.resize(operatorIndex);
104+ break;
105+ }
106+ }
107+ 
108+ HCCL_VM_INFO("Loaded multi-operator data, syncIter={}, operatorCount={}, rankCount={}", syncIter,
109+ data.operators.size(), compositeData.size());
110+ return HCCL_SUCCESS;
111+}
112+ 
113+} // namespace BigGraphCheckV3
114+} // namespace HcclSim
@@ -0,0 +1,66 @@
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+#ifndef CHECKER_BIG_GRAPH_DATA_LOADER_H
12+#define CHECKER_BIG_GRAPH_DATA_LOADER_H
13+ 
14+#include <cstdint>
15+#include <map>
16+#include <vector>
17+ 
18+#include "binary_data_type_pub.h"
19+#include "hccl_types.h"
20+#include "sim_loader.h"
21+#include "sim_op_db_types.h"
22+#include "task_graph_generator_v3/task_def_v3.h"
23+ 
24+namespace HcclSim {
25+namespace BigGraphCheckV3 {
26+ 
27+struct OperatorRankData {
28+ uint32_t rankId{UINT32_MAX};
29+ sim::CompositeOpDetail op;
30+ std::vector<HcclTaskMetaData> taskMetas;
31+};
32+ 
33+struct OpParam {
34+ TaskGraphGeneratorV3::OperatorId operatorId{TaskGraphGeneratorV3::INVALID_OPERATOR_ID};
35+ uint32_t syncIter{0};
36+ uint32_t opIter{0};
37+ std::vector<OperatorRankData> ranks;
38+};
39+ 
40+struct BigGraphData {
41+ uint32_t syncIter{0};
42+ std::vector<sim::CcuChannelTab> channels;
43+ std::vector<sim::CcuInstrResTab> instrRes;
44+ std::vector<OpParam> operators;
45+ 
46+ void Clear()
47+ {
48+ syncIter = 0;
49+ channels.clear();
50+ instrRes.clear();
51+ operators.clear();
52+ }
53+};
54+ 
55+class BigGraphDataLoader {
56+public:
57+ HcclResult Load(loader::Loader &loader, uint32_t syncIter, BigGraphData &data) const;
58+ 
59+private:
60+ static HcclResult DecodeTaskMeta(const sim::OpTaskTab &task, HcclTaskMetaData &taskMeta);
61+};
62+ 
63+} // namespace BigGraphCheckV3
64+} // namespace HcclSim
65+ 
66+#endif // CHECKER_BIG_GRAPH_DATA_LOADER_H
@@ -121,4 +121,82 @@ HcclResult TaskCheckBatchSendRecvSemantics(std::map<RankId, RankMemorySemantics>
121 121 
122 return HcclResult::HCCL_SUCCESS;122 return HcclResult::HCCL_SUCCESS;
123}123}
124+ 
125+HcclResult TaskCheckBatchSendRecvRingSemantics(std::map<RankId, RankMemorySemantics> &allRankMemSemantics,
126+ u32 expectedRankSize, u64 dataSize)
127+{
128+ if (expectedRankSize < 2 || allRankMemSemantics.size() != expectedRankSize) {
129+ HCCL_VM_ERROR("{} BatchSendRecv ring rank set size mismatch: expected {}, actual {}.",
130+ MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_MISSING), expectedRankSize, allRankMemSemantics.size());
131+ return HcclResult::HCCL_E_PARA;
132+ }
133+ 
134+ for (RankId rankId = 0; rankId < expectedRankSize; ++rankId) {
135+ const auto rankIt = allRankMemSemantics.find(rankId);
136+ if (rankIt == allRankMemSemantics.end()) {
137+ HCCL_VM_ERROR("{} BatchSendRecv ring produced no result data for rank {}.",
138+ MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_MISSING), rankId);
139+ return HcclResult::HCCL_E_PARA;
140+ }
141+ 
142+ const RankId expectedSrcRank = (rankId + expectedRankSize - 1U) % expectedRankSize;
143+ const auto outputIt = rankIt->second.find(BufferType::OUTPUT);
144+ if (dataSize == 0) {
145+ if (outputIt != rankIt->second.end()) {
146+ for (const auto &output : outputIt->second) {
147+ if (output.size != 0) {
148+ HCCL_VM_ERROR("{} BatchSendRecv ring rank {} should have an empty output, but range "
149+ "[0x{:x},0x{:x}) is present.", MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_SIZE_ERROR),
150+ rankId, output.startAddr, output.startAddr + output.size);
151+ return HcclResult::HCCL_E_PARA;
152+ }
153+ }
154+ }
155+ continue;
156+ }
157+ if (outputIt == rankIt->second.end() || outputIt->second.empty()) {
158+ HCCL_VM_ERROR("{} BatchSendRecv ring output is missing for rank {}, expected size 0x{:x}.",
159+ MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_MISSING), rankId, dataSize);
160+ return HcclResult::HCCL_E_PARA;
161+ }
162+ 
163+ u64 totalSize = 0;
164+ for (const auto &output : outputIt->second) {
165+ const u64 rangeEnd = output.startAddr + output.size;
166+ if (rangeEnd < output.startAddr || output.startAddr != totalSize || output.size > dataSize - totalSize) {
167+ HCCL_VM_ERROR("{} BatchSendRecv ring output for rank {} is not a contiguous range of size "
168+ "0x{:x}; next actual range is [0x{:x},0x{:x}).\nCurrent result range detail:\n{}",
169+ MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_SIZE_ERROR), rankId, dataSize,
170+ output.startAddr, rangeEnd, output.Describe());
171+ return HcclResult::HCCL_E_PARA;
172+ }
173+ if (output.srcBufs.size() != 1) {
174+ HCCL_VM_ERROR("{} BatchSendRecv ring output range [0x{:x},0x{:x}) for rank {} should "
175+ "come from exactly one source, but it comes from {} sources.\nCurrent result range detail:\n{}",
176+ MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_REDUCE_ERROR), output.startAddr, rangeEnd,
177+ rankId, output.srcBufs.size(), output.Describe());
178+ return HcclResult::HCCL_E_PARA;
179+ }
180+ 
181+ const auto &srcBuf = *output.srcBufs.begin();
182+ if (srcBuf.rankId != expectedSrcRank || srcBuf.bufType != BufferType::INPUT ||
183+ srcBuf.srcAddr != output.startAddr) {
184+ HCCL_VM_ERROR("{} BatchSendRecv ring output range [0x{:x},0x{:x}) for rank {} should "
185+ "come from rank{}.INPUT at address 0x{:x}, but it comes from rank{}.{} at address "
186+ "0x{:x}.\nCurrent result range detail:\n{}",
187+ MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_SRC_ERROR), output.startAddr, rangeEnd, rankId,
188+ expectedSrcRank, output.startAddr, srcBuf.rankId, BufferTypeToString(srcBuf.bufType),
189+ srcBuf.srcAddr, output.Describe());
190+ return HcclResult::HCCL_E_PARA;
191+ }
192+ totalSize += output.size;
193+ }
194+ if (totalSize != dataSize) {
195+ HCCL_VM_ERROR("{} BatchSendRecv ring output for rank {} has size 0x{:x}, expected 0x{:x}.",
196+ MakeErrorCodeText(ErrorCode::SEMANTIC_FINAL_MISSING), rankId, totalSize, dataSize);
197+ return HcclResult::HCCL_E_PARA;
198+ }
199+ }
200+ return HcclResult::HCCL_SUCCESS;
201+}
124} // namespace HcclSim202} // namespace HcclSim
@@ -17,6 +17,8 @@
17namespace HcclSim {17namespace HcclSim {
18HcclResult TaskCheckBatchSendRecvSemantics(std::map<RankId, RankMemorySemantics> &allRankMemSemantics,18HcclResult TaskCheckBatchSendRecvSemantics(std::map<RankId, RankMemorySemantics> &allRankMemSemantics,
19 u32 expectedRankSize, u64 dataSize);19 u32 expectedRankSize, u64 dataSize);
20+HcclResult TaskCheckBatchSendRecvRingSemantics(std::map<RankId, RankMemorySemantics> &allRankMemSemantics,
21+ u32 expectedRankSize, u64 dataSize);
20}22}
21 23 
22#endif24#endif
@@ -1085,7 +1085,7 @@ HcclResult TaskCheckOpSemantics::Execute()
1085 } else if (opType_ == HcclCMDType::HCCL_CMD_SCATTER) {1085 } else if (opType_ == HcclCMDType::HCCL_CMD_SCATTER) {
1086 ret = TaskCheckScatterSemantics(allRankMemSemantics_, dataSize_, root_);1086 ret = TaskCheckScatterSemantics(allRankMemSemantics_, dataSize_, root_);
1087 } else if (opType_ == HcclCMDType::HCCL_CMD_BATCH_SEND_RECV) {1087 } else if (opType_ == HcclCMDType::HCCL_CMD_BATCH_SEND_RECV) {
1088- ret = TaskCheckBatchSendRecvSemantics(allRankMemSemantics_, rankSize_, dataSize_);1088+ ret = TaskCheckBatchSendRecvRingSemantics(allRankMemSemantics_, rankSize_, dataSize_);
1089 } else {1089 } else {
1090 HCCL_ERROR("unsupported op type[%d]", opType_);1090 HCCL_ERROR("unsupported op type[%d]", opType_);
1091 ret = HcclResult::HCCL_E_NOT_SUPPORT;1091 ret = HcclResult::HCCL_E_NOT_SUPPORT;
@@ -44,7 +44,7 @@ public:
44 44 
45 // rankId -> dieId -> 寄存器Id -> 寄存器value45 // rankId -> dieId -> 寄存器Id -> 寄存器value
46 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curXn;46 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curXn;
47- std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curGSA;// A6没有GSA,A5使用47+ std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curGSA;
48 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint16_t>>> curCKE;48 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint16_t>>> curCKE;
49 49 
50 std::map<uint32_t, std::map<uint32_t, std::map<uint64_t, std::vector<uint64_t>>>> curHBM;// 模拟HBM,记录每个rank的每个die的每个HBM的使用情况50 std::map<uint32_t, std::map<uint32_t, std::map<uint64_t, std::vector<uint64_t>>>> curHBM;// 模拟HBM,记录每个rank的每个die的每个HBM的使用情况
@@ -149,9 +149,10 @@ bool IsValidPipe(uint32_t pipe)
149}149}
150 150 
151TaskPosition MakeAivPosition(RankId rankId, uint64_t launchIdx, uint32_t blockId, uint32_t pipe,151TaskPosition MakeAivPosition(RankId rankId, uint64_t launchIdx, uint32_t blockId, uint32_t pipe,
152- uint32_t taskId = std::numeric_limits<uint32_t>::max())152+ uint32_t taskId, OperatorId operatorId)
153{153{
154 TaskPosition position;154 TaskPosition position;
155+ position.operatorId = operatorId;
155 position.rankId = rankId;156 position.rankId = rankId;
156 position.streamId = INVALID_STREAM_ID;157 position.streamId = INVALID_STREAM_ID;
157 position.launchIdx = launchIdx;158 position.launchIdx = launchIdx;
@@ -193,9 +194,9 @@ MemSlice ConvertAivSlice(RankId rankId, const AivDataSliceV3 &slice)
193 return result;194 return result;
194}195}
195 196 
196-TaskPosition MakeAivLocation(const AivRuntimeTaskV3 &task, uint64_t launchIdx)197+TaskPosition MakeAivLocation(const AivRuntimeTaskV3 &task, uint64_t launchIdx, OperatorId operatorId)
197{198{
198- return MakeAivPosition(task.rankId, launchIdx, task.blockId, task.curPipe, task.taskId);199+ return MakeAivPosition(task.rankId, launchIdx, task.blockId, task.curPipe, task.taskId, operatorId);
199}200}
200 201 
201SetWaitKey MakeSetWaitKey(const AivPipeEvent &event)202SetWaitKey MakeSetWaitKey(const AivPipeEvent &event)
@@ -208,7 +209,8 @@ FlagCellKey MakeFlagCellKey(const AivFlagSync &flag)
208 return FlagCellKey{flag.flagOwnerRank, flag.launchIdx, flag.commInfoOffset};209 return FlagCellKey{flag.flagOwnerRank, flag.launchIdx, flag.commInfoOffset};
209}210}
210 211 
211-std::unique_ptr<TaskNode> TranslateAivRuntimeTask(const AivRuntimeTaskV3 &task, uint64_t launchIdx)212+std::unique_ptr<TaskNode> TranslateAivRuntimeTask(const AivRuntimeTaskV3 &task, uint64_t launchIdx,
213+ OperatorId operatorId)
212{214{
213 switch (task.taskType) {215 switch (task.taskType) {
214 case AivRuntimeTaskTypeV3::MEM_COPY: {216 case AivRuntimeTaskTypeV3::MEM_COPY: {
@@ -249,14 +251,14 @@ std::unique_ptr<TaskNode> TranslateAivRuntimeTask(const AivRuntimeTaskV3 &task,
249 }251 }
250 case AivRuntimeTaskTypeV3::PIPE_BARRIER: {252 case AivRuntimeTaskTypeV3::PIPE_BARRIER: {
251 AivBarrierInfo info;253 AivBarrierInfo info;
252- info.taskLoc = MakeAivLocation(task, launchIdx);254+ info.taskLoc = MakeAivLocation(task, launchIdx, operatorId);
253 info.pipeType = task.pipeType;255 info.pipeType = task.pipeType;
254 info.memberTaskIds = task.barrierGroupTaskIds;256 info.memberTaskIds = task.barrierGroupTaskIds;
255 return std::make_unique<TaskAivPipeBarrier>(std::move(info));257 return std::make_unique<TaskAivPipeBarrier>(std::move(info));
256 }258 }
257 case AivRuntimeTaskTypeV3::SYNC_ALL: {259 case AivRuntimeTaskTypeV3::SYNC_ALL: {
258 AivSyncAllInfo info;260 AivSyncAllInfo info;
259- info.taskLoc = MakeAivLocation(task, launchIdx);261+ info.taskLoc = MakeAivLocation(task, launchIdx, operatorId);
260 info.syncRound = task.syncRound;262 info.syncRound = task.syncRound;
261 return std::make_unique<TaskAivSyncAll>(std::move(info));263 return std::make_unique<TaskAivSyncAll>(std::move(info));
262 }264 }
@@ -352,7 +354,7 @@ HcclResult ValidateSnapshot(const AivLaunchContext &ctx)
352 if (ctx.storage == nullptr || ctx.placeholder == nullptr) {354 if (ctx.storage == nullptr || ctx.placeholder == nullptr) {
353 return HCCL_E_PTR;355 return HCCL_E_PTR;
354 }356 }
355- const CheckerParam param = ctx.storage->GetCheckerParam();357+ const CheckerParam param = ctx.storage->GetCheckerParam(ctx.placeholder->GetOperatorId());
356 if (ctx.snapshot.rankSize != 0 && param.rankSize != 0 && ctx.snapshot.rankSize != param.rankSize) {358 if (ctx.snapshot.rankSize != 0 && param.rankSize != 0 && ctx.snapshot.rankSize != param.rankSize) {
357 HCCL_VM_ERROR("{} The AIV snapshot was captured for a different rank count than the current "359 HCCL_VM_ERROR("{} The AIV snapshot was captured for a different rank count than the current "
358 "checker input, rankId={}, launchId={}, snapshotRankCount={}, currentRankCount={}, snapshotFile={}",360 "checker input, rankId={}, launchId={}, snapshotRankCount={}, currentRankCount={}, snapshotFile={}",
@@ -386,7 +388,8 @@ HcclResult UpdateAivBufferSize(uint64_t snapshotSize, const char *fieldName, con
386 388 
387HcclResult AppendRuntimeTask(AivLaunchContext &ctx, const AivRuntimeTaskV3 &task, uint64_t order, NodeId &nodeId)389HcclResult AppendRuntimeTask(AivLaunchContext &ctx, const AivRuntimeTaskV3 &task, uint64_t order, NodeId &nodeId)
388{390{
389- std::unique_ptr<TaskNode> node = TranslateAivRuntimeTask(task, ctx.placeholder->GetLaunchIdx());391+ std::unique_ptr<TaskNode> node = TranslateAivRuntimeTask(task, ctx.placeholder->GetLaunchIdx(),
392+ ctx.placeholder->GetOperatorId());
390 if (node == nullptr) {393 if (node == nullptr) {
391 HCCL_VM_ERROR("{} One AIV runtime task type is not supported, "394 HCCL_VM_ERROR("{} One AIV runtime task type is not supported, "
392 "rankId={}, launchId={}, taskId={}, taskType={}, snapshotFile={}",395 "rankId={}, launchId={}, taskId={}, taskType={}, snapshotFile={}",
@@ -397,7 +400,7 @@ HcclResult AppendRuntimeTask(AivLaunchContext &ctx, const AivRuntimeTaskV3 &task
397 }400 }
398 401 
399 const TaskPosition position = MakeAivPosition(task.rankId, ctx.placeholder->GetLaunchIdx(), task.blockId,402 const TaskPosition position = MakeAivPosition(task.rankId, ctx.placeholder->GetLaunchIdx(), task.blockId,
400- task.curPipe, task.taskId);403+ task.curPipe, task.taskId, ctx.placeholder->GetOperatorId());
401 HcclResult ret = ctx.graph->AppendGeneratedNode(std::move(node), position, nodeId);404 HcclResult ret = ctx.graph->AppendGeneratedNode(std::move(node), position, nodeId);
402 if (ret != HCCL_SUCCESS) {405 if (ret != HCCL_SUCCESS) {
403 return ret;406 return ret;
@@ -1793,7 +1796,7 @@ HcclResult MergePipeBarrierGroups(AivLaunchContext &ctx)
1793 const uint32_t mergedTaskId = group.memberTaskIds.empty() ? std::numeric_limits<uint32_t>::max() :1796 const uint32_t mergedTaskId = group.memberTaskIds.empty() ? std::numeric_limits<uint32_t>::max() :
1794 group.memberTaskIds.front();1797 group.memberTaskIds.front();
1795 info.taskLoc = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(), group.blockId,1798 info.taskLoc = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(), group.blockId,
1796- std::numeric_limits<uint32_t>::max(), mergedTaskId);1799+ std::numeric_limits<uint32_t>::max(), mergedTaskId, ctx.placeholder->GetOperatorId());
1797 info.pipeType = group.pipeType;1800 info.pipeType = group.pipeType;
1798 info.merged = true;1801 info.merged = true;
1799 info.memberNodeIds = group.memberNodeIds;1802 info.memberNodeIds = group.memberNodeIds;
@@ -1802,7 +1805,7 @@ HcclResult MergePipeBarrierGroups(AivLaunchContext &ctx)
1802 1805 
1803 NodeId mergeNodeId = INVALID_NODE_ID;1806 NodeId mergeNodeId = INVALID_NODE_ID;
1804 const TaskPosition position = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(),1807 const TaskPosition position = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(),
1805- group.blockId, std::numeric_limits<uint32_t>::max(), mergedTaskId);1808+ group.blockId, std::numeric_limits<uint32_t>::max(), mergedTaskId, ctx.placeholder->GetOperatorId());
1806 HcclResult ret = ctx.graph->AppendGeneratedNode(std::make_unique<TaskAivPipeBarrier>(std::move(info)),1809 HcclResult ret = ctx.graph->AppendGeneratedNode(std::make_unique<TaskAivPipeBarrier>(std::move(info)),
1807 position, mergeNodeId);1810 position, mergeNodeId);
1808 if (ret != HCCL_SUCCESS) {1811 if (ret != HCCL_SUCCESS) {
@@ -1876,7 +1879,8 @@ HcclResult MergeSyncAllGroups(AivLaunchContext &ctx)
1876 const uint32_t mergedTaskId = group.memberTaskIds.empty() ? std::numeric_limits<uint32_t>::max() :1879 const uint32_t mergedTaskId = group.memberTaskIds.empty() ? std::numeric_limits<uint32_t>::max() :
1877 group.memberTaskIds.front();1880 group.memberTaskIds.front();
1878 info.taskLoc = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(),1881 info.taskLoc = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(),
1879- std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(), mergedTaskId);1882+ std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(), mergedTaskId,
1883+ ctx.placeholder->GetOperatorId());
1880 info.syncRound = group.syncRound;1884 info.syncRound = group.syncRound;
1881 info.merged = true;1885 info.merged = true;
1882 info.memberNodeIds = group.memberNodeIds;1886 info.memberNodeIds = group.memberNodeIds;
@@ -1885,7 +1889,8 @@ HcclResult MergeSyncAllGroups(AivLaunchContext &ctx)
1885 1889 
1886 NodeId mergeNodeId = INVALID_NODE_ID;1890 NodeId mergeNodeId = INVALID_NODE_ID;
1887 const TaskPosition position = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(),1891 const TaskPosition position = MakeAivPosition(ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(),
1888- std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(), mergedTaskId);1892+ std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(), mergedTaskId,
1893+ ctx.placeholder->GetOperatorId());
1889 HcclResult ret = ctx.graph->AppendGeneratedNode(std::make_unique<TaskAivSyncAll>(std::move(info)), position,1894 HcclResult ret = ctx.graph->AppendGeneratedNode(std::make_unique<TaskAivSyncAll>(std::move(info)), position,
1890 mergeNodeId);1895 mergeNodeId);
1891 if (ret != HCCL_SUCCESS) {1896 if (ret != HCCL_SUCCESS) {
@@ -37,7 +37,11 @@ void AllRankParamRecorder::Reset()
37 37 
38void AllRankParamRecorder::InitParam()38void AllRankParamRecorder::InitParam()
39{39{
40- return;40+ curXn.clear();
41+ curGSA.clear();
42+ curHBM.clear();
43+ seenPost.clear();
44+ postNodeMeta.clear();
41}45}
42 46 
43void AllRankParamRecorder::RegisterPostNode(TaskNode *node, const CcuPostNodeMetaV3 &meta)47void AllRankParamRecorder::RegisterPostNode(TaskNode *node, const CcuPostNodeMetaV3 &meta)
@@ -60,7 +60,7 @@ public:
60 60 
61 // rankId -> dieId -> 寄存器Id -> 寄存器value61 // rankId -> dieId -> 寄存器Id -> 寄存器value
62 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curXn;62 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curXn;
63- std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curGSA;// A6没有GSA,A5使用63+ std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint64_t>>> curGSA;
64 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint16_t>>> curCKE;64 std::map<uint32_t, std::map<uint32_t, std::map<uint16_t, uint16_t>>> curCKE;
65 65 
66 std::map<uint32_t, std::map<uint32_t, std::map<uint64_t, std::vector<uint64_t>>>> curHBM;// 模拟HBM,记录每个rank的每个die的每个HBM的使用情况66 std::map<uint32_t, std::map<uint32_t, std::map<uint64_t, std::vector<uint64_t>>>> curHBM;// 模拟HBM,记录每个rank的每个die的每个HBM的使用情况
@@ -168,6 +168,7 @@ MemSlice MakeMemSlice(RankId rankId, const DataSlice &slice)
168 memSlice.memType = ConvertMemType(slice.GetType());168 memSlice.memType = ConvertMemType(slice.GetType());
169 memSlice.offset = slice.GetOffset();169 memSlice.offset = slice.GetOffset();
170 memSlice.len = slice.GetSize();170 memSlice.len = slice.GetSize();
171+ memSlice.rawAddr = slice.GetRawAddr();
171 return memSlice;172 return memSlice;
172}173}
173 174 
@@ -254,7 +255,7 @@ HcclResult FindInstrForQueue(StorageManager &storage, RankId rankId, uint32_t di
254} // namespace255} // namespace
255 256 
256CcuGraphStateV3::CcuGraphStateV3(TaskGraphGeneratorV3 &graphIn, TaskCcuGraph &ccuGraphIn)257CcuGraphStateV3::CcuGraphStateV3(TaskGraphGeneratorV3 &graphIn, TaskCcuGraph &ccuGraphIn)
257- : graph(graphIn), ccuGraph(ccuGraphIn), rankId(ccuGraphIn.GetPosition().rankId)258+ : graph(graphIn), ccuGraph(ccuGraphIn), rankId(ccuGraphIn.GetPosition().rankId), storage_(graphIn.GetStorageManager())
258{259{
259}260}
260 261 
@@ -307,6 +308,7 @@ HcclResult CcuGraphStateV3::AppendGeneratedNode(std::unique_ptr<TaskNode> node,
307{308{
308 TaskPosition position = MakeCcuPosition(nodeRankId, queId);309 TaskPosition position = MakeCcuPosition(nodeRankId, queId);
309 position.streamId = ccuGraph.GetPosition().streamId;310 position.streamId = ccuGraph.GetPosition().streamId;
311+ position.operatorId = ccuGraph.GetPosition().operatorId;
310 return AppendGeneratedNode(std::move(node), position, role, outNode, peerRank, remainingCkeMask,312 return AppendGeneratedNode(std::move(node), position, role, outNode, peerRank, remainingCkeMask,
311 dieId, ckeId, invalidPost);313 dieId, ckeId, invalidPost);
312}314}
@@ -116,6 +116,7 @@ public:
116 116 
117 void GetSqe(uint32_t queId, uint16_t sqeArgsId, uint64_t &argVal);117 void GetSqe(uint32_t queId, uint16_t sqeArgsId, uint64_t &argVal);
118 void GetDieId(uint32_t queId, uint32_t &dieId) const;118 void GetDieId(uint32_t queId, uint32_t &dieId) const;
119+ StorageManager &GetStorageManager() const { return storage_; }
119 uint32_t GetMissionEndInstrId(uint32_t queId) const;120 uint32_t GetMissionEndInstrId(uint32_t queId) const;
120 RankId GetRankId() const { return rankId; }121 RankId GetRankId() const { return rankId; }
121 122 
@@ -145,6 +146,7 @@ public:
145 std::vector<std::map<TaskNode *, TaskNode *>> bilateralPart2_;146 std::vector<std::map<TaskNode *, TaskNode *>> bilateralPart2_;
146 std::vector<std::vector<BilateralNodeV3>> bilateralNodes_;147 std::vector<std::vector<BilateralNodeV3>> bilateralNodes_;
147 size_t internalNodeCount{0};148 size_t internalNodeCount{0};
149+ StorageManager &storage_;
148 150 
149private:151private:
150 std::map<const TaskNode *, CcuNodeMetaV3> nodeMetas_;152 std::map<const TaskNode *, CcuNodeMetaV3> nodeMetas_;
@@ -437,8 +437,8 @@ HcclResult TransformTransLocMemToRmtMemInstr(const CcuRep::CcuInstr *instr, CcuG
437 RankId rId;437 RankId rId;
438 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息438 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息
439 // 南向接口:input/output buffer同北向一样劫持算子入口函数;CCL buffer需要劫持北向接口HcclGetHcclBuffer439 // 南向接口:input/output buffer同北向一样劫持算子入口函数;CCL buffer需要劫持北向接口HcclGetHcclBuffer
440- CHK_RET(StorageManager::GetInstance().GetSlice(locAddr, len, srcSlice));440+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(locAddr, len, srcSlice));
441- CHK_RET(StorageManager::GetInstance().GetSlice(rmtAddr, len, dstSlice, &rId));441+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(rmtAddr, len, dstSlice, &rId));
442 442 
443 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;443 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;
444 HCCL_VM_DEBUG("Preparing local-memory to remote-memory transfer, localRankId={}, remoteRankId={}",444 HCCL_VM_DEBUG("Preparing local-memory to remote-memory transfer, localRankId={}, remoteRankId={}",
@@ -546,8 +546,8 @@ HcclResult TransformTransLocMemToLocMemInstr(const CcuRep::CcuInstr *instr, CcuG
546 DataSlice srcSlice;546 DataSlice srcSlice;
547 DataSlice dstSlice;547 DataSlice dstSlice;
548 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息548 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息
549- CHK_RET(StorageManager::GetInstance().GetSlice(srcAddr, len, srcSlice));549+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(srcAddr, len, srcSlice));
550- CHK_RET(StorageManager::GetInstance().GetSlice(dstAddr, len, dstSlice));550+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(dstAddr, len, dstSlice));
551 551 
552 HCCL_VM_DEBUG("Built local-memory to local-memory copy, rankId={}, srcSlice={}, dstSlice={}, "552 HCCL_VM_DEBUG("Built local-memory to local-memory copy, rankId={}, srcSlice={}, dstSlice={}, "
553 "transferSize={}", rankId, srcSlice.Describe(), dstSlice.Describe(), len);553 "transferSize={}", rankId, srcSlice.Describe(), dstSlice.Describe(), len);
@@ -764,7 +764,7 @@ HcclResult TransformTransLocMemToLocMSInstr(const CcuRep::CcuInstr *instr, CcuGr
764 DataSlice srcSlice;764 DataSlice srcSlice;
765 DataSlice dstSlice;765 DataSlice dstSlice;
766 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息766 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息
767- CHK_RET(StorageManager::GetInstance().GetSlice(locMemAddr, len, srcSlice));767+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(locMemAddr, len, srcSlice));
768 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));768 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));
769 769 
770 AddLocalCopy(rankId, queId, curCcuTask, srcSlice, dstSlice);770 AddLocalCopy(rankId, queId, curCcuTask, srcSlice, dstSlice);
@@ -828,7 +828,7 @@ HcclResult TransformTransLocMSToLocMemInstr(const CcuRep::CcuInstr *instr, CcuGr
828 CHK_GET_GSA_V3(curCcuTask, queId, locGSAId, locMemAddr);828 CHK_GET_GSA_V3(curCcuTask, queId, locGSAId, locMemAddr);
829 locMemAddr = UpdateGSAValue(locMemAddr, loopGroupParam);829 locMemAddr = UpdateGSAValue(locMemAddr, loopGroupParam);
830 DataSlice dstSlice;830 DataSlice dstSlice;
831- CHK_RET(StorageManager::GetInstance().GetSlice(locMemAddr, len, dstSlice));831+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(locMemAddr, len, dstSlice));
832 832 
833 AddLocalCopy(rankId, queId, curCcuTask, srcSlice, dstSlice);833 AddLocalCopy(rankId, queId, curCcuTask, srcSlice, dstSlice);
834 834 
@@ -950,7 +950,7 @@ HcclResult TransformTransLocMSToRmtMemInstr(const CcuRep::CcuInstr *instr, CcuGr
950 rmtMemAddr = UpdateGSAValue(rmtMemAddr, loopGroupParam);950 rmtMemAddr = UpdateGSAValue(rmtMemAddr, loopGroupParam);
951 DataSlice dstSlice;951 DataSlice dstSlice;
952 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息952 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息
953- CHK_RET(StorageManager::GetInstance().GetSlice(rmtMemAddr, len, dstSlice));953+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(rmtMemAddr, len, dstSlice));
954 954 
955 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;955 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;
956 AddWrite(rankId, rmtRankId, queId, curCcuTask, srcSlice, dstSlice);956 AddWrite(rankId, rmtRankId, queId, curCcuTask, srcSlice, dstSlice);
@@ -1087,7 +1087,7 @@ HcclResult TransformTransRmtMemToLocMSInstr(const CcuRep::CcuInstr *instr, CcuGr
1087 DataSlice srcSlice;1087 DataSlice srcSlice;
1088 DataSlice dstSlice;1088 DataSlice dstSlice;
1089 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息1089 // todo: 后续插件通过读取vm的输出文件,重建memlayout的地址类型信息
1090- CHK_RET(StorageManager::GetInstance().GetSlice(rmtAddr, len, srcSlice));1090+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(rmtAddr, len, srcSlice));
1091 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));1091 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));
1092 1092 
1093 // 获取远端rankId与dieId1093 // 获取远端rankId与dieId
@@ -1161,7 +1161,7 @@ HcclResult TransformTransRmtMSToLocMemInstr(const CcuRep::CcuInstr *instr, CcuGr
1161 CHK_GET_GSA_V3(curCcuTask, queId, locGSAId, localAddr);1161 CHK_GET_GSA_V3(curCcuTask, queId, locGSAId, localAddr);
1162 localAddr = UpdateGSAValue(localAddr, loopGroupParam);1162 localAddr = UpdateGSAValue(localAddr, loopGroupParam);
1163 DataSlice dstSlice;1163 DataSlice dstSlice;
1164- CHK_RET(StorageManager::GetInstance().GetSlice(localAddr, len, dstSlice));1164+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(localAddr, len, dstSlice));
1165 1165 
1166 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;1166 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;
1167 AddRead(rankId, rmtRankId, queId, curCcuTask, srcSlice, dstSlice);1167 AddRead(rankId, rmtRankId, queId, curCcuTask, srcSlice, dstSlice);
@@ -1298,9 +1298,9 @@ HcclResult TransformTransRmtMemToLocMemInstr(const CcuRep::CcuInstr *instr, CcuG
1298 1298 
1299 DataSlice srcSlice;1299 DataSlice srcSlice;
1300 RankId rId;1300 RankId rId;
1301- CHK_RET(StorageManager::GetInstance().GetSlice(rmtAddr, len, srcSlice, &rId));1301+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(rmtAddr, len, srcSlice, &rId));
1302 DataSlice dstSlice;1302 DataSlice dstSlice;
1303- CHK_RET(StorageManager::GetInstance().GetSlice(localAddr, len, dstSlice));1303+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(localAddr, len, dstSlice));
1304 1304 
1305 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;1305 RankId rmtRankId = g_allRankChannelInfo[rankId][dieId][channelId].dstRank;
1306 HCCL_VM_DEBUG("Preparing remote-memory to local-memory transfer, localRankId={}, remoteRankId={}",1306 HCCL_VM_DEBUG("Preparing remote-memory to local-memory transfer, localRankId={}, remoteRankId={}",
@@ -1538,7 +1538,7 @@ static HcclResult CollectTransLoopInstrA5(const CcuRep::CcuInstr *instr, CcuGrap
1538 CHK_GET_XN_V3(curCcuTask, queId, op.lengthXnId, len);1538 CHK_GET_XN_V3(curCcuTask, queId, op.lengthXnId, len);
1539 CHK_RET(ValidateLoopLen(len));1539 CHK_RET(ValidateLoopLen(len));
1540 locMemAddr = UpdateGSAValue(locMemAddr, &iterParam);1540 locMemAddr = UpdateGSAValue(locMemAddr, &iterParam);
1541- CHK_RET(StorageManager::GetInstance().GetSlice(locMemAddr, len, srcSlice));1541+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(locMemAddr, len, srcSlice));
1542 const uint16_t locMSId = UpdateMSId(op.locMSId, &iterParam);1542 const uint16_t locMSId = UpdateMSId(op.locMSId, &iterParam);
1543 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));1543 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));
1544 transInstr->srcs.push_back(MakeCcuMemSlice(rankId, srcSlice));1544 transInstr->srcs.push_back(MakeCcuMemSlice(rankId, srcSlice));
@@ -1554,7 +1554,7 @@ static HcclResult CollectTransLoopInstrA5(const CcuRep::CcuInstr *instr, CcuGrap
1554 CHK_GET_XN_V3(curCcuTask, queId, op.lengthXnId, len);1554 CHK_GET_XN_V3(curCcuTask, queId, op.lengthXnId, len);
1555 CHK_RET(ValidateLoopLen(len));1555 CHK_RET(ValidateLoopLen(len));
1556 rmtAddr = UpdateGSAValue(rmtAddr, &iterParam);1556 rmtAddr = UpdateGSAValue(rmtAddr, &iterParam);
1557- CHK_RET(StorageManager::GetInstance().GetSlice(rmtAddr, len, srcSlice));1557+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(rmtAddr, len, srcSlice));
1558 const uint16_t locMSId = UpdateMSId(op.locMSId, &iterParam);1558 const uint16_t locMSId = UpdateMSId(op.locMSId, &iterParam);
1559 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));1559 CHK_RET(GenSliceFromMs(locMSId, len, dstSlice));
1560 transInstr->srcs.push_back(MakeCcuMemSlice(rmtRankId, srcSlice));1560 transInstr->srcs.push_back(MakeCcuMemSlice(rmtRankId, srcSlice));
@@ -1571,7 +1571,7 @@ static HcclResult CollectTransLoopInstrA5(const CcuRep::CcuInstr *instr, CcuGrap
1571 uint64_t locMemAddr = 0;1571 uint64_t locMemAddr = 0;
1572 CHK_GET_GSA_V3(curCcuTask, queId, op.locGSAId, locMemAddr);1572 CHK_GET_GSA_V3(curCcuTask, queId, op.locGSAId, locMemAddr);
1573 locMemAddr = UpdateGSAValue(locMemAddr, &iterParam);1573 locMemAddr = UpdateGSAValue(locMemAddr, &iterParam);
1574- CHK_RET(StorageManager::GetInstance().GetSlice(locMemAddr, len, dstSlice));1574+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(locMemAddr, len, dstSlice));
1575 transInstr->srcs.push_back(MakeCcuMemSlice(rankId, srcSlice));1575 transInstr->srcs.push_back(MakeCcuMemSlice(rankId, srcSlice));
1576 transInstr->dsts.push_back(MakeCcuMemSlice(rankId, dstSlice));1576 transInstr->dsts.push_back(MakeCcuMemSlice(rankId, dstSlice));
1577 transInstr->msIds.insert(locMSId);1577 transInstr->msIds.insert(locMSId);
@@ -1587,7 +1587,7 @@ static HcclResult CollectTransLoopInstrA5(const CcuRep::CcuInstr *instr, CcuGrap
1587 uint64_t rmtMemAddr = 0;1587 uint64_t rmtMemAddr = 0;
1588 CHK_GET_GSA_V3(curCcuTask, queId, op.rmtGSAId, rmtMemAddr);1588 CHK_GET_GSA_V3(curCcuTask, queId, op.rmtGSAId, rmtMemAddr);
1589 rmtMemAddr = UpdateGSAValue(rmtMemAddr, &iterParam);1589 rmtMemAddr = UpdateGSAValue(rmtMemAddr, &iterParam);
1590- CHK_RET(StorageManager::GetInstance().GetSlice(rmtMemAddr, len, dstSlice));1590+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(rmtMemAddr, len, dstSlice));
1591 transInstr->srcs.push_back(MakeCcuMemSlice(rankId, srcSlice));1591 transInstr->srcs.push_back(MakeCcuMemSlice(rankId, srcSlice));
1592 transInstr->dsts.push_back(MakeCcuMemSlice(rmtRankId, dstSlice));1592 transInstr->dsts.push_back(MakeCcuMemSlice(rmtRankId, dstSlice));
1593 transInstr->msIds.insert(locMSId);1593 transInstr->msIds.insert(locMSId);
@@ -1603,7 +1603,7 @@ static HcclResult CollectTransLoopInstrA5(const CcuRep::CcuInstr *instr, CcuGrap
1603 uint64_t localAddr = 0;1603 uint64_t localAddr = 0;
1604 CHK_GET_GSA_V3(curCcuTask, queId, op.locGSAId, localAddr);1604 CHK_GET_GSA_V3(curCcuTask, queId, op.locGSAId, localAddr);
1605 localAddr = UpdateGSAValue(localAddr, &iterParam);1605 localAddr = UpdateGSAValue(localAddr, &iterParam);
1606- CHK_RET(StorageManager::GetInstance().GetSlice(localAddr, len, dstSlice));1606+ CHK_RET(curCcuTask->GetStorageManager().GetSlice(localAddr, len, dstSlice));
1607 transInstr->srcs.push_back(MakeCcuMemSlice(rmtRankId, srcSlice));1607 transInstr->srcs.push_back(MakeCcuMemSlice(rmtRankId, srcSlice));
1608 transInstr->dsts.push_back(MakeCcuMemSlice(rankId, dstSlice));1608 transInstr->dsts.push_back(MakeCcuMemSlice(rankId, dstSlice));
1609 transInstr->msIds.insert(rmtMSId);1609 transInstr->msIds.insert(rmtMSId);
@@ -167,10 +167,6 @@ CcuInstrVersion GetCcuInstrVersion()
167 DevType devType = AllRankParamRecorder::Global()->GetDevType();167 DevType devType = AllRankParamRecorder::Global()->GetDevType();
168 if (devType == DevType::DEV_TYPE_950) {168 if (devType == DevType::DEV_TYPE_950) {
169 return CcuInstrVersion::VERSION_A5;169 return CcuInstrVersion::VERSION_A5;
170-#ifdef BUILD_A6_CCU_INSTR
171- } else if (devType == DevType::DEV_TYPE_960) {
172- return CcuInstrVersion::VERSION_A6;
173-#endif
174 }170 }
175 return CcuInstrVersion::VERSION_A5;171 return CcuInstrVersion::VERSION_A5;
176}172}
@@ -225,7 +221,7 @@ HcclResult TransformInstrQue(TaskNode *node, CcuGraphStateV3 *curCcuTask, uint32
225HcclResult ProcessCcuNode(TaskNode *node, CcuGraphStateV3 *curCcuTask)221HcclResult ProcessCcuNode(TaskNode *node, CcuGraphStateV3 *curCcuTask)
226{222{
227 curCcuTask->queueNum_ = static_cast<uint32_t>(curCcuTask->instrInfo.size());223 curCcuTask->queueNum_ = static_cast<uint32_t>(curCcuTask->instrInfo.size());
228- uint32_t rankSize = HcclSim::StorageManager::GetInstance().GetRankSize();224+ uint32_t rankSize = curCcuTask->GetStorageManager().GetRankSize();
229 curCcuTask->bilateralPart1_.resize(curCcuTask->queueNum_);225 curCcuTask->bilateralPart1_.resize(curCcuTask->queueNum_);
230 curCcuTask->bilateralPart2_.resize(curCcuTask->queueNum_);226 curCcuTask->bilateralPart2_.resize(curCcuTask->queueNum_);
231 curCcuTask->bilateralNodes_.resize(curCcuTask->queueNum_);227 curCcuTask->bilateralNodes_.resize(curCcuTask->queueNum_);
@@ -23,6 +23,7 @@
23namespace HcclSim {23namespace HcclSim {
24namespace TaskGraphGeneratorV3 {24namespace TaskGraphGeneratorV3 {
25using NodeId = int32_t;25using NodeId = int32_t;
26+using OperatorId = uint32_t;
26using RankId = uint32_t;27using RankId = uint32_t;
27using StreamId = uint32_t;28using StreamId = uint32_t;
28using QueueId = uint32_t;29using QueueId = uint32_t;
@@ -30,6 +31,7 @@ using ChannelId = uint16_t; // for CCU mode
30 31 
31constexpr NodeId MAIN_START_NODE_ID = -1;32constexpr NodeId MAIN_START_NODE_ID = -1;
32constexpr NodeId INVALID_NODE_ID = std::numeric_limits<NodeId>::min();33constexpr NodeId INVALID_NODE_ID = std::numeric_limits<NodeId>::min();
34+constexpr OperatorId INVALID_OPERATOR_ID = std::numeric_limits<OperatorId>::max();
33constexpr size_t MAX_NODE_COUNT = static_cast<size_t>(std::numeric_limits<NodeId>::max());35constexpr size_t MAX_NODE_COUNT = static_cast<size_t>(std::numeric_limits<NodeId>::max());
34constexpr RankId INVALID_RANK_ID = std::numeric_limits<RankId>::max();36constexpr RankId INVALID_RANK_ID = std::numeric_limits<RankId>::max();
35constexpr StreamId INVALID_STREAM_ID = std::numeric_limits<StreamId>::max();37constexpr StreamId INVALID_STREAM_ID = std::numeric_limits<StreamId>::max();
@@ -111,6 +113,7 @@ enum class ProtocolType : uint8_t {
111};113};
112 114 
113struct TaskPosition {115struct TaskPosition {
116+ OperatorId operatorId{INVALID_OPERATOR_ID};
114 RankId rankId{INVALID_RANK_ID};117 RankId rankId{INVALID_RANK_ID};
115 StreamId streamId{INVALID_STREAM_ID};118 StreamId streamId{INVALID_STREAM_ID};
116 QueueId queueId{INVALID_QUEUE_ID};119 QueueId queueId{INVALID_QUEUE_ID};
@@ -127,6 +130,7 @@ struct MemSlice {
127 MemType memType{MemType::INVALID};130 MemType memType{MemType::INVALID};
128 uint64_t offset{0};131 uint64_t offset{0};
129 uint64_t len{0};132 uint64_t len{0};
133+ uint64_t rawAddr{0};
130};134};
131 135 
132struct AivPipeEvent {136struct AivPipeEvent {
@@ -242,6 +246,12 @@ public:
242 virtual std::string DescribeShort() const { return Describe(); }246 virtual std::string DescribeShort() const { return Describe(); }
243 247 
244 TaskType GetType() const { return type_; }248 TaskType GetType() const { return type_; }
249+ OperatorId GetOperatorId() const { return operatorId_; }
250+ void SetOperatorId(OperatorId operatorId)
251+ {
252+ operatorId_ = operatorId;
253+ loc_.operatorId = operatorId;
254+ }
245 NodeId GetNodeId() const { return nodeId_; }255 NodeId GetNodeId() const { return nodeId_; }
246 void SetNodeId(NodeId id) { nodeId_ = id; }256 void SetNodeId(NodeId id) { nodeId_ = id; }
247 257 
@@ -249,6 +259,7 @@ public:
249 void SetPosition(const TaskPosition &position)259 void SetPosition(const TaskPosition &position)
250 {260 {
251 loc_ = position;261 loc_ = position;
262+ operatorId_ = position.operatorId;
252 if (ccuTraceValid_) {263 if (ccuTraceValid_) {
253 ccuTrace_.position = position;264 ccuTrace_.position = position;
254 ccuTrace_.taskLoc = position;265 ccuTrace_.taskLoc = position;
@@ -300,6 +311,7 @@ public:
300 311 
301protected:312protected:
302 TaskType type_{TaskType::INVALID};313 TaskType type_{TaskType::INVALID};
314+ OperatorId operatorId_{INVALID_OPERATOR_ID};
303 NodeId nodeId_{INVALID_NODE_ID};315 NodeId nodeId_{INVALID_NODE_ID};
304 TaskPosition loc_;316 TaskPosition loc_;
305 CcuTraceInfo ccuTrace_;317 CcuTraceInfo ccuTrace_;
@@ -99,6 +99,11 @@ bool TaskGraphGeneratorV3::IsMainStartNodeId(NodeId nodeId) const
99 return mainStart_ != nullptr && nodeId == mainStartNodeId_;99 return mainStart_ != nullptr && nodeId == mainStartNodeId_;
100}100}
101 101 
102+StorageManager &TaskGraphGeneratorV3::GetStorageManager() const
103+{
104+ return storage_ == nullptr ? StorageManager::GetInstance() : *storage_;
105+}
106+ 
102TaskNode *TaskGraphGeneratorV3::GetNode(NodeId nodeId)107TaskNode *TaskGraphGeneratorV3::GetNode(NodeId nodeId)
103{108{
104 if (IsMainStartNodeId(nodeId)) {109 if (IsMainStartNodeId(nodeId)) {
@@ -445,7 +450,7 @@ HcclResult TaskGraphGeneratorV3::ExpandAivSubGraphs()
445{450{
446 const size_t originalNodeCount = nodes_.size();451 const size_t originalNodeCount = nodes_.size();
447 AivExpandStats stats;452 AivExpandStats stats;
448- StorageManager &storage = StorageManager::GetInstance();453+ StorageManager &storage = GetStorageManager();
449 std::vector<TaskAivGraph *> aivGraphs;454 std::vector<TaskAivGraph *> aivGraphs;
450 455 
451 for (size_t nodeIndex = 0; nodeIndex < originalNodeCount; ++nodeIndex) {456 for (size_t nodeIndex = 0; nodeIndex < originalNodeCount; ++nodeIndex) {
@@ -514,7 +519,7 @@ HcclResult TaskGraphGeneratorV3::ExpandCcuSubGraphs()
514{519{
515 const size_t originalNodeCount = nodes_.size();520 const size_t originalNodeCount = nodes_.size();
516 CcuExpandStats stats;521 CcuExpandStats stats;
517- StorageManager &storage = StorageManager::GetInstance();522+ StorageManager &storage = GetStorageManager();
518 std::vector<TaskCcuGraph *> ccuGraphs;523 std::vector<TaskCcuGraph *> ccuGraphs;
519 524 
520 for (size_t nodeIndex = 0; nodeIndex < originalNodeCount; ++nodeIndex) {525 for (size_t nodeIndex = 0; nodeIndex < originalNodeCount; ++nodeIndex) {
@@ -21,6 +21,7 @@
21#include "task_def_v3.h"21#include "task_def_v3.h"
22 22 
23namespace HcclSim {23namespace HcclSim {
24+class StorageManager;
24namespace TaskGraphGeneratorV3 {25namespace TaskGraphGeneratorV3 {
25using RankNodeQueues = std::vector<std::vector<NodeId>>;26using RankNodeQueues = std::vector<std::vector<NodeId>>;
26using AllRankNodeQueues = std::map<RankId, RankNodeQueues>;27using AllRankNodeQueues = std::map<RankId, RankNodeQueues>;
@@ -63,6 +64,8 @@ public:
63 HcclResult GenGraph(std::vector<std::unique_ptr<TaskNode>> translatedNodes,64 HcclResult GenGraph(std::vector<std::unique_ptr<TaskNode>> translatedNodes,
64 AllRankNodeQueues translatedTaskQueues);65 AllRankNodeQueues translatedTaskQueues);
65 void Reset();66 void Reset();
67+ void SetStorageManager(StorageManager *storage) { storage_ = storage; }
68+ StorageManager &GetStorageManager() const;
66 69 
67 NodeId GetMainStartNodeId() const { return mainStartNodeId_; }70 NodeId GetMainStartNodeId() const { return mainStartNodeId_; }
68 TaskNode *GetMainStartNode() { return mainStart_.get(); }71 TaskNode *GetMainStartNode() { return mainStart_.get(); }
@@ -110,6 +113,7 @@ private:
110 bool hasCcu_{false};113 bool hasCcu_{false};
111 AivExpandStats aivExpandStats_;114 AivExpandStats aivExpandStats_;
112 CcuExpandStats ccuExpandStats_;115 CcuExpandStats ccuExpandStats_;
116+ StorageManager *storage_{nullptr};
113};117};
114} // namespace TaskGraphGeneratorV3118} // namespace TaskGraphGeneratorV3
115} // namespace HcclSim119} // namespace HcclSim
@@ -951,7 +951,7 @@ HcclResult CheckFinalOutput(const SemanticState &state)
951 case HCCL_CMD_SCATTER:951 case HCCL_CMD_SCATTER:
952 return TaskCheckScatterSemantics(allRankMemSemantics, state.dataSize, state.param.root);952 return TaskCheckScatterSemantics(allRankMemSemantics, state.dataSize, state.param.root);
953 case HCCL_CMD_BATCH_SEND_RECV:953 case HCCL_CMD_BATCH_SEND_RECV:
954- return TaskCheckBatchSendRecvSemantics(allRankMemSemantics, state.param.rankSize, state.dataSize);954+ return TaskCheckBatchSendRecvRingSemantics(allRankMemSemantics, state.param.rankSize, state.dataSize);
955 default:955 default:
956 HCCL_VM_WARN("{} Final output validation does not support this collective type yet, "956 HCCL_VM_WARN("{} Final output validation does not support this collective type yet, "
957 "collectiveType={}, rankCount={}, dataType={}, elementCount={}, reduceType={}",957 "collectiveType={}, rankCount={}, dataType={}, elementCount={}, reduceType={}",
@@ -1,9 +1,11 @@
1/**1/**
2 * Copyright (c) 2026 Huawei Technologies Co., Ltd.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 of3+ * 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").4 * CANN Open Software License Agreement Version 2.0 (the "License").
5- * Please refer to the License for details. This software is distributed on an "AS IS" BASIS,5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.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.
7 */9 */
8 10 
9#include "task_graph_sync_conflict_v3.h"11#include "task_graph_sync_conflict_v3.h"
@@ -1,9 +1,11 @@
1/**1/**
2 * Copyright (c) 2026 Huawei Technologies Co., Ltd.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 of3+ * 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").4 * CANN Open Software License Agreement Version 2.0 (the "License").
5- * Please refer to the License for details. This software is distributed on an "AS IS" BASIS,5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.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.
7 */9 */
8 10 
9#ifndef CHECKER_TASK_GRAPH_GENERATOR_V3_TASK_GRAPH_SYNC_CONFLICT_V3_H11#ifndef CHECKER_TASK_GRAPH_GENERATOR_V3_TASK_GRAPH_SYNC_CONFLICT_V3_H
@@ -60,15 +60,17 @@ MemSlice MakeMemSlice(RankId rankId, const DataSlice &slice)
60 memSlice.memType = ConvertMemType(slice.GetType());60 memSlice.memType = ConvertMemType(slice.GetType());
61 memSlice.offset = slice.GetOffset();61 memSlice.offset = slice.GetOffset();
62 memSlice.len = slice.GetSize();62 memSlice.len = slice.GetSize();
63+ memSlice.rawAddr = slice.GetRawAddr();
63 return memSlice;64 return memSlice;
64}65}
65 66 
66-HcclResult MakeTaskPosition(const HcclTaskMetaData &taskMeta, TaskPosition &position)67+HcclResult MakeTaskPosition(const HcclTaskMetaData &taskMeta, OperatorId operatorId, TaskPosition &position)
67{68{
68 if (taskMeta.streamId > std::numeric_limits<StreamId>::max()) {69 if (taskMeta.streamId > std::numeric_limits<StreamId>::max()) {
69 return HCCL_E_PARA;70 return HCCL_E_PARA;
70 }71 }
71 72 
73+ position.operatorId = operatorId;
72 position.rankId = taskMeta.rankId;74 position.rankId = taskMeta.rankId;
73 position.streamId = static_cast<StreamId>(taskMeta.streamId);75 position.streamId = static_cast<StreamId>(taskMeta.streamId);
74 return HCCL_SUCCESS;76 return HCCL_SUCCESS;
@@ -226,7 +228,7 @@ AllRankNodeQueues TaskMetaTranslatorV3::TakeTaskQueues()
226 return result;228 return result;
227}229}
228 230 
229-HcclResult TaskMetaTranslatorV3::Translate(StorageManager &storage)231+HcclResult TaskMetaTranslatorV3::Translate(StorageManager &storage, OperatorId operatorId)
230{232{
231 Reset();233 Reset();
232 234 
@@ -236,7 +238,7 @@ HcclResult TaskMetaTranslatorV3::Translate(StorageManager &storage)
236 taskMetaVec.size());238 taskMetaVec.size());
237 for (uint32_t i = 0; i < taskMetaVec.size(); ++i) {239 for (uint32_t i = 0; i < taskMetaVec.size(); ++i) {
238 NodeId nodeId = INVALID_NODE_ID;240 NodeId nodeId = INVALID_NODE_ID;
239- const HcclResult ret = TranslateOneTaskMeta(taskMetaVec[i], storage, i, nodeId);241+ const HcclResult ret = TranslateOneTaskMeta(taskMetaVec[i], storage, i, operatorId, nodeId);
240 if (ret != HCCL_SUCCESS) {242 if (ret != HCCL_SUCCESS) {
241 HCCL_VM_ERROR("{} Failed to convert one task into a graph node, taskIndex={}, "243 HCCL_VM_ERROR("{} Failed to convert one task into a graph node, taskIndex={}, "
242 "ret={}, taskMeta={}",244 "ret={}, taskMeta={}",
@@ -283,10 +285,10 @@ HcclResult TaskMetaTranslatorV3::AddTaskNode(const TaskPosition &position, std::
283}285}
284 286 
285HcclResult TaskMetaTranslatorV3::TranslateOneTaskMeta(const HcclTaskMetaData &taskMeta, StorageManager &storage,287HcclResult TaskMetaTranslatorV3::TranslateOneTaskMeta(const HcclTaskMetaData &taskMeta, StorageManager &storage,
286- uint32_t taskIndex, NodeId &nodeId)288+ uint32_t taskIndex, OperatorId operatorId, NodeId &nodeId)
287{289{
288 TaskPosition position;290 TaskPosition position;
289- HcclResult ret = MakeTaskPosition(taskMeta, position);291+ HcclResult ret = MakeTaskPosition(taskMeta, operatorId, position);
290 if (ret != HCCL_SUCCESS) {292 if (ret != HCCL_SUCCESS) {
291 return ret;293 return ret;
292 }294 }
@@ -33,7 +33,7 @@ public:
33 TaskMetaTranslatorV3(const TaskMetaTranslatorV3 &) = delete;33 TaskMetaTranslatorV3(const TaskMetaTranslatorV3 &) = delete;
34 TaskMetaTranslatorV3 &operator=(const TaskMetaTranslatorV3 &) = delete;34 TaskMetaTranslatorV3 &operator=(const TaskMetaTranslatorV3 &) = delete;
35 35 
36- HcclResult Translate(StorageManager &storage);36+ HcclResult Translate(StorageManager &storage, OperatorId operatorId);
37 void Reset();37 void Reset();
38 38 
39 const std::vector<std::unique_ptr<TaskNode>> &GetNodes() const { return nodes_; }39 const std::vector<std::unique_ptr<TaskNode>> &GetNodes() const { return nodes_; }
@@ -60,7 +60,7 @@ private:
60 };60 };
61 61 
62 HcclResult TranslateOneTaskMeta(const HcclTaskMetaData &taskMeta, StorageManager &storage, uint32_t taskIndex,62 HcclResult TranslateOneTaskMeta(const HcclTaskMetaData &taskMeta, StorageManager &storage, uint32_t taskIndex,
63- NodeId &nodeId);63+ OperatorId operatorId, NodeId &nodeId);
64 HcclResult AddTaskNode(const TaskPosition &position, std::unique_ptr<TaskNode> node, NodeId &nodeId);64 HcclResult AddTaskNode(const TaskPosition &position, std::unique_ptr<TaskNode> node, NodeId &nodeId);
65 65 
66 std::vector<std::unique_ptr<TaskNode>> nodes_;66 std::vector<std::unique_ptr<TaskNode>> nodes_;
@@ -107,8 +107,8 @@ void CalcInputOutputSize(HcclCMDType opType, uint32_t rankSize, uint64_t count,
107 inputSize = curSendOffset;107 inputSize = curSendOffset;
108 outputSize = curRecvOffset;108 outputSize = curRecvOffset;
109 } else if (opType == HcclCMDType::HCCL_CMD_BATCH_SEND_RECV) {109 } else if (opType == HcclCMDType::HCCL_CMD_BATCH_SEND_RECV) {
110- inputSize = count * unitSize * rankSize;110+ inputSize = count * unitSize;
111- outputSize = count * unitSize * rankSize;111+ outputSize = count * unitSize;
112 } else if (opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER_V) {112 } else if (opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER_V) {
113 inputSize = 0;113 inputSize = 0;
114 for (u32 i = 0; i < rankSize; i++) {114 for (u32 i = 0; i < rankSize; i++) {
@@ -24,6 +24,7 @@ static const std::string SETTING_KEY_ENABLE_INSIGHT_DUMP = "enable_insight_dump"
24static const std::string SETTING_KEY_ENABLE_MEMORY_SNAPSHOT_DUMP = "enable_memory_snapshot_dump";24static const std::string SETTING_KEY_ENABLE_MEMORY_SNAPSHOT_DUMP = "enable_memory_snapshot_dump";
25static const std::string SETTING_KEY_ENABLE_NEW_CHECKER = "enable_new_checker";25static const std::string SETTING_KEY_ENABLE_NEW_CHECKER = "enable_new_checker";
26static const std::string SETTING_KEY_ENABLE_OLD_CHECKER = "enable_old_checker";26static const std::string SETTING_KEY_ENABLE_OLD_CHECKER = "enable_old_checker";
27+static const std::string SETTING_KEY_ENABLE_BIG_GRAPH_CHECKER = "enable_big_graph_checker";
27 28 
28} // namespace29} // namespace
29 30 
@@ -63,6 +64,7 @@ HcclResult SettingManager::Refresh()
63 newSettings.enableMemorySnapshotDump = settings.value(SETTING_KEY_ENABLE_MEMORY_SNAPSHOT_DUMP, true);64 newSettings.enableMemorySnapshotDump = settings.value(SETTING_KEY_ENABLE_MEMORY_SNAPSHOT_DUMP, true);
64 newSettings.enableNewChecker = settings.value(SETTING_KEY_ENABLE_NEW_CHECKER, true);65 newSettings.enableNewChecker = settings.value(SETTING_KEY_ENABLE_NEW_CHECKER, true);
65 newSettings.enableOldChecker = settings.value(SETTING_KEY_ENABLE_OLD_CHECKER, true);66 newSettings.enableOldChecker = settings.value(SETTING_KEY_ENABLE_OLD_CHECKER, true);
67+ newSettings.enableBigGraphChecker = settings.value(SETTING_KEY_ENABLE_BIG_GRAPH_CHECKER, false);
66 } catch (const std::exception &ex) {68 } catch (const std::exception &ex) {
67 HCCL_VM_ERROR("parse manifest failed: {}", ex.what());69 HCCL_VM_ERROR("parse manifest failed: {}", ex.what());
68 return HcclResult::HCCL_E_INTERNAL;70 return HcclResult::HCCL_E_INTERNAL;
@@ -76,8 +78,9 @@ HcclResult SettingManager::Refresh()
76 }78 }
77 79 
78 HCCL_VM_INFO("settings refreshed: insight_dump={}, memory_snapshot_dump={}, "80 HCCL_VM_INFO("settings refreshed: insight_dump={}, memory_snapshot_dump={}, "
79- "new_checker={}, old_checker={}", newSettings.enableInsightDump, newSettings.enableMemorySnapshotDump,81+ "new_checker={}, old_checker={}, big_graph_checker={}", newSettings.enableInsightDump,
80- newSettings.enableNewChecker, newSettings.enableOldChecker);82+ newSettings.enableMemorySnapshotDump, newSettings.enableNewChecker, newSettings.enableOldChecker,
83+ newSettings.enableBigGraphChecker);
81 return HcclResult::HCCL_SUCCESS;84 return HcclResult::HCCL_SUCCESS;
82}85}
83 86 
@@ -119,4 +122,10 @@ bool SettingManager::IsOldCheckerEnabled() const
119 return m_settings.enableOldChecker;122 return m_settings.enableOldChecker;
120}123}
121 124 
125+bool SettingManager::IsBigGraphCheckerEnabled() const
126+{
127+ std::lock_guard<std::mutex> lock(m_mutex);
128+ return m_settings.enableBigGraphChecker;
129+}
130+ 
122} // namespace HcclSim131} // namespace HcclSim
@@ -23,6 +23,7 @@ struct CheckerSettings {
23 bool enableMemorySnapshotDump{false};23 bool enableMemorySnapshotDump{false};
24 bool enableNewChecker{true};24 bool enableNewChecker{true};
25 bool enableOldChecker{true};25 bool enableOldChecker{true};
26+ bool enableBigGraphChecker{false};
26};27};
27 28 
28class SettingManager {29class SettingManager {
@@ -44,6 +45,7 @@ public:
44 bool IsMemorySnapshotEnabled() const;45 bool IsMemorySnapshotEnabled() const;
45 bool IsNewCheckerEnabled() const;46 bool IsNewCheckerEnabled() const;
46 bool IsOldCheckerEnabled() const;47 bool IsOldCheckerEnabled() const;
48+ bool IsBigGraphCheckerEnabled() const;
47 49 
48private:50private:
49 SettingManager() = default;51 SettingManager() = default;
@@ -157,37 +157,80 @@ HcclResult FinalizeVDataDes(CheckerParam &checkerParam, bool isAllGatherV)
157 return HcclResult::HCCL_SUCCESS;157 return HcclResult::HCCL_SUCCESS;
158}158}
159 159 
160-HcclResult FinalizeBatchSendRecv(CheckerParam &checkerParam)160+HcclResult FinalizeBatchSendRecvRing(CheckerParam &checkerParam)
161{161{
162 const uint32_t rankSize = checkerParam.rankSize;162 const uint32_t rankSize = checkerParam.rankSize;
163- if (rankSize == 0 || checkerParam.batchSendRecvRankParams.size() != rankSize) {163+ if (rankSize < 2 || checkerParam.batchSendRecvRankParams.size() != rankSize) {
164- HCCL_VM_ERROR("Invalid BatchSendRecv report set, rankSize={}, reportedRanks={}",164+ HCCL_VM_ERROR("Invalid BatchSendRecv ring report set, rankSize={}, reportedRanks={}",
165 rankSize, checkerParam.batchSendRecvRankParams.size());165 rankSize, checkerParam.batchSendRecvRankParams.size());
166 return HcclResult::HCCL_E_PARA;166 return HcclResult::HCCL_E_PARA;
167 }167 }
168 168 
169- const uint64_t expectedItemNum = static_cast<uint64_t>(rankSize) * 2U;
170 const uint64_t peerCount = checkerParam.batchSendRecvRankParams[0].peerCount;169 const uint64_t peerCount = checkerParam.batchSendRecvRankParams[0].peerCount;
170+ const HcclDataType dataType = checkerParam.batchSendRecvRankParams[0].dataType;
171 for (uint32_t rankId = 0; rankId < rankSize; ++rankId) {171 for (uint32_t rankId = 0; rankId < rankSize; ++rankId) {
172 const BatchSendRecvRankParam &current = checkerParam.batchSendRecvRankParams[rankId];172 const BatchSendRecvRankParam &current = checkerParam.batchSendRecvRankParams[rankId];
173- if (static_cast<uint64_t>(current.itemNum) != expectedItemNum || current.peerCount != peerCount) {173+ const uint32_t expectedSendPeer = (rankId + 1U) % rankSize;
174- HCCL_VM_ERROR("Invalid BatchSendRecv all-to-all parameters at rank {}: itemNum={} vs {}, "174+ const uint32_t expectedRecvPeer = (rankId + rankSize - 1U) % rankSize;
175- "peerCount={} vs {}", rankId, current.itemNum, expectedItemNum, current.peerCount, peerCount);175+ if (current.itemNum != 2 || current.peerCount != peerCount || current.dataType != dataType ||
176+ current.sendPeer != expectedSendPeer || current.recvPeer != expectedRecvPeer) {
177+ HCCL_VM_ERROR("Invalid BatchSendRecv ring parameters at rank {}: itemNum={}, peerCount={}, "
178+ "dataType={}, sendPeer={}, recvPeer={}; expected itemNum=2, peerCount={}, dataType={}, "
179+ "sendPeer={}, recvPeer={}", rankId, current.itemNum, current.peerCount,
180+ static_cast<uint32_t>(current.dataType), current.sendPeer, current.recvPeer, peerCount,
181+ static_cast<uint32_t>(dataType), expectedSendPeer, expectedRecvPeer);
176 return HcclResult::HCCL_E_PARA;182 return HcclResult::HCCL_E_PARA;
177 }183 }
178 }184 }
179 185 
180 checkerParam.dataCount = peerCount;186 checkerParam.dataCount = peerCount;
187+ checkerParam.dataType = dataType;
181 return HcclResult::HCCL_SUCCESS;188 return HcclResult::HCCL_SUCCESS;
182}189}
190+ 
191+void UpdateNotifyPeerRanks(HcclVmTaskMetaData &taskMetaData)
192+{
193+ std::unordered_map<uint32_t, std::set<uint32_t>> notifyId2Ranks;
194+ for (const auto &taskMeta : taskMetaData.task_meta) {
195+ if (taskMeta.taskType == HccLTaskMetaType::NOTIFY_RECORD ||
196+ taskMeta.taskType == HccLTaskMetaType::NOTIFY_WAIT) {
197+ const uint64_t notifyId = taskMeta.taskData.notify.notifyId;
198+ notifyId2Ranks[notifyId].insert(taskMeta.rankId);
199+ }
200+ }
201+ 
202+ // AICPU生成的Task需要更新Notify节点的对端信息
203+ for (auto &taskMeta : taskMetaData.task_meta) {
204+ if (taskMeta.taskType != HccLTaskMetaType::NOTIFY_RECORD &&
205+ taskMeta.taskType != HccLTaskMetaType::NOTIFY_WAIT) {
206+ continue;
207+ }
208+ uint32_t rankId = taskMeta.rankId;
209+ for (auto id : notifyId2Ranks[taskMeta.taskData.notify.notifyId]) {
210+ if (id != rankId) {
211+ rankId = id;
212+ break;
213+ }
214+ }
215+ 
216+ if (taskMeta.taskType == HccLTaskMetaType::NOTIFY_RECORD) {
217+ taskMeta.taskData.notify.dstRankId = rankId;
218+ } else if (taskMeta.taskType == HccLTaskMetaType::NOTIFY_WAIT) {
219+ taskMeta.taskData.notify.srcRankId = rankId;
220+ }
221+ }
222+}
183} // namespace223} // namespace
184 224 
185-void StorageManager::Reset()225+void StorageManager::Reset(bool clearMemLayout)
186{226{
187 std::lock_guard<std::mutex> lock(m_mutex);227 std::lock_guard<std::mutex> lock(m_mutex);
188- m_mem_layout.clear();228+ if (clearMemLayout) {
229+ m_mem_layout.clear();
230+ }
189 m_allRankChannelInfo.clear();231 m_allRankChannelInfo.clear();
190 m_checker_param = CheckerParam{};232 m_checker_param = CheckerParam{};
233+ m_checker_params.clear();
191 m_all2AllvSendMatrices.clear();234 m_all2AllvSendMatrices.clear();
192 m_synData = HcclVmSynData{};235 m_synData = HcclVmSynData{};
193 m_instrData = HcclVmInstrData{};236 m_instrData = HcclVmInstrData{};
@@ -275,12 +318,20 @@ HcclResult StorageManager::Trans2CheckerParam(sim::OpDetailTab& detailTab, ::OpD
275 detailTab.rankId, detailTab.opExtInfo.size());318 detailTab.rankId, detailTab.opExtInfo.size());
276 return HcclResult::HCCL_E_PARA;319 return HcclResult::HCCL_E_PARA;
277 }320 }
278- if (static_cast<uint64_t>(rankParam.itemNum) != static_cast<uint64_t>(detailTab.rankSize) * 2U) {321+ const uint32_t expectedSendPeer = (detailTab.rankId + 1U) % detailTab.rankSize;
279- HCCL_VM_ERROR("BatchSendRecv is not a complete all-to-all at rank {}: itemNum={}, rankSize={}",322+ const uint32_t expectedRecvPeer =
280- detailTab.rankId, rankParam.itemNum, detailTab.rankSize);323+ (detailTab.rankId + detailTab.rankSize - 1U) % detailTab.rankSize;
324+ if (detailTab.rankSize < 2 || rankParam.itemNum != 2 || detailTab.dstRank != expectedSendPeer ||
325+ detailTab.srcRank != expectedRecvPeer) {
326+ HCCL_VM_ERROR("BatchSendRecv is not a valid ring at rank {}: itemNum={}, rankSize={}, "
327+ "sendPeer={}, recvPeer={}", detailTab.rankId, rankParam.itemNum, detailTab.rankSize,
328+ detailTab.dstRank, detailTab.srcRank);
281 return HcclResult::HCCL_E_PARA;329 return HcclResult::HCCL_E_PARA;
282 }330 }
283 rankParam.peerCount = detail.opV1.count;331 rankParam.peerCount = detail.opV1.count;
332+ rankParam.dataType = static_cast<HcclDataType>(detail.dataType);
333+ rankParam.sendPeer = detailTab.dstRank;
334+ rankParam.recvPeer = detailTab.srcRank;
284 m_checker_param.batchSendRecvRankParams[detailTab.rankId] = rankParam;335 m_checker_param.batchSendRecvRankParams[detailTab.rankId] = rankParam;
285 }336 }
286 337 
@@ -351,7 +402,7 @@ HcclResult StorageManager::FinalizeOpGroup()
351 case HcclCMDType::HCCL_CMD_REDUCE_SCATTER_V:402 case HcclCMDType::HCCL_CMD_REDUCE_SCATTER_V:
352 return FinalizeVDataDes(m_checker_param, false);403 return FinalizeVDataDes(m_checker_param, false);
353 case HcclCMDType::HCCL_CMD_BATCH_SEND_RECV:404 case HcclCMDType::HCCL_CMD_BATCH_SEND_RECV:
354- return FinalizeBatchSendRecv(m_checker_param);405+ return FinalizeBatchSendRecvRing(m_checker_param);
355 case HcclCMDType::HCCL_CMD_SEND:406 case HcclCMDType::HCCL_CMD_SEND:
356 case HcclCMDType::HCCL_CMD_RECEIVE:407 case HcclCMDType::HCCL_CMD_RECEIVE:
357 for (const auto &pair : m_checker_param.sendRecvPairs) {408 for (const auto &pair : m_checker_param.sendRecvPairs) {
@@ -506,34 +557,27 @@ HcclResult StorageManager::LoadHcclVmTaskMetaData(std::vector<std::vector<sim::O
506 }557 }
507 }558 }
508 m_taskMeataData = taskMeataData;559 m_taskMeataData = taskMeataData;
509- std::unordered_map<uint32_t, std::set<uint32_t>> notifyId2Ranks;560+ UpdateNotifyPeerRanks(m_taskMeataData);
510- for (auto &taskMeta : m_taskMeataData.task_meta) {561+ return HcclResult::HCCL_SUCCESS;
511- if (taskMeta.taskType == HccLTaskMetaType::NOTIFY_RECORD || taskMeta.taskType == HccLTaskMetaType::NOTIFY_WAIT) {562+}
512- uint64_t notifyId = taskMeta.taskData.notify.notifyId;563+ 
513- notifyId2Ranks[notifyId].insert(taskMeta.rankId);564+HcclResult StorageManager::LoadDecodedHcclVmTaskMetaData(
514- }565+ const std::vector<std::vector<HcclTaskMetaData>>& allTaskMetas)
515- }566+{
516- 567+ size_t totalTasks = 0;
517- // AICPU生成的Task需要更新Notify节点的对端信息568+ for (const auto &rankTaskMetas : allTaskMetas) {
518- for (auto &taskMeta : m_taskMeataData.task_meta) {569+ totalTasks += rankTaskMetas.size();
519- if (taskMeta.taskType != HccLTaskMetaType::NOTIFY_RECORD && taskMeta.taskType != HccLTaskMetaType::NOTIFY_WAIT) {570+ }
520- continue;571+ HCCL_VM_INFO("total decoded tasks: {}, ranks: {}", totalTasks, allTaskMetas.size());
521- }572+ 
522- uint32_t rankId = taskMeta.rankId;573+ HcclVmTaskMetaData taskMeataData;
523- for (auto id : notifyId2Ranks[taskMeta.taskData.notify.notifyId]) {574+ taskMeataData.task_meta.reserve(totalTasks);
524- if (id != rankId) {575+ for (const auto &rankTaskMetas : allTaskMetas) {
525- rankId = id;576+ taskMeataData.task_meta.insert(taskMeataData.task_meta.end(), rankTaskMetas.begin(), rankTaskMetas.end());
526- break;
527- }
528- }
529- 
530- if (taskMeta.taskType == HccLTaskMetaType::NOTIFY_RECORD) {
531- taskMeta.taskData.notify.dstRankId = rankId;
532- } else if (taskMeta.taskType == HccLTaskMetaType::NOTIFY_WAIT) {
533- taskMeta.taskData.notify.srcRankId = rankId;
534- }
535 }577 }
536 578 
579+ m_taskMeataData = std::move(taskMeataData);
580+ UpdateNotifyPeerRanks(m_taskMeataData);
537 return HcclResult::HCCL_SUCCESS;581 return HcclResult::HCCL_SUCCESS;
538}582}
539 583 
@@ -589,6 +633,7 @@ HcclResult StorageManager::GetSlice(uint64_t addr, uint64_t len, DataSlice& data
589 // 如果允许跨块,逻辑会更复杂,这里按单块逻辑处理633 // 如果允许跨块,逻辑会更复杂,这里按单块逻辑处理
590 634
591 dataSlice.SetBufferType(block.bufferType);635 dataSlice.SetBufferType(block.bufferType);
636+ dataSlice.SetRawAddr(addr);
592 // 核心转换公式:逻辑基址 + (物理地址 - 物理块基址)637 // 核心转换公式:逻辑基址 + (物理地址 - 物理块基址)
593 dataSlice.SetOffset(block.globalOffset + (addr - block.startAddr));638 dataSlice.SetOffset(block.globalOffset + (addr - block.startAddr));
594 if (rank != nullptr) {639 if (rank != nullptr) {
@@ -22,6 +22,7 @@
22#include "sim_common.h"22#include "sim_common.h"
23#include "sim_op_db_types.h"23#include "sim_op_db_types.h"
24#include "task_meta_defs.h"24#include "task_meta_defs.h"
25+#include "framework/task_graph_generator_v3/task_def_v3.h"
25 26 
26namespace HcclSim {27namespace HcclSim {
27struct MemBlock {28struct MemBlock {
@@ -48,6 +49,9 @@ struct SendRecvPairParam {
48struct BatchSendRecvRankParam {49struct BatchSendRecvRankParam {
49 uint32_t itemNum = 0;50 uint32_t itemNum = 0;
50 uint64_t peerCount = 0;51 uint64_t peerCount = 0;
52+ HcclDataType dataType = static_cast<HcclDataType>(0);
53+ uint32_t sendPeer = 0;
54+ uint32_t recvPeer = 0;
51};55};
52 56 
53struct CheckerParam {57struct CheckerParam {
@@ -78,6 +82,7 @@ using ChannelsPerDie = std::map<uint32_t, RemoteDieInfo>;
78 82 
79class StorageManager {83class StorageManager {
80public:84public:
85+ StorageManager() = default;
81 static StorageManager& GetInstance() {86 static StorageManager& GetInstance() {
82 static StorageManager instance;87 static StorageManager instance;
83 return instance;88 return instance;
@@ -101,10 +106,22 @@ public:
101 return m_checker_param;106 return m_checker_param;
102 }107 }
103 108 
109+ CheckerParam GetCheckerParam(TaskGraphGeneratorV3::OperatorId operatorId) const {
110+ std::lock_guard<std::mutex> lock(m_mutex);
111+ const auto it = m_checker_params.find(operatorId);
112+ return it == m_checker_params.end() ? m_checker_param : it->second;
113+ }
114+ 
115+ void SaveCheckerParam(TaskGraphGeneratorV3::OperatorId operatorId) {
116+ std::lock_guard<std::mutex> lock(m_mutex);
117+ m_checker_params[operatorId] = m_checker_param;
118+ }
119+ 
104 HcclResult LoadHcclVmSynthesisData(uint32_t rankId, sim::OpMemInfoTab memInfo, std::vector<sim::CcuChannelTab>& channels);120 HcclResult LoadHcclVmSynthesisData(uint32_t rankId, sim::OpMemInfoTab memInfo, std::vector<sim::CcuChannelTab>& channels);
105 HcclResult LoadHcclVmInstrData(std::vector<sim::CcuInstrResTab>& instrRes);121 HcclResult LoadHcclVmInstrData(std::vector<sim::CcuInstrResTab>& instrRes);
106 HcclResult LoadHcclVmTaskMetaData(std::vector<std::vector<sim::OpTaskTab>>& allTasks);122 HcclResult LoadHcclVmTaskMetaData(std::vector<std::vector<sim::OpTaskTab>>& allTasks);
107- void Reset();123+ HcclResult LoadDecodedHcclVmTaskMetaData(const std::vector<std::vector<HcclTaskMetaData>>& allTaskMetas);
124+ void Reset(bool clearMemLayout = true);
108 uint64_t GetBlockSize(uint32_t rankId, BufferType bufferType);125 uint64_t GetBlockSize(uint32_t rankId, BufferType bufferType);
109 HcclResult GetSlice(uint64_t addr, uint64_t len, DataSlice& dataSlice, uint32_t* rank = nullptr);126 HcclResult GetSlice(uint64_t addr, uint64_t len, DataSlice& dataSlice, uint32_t* rank = nullptr);
110 uint32_t GetRankSize() const;127 uint32_t GetRankSize() const;
@@ -122,8 +139,6 @@ public:
122 void MergeAll2AllVSendCountMatrix();139 void MergeAll2AllVSendCountMatrix();
123 140 
124private:141private:
125- StorageManager() = default;
126- 
127 std::string FindRootPath();142 std::string FindRootPath();
128 bool IsDirExists(const std::string& path);143 bool IsDirExists(const std::string& path);
129 144 
@@ -134,6 +149,7 @@ private:
134 std::map<uint32_t, std::map<BufferType, std::map<uint64_t, MemBlock>>> m_mem_layout;149 std::map<uint32_t, std::map<BufferType, std::map<uint64_t, MemBlock>>> m_mem_layout;
135 std::map<RankId, std::map<uint32_t, ChannelsPerDie>> m_allRankChannelInfo;150 std::map<RankId, std::map<uint32_t, ChannelsPerDie>> m_allRankChannelInfo;
136 CheckerParam m_checker_param;151 CheckerParam m_checker_param;
152+ std::map<TaskGraphGeneratorV3::OperatorId, CheckerParam> m_checker_params;
137 // 用于收集每一轮算子中所有rank的发送矩阵数据153 // 用于收集每一轮算子中所有rank的发送矩阵数据
138 std::map<uint32_t, std::vector<uint64_t>> m_all2AllvSendMatrices;154 std::map<uint32_t, std::vector<uint64_t>> m_all2AllvSendMatrices;
139 155 
@@ -36,9 +36,10 @@ target_compile_options(runner PRIVATE
36)36)
37 37 
38target_include_directories(runner PRIVATE38target_include_directories(runner PRIVATE
39- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include39+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include
40- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc40+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc
41- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl41+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl
42+ 
42 43
43 ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode44 ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode
44 45 
@@ -37,6 +37,7 @@ target_include_directories(hccl_proxy_level2 PRIVATE
37 ${HCOMM_VM_ROOT_PATH}/src/host/hccl_vm37 ${HCOMM_VM_ROOT_PATH}/src/host/hccl_vm
38 ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin38 ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin
39 ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin/checker/utils39 ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin/checker/utils
40+ ${HCOMM_VM_ROOT_PATH}/src/common
40)41)
41 42 
42target_include_directories(hccl_proxy_level2 PRIVATE43target_include_directories(hccl_proxy_level2 PRIVATE
@@ -125,6 +126,7 @@ target_compile_options(hccl_proxy_level2 PRIVATE
125target_link_libraries(hccl_proxy_level2 PRIVATE126target_link_libraries(hccl_proxy_level2 PRIVATE
126 -Wl,--whole-archive127 -Wl,--whole-archive
127 log128 log
129+ common
128 runnerdb130 runnerdb
129 modeldb131 modeldb
130 store132 store
@@ -134,11 +136,11 @@ target_link_libraries(hccl_proxy_level2 PRIVATE
134 rt136 rt
135 SQLite::SQLite3137 SQLite::SQLite3
136 JSON::JSON138 JSON::JSON
137- ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.a139+ ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/lib64/libc_sec.a
138)140)
139 141 
140install(TARGETS hccl_proxy_level2142install(TARGETS hccl_proxy_level2
141- DESTINATION "lib/x86_64"143+ DESTINATION "lib/${CMAKE_SYSTEM_PROCESSOR}"
142 # 文件的权限 (755)144 # 文件的权限 (755)
143 PERMISSIONS145 PERMISSIONS
144 OWNER_READ OWNER_WRITE OWNER_EXECUTE146 OWNER_READ OWNER_WRITE OWNER_EXECUTE
@@ -23,15 +23,19 @@
23#include "sim_common_macro.h"23#include "sim_common_macro.h"
24#include "sim_log.h"24#include "sim_log.h"
25#include "db_sim_runner_ops.h"25#include "db_sim_runner_ops.h"
26- 26+#include "db_sim_runner_common.h"
27 27 
28#ifdef __cplusplus28#ifdef __cplusplus
29extern "C" {29extern "C" {
30#endif // __cplusplus30#endif // __cplusplus
31aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId)31aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId)
32{32{
33+ auto serverId = sim::GetCurServerId();
34+ if (serverId == 0) {
35+ return ACL_ERROR_INVALID_PARAM;
36+ }
33 sim::Runner runner;37 sim::Runner runner;
34- if (!sim::GetCurrRunnerTls(0, runner)) {38+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
35 return ACL_ERROR_INVALID_PARAM;39 return ACL_ERROR_INVALID_PARAM;
36 }40 }
37 auto ret = RunnerDB::GetOneByPred<sim::Device>([deviceId](const sim::Device& d) {41 auto ret = RunnerDB::GetOneByPred<sim::Device>([deviceId](const sim::Device& d) {
@@ -83,8 +87,12 @@ aclError aclrtSetCurrentContext(aclrtContext context)
83 87 
84aclError aclrtGetCurrentContext(aclrtContext *context)88aclError aclrtGetCurrentContext(aclrtContext *context)
85{89{
90+ auto serverId = sim::GetCurServerId();
91+ if (serverId == 0) {
92+ return ACL_ERROR_INVALID_PARAM;
93+ }
86 sim::Runner runner;94 sim::Runner runner;
87- if (!sim::GetCurrRunnerTls(0, runner)) {95+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
88 return ACL_ERROR_INVALID_PARAM;96 return ACL_ERROR_INVALID_PARAM;
89 }97 }
90 *context = (aclrtContext)runner.current_ctx_id;98 *context = (aclrtContext)runner.current_ctx_id;
@@ -93,8 +101,12 @@ aclError aclrtGetCurrentContext(aclrtContext *context)
93 101 
94aclError aclrtCtxGetCurrentDefaultStream(aclrtStream *stream)102aclError aclrtCtxGetCurrentDefaultStream(aclrtStream *stream)
95{103{
104+ auto serverId = sim::GetCurServerId();
105+ if (serverId == 0) {
106+ return ACL_ERROR_INVALID_PARAM;
107+ }
96 sim::Runner runner;108 sim::Runner runner;
97- if (!sim::GetCurrRunnerTls(0, runner)) {109+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
98 return ACL_ERROR_INVALID_PARAM;110 return ACL_ERROR_INVALID_PARAM;
99 }111 }
100 auto curCtxId = runner.current_ctx_id;112 auto curCtxId = runner.current_ctx_id;
@@ -114,8 +126,12 @@ aclError aclrtGetPrimaryCtxState(int32_t deviceId, uint32_t *flags, int32_t *act
114{126{
115 (void) deviceId;127 (void) deviceId;
116 (void) flags;128 (void) flags;
129+ auto serverId = sim::GetCurServerId();
130+ if (serverId == 0) {
131+ return ACL_ERROR_INVALID_PARAM;
132+ }
117 sim::Runner runner;133 sim::Runner runner;
118- if (!sim::GetCurrRunnerTls(0, runner)) {134+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
119 return ACL_ERROR_INVALID_PARAM;135 return ACL_ERROR_INVALID_PARAM;
120 }136 }
121 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);137 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -27,6 +27,7 @@
27#include "runtime/base.h"27#include "runtime/base.h"
28#include "db_sim_runner_common.h"28#include "db_sim_runner_common.h"
29#include "db_sim_runner_ops.h"29#include "db_sim_runner_ops.h"
30+#include "sim_sub_process_manager.h"
30 31 
31// current host id32// current host id
32uint64_t g_host_id;33uint64_t g_host_id;
@@ -69,46 +70,57 @@ aclError aclrtSetDevice(int32_t deviceId)
69{70{
70 try {71 try {
71 HCCL_VM_DEBUG("set id:{:d}", deviceId);72 HCCL_VM_DEBUG("set id:{:d}", deviceId);
72- uint32_t rankId;73+ uint64_t serverId = sim::GetCurServerId();
73- uint64_t serverId = 0;74+ if (serverId == 0) {
74- if (!sim::GetRankIdByMPI(rankId, serverId)) {75+ HCCL_VM_ERROR("GetCurServerId failed");
75- HCCL_VM_ERROR("get rankId by MPI fail serverId:{:d}", serverId);
76 return ACL_ERROR_INVALID_PARAM;76 return ACL_ERROR_INVALID_PARAM;
77 }77 }
78 78 
79+ uint32_t rankId;
80+ uint64_t servId = 0;
81+ if (!sim::GetRankIdByMPI(rankId, servId)) {
82+ HCCL_VM_ERROR("get rankId by MPI fail servId:{:d}", servId);
83+ return 0;
84+ }
85+ 
79 sim::Device device{};86 sim::Device device{};
80- if (serverId == 0) {87+ auto ret = RunnerDB::GetOneByPred<sim::Device>([serverId, deviceId](const sim::Device &d) {
81- auto devRet = sim::GetDeviceByRankId(rankId, device);88+ return d.server_id == serverId && d.logic_id == (uint32_t)deviceId;
82- if (devRet != ACL_SUCCESS) {89+ });
83- HCCL_VM_ERROR("device not found by rankId:{:d}", rankId);90+ if (!ret.second) {
84- return devRet;91+ HCCL_VM_ERROR("device not found logicId:{:d} serverId:{:d}", deviceId, serverId);
85- }92+ return ACL_ERROR_INVALID_PARAM;
86- serverId = device.server_id;93+ }
87- HCCL_VM_DEBUG("logicId:{:d} rankId:{:d} key:{:d}", device.logic_id, rankId, device.id);94+ device = ret.first;
88- } else {95+ HCCL_VM_DEBUG("logicId:{:d} serverId:{:d} key:{:d}", device.logic_id, serverId, device.id);
89- auto ret = RunnerDB::GetOneByPred<sim::Device>([serverId, deviceId](const sim::Device &d) {96+ 
90- return d.server_id == serverId && d.logic_id == (uint32_t)deviceId;97+ uint64_t deviceKey = device.id;
91- });98+ SetDevIdPayload payload{};
92- if (!ret.second) {99+ payload.rankId = rankId;
93- HCCL_VM_ERROR("device not found logicId:{:d} serverId:{:d}", deviceId, serverId);100+ payload.deviceKey = deviceKey;
101+ uint8_t rspCmd;
102+ uint64_t rspPayload = 0xFF;
103+ uint32_t rspLen = 0;
104+ if (sim::GetAicpuProcMgr().IsAlive()) {
105+ if (sim::GetAicpuProcMgr().Request(PIPE_CMD_SET_DEV_ID, &payload, sizeof(payload),
106+ rspCmd, &rspPayload, sizeof(rspPayload), rspLen) != 0) {
107+ HCCL_VM_ERROR("Request PIPE_CMD_SET_DEV_ID failed.");
94 return ACL_ERROR_INVALID_PARAM;108 return ACL_ERROR_INVALID_PARAM;
95 }109 }
96- device = ret.first;110+ HCCL_VM_INFO("device rank id: {:d}, deviceKey: {:d}, set to sub process", rankId, deviceKey);
97- HCCL_VM_DEBUG("logicId:{:d} serverId:{:d} key:{:d}", device.logic_id, serverId, device.id);
98 }111 }
99 112 
100 sim::Runner runner{};113 sim::Runner runner{};
101 if (!sim::GetCurrRunnerTls(serverId, runner)) {114 if (!sim::GetCurrRunnerTls(serverId, runner)) {
102- return ACL_ERROR_INVALID_PARAM;115+ return ACL_ERROR_INVALID_PARAM;
103 }116 }
104 auto curRunnerId = runner.id;117 auto curRunnerId = runner.id;
105 118 
106 uint64_t currCtxId = 0;119 uint64_t currCtxId = 0;
107- uint64_t deviceKey = device.id;120+ auto ctxRet = RunnerDB::GetOneByPred<sim::Context>([deviceKey](const sim::Context &ctx) {
108- auto ret = RunnerDB::GetOneByPred<sim::Context>([deviceKey](const sim::Context &ctx) {
109 return ctx.device_id == deviceKey && ctx.is_default == 1;121 return ctx.device_id == deviceKey && ctx.is_default == 1;
110 });122 });
111- if (!ret.second) {123+ if (!ctxRet.second) {
112 sim::Context context{};124 sim::Context context{};
113 context.device_id = device.id;125 context.device_id = device.id;
114 context.run_id = curRunnerId;126 context.run_id = curRunnerId;
@@ -122,9 +134,8 @@ aclError aclrtSetDevice(int32_t deviceId)
122 stream.is_primary_default = 1;134 stream.is_primary_default = 1;
123 RunnerDB::Add<sim::Stream>(stream);135 RunnerDB::Add<sim::Stream>(stream);
124 } else {136 } else {
125- currCtxId = ret.first.id;137+ currCtxId = ctxRet.first.id;
126 RunnerDB::Update<sim::Context>(currCtxId, [](sim::Context &ctx) { ctx.ref_cnt++;});138 RunnerDB::Update<sim::Context>(currCtxId, [](sim::Context &ctx) { ctx.ref_cnt++;});
127- currCtxId = ret.first.id;
128 }139 }
129 140 
130 sim::SetCurrCtxTls(currCtxId);141 sim::SetCurrCtxTls(currCtxId);
@@ -139,8 +150,12 @@ aclError aclrtResetDevice(int32_t deviceId)
139{150{
140 try {151 try {
141 HCCL_VM_INFO("deviceId:{:d}", deviceId);152 HCCL_VM_INFO("deviceId:{:d}", deviceId);
153+ auto serverId = sim::GetCurServerId();
154+ if (serverId == 0){
155+ return ACL_ERROR_INVALID_PARAM;
156+ }
142 sim::Runner runner{};157 sim::Runner runner{};
143- if (!sim::GetCurrRunnerTls(0, runner)) {158+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
144 return ACL_ERROR_INVALID_PARAM;159 return ACL_ERROR_INVALID_PARAM;
145 }160 }
146 auto curCtxId = runner.current_ctx_id;161 auto curCtxId = runner.current_ctx_id;
@@ -182,7 +197,11 @@ aclError aclrtResetDeviceForce(int32_t deviceId)
182 try {197 try {
183 HCCL_VM_DEBUG("stream not found deviceId:{:d}", deviceId);198 HCCL_VM_DEBUG("stream not found deviceId:{:d}", deviceId);
184 sim::Runner runner{};199 sim::Runner runner{};
185- if (!sim::GetCurrRunnerTls(0, runner)) {200+ auto serverId = sim::GetCurServerId();
201+ if (serverId == 0) {
202+ return ACL_ERROR_INVALID_PARAM;
203+ }
204+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
186 return ACL_ERROR_INVALID_PARAM;205 return ACL_ERROR_INVALID_PARAM;
187 }206 }
188 auto curCtxId = runner.current_ctx_id;207 auto curCtxId = runner.current_ctx_id;
@@ -218,7 +237,11 @@ aclError aclrtGetDevice(int32_t* device)
218{237{
219 try {238 try {
220 sim::Runner runner{};239 sim::Runner runner{};
221- if (!sim::GetCurrRunnerTls(0, runner)) {240+ auto serverId = sim::GetCurServerId();
241+ if (serverId == 0) {
242+ return ACL_ERROR_INVALID_PARAM;
243+ }
244+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
222 return ACL_ERROR_INVALID_PARAM;245 return ACL_ERROR_INVALID_PARAM;
223 }246 }
224 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);247 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -255,7 +278,11 @@ aclError aclrtSetTsDevice(aclrtTsId tsId)
255 }278 }
256 279 
257 sim::Runner runner{};280 sim::Runner runner{};
258- if (!sim::GetCurrRunnerTls(0, runner)) {281+ auto serverId = sim::GetCurServerId();
282+ if (serverId == 0) {
283+ return ACL_ERROR_INVALID_PARAM;
284+ }
285+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
259 return ACL_ERROR_INVALID_PARAM;286 return ACL_ERROR_INVALID_PARAM;
260 }287 }
261 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);288 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -285,9 +312,14 @@ aclError aclrtSetTsDevice(aclrtTsId tsId)
285aclError aclrtGetDeviceCount(uint32_t *count)312aclError aclrtGetDeviceCount(uint32_t *count)
286{313{
287 try {314 try {
288- auto devs = RunnerDB::GetByPred<sim::Device>([](const sim::Device& d) {315+ uint64_t serverId = sim::GetCurServerId();
289- return d.status == 0;316+ if (serverId == 0) {
290- });317+ HCCL_VM_ERROR("GetCurServerId failed");
318+ return ACL_ERROR_INVALID_PARAM;
319+ }
320+ auto devs = RunnerDB::GetByPred<sim::Device>([serverId](const sim::Device& d) {
321+ return d.status == 1 && d.server_id == serverId;
322+ });
291 323 
292 if (devs.empty()) {324 if (devs.empty()) {
293 HCCL_VM_ERROR("devices not found");325 HCCL_VM_ERROR("devices not found");
@@ -369,7 +401,12 @@ aclError aclrtSetDeviceSatMode(aclrtFloatOverflowMode mode)
369{401{
370 try {402 try {
371 sim::Runner runner{};403 sim::Runner runner{};
372- if (!sim::GetCurrRunnerTls(0, runner)) {404+ uint64_t serverId = sim::GetCurServerId();
405+ if (serverId == 0) {
406+ HCCL_VM_ERROR("GetCurServerId failed");
407+ return ACL_ERROR_INVALID_PARAM;
408+ }
409+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
373 return ACL_ERROR_INVALID_PARAM;410 return ACL_ERROR_INVALID_PARAM;
374 }411 }
375 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);412 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -391,7 +428,12 @@ aclError aclrtGetDeviceSatMode(aclrtFloatOverflowMode *mode)
391{428{
392 try {429 try {
393 sim::Runner runner{};430 sim::Runner runner{};
394- if (!sim::GetCurrRunnerTls(0, runner)) {431+ uint64_t serverId = sim::GetCurServerId();
432+ if (serverId == 0) {
433+ HCCL_VM_ERROR("GetCurServerId failed");
434+ return ACL_ERROR_INVALID_PARAM;
435+ }
436+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
395 return ACL_ERROR_INVALID_PARAM;437 return ACL_ERROR_INVALID_PARAM;
396 }438 }
397 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);439 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -456,7 +498,12 @@ aclError aclrtDeviceEnablePeerAccess(int32_t peerDeviceId, uint32_t flags)
456 (void) flags;498 (void) flags;
457 try {499 try {
458 sim::Runner runner{};500 sim::Runner runner{};
459- if (!sim::GetCurrRunnerTls(0, runner)) {501+ uint64_t serverId = sim::GetCurServerId();
502+ if (serverId == 0) {
503+ HCCL_VM_ERROR("GetCurServerId failed");
504+ return ACL_ERROR_INVALID_PARAM;
505+ }
506+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
460 return ACL_ERROR_INVALID_PARAM;507 return ACL_ERROR_INVALID_PARAM;
461 }508 }
462 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);509 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -506,7 +553,12 @@ aclError aclrtDeviceDisablePeerAccess(int32_t peerDeviceId)
506{553{
507 try {554 try {
508 sim::Runner runner{};555 sim::Runner runner{};
509- if (!sim::GetCurrRunnerTls(0, runner)) {556+ uint64_t serverId = sim::GetCurServerId();
557+ if (serverId == 0) {
558+ HCCL_VM_ERROR("GetCurServerId failed");
559+ return ACL_ERROR_INVALID_PARAM;
560+ }
561+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
510 return ACL_ERROR_INVALID_PARAM;562 return ACL_ERROR_INVALID_PARAM;
511 }563 }
512 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);564 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -705,16 +757,24 @@ aclError aclrtDevicePeerAccessStatus(int32_t deviceId, int32_t peerDeviceId, int
705aclError aclInit(const char *configPath)757aclError aclInit(const char *configPath)
706{758{
707 HCCL_VM_INFO("-----[acl start]----------");759 HCCL_VM_INFO("-----[acl start]----------");
708- (void) configPath;760+ const char *expanEnv = std::getenv("HCCL_OP_EXPANSION_MODE");
761+ bool aicpuMode = (expanEnv != nullptr) && (std::string(expanEnv) == "AI_CPU");
762+ if (aicpuMode) {
763+ auto config = sim::CreateAicpuDeviceConfig(0);
764+ if (sim::GetAicpuProcMgr().CreateProcess(config) != 0) {
765+ HCCL_VM_ERROR("failed to create device process.");
766+ exit(EXIT_FAILURE);
767+ }
768+ }
769+ 
770+ HCCL_VM_INFO("Success exp mode:{}", expanEnv ? expanEnv : "");
709 return ACL_SUCCESS;771 return ACL_SUCCESS;
710}772}
711 773 
712aclError aclFinalize()774aclError aclFinalize()
713{775{
714- if (g_devicePid != 0) {
715- kill(g_devicePid, SIGKILL);
716- }
717 HCCL_VM_INFO("-----[acl finalize]----------");776 HCCL_VM_INFO("-----[acl finalize]----------");
777+ sim::GetAicpuProcMgr().DestroyProcess();
718 FlushLog();778 FlushLog();
719 return ACL_SUCCESS;779 return ACL_SUCCESS;
720}780}
@@ -23,6 +23,7 @@
23#include "acl/acl_rt.h"23#include "acl/acl_rt.h"
24#include "sim_log.h"24#include "sim_log.h"
25#include "db_sim_runner_ops.h"25#include "db_sim_runner_ops.h"
26+#include "db_sim_runner_common.h"
26 27 
27 28 
28#ifdef __cplusplus29#ifdef __cplusplus
@@ -32,7 +33,12 @@ extern "C" {
32aclError aclrtCreateEventWithFlag(aclrtEvent *event, uint32_t flag)33aclError aclrtCreateEventWithFlag(aclrtEvent *event, uint32_t flag)
33{34{
34 sim::Runner runner;35 sim::Runner runner;
35- if (!sim::GetCurrRunnerTls(0, runner)) {36+ uint64_t serverId = sim::GetCurServerId();
37+ if (serverId == 0) {
38+ HCCL_VM_ERROR("GetCurServerId failed");
39+ return ACL_ERROR_INVALID_PARAM;
40+ }
41+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
36 return ACL_ERROR_INVALID_PARAM;42 return ACL_ERROR_INVALID_PARAM;
37 }43 }
38 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);44 auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id);
@@ -186,7 +192,12 @@ aclError aclrtGetEventId(aclrtEvent event, uint32_t *eventId)
186aclError aclrtGetEventAvailNum(uint32_t *eventCount)192aclError aclrtGetEventAvailNum(uint32_t *eventCount)
187{193{
188 sim::Runner runner;194 sim::Runner runner;
189- if (!sim::GetCurrRunnerTls(0, runner)) {195+ uint64_t serverId = sim::GetCurServerId();
196+ if (serverId == 0) {
197+ HCCL_VM_ERROR("GetCurServerId failed");
198+ return ACL_ERROR_INVALID_PARAM;
199+ }
200+ if (!sim::GetCurrRunnerTls(serverId, runner)) {
190 return ACL_ERROR_INVALID_PARAM;201 return ACL_ERROR_INVALID_PARAM;
191 }202 }
192 if (runner.current_ctx_id == 0) {203 if (runner.current_ctx_id == 0) {