已合并
同步 CheckerL2 最新代码到 hccl_vm #4305
git_qk创建于 7月31日
同步 CheckerL2 最新代码到 hccl_vm #4305
已合并
共 105 个文件变更+4603-975
| @@ -41,6 +41,13 @@ if(NOT DEFINED ASCEND_CANN_PACKAGE_PATH) | |||
| 41 | endif() | 41 | endif() |
| 42 | message(STATUS "ASCEND_CANN_PACKAGE_PATH: ${ASCEND_CANN_PACKAGE_PATH}") | 42 | message(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 | + | ||
| 44 | if(BUILD_DEVICE_ARM) | 51 | if(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` 命令进行安装 | |||
| 677 | Checker插件,即算法分析器插件:功能是将hccl生成的所有task形成一个DAG图,并且通过分析DAG图,判断是否存在内存冲突;通过模拟执行DAG图,判断是否存在语义错误等问题。 | 677 | Checker插件,即算法分析器插件:功能是将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 | ```bash | 682 | ```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 | ```bash | 773 | ```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_PATH | 102 | # 5.获得CANN安装目录: ASCEND_INSTALL_PATH |
| 103 | ASCEND_INSTALL_PATH=$(dirname "$ASCEND_HOME_PATH") | 103 | ASCEND_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 | + | ||
| 105 | echo "--- 环境变量解析成功 ---" | 115 | echo "--- 环境变量解析成功 ---" |
| 106 | echo "HCCL_VM_PATH: $HCCL_VM_PATH" | 116 | echo "HCCL_VM_PATH: $HCCL_VM_PATH" |
| 107 | echo "ASCEND_INSTALL_PATH: $ASCEND_INSTALL_PATH" | 117 | echo "ASCEND_INSTALL_PATH: $ASCEND_INSTALL_PATH" |
| @@ -132,7 +142,7 @@ if [ "$BUILD_HCOMM" = true ]; then | |||
| 132 | if [ $? -eq 0 ]; then | 142 | 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" ]; then | 148 | if [ ! -f "$CANN_HCOMM_PACKAGE" ]; then |
| @@ -161,7 +171,7 @@ if [ "$BUILD_HCCL" = true ]; then | |||
| 161 | if [ $? -eq 0 ]; then | 171 | 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" ]; then | 177 | 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 文件全路径(收尾 | |||
| 67 | CANN_CHANNEL="master" # CANN 镜像下载通道,apply_defaults 按 profile 落定(campus=legacy / main=master) | 68 | CANN_CHANNEL="master" # CANN 镜像下载通道,apply_defaults 按 profile 落定(campus=legacy / main=master) |
| 68 | HCCL_TEST_RESULT="" # build_hccl_test 写入:built | skipped | failed:<原因> | 69 | HCCL_TEST_RESULT="" # build_hccl_test 写入:built | skipped | failed:<原因> |
| 69 | HCCL_TEST_BIN_DIR="" # build_hccl_test 写入:hccl_test 可执行文件所在目录(原地编译) | 70 | HCCL_TEST_BIN_DIR="" # build_hccl_test 写入:hccl_test 可执行文件所在目录(原地编译) |
| 71 | +PKG_MGR="" # detect_pkg_mgr 写入:apt(Ubuntu/Debian)或 dnf(HCE/openEuler/EulerOS) | ||
| 70 | SUDO_PREFIX="" # setup_sudo 解析:root 为空;非 root 有 sudo 为 "sudo" | 72 | SUDO_PREFIX="" # setup_sudo 解析:root 为空;非 root 有 sudo 为 "sudo" |
| 71 | SUDO_KEEPALIVE_PID="" # sudo 授权保活后台进程 PID(cleanup_sudo 负责回收) | 73 | SUDO_KEEPALIVE_PID="" # sudo 授权保活后台进程 PID(cleanup_sudo 负责回收) |
| 72 | STEP_TOTAL=9 # 编译 HCCL-VM(7) → 编译安装子包(8) → 编译 hccl_test(9) | 74 | STEP_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 ]; then | 138 | if [ "${HCCL_TEST_RESULT}" = built ]; then |
| 133 | info "后续步骤(可直接复制,运行一个 hccl_test 用例并由 checker 校验):" | 139 | info "后续步骤(可直接复制,运行一个 hccl_test 用例并由 checker 校验):" |
| 134 | echo " source ${setenv}" >&2 | 140 | echo " source ${setenv}" >&2 |
| 135 | echo " source ${inst}/script/hccl_config.sh # 设 RANK_TABLE_FILE 等运行变量" >&2 | 141 | 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" >&2 | 142 | echo " cd ${inst}/bin && ./hccl-vm start ascend950_cluster_32_server_normal.yaml" >&2 |
| 137 | echo " (hvm)\$> hccl-vm mock-comm 112" >&2 | 143 | 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" >&2 | 144 | + 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" >&2 | 145 | echo " (hvm)\$> hccl-vm plugin run @checker" >&2 |
| 140 | echo " (hvm)\$> exit" >&2 | 146 | echo " (hvm)\$> exit" >&2 |
| 141 | else | 147 | else |
| @@ -149,11 +155,29 @@ success_summary() { | |||
| 149 | fi | 155 | 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 后使用。 | ||
| 153 | check_package() { | 160 | check_package() { |
| 154 | - local status | 161 | + if [ "${PKG_MGR:-}" = "apt" ]; then |
| 155 | - status="$(dpkg-query -W -f='${Status}' "$1" 2>/dev/null)" || return 1 | 162 | + 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 0 | 451 | return 0 |
| 428 | } | 452 | } |
| 429 | 453 | ||
| 430 | -# 运行环境自检:必须 Linux + 具备 apt + 受支持架构 | 454 | +# 运行环境自检:必须 Linux + 具备 apt 或 dnf + 受支持架构(x86_64 / aarch64) |
| 431 | check_env() { | 455 | check_env() { |
| 432 | if ! is_supported_os "$(uname -s)"; then | 456 | if ! is_supported_os "$(uname -s)"; then |
| 433 | error "本工具仅支持 Linux。Windows 请在 WSL2 或远端 Linux 中运行。" | 457 | error "本工具仅支持 Linux。Windows 请在 WSL2 或远端 Linux 中运行。" |
| 434 | fi | 458 | fi |
| 435 | - if ! command -v apt-get &> /dev/null; then | 459 | + # 检测包管理器: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 | fi | 465 | fi |
| 440 | if ! normalize_arch "$(uname -m)" &> /dev/null; then | 466 | 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 | fi | 468 | fi |
| 443 | - # 非官方验证环境软警告(不阻断):官方仅验证 x86_64 Ubuntu 22.04+ | 469 | + # 非受支持架构软警告(不阻断):仅 x86_64 / aarch64 为受支持架构,其他架构报错已在上面处理 |
| 444 | - if [ "$(uname -m)" != "x86_64" ]; then | 470 | + # Ubuntu 版本检查仅对 apt 系有意义;dnf 系(HCE/openEuler)无 Ubuntu 版本号,跳过 |
| 445 | - warn "当前架构 $(uname -m) 非官方验证环境(官方仅验证 x86_64);可继续,但编译失败概率较高,出问题请优先换 x86_64。" | 471 | + if [ "${PKG_MGR}" = "apt" ] && ! ubuntu_version_ok; then |
| 446 | - fi | 472 | + warn "当前系统非 Ubuntu 22.04+(官方验证 x86_64 / aarch64 Ubuntu 22.04+);可继续,但遇到编译问题请优先换官方环境。" |
| 447 | - if ! ubuntu_version_ok; then | ||
| 448 | - warn "当前系统非 Ubuntu 22.04+(官方仅验证该版本);可继续,但遇到编译问题请优先换官方环境。" | ||
| 449 | fi | 473 | 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.04 | 475 | + # 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_major | 479 | 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; then | 481 | if [ -n "${_gcc_major}" ] && [ "${_gcc_major}" -ge 15 ] 2>/dev/null; then |
| @@ -488,12 +513,12 @@ check_env() { | |||
| 488 | fi | 513 | fi |
| 489 | # 管道模式(curl|bash)下 stdin 非终端:明确非交互 | 514 | # 管道模式(curl|bash)下 stdin 非终端:明确非交互 |
| 490 | if [ ! -t 0 ]; then | 515 | if [ ! -t 0 ]; then |
| 491 | - info "检测到管道模式(curl|bash):apt 依赖自动安装;需确认的操作会在检测到终端时提示(超时按默认值继续),无终端时按默认值自动执行。" | 516 | + info "检测到管道模式(curl|bash):系统依赖自动安装(${PKG_MGR});需确认的操作会在检测到终端时提示(超时按默认值继续),无终端时按默认值自动执行。" |
| 492 | fi | 517 | fi |
| 493 | cann_phase1_decide | 518 | 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)调用 |
| 497 | ubuntu_version_ok() { | 522 | ubuntu_version_ok() { |
| 498 | local id ver_major | 523 | local id ver_major |
| 499 | [ -r /etc/os-release ] || return 1 | 524 | [ -r /etc/os-release ] || return 1 |
| @@ -556,23 +581,38 @@ pick_qemu_pkg() { | |||
| 556 | fi | 581 | fi |
| 557 | } | 582 | } |
| 558 | 583 | ||
| 559 | -# 依赖清单:编译基础包 + 运行时 python-yaml(hccl-vm start 生成组网拓扑需) + 仅 x86_64 宿主需要的 device(arm) 交叉编译工具链 | 584 | +# 依赖清单:编译基础包 + 运行时 python-yaml(hccl-vm start 生成组网拓扑需);按 PKG_MGR 输出对应包名。 |
| 560 | -# sudo:build_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 环境需补装。 | ||
| 561 | dependency_list() { | 588 | dependency_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" ]; then | 593 | + # 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 | fi | 606 | 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 统一刷新。 |
| 575 | ensure_universe_enabled() { | 614 | ensure_universe_enabled() { |
| 615 | + [ "${PKG_MGR:-}" = "apt" ] || return 0 # dnf 系无需处理,直接返回 | ||
| 576 | local apt_prefix="$1" apt_log="$2" cand base_line | 616 | 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 | fi | 635 | fi |
| 596 | } | 636 | } |
| 597 | 637 | ||
| 598 | -# 安装第三方依赖 | 638 | +# 安装第三方依赖:按 PKG_MGR 走 apt 或 dnf 分支 |
| 599 | install_deps() { | 639 | install_deps() { |
| 600 | info "检查第三方依赖..." | 640 | info "检查第三方依赖..." |
| 601 | local dependencies=() dep_line | 641 | 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}" ]; then | 659 | + if [ "$(id -u)" -ne 0 ] && [ -z "${pkg_prefix}" ]; then |
| 620 | warn "缺少系统依赖,但当前非 root 且无 sudo,无法自动安装:" | 660 | warn "缺少系统依赖,但当前非 root 且无 sudo,无法自动安装:" |
| 621 | echo " ${missing_deps[*]}" >&2 | 661 | echo " ${missing_deps[*]}" >&2 |
| 622 | echo " 请让管理员安装后重试,或改用 root 运行,或手动执行:" >&2 | 662 | echo " 请让管理员安装后重试,或改用 root 运行,或手动执行:" >&2 |
| 623 | - echo " sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}" >&2 | 663 | + 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 1 | 668 | exit 1 |
| 625 | fi | 669 | 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=0 | 677 | local rc=0 |
| 634 | - if [ "${VERBOSE}" = true ]; then | 678 | + 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}"; then | 680 | + if { ${pkg_prefix} apt-get update -y \ |
| 637 | - rc=0 | 681 | + && ${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 | else | 686 | 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 | fi | 692 | fi |
| 641 | else | 693 | 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 | fi | 707 | fi |
| 648 | if [ "${rc}" -ne 0 ]; then | 708 | if [ "${rc}" -ne 0 ]; then |
| 649 | warn "依赖安装失败,末尾日志:" | 709 | warn "依赖安装失败,末尾日志:" |
| 650 | - tail -n 20 "${apt_log}" >&2 | 710 | + tail -n 20 "${pkg_log}" >&2 |
| 651 | echo " 仍无法解决可带完整日志到 https://gitcode.com/cann/hcomm/issues 反馈。" >&2 | 711 | echo " 仍无法解决可带完整日志到 https://gitcode.com/cann/hcomm/issues 反馈。" >&2 |
| 652 | - error "apt 安装依赖失败,请检查网络 / apt 源 / 磁盘 / apt 锁后重试(完整日志: ${apt_log})。" | 712 | + error "${PKG_MGR} 安装依赖失败,请检查网络 / 源 / 磁盘 / 锁后重试(完整日志: ${pkg_log})。" |
| 653 | fi | 713 | 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;否则只取正式发布版) |
| 763 | pick_toolkit_file() { | 823 | pick_toolkit_file() { |
| 764 | - local snap="$1" allow_weekly="${2:-false}" base all file | 824 | + 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)" || true | 827 | + all="$(curl -fsSL "${base}/" 2>/dev/null | grep -oE "Ascend-cann-toolkit_[^\"< ]*linux-${arch}\\.run" | sort -u)" || true |
| 767 | if [ "${allow_weekly}" = true ]; then | 828 | 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 | else | 832 | 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 | fi | 835 | fi |
| 775 | [ -n "${file}" ] || return 1 | 836 | [ -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}")" || true | 1063 | 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}" total | 1069 | local url="${base}/${file}" total |
| @@ -1134,6 +1197,7 @@ build_hccl_vm() { | |||
| 1134 | echo " ① 第三方库下载失败(网络/SSL):已清理下载缓存,重跑本脚本即可重新下载;" >&2 | 1197 | 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)运行;" >&2 | 1198 | 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/ ;" >&2 | 1199 | 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 反馈。" >&2 | 1201 | echo " 仍无法解决可带完整日志到 https://gitcode.com/cann/hcomm/issues 反馈。" >&2 |
| 1138 | clean_thirdparty_dl_cache | 1202 | clean_thirdparty_dl_cache |
| 1139 | error "编译未通过(完整日志: ${build_log})。" | 1203 | error "编译未通过(完整日志: ${build_log})。" |
| @@ -1230,17 +1294,81 @@ build_hccl_test() { | |||
| 1230 | fi | 1294 | fi |
| 1231 | chmod -R u+w "${work}" 2>/dev/null || true | 1295 | 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; then | 1298 | + # 首次运行:把已污染的 Makefile 清理为干净状态(-lmpi_cxxcxx / -lmpicxxcxx 等所有历史残留均消除), |
| 1235 | - sed -i 's/-lmpi/-lmpi -lmpi_cxx/g' "${work}/Makefile" 2>/dev/null || true | 1299 | + # 保存为 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 | fi | 1317 | fi |
| 1237 | mkdir -p "${LOG_DIR}" | 1318 | mkdir -p "${LOG_DIR}" |
| 1238 | local ht_log="${LOG_DIR}/hccl_test-build-${RUN_TS}.log" rc=0 | 1319 | 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); | |||
| 36 | int GetRankIdByDeviceId(uint32_t deviceId); | 36 | int GetRankIdByDeviceId(uint32_t deviceId); |
| 37 | bool ResetAllDeviceLogicId(); | 37 | bool ResetAllDeviceLogicId(); |
| 38 | bool GetRankIdByMPI(uint32_t &rankId, uint64_t &serverId); | 38 | bool GetRankIdByMPI(uint32_t &rankId, uint64_t &serverId); |
| 39 | +uint64_t GetCurServerId(); | ||
| 39 | } | 40 | } |
| 40 | 41 | ||
| @@ -271,14 +271,18 @@ enum VirMemType { | |||
| 271 | 271 | ||
| 272 | typedef struct { | 272 | typedef 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: device | 283 | + uint8_t src_type; // 0: host, 1: device |
| 280 | uint8_t policy; | 284 | uint8_t policy; |
| 281 | - uint8_t is_freed; // 0: using, 1: freed | 285 | + uint8_t is_freed; // 0: using, 1: freed |
| 282 | } VirtualMemBlock; | 286 | } VirtualMemBlock; |
| 283 | 287 | ||
| 284 | typedef struct { | 288 | typedef 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 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 | + | ||
| 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 | + | ||
| 72 | + | ||
| 73 | + | ||
| @@ -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 | 330 | ||
| 347 | 331 | ||
| 348 | enum BufferType { | 332 | enum BufferType { |
| @@ -263,7 +263,7 @@ build_hccl_test() { | |||
| 263 | if ! grep -q '\-lmpi_cxx' Makefile; then | 263 | if ! grep -q '\-lmpi_cxx' Makefile; then |
| 264 | sed -i 's/-lmpi/-lmpi -lmpi_cxx/g' Makefile | 264 | sed -i 's/-lmpi/-lmpi -lmpi_cxx/g' Makefile |
| 265 | fi | 265 | 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_inc | 42 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc |
| 43 | ${ASCEND_CANN_PACKAGE_PATH}/include | 43 | ${ASCEND_CANN_PACKAGE_PATH}/include |
| 44 | ${ASCEND_CANN_PACKAGE_PATH}/include/hccl | 44 | ${ASCEND_CANN_PACKAGE_PATH}/include/hccl |
| 45 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/toolchain | 45 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/toolchain |
| 46 | 46 | ||
| 47 | # cann包头文件 | 47 | # cann包头文件 |
| 48 | ${ASCEND_CANN_PACKAGE_PATH}/include/driver | 48 | ${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_inc | 39 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc |
| 40 | ${ASCEND_CANN_PACKAGE_PATH}/include | 40 | ${ASCEND_CANN_PACKAGE_PATH}/include |
| 41 | ${ASCEND_CANN_PACKAGE_PATH}/include/hccl | 41 | ${ASCEND_CANN_PACKAGE_PATH}/include/hccl |
| 42 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/toolchain | 42 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/toolchain |
| 43 | 43 | ||
| 44 | ${ASCEND_CANN_PACKAGE_PATH}/include/driver | 44 | ${ASCEND_CANN_PACKAGE_PATH}/include/driver |
| 45 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/trace | 45 | ${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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 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 | + | ||
| @@ -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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 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 | + | ||
| @@ -52,7 +52,8 @@ add_executable(device | |||
| 52 | main.cc | 52 | main.cc |
| 53 | hccl_device_pub.cc | 53 | hccl_device_pub.cc |
| 54 | hccl_task_collection.cc | 54 | hccl_task_collection.cc |
| 55 | - hccl_kernel_executor.cc | 55 | + sim_aicpu_pipe_handler.cc |
| 56 | + sim_kernel_lib_mgr.cc | ||
| 56 | ${HCCL_VM_SRC}/store/store_sim_memory_manager.cc | 57 | ${HCCL_VM_SRC}/store/store_sim_memory_manager.cc |
| 57 | ${HCCL_VM_SRC}/store/store_sim_shm_ops.cc | 58 | ${HCCL_VM_SRC}/store/store_sim_shm_ops.cc |
| 58 | ${HCCL_VM_SRC}/runnerdb/tracedb/db_sim_sqlite_db.cc | 59 | ${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.cc | 65 | ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_op_db_ops.cc |
| 65 | ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_factory.cc | 66 | ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_factory.cc |
| 66 | ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_sqlite.cc | 67 | ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_db_sqlite.cc |
| 68 | + ${HCCL_VM_SRC}/common/sim_pipe_io.cc | ||
| 67 | ) | 69 | ) |
| 68 | 70 | ||
| 69 | target_link_libraries(device PRIVATE | 71 | target_link_libraries(device PRIVATE |
| @@ -79,22 +81,24 @@ target_include_directories(device PRIVATE | |||
| 79 | ${HCCL_CODE_ROOT}/src/common | 81 | ${HCCL_CODE_ROOT}/src/common |
| 80 | ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym | 82 | ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym |
| 81 | ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym/ccu | 83 | ${HCCL_CODE_ROOT}/src/common/hcomm_dlsym/ccu |
| 82 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc | 84 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc |
| 83 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl | 85 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl |
| 84 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include | 86 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include |
| 85 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/hccl | 87 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/hccl |
| 86 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/base | 88 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/base |
| 87 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/hcomm/ccu | 89 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/hcomm/ccu |
| 88 | 90 | ||
| 89 | ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode | 91 | ${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}/store | 95 | ${HCCL_VM_INCLUDE}/store |
| 93 | ${HCCL_VM_INCLUDE}/runnerdb | 96 | ${HCCL_VM_INCLUDE}/runnerdb |
| 94 | 97 | ||
| 95 | ${HCCL_VM_SRC}/utils | 98 | ${HCCL_VM_SRC}/utils |
| 96 | ${HCCL_VM_SRC}/device_arm | 99 | ${HCCL_VM_SRC}/device_arm |
| 97 | ${HCCL_VM_SRC}/runnerdb/modeldb | 100 | ${HCCL_VM_SRC}/runnerdb/modeldb |
| 101 | + ${HCCL_VM_SRC}/common | ||
| 98 | ${THRID_PARTY_DIR} | 102 | ${THRID_PARTY_DIR} |
| 99 | ${THRID_PARTY_DIR}/spdlog | 103 | ${THRID_PARTY_DIR}/spdlog |
| 100 | ) | 104 | ) |
| @@ -122,7 +126,6 @@ endif() | |||
| 122 | target_compile_options(device PRIVATE | 126 | target_compile_options(device PRIVATE |
| 123 | -O0 | 127 | -O0 |
| 124 | -g | 128 | -g |
| 125 | - -rdynamic | ||
| 126 | -D_GLIBCXX_USE_CXX11_ABI=0 | 129 | -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_CONFIG | 131 | -DNO_YAML_CONFIG |
| @@ -12,13 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 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; | ||
| 22 | constexpr uint32_t HCOMID_MAX_SIZE = 128; | 16 | constexpr uint32_t HCOMID_MAX_SIZE = 128; |
| 23 | 17 | ||
| 24 | constexpr uint32_t P2P_MAX_ARG_SIZE_STUB = 8192; | 18 | constexpr uint32_t P2P_MAX_ARG_SIZE_STUB = 8192; |
| @@ -51,6 +45,7 @@ struct HDCommunicateParams { | |||
| 51 | 45 | ||
| 52 | struct DevAicpuCommConfig { | 46 | struct DevAicpuCommConfig { |
| 53 | bool taskExceptionEnable{true}; | 47 | bool taskExceptionEnable{true}; |
| 48 | + uint32_t notifyWaitTimeout{1836}; | ||
| 54 | // 如要新增配置类字段,在此处添加 | 49 | // 如要新增配置类字段,在此处添加 |
| 55 | }; | 50 | }; |
| 56 | struct CommAicpuParam { | 51 | struct 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 | - | ||
| 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 | - | ||
| 143 | - | ||
| 144 | 63 | ||
| @@ -10,10 +10,12 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 13 | 14 | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 18 | + | ||
| 17 | 19 | ||
| 18 | 20 | ||
| 19 | 21 | ||
| @@ -26,17 +28,20 @@ | |||
| 26 | 28 | ||
| 27 | 29 | ||
| 28 | 30 | ||
| 31 | + | ||
| 29 | 32 | ||
| 30 | 33 | ||
| 31 | extern "C" { | 34 | extern "C" { |
| 32 | 35 | ||
| 33 | 36 | ||
| 34 | uint32_t g_rankId = 0; | 37 | uint32_t g_rankId = 0; |
| 38 | +uint32_t g_deviceKey = 0; | ||
| 35 | 39 | ||
| 36 | char g_crash_file_name[64] = "crash_default.log"; | 40 | char g_crash_file_name[64] = "crash_default.log"; |
| 37 | 41 | ||
| 38 | HcclVmResult SetCurRankId(uint32_t rankId) | 42 | HcclVmResult 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 | + | ||
| 50 | uint8_t sqBuffer[HCCL_SQE_SIZE * HCCL_SQE_MAX_CNT]; | 66 | uint8_t sqBuffer[HCCL_SQE_SIZE * HCCL_SQE_MAX_CNT]; |
| 51 | HcclVmResult GetSqBufferAddr(uint8_t **sqBuff) | 67 | HcclVmResult 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 | ||
| 108 | uint32_t GetRankIdByDevAddr(uint64_t devAddr) | 180 | uint32_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 | - | ||
| 148 | uint32_t GetRankIdByIpAddr(std::string ipAddr) | 209 | uint32_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 | 394 | ||
| 293 | } | 395 | } |
| 294 | 396 | ||
| @@ -25,22 +25,28 @@ HcclSim::HcclVmResult SetCurRankId(uint32_t rankId); | |||
| 25 | 25 | ||
| 26 | HcclSim::HcclVmResult GetCurRankId(uint32_t *rankId); | 26 | HcclSim::HcclVmResult GetCurRankId(uint32_t *rankId); |
| 27 | 27 | ||
| 28 | +void SetCurDeviceKey(uint32_t deviceKey); | ||
| 29 | + | ||
| 30 | +uint32_t GetCurDeviceKey(); | ||
| 31 | + | ||
| 28 | HcclSim::HcclVmResult GetSqBufferAddr(uint8_t **sqBuff); | 32 | HcclSim::HcclVmResult GetSqBufferAddr(uint8_t **sqBuff); |
| 29 | 33 | ||
| 30 | HcclSim::HcclVmResult GetPiValByJettyId(uint32_t jettyId, uint32_t *piValue); | 34 | HcclSim::HcclVmResult GetPiValByJettyId(uint32_t jettyId, uint32_t *piValue); |
| 31 | 35 | ||
| 32 | HcclSim::HcclVmResult UpdatePiValByJettyId(uint32_t jettyId, uint32_t piValue); | 36 | HcclSim::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 | ||
| 38 | uint32_t GetRankIdByDevAddr(uint64_t devAddr); | 42 | uint32_t GetRankIdByDevAddr(uint64_t devAddr); |
| 39 | 43 | ||
| 40 | -HcclAicpuData *GetHcclAicpuDataShmPtr(); | ||
| 41 | - | ||
| 42 | uint32_t GetRankIdByIpAddr(std::string ipAddr); | 44 | uint32_t GetRankIdByIpAddr(std::string ipAddr); |
| 43 | 45 | ||
| 46 | +uint64_t GetDevMapperAddrByDevAddrImpl(uint64_t devAddr, const char *file, int line); | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + | ||
| 44 | void UpdataKfcStatus(uint64_t d2hAddr); | 50 | void UpdataKfcStatus(uint64_t d2hAddr); |
| 45 | 51 | ||
| 46 | void RegisterSignalHandler(); | 52 | void RegisterSignalHandler(); |
| @@ -49,6 +55,14 @@ uint32_t GetSqTail(uint32_t sqId); | |||
| 49 | 55 | ||
| 50 | void UpdateSqTail(uint32_t sqId, uint32_t newTail); | 56 | void 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 | 66 | ||
| 53 | } | 67 | } |
| 54 | 68 | ||
| @@ -9,20 +9,18 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | -#include <cstdint> | 12 | +#include <cstdlib> |
| 13 | 13 | ||
| 14 | -#include <iostream> | 14 | +#include <string> |
| 15 | + | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | - | ||
| 18 | - | ||
| 19 | 18 | ||
| 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 | ||
| 27 | int main(int argc, char *argv[]) | 25 | int 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}/spdlog | 31 | ${THRID_PARTY_DIR}/spdlog |
| 32 | ${HCCL_VM_SRC}/device_arm | 32 | ${HCCL_VM_SRC}/device_arm |
| 33 | 33 | ||
| 34 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc | 34 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc |
| 35 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl | 35 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl |
| 36 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include | 36 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include |
| 37 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include/hccl | 37 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include/hccl |
| 38 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/driver | 38 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/driver |
| 39 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/runtime | 39 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/runtime |
| 40 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/toolchain | 40 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/toolchain |
| 41 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/profiling | 41 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/profiling |
| 42 | ) | 42 | ) |
| 43 | 43 | ||
| 44 | install(TARGETS hccl_device_proxy | 44 | install(TARGETS hccl_device_proxy |
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | - | 13 | +#include <thread> |
| 14 | namespace aicpu { | 14 | namespace aicpu { |
| 15 | std::mutex g_sqeIdMtx; | 15 | std::mutex g_sqeIdMtx; |
| 16 | constexpr uint32_t INITAL_SQE_ID = 0x80000000U; | 16 | constexpr 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 | } // aicpu | 35 | } // 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 | ||
| 31 | void ParseA5SqeFromSqBuffer(uint32_t devId, struct halSqCqConfigInfo *info) | 31 | void 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 写Notify | 235 | // 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 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.h→test/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_H | 11 | +#ifndef SIM_AICPU_PIPE_HANDLER_H |
| 12 | -#define HCCL_KERNEL_EXECUTOR_H | 12 | +#define SIM_AICPU_PIPE_HANDLER_H |
| 13 | + | ||
| 13 | 14 | ||
| 14 | - | ||
| 15 | - | ||
| 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 | 28 | ||
| @@ -0,0 +1,105 @@ | |||
| 1 | + | ||
| 2 | + | ||
| 3 | + | ||
| 4 | + | ||
| 5 | + | ||
| 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 | + | ||
| 2 | + | ||
| 3 | + | ||
| 4 | + | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + | ||
| 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 | + | ||
| @@ -23,9 +23,9 @@ add_subdirectory(src) | |||
| 23 | 23 | ||
| 24 | # 如果需要暴露头文件目录 | 24 | # 如果需要暴露头文件目录 |
| 25 | target_include_directories(checker PUBLIC | 25 | target_include_directories(checker PUBLIC |
| 26 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include | 26 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include |
| 27 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc | 27 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc |
| 28 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl | 28 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl |
| 29 | 29 | ||
| 30 | ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode | 30 | ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode |
| 31 | 31 | ||
| @@ -62,7 +62,7 @@ target_link_libraries(checker PRIVATE | |||
| 62 | modeldb | 62 | modeldb |
| 63 | store | 63 | store |
| 64 | common | 64 | common |
| 65 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.so | 65 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/lib64/libc_sec.so |
| 66 | pthread | 66 | pthread |
| 67 | yaml-cpp::yaml-cpp | 67 | yaml-cpp::yaml-cpp |
| 68 | sqlite3 | 68 | sqlite3 |
| @@ -15,19 +15,22 @@ | |||
| 15 | 15 | ||
| 16 | class DataSlice { | 16 | class DataSlice { |
| 17 | public: | 17 | public: |
| 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; } | ||
| 27 | private: | 29 | private: |
| 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 | 36 | ||
| @@ -9,12 +9,16 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 12 | 15 | ||
| 13 | 16 | ||
| 14 | 17 | ||
| 15 | 18 | ||
| 16 | 19 | ||
| 17 | 20 | ||
| 21 | + | ||
| 18 | 22 | ||
| 19 | 23 | ||
| 20 | 24 | ||
| @@ -25,6 +29,7 @@ | |||
| 25 | 29 | ||
| 26 | 30 | ||
| 27 | 31 | ||
| 32 | + | ||
| 28 | 33 | ||
| 29 | 34 | ||
| 30 | 35 | ||
| @@ -44,6 +49,12 @@ std::mutex g_run_checker_mutex; | |||
| 44 | std::mutex g_worker_mutex; | 49 | std::mutex g_worker_mutex; |
| 45 | std::thread g_worker_thread; | 50 | std::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 | + | ||
| 47 | static std::vector<std::map<uint32_t, sim::CompositeOpDetail>> TransposeCompositeOpMap( | 58 | static 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 | + | ||
| 420 | json BuildOpParamSummaryJson(const HcclSim::CheckerParam ¶m) | 489 | json BuildOpParamSummaryJson(const HcclSim::CheckerParam ¶m) |
| 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": false | 13 | "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) | |||
| 13 | add_subdirectory(singletask_check) | 13 | add_subdirectory(singletask_check) |
| 14 | add_subdirectory(task_graph_generator) | 14 | add_subdirectory(task_graph_generator) |
| 15 | add_subdirectory(task_graph_generator_v3) | 15 | add_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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 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 | + | ||
| @@ -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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 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 | + | ||
Mtest/hccl_vm/src/plugin/checker/src/framework/semantics_check/batchsendrecv_semantics_checker.cc+78-0
| @@ -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 HcclSim | 202 | } // namespace HcclSim |
Mtest/hccl_vm/src/plugin/checker/src/framework/semantics_check/batchsendrecv_semantics_checker.h+2-0
| @@ -17,6 +17,8 @@ | |||
| 17 | namespace HcclSim { | 17 | namespace HcclSim { |
| 18 | HcclResult TaskCheckBatchSendRecvSemantics(std::map<RankId, RankMemorySemantics> &allRankMemSemantics, | 18 | HcclResult 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 | 24 | ||
| @@ -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; |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator/ccu_all_rank_param_recorder.h+1-1
| @@ -44,7 +44,7 @@ public: | |||
| 44 | 44 | ||
| 45 | // rankId -> dieId -> 寄存器Id -> 寄存器value | 45 | // 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 | ||
| 151 | TaskPosition MakeAivPosition(RankId rankId, uint64_t launchIdx, uint32_t blockId, uint32_t pipe, | 151 | TaskPosition 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 | ||
| 201 | SetWaitKey MakeSetWaitKey(const AivPipeEvent &event) | 202 | SetWaitKey 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 | ||
| 387 | HcclResult AppendRuntimeTask(AivLaunchContext &ctx, const AivRuntimeTaskV3 &task, uint64_t order, NodeId &nodeId) | 389 | HcclResult 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 | ||
| 38 | void AllRankParamRecorder::InitParam() | 38 | void 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 | ||
| 43 | void AllRankParamRecorder::RegisterPostNode(TaskNode *node, const CcuPostNodeMetaV3 &meta) | 47 | void AllRankParamRecorder::RegisterPostNode(TaskNode *node, const CcuPostNodeMetaV3 &meta) |
| @@ -60,7 +60,7 @@ public: | |||
| 60 | 60 | ||
| 61 | // rankId -> dieId -> 寄存器Id -> 寄存器value | 61 | // 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 | } // namespace | 255 | } // namespace |
| 255 | 256 | ||
| 256 | CcuGraphStateV3::CcuGraphStateV3(TaskGraphGeneratorV3 &graphIn, TaskCcuGraph &ccuGraphIn) | 257 | CcuGraphStateV3::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 | ||
| 149 | private: | 151 | private: |
| 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需要劫持北向接口HcclGetHcclBuffer | 439 | // 南向接口: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与dieId | 1093 | // 获取远端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 | - | ||
| 171 | - } else if (devType == DevType::DEV_TYPE_960) { | ||
| 172 | - return CcuInstrVersion::VERSION_A6; | ||
| 173 | - | ||
| 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 | |||
| 225 | HcclResult ProcessCcuNode(TaskNode *node, CcuGraphStateV3 *curCcuTask) | 221 | HcclResult 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 @@ | |||
| 23 | namespace HcclSim { | 23 | namespace HcclSim { |
| 24 | namespace TaskGraphGeneratorV3 { | 24 | namespace TaskGraphGeneratorV3 { |
| 25 | using NodeId = int32_t; | 25 | using NodeId = int32_t; |
| 26 | +using OperatorId = uint32_t; | ||
| 26 | using RankId = uint32_t; | 27 | using RankId = uint32_t; |
| 27 | using StreamId = uint32_t; | 28 | using StreamId = uint32_t; |
| 28 | using QueueId = uint32_t; | 29 | using QueueId = uint32_t; |
| @@ -30,6 +31,7 @@ using ChannelId = uint16_t; // for CCU mode | |||
| 30 | 31 | ||
| 31 | constexpr NodeId MAIN_START_NODE_ID = -1; | 32 | constexpr NodeId MAIN_START_NODE_ID = -1; |
| 32 | constexpr NodeId INVALID_NODE_ID = std::numeric_limits<NodeId>::min(); | 33 | constexpr NodeId INVALID_NODE_ID = std::numeric_limits<NodeId>::min(); |
| 34 | +constexpr OperatorId INVALID_OPERATOR_ID = std::numeric_limits<OperatorId>::max(); | ||
| 33 | constexpr size_t MAX_NODE_COUNT = static_cast<size_t>(std::numeric_limits<NodeId>::max()); | 35 | constexpr size_t MAX_NODE_COUNT = static_cast<size_t>(std::numeric_limits<NodeId>::max()); |
| 34 | constexpr RankId INVALID_RANK_ID = std::numeric_limits<RankId>::max(); | 36 | constexpr RankId INVALID_RANK_ID = std::numeric_limits<RankId>::max(); |
| 35 | constexpr StreamId INVALID_STREAM_ID = std::numeric_limits<StreamId>::max(); | 37 | constexpr StreamId INVALID_STREAM_ID = std::numeric_limits<StreamId>::max(); |
| @@ -111,6 +113,7 @@ enum class ProtocolType : uint8_t { | |||
| 111 | }; | 113 | }; |
| 112 | 114 | ||
| 113 | struct TaskPosition { | 115 | struct 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 | ||
| 132 | struct AivPipeEvent { | 136 | struct 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 | ||
| 301 | protected: | 312 | protected: |
| 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_; |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_generator_v3.cc+7-2
| @@ -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 | + | ||
| 102 | TaskNode *TaskGraphGeneratorV3::GetNode(NodeId nodeId) | 107 | TaskNode *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) { |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_generator_v3.h+4-0
| @@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | namespace HcclSim { | 23 | namespace HcclSim { |
| 24 | +class StorageManager; | ||
| 24 | namespace TaskGraphGeneratorV3 { | 25 | namespace TaskGraphGeneratorV3 { |
| 25 | using RankNodeQueues = std::vector<std::vector<NodeId>>; | 26 | using RankNodeQueues = std::vector<std::vector<NodeId>>; |
| 26 | using AllRankNodeQueues = std::map<RankId, RankNodeQueues>; | 27 | using 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 TaskGraphGeneratorV3 | 118 | } // namespace TaskGraphGeneratorV3 |
| 115 | } // namespace HcclSim | 119 | } // 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={}", |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_sync_conflict_v3.cc+5-3
| @@ -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 of | 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"). | 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 | 11 | ||
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_sync_conflict_v3.h+5-3
| @@ -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 of | 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"). | 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 | 11 | ||
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_meta_translator_v3.cc+7-5
| @@ -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 | ||
| 285 | HcclResult TaskMetaTranslatorV3::TranslateOneTaskMeta(const HcclTaskMetaData &taskMeta, StorageManager &storage, | 287 | HcclResult 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 | } |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_meta_translator_v3.h+2-2
| @@ -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" | |||
| 24 | static const std::string SETTING_KEY_ENABLE_MEMORY_SNAPSHOT_DUMP = "enable_memory_snapshot_dump"; | 24 | static const std::string SETTING_KEY_ENABLE_MEMORY_SNAPSHOT_DUMP = "enable_memory_snapshot_dump"; |
| 25 | static const std::string SETTING_KEY_ENABLE_NEW_CHECKER = "enable_new_checker"; | 25 | static const std::string SETTING_KEY_ENABLE_NEW_CHECKER = "enable_new_checker"; |
| 26 | static const std::string SETTING_KEY_ENABLE_OLD_CHECKER = "enable_old_checker"; | 26 | static 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 | } // namespace | 29 | } // 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 HcclSim | 131 | } // 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 | ||
| 28 | class SettingManager { | 29 | class 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 | ||
| 48 | private: | 50 | private: |
| 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 ¤t = checkerParam.batchSendRecvRankParams[rankId]; | 172 | const BatchSendRecvRankParam ¤t = 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 | } // namespace | 223 | } // 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 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | + | ||
| 25 | 26 | ||
| 26 | namespace HcclSim { | 27 | namespace HcclSim { |
| 27 | struct MemBlock { | 28 | struct MemBlock { |
| @@ -48,6 +49,9 @@ struct SendRecvPairParam { | |||
| 48 | struct BatchSendRecvRankParam { | 49 | struct 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 | ||
| 53 | struct CheckerParam { | 57 | struct CheckerParam { |
| @@ -78,6 +82,7 @@ using ChannelsPerDie = std::map<uint32_t, RemoteDieInfo>; | |||
| 78 | 82 | ||
| 79 | class StorageManager { | 83 | class StorageManager { |
| 80 | public: | 84 | public: |
| 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 | ||
| 124 | private: | 141 | private: |
| 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 | ||
| 38 | target_include_directories(runner PRIVATE | 38 | target_include_directories(runner PRIVATE |
| 39 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include | 39 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/include |
| 40 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc | 40 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc |
| 41 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl | 41 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/pkg_inc/hccl |
| 42 | + | ||
| 42 | 43 | ||
| 43 | ${HCOMM_CODE_ROOT}/src/base_comm/resources/ccu/ccu_microcode | 44 | ${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_vm | 37 | ${HCOMM_VM_ROOT_PATH}/src/host/hccl_vm |
| 38 | ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin | 38 | ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin |
| 39 | ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin/checker/utils | 39 | ${HCOMM_VM_ROOT_PATH}/src/host/hccl_check_plugin/checker/utils |
| 40 | + ${HCOMM_VM_ROOT_PATH}/src/common | ||
| 40 | ) | 41 | ) |
| 41 | 42 | ||
| 42 | target_include_directories(hccl_proxy_level2 PRIVATE | 43 | target_include_directories(hccl_proxy_level2 PRIVATE |
| @@ -125,6 +126,7 @@ target_compile_options(hccl_proxy_level2 PRIVATE | |||
| 125 | target_link_libraries(hccl_proxy_level2 PRIVATE | 126 | target_link_libraries(hccl_proxy_level2 PRIVATE |
| 126 | -Wl,--whole-archive | 127 | -Wl,--whole-archive |
| 127 | log | 128 | log |
| 129 | + common | ||
| 128 | runnerdb | 130 | runnerdb |
| 129 | modeldb | 131 | modeldb |
| 130 | store | 132 | store |
| @@ -134,11 +136,11 @@ target_link_libraries(hccl_proxy_level2 PRIVATE | |||
| 134 | rt | 136 | rt |
| 135 | SQLite::SQLite3 | 137 | SQLite::SQLite3 |
| 136 | JSON::JSON | 138 | JSON::JSON |
| 137 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.a | 139 | + ${ASCEND_CANN_PACKAGE_PATH}/${CANN_ARCH_DIR}/lib64/libc_sec.a |
| 138 | ) | 140 | ) |
| 139 | 141 | ||
| 140 | install(TARGETS hccl_proxy_level2 | 142 | install(TARGETS hccl_proxy_level2 |
| 141 | - DESTINATION "lib/x86_64" | 143 | + DESTINATION "lib/${CMAKE_SYSTEM_PROCESSOR}" |
| 142 | # 文件的权限 (755) | 144 | # 文件的权限 (755) |
| 143 | PERMISSIONS | 145 | PERMISSIONS |
| 144 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 146 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| @@ -23,15 +23,19 @@ | |||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | - | 26 | +#include "db_sim_runner_common.h" |
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | extern "C" { | 29 | extern "C" { |
| 30 | 30 | ||
| 31 | aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId) | 31 | aclError 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 | ||
| 84 | aclError aclrtGetCurrentContext(aclrtContext *context) | 88 | aclError 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 | ||
| 94 | aclError aclrtCtxGetCurrentDefaultStream(aclrtStream *stream) | 102 | aclError 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 | 27 | ||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | + | ||
| 30 | 31 | ||
| 31 | // current host id | 32 | // current host id |
| 32 | uint64_t g_host_id; | 33 | uint64_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) | |||
| 285 | aclError aclrtGetDeviceCount(uint32_t *count) | 312 | aclError 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 | |||
| 705 | aclError aclInit(const char *configPath) | 757 | aclError 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 | ||
| 712 | aclError aclFinalize() | 774 | aclError 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 | 23 | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | + | ||
| 26 | 27 | ||
| 27 | 28 | ||
| 28 | 29 | ||
| @@ -32,7 +33,12 @@ extern "C" { | |||
| 32 | aclError aclrtCreateEventWithFlag(aclrtEvent *event, uint32_t flag) | 33 | aclError 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) | |||
| 186 | aclError aclrtGetEventAvailNum(uint32_t *eventCount) | 192 | aclError 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) { |