已合并
同步开源代码 #3121
c15029001705创建于 6月26日
同步开源代码 #3121
已合并
共 127 个文件变更+5504-2650
| @@ -85,19 +85,46 @@ include(cmake/third_party/cli11.cmake) | |||
| 85 | include(cmake/third_party/spdlog.cmake) | 85 | include(cmake/third_party/spdlog.cmake) |
| 86 | include(cmake/third_party/sqlite3.cmake) | 86 | include(cmake/third_party/sqlite3.cmake) |
| 87 | 87 | ||
| 88 | +include_directories( | ||
| 89 | + ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | ||
| 90 | + ${CMAKE_SOURCE_DIR}/third_party | ||
| 91 | + ${CMAKE_SOURCE_DIR}/third_party/yaml-cpp/include | ||
| 92 | +) | ||
| 93 | + | ||
| 88 | function(config_hcclvm_install) | 94 | function(config_hcclvm_install) |
| 89 | install(DIRECTORY DESTINATION "data") | 95 | install(DIRECTORY DESTINATION "data") |
| 90 | - install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/asset/" | 96 | + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/config/" |
| 91 | - DESTINATION "." | 97 | + DESTINATION "config") |
| 92 | - # 文件的权限 (755) | 98 | + install(FILES |
| 93 | - FILE_PERMISSIONS | 99 | + "${CMAKE_CURRENT_SOURCE_DIR}/asset/allocate_eid.sh" |
| 94 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | 100 | + "${CMAKE_CURRENT_SOURCE_DIR}/asset/generate_cluster_topo.sh" |
| 95 | - GROUP_READ GROUP_EXECUTE | 101 | + "${CMAKE_CURRENT_SOURCE_DIR}/asset/generate_server_topo.sh" |
| 102 | + "${CMAKE_CURRENT_SOURCE_DIR}/asset/hccl_config.sh" | ||
| 103 | + DESTINATION "script" | ||
| 104 | + PERMISSIONS | ||
| 105 | + OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 106 | + GROUP_READ GROUP_EXECUTE | ||
| 96 | WORLD_READ WORLD_EXECUTE | 107 | WORLD_READ WORLD_EXECUTE |
| 97 | - # 目录的权限 (755) | 108 | + ) |
| 109 | + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/asset/cluster_model/config/cluster" | ||
| 110 | + DESTINATION "config" | ||
| 98 | DIRECTORY_PERMISSIONS | 111 | DIRECTORY_PERMISSIONS |
| 99 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | 112 | + OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| 100 | - GROUP_READ GROUP_EXECUTE | 113 | + GROUP_READ GROUP_EXECUTE |
| 114 | + WORLD_READ WORLD_EXECUTE | ||
| 115 | + ) | ||
| 116 | + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/asset/cluster_model/config/server_or_pod" | ||
| 117 | + DESTINATION "config" | ||
| 118 | + DIRECTORY_PERMISSIONS | ||
| 119 | + OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 120 | + GROUP_READ GROUP_EXECUTE | ||
| 121 | + WORLD_READ WORLD_EXECUTE | ||
| 122 | + ) | ||
| 123 | + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/asset/cluster_model/topo_meta" | ||
| 124 | + DESTINATION "config" | ||
| 125 | + DIRECTORY_PERMISSIONS | ||
| 126 | + OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 127 | + GROUP_READ GROUP_EXECUTE | ||
| 101 | WORLD_READ WORLD_EXECUTE | 128 | WORLD_READ WORLD_EXECUTE |
| 102 | ) | 129 | ) |
| 103 | endfunction() | 130 | endfunction() |
| @@ -116,7 +143,7 @@ include(CPack) | |||
| 116 | if(BUILD_DEVICE_ARM) | 143 | if(BUILD_DEVICE_ARM) |
| 117 | message(STATUS "BUILD_DEVICE_ARM start") | 144 | message(STATUS "BUILD_DEVICE_ARM start") |
| 118 | set(DEVICE_ARM_BUILD_DIR ${CMAKE_SOURCE_DIR}/build_device) | 145 | set(DEVICE_ARM_BUILD_DIR ${CMAKE_SOURCE_DIR}/build_device) |
| 119 | - set(DEVICE_ARM_INSTALL_DIR ${CMAKE_SOURCE_DIR}/hccl_vm_install/device) | 146 | + set(DEVICE_ARM_INSTALL_DIR ${CMAKE_SOURCE_DIR}/hccl_vm_install) |
| 120 | include(ExternalProject) | 147 | include(ExternalProject) |
| 121 | ExternalProject_Add(device_arm_external | 148 | ExternalProject_Add(device_arm_external |
| 122 | SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/device_arm | 149 | SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/device_arm |
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | HCCL-VM是面向华为昇腾NPU卡的高性能集合通信的虚拟执行环境,该工具旨在无真实昇腾硬件的条件下,实现HCCL集合通信算子的开发和功能验证。 | 5 | HCCL-VM是面向华为昇腾NPU卡的高性能集合通信的虚拟执行环境,该工具旨在无真实昇腾硬件的条件下,实现HCCL集合通信算子的开发和功能验证。 |
| 6 | 6 | ||
| 7 | + | ||
| 8 | + | ||
| 7 | ## 2. 前置依赖 | 9 | ## 2. 前置依赖 |
| 8 | 10 | ||
| 9 | | | | | 11 | | | | |
| @@ -40,13 +42,13 @@ cd /home/workspace | |||
| 40 | # 2. 下载依赖源码 | 42 | # 2. 下载依赖源码 |
| 41 | git clone https://gitcode.com/cann/hccl.git | 43 | git clone https://gitcode.com/cann/hccl.git |
| 42 | git clone https://gitcode.com/cann/hcomm.git | 44 | git clone https://gitcode.com/cann/hcomm.git |
| 43 | -git clone https://gitcode.com/zhupc158/CheckerL2.git | ||
| 44 | 45 | ||
| 45 | # 3. 安装第三方依赖 | 46 | # 3. 安装第三方依赖 |
| 46 | sudo apt-get update | 47 | sudo apt-get update |
| 47 | sudo apt install build-essential cmake libsqlite3-dev rdma-core libibverbs-dev pkg-config gcc-aarch64-linux-gnu g++-aarch64-linux-gnu qemu-user-static binfmt-support | 48 | sudo apt install build-essential cmake libsqlite3-dev rdma-core libibverbs-dev pkg-config gcc-aarch64-linux-gnu g++-aarch64-linux-gnu qemu-user-static binfmt-support |
| 48 | 49 | ||
| 49 | -# 4. 编译HCCL-VM工具 | 50 | +# 4. 编译HCCL-VM工具,下载hcomm代码之后,工具源码所在路径:/home/workspace/hcomm/test/hccl_vm |
| 51 | +cd /home/workspace/hcomm/test/hccl_vm | ||
| 50 | source /home/Ascend/cann/set_env.sh | 52 | source /home/Ascend/cann/set_env.sh |
| 51 | export HCCL_CODE_HOME=/home/workspace/hccl | 53 | export HCCL_CODE_HOME=/home/workspace/hccl |
| 52 | export HCOMM_CODE_HOME=/home/workspace/hcomm | 54 | export HCOMM_CODE_HOME=/home/workspace/hcomm |
| @@ -65,18 +67,22 @@ export HCOMM_CODE_HOME=/home/workspace/hcomm | |||
| 65 | 67 | ||
| 66 | ```bash | 68 | ```bash |
| 67 | # 进入工具安装目录 | 69 | # 进入工具安装目录 |
| 68 | -cd /home/workspace/CheckerL2/hccl_vm_install | 70 | +cd /home/workspace/hcomm/test/hccl_vm/hccl_vm_install |
| 69 | source /home/Ascend/cann/set_env.sh | 71 | source /home/Ascend/cann/set_env.sh |
| 70 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH | 72 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH |
| 71 | -export RANK_TABLE_FILE=$(pwd)/ranktable.json | 73 | +export RANK_TABLE_FILE=$(pwd)/data/ranktable.json |
| 72 | export HCCL_OP_EXPANSION_MODE="CCU_SCHED" | 74 | export HCCL_OP_EXPANSION_MODE="CCU_SCHED" |
| 73 | ``` | 75 | ``` |
| 74 | 76 | ||
| 75 | 2. 执行 | 77 | 2. 执行 |
| 76 | 78 | ||
| 79 | + | ||
| 77 | ```bash | 80 | ```bash |
| 78 | # 进入工具安装目录 | 81 | # 进入工具安装目录 |
| 79 | -cd /home/workspace/CheckerL2/hccl_vm_install | 82 | +cd /home/workspace/hcomm/test/hccl_vm/hccl_vm_install |
| 83 | + | ||
| 84 | +# 需要进入到新的bin文件目录下执行hccl-vm | ||
| 85 | +cd ./bin | ||
| 80 | 86 | ||
| 81 | # 选择昇腾集群拓扑配置文件,启动工具,初始化集群环境,进入工具命令行 | 87 | # 选择昇腾集群拓扑配置文件,启动工具,初始化集群环境,进入工具命令行 |
| 82 | ./hccl-vm start ascend950_cluster_32_server_normal.yaml | 88 | ./hccl-vm start ascend950_cluster_32_server_normal.yaml |
| @@ -106,7 +112,7 @@ AICPU展开模式需要将算法展开步骤放到设备侧执行,因此hccl-v | |||
| 106 | 1. HCCL设备侧符号编译、安装、拷贝等 | 112 | 1. HCCL设备侧符号编译、安装、拷贝等 |
| 107 | 113 | ||
| 108 | ```bash | 114 | ```bash |
| 109 | -cd /home/workspace/CheckerL2 | 115 | +cd /home/workspace/hcomm/test/hccl_vm/ |
| 110 | bash ./build_pkg.sh | 116 | bash ./build_pkg.sh |
| 111 | ``` | 117 | ``` |
| 112 | 118 | ||
| @@ -114,10 +120,10 @@ bash ./build_pkg.sh | |||
| 114 | 120 | ||
| 115 | ```bash | 121 | ```bash |
| 116 | # 进入工具安装目录 | 122 | # 进入工具安装目录 |
| 117 | -cd /home/workspace/CheckerL2/hccl_vm_install | 123 | +cd /home/workspace/hcomm/test/hccl_vm/hccl_vm_install |
| 118 | source /home/Ascend/cann/set_env.sh | 124 | source /home/Ascend/cann/set_env.sh |
| 119 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH | 125 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH |
| 120 | -export RANK_TABLE_FILE=$(pwd)/ranktable.json | 126 | +export RANK_TABLE_FILE=$(pwd)/data/ranktable.json |
| 121 | export HCCL_OP_EXPANSION_MODE="AI_CPU" | 127 | export HCCL_OP_EXPANSION_MODE="AI_CPU" |
| 122 | ``` | 128 | ``` |
| 123 | 129 | ||
| @@ -125,7 +131,10 @@ export HCCL_OP_EXPANSION_MODE="AI_CPU" | |||
| 125 | 131 | ||
| 126 | ```bash | 132 | ```bash |
| 127 | # 进入工具安装目录 | 133 | # 进入工具安装目录 |
| 128 | -cd /home/workspace/CheckerL2/hccl_vm_install | 134 | +cd /home/workspace/hcomm/test/hccl_vm/hccl_vm_install |
| 135 | + | ||
| 136 | +# 需要进入到新的bin文件目录下执行hccl-vm | ||
| 137 | +cd ./bin | ||
| 129 | 138 | ||
| 130 | # 选择昇腾集群拓扑配置文件,启动工具,初始化集群环境,进入工具命令行 | 139 | # 选择昇腾集群拓扑配置文件,启动工具,初始化集群环境,进入工具命令行 |
| 131 | ./hccl-vm start ascend950_cluster_32_server_normal.yaml | 140 | ./hccl-vm start ascend950_cluster_32_server_normal.yaml |
| @@ -154,10 +163,10 @@ cd /home/workspace/CheckerL2/hccl_vm_install | |||
| 154 | 163 | ||
| 155 | ```bash | 164 | ```bash |
| 156 | # 进入工具安装目录 | 165 | # 进入工具安装目录 |
| 157 | -cd /home/workspace/CheckerL2/hccl_vm_install | 166 | +cd /home/workspace/hcomm/test/hccl_vm/hccl_vm_install |
| 158 | source /home/Ascend/cann/set_env.sh | 167 | source /home/Ascend/cann/set_env.sh |
| 159 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH | 168 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH |
| 160 | -export RANK_TABLE_FILE=$(pwd)/ranktable.json | 169 | +export RANK_TABLE_FILE=$(pwd)/data/ranktable.json |
| 161 | export HCCL_OP_EXPANSION_MODE="AIV" | 170 | export HCCL_OP_EXPANSION_MODE="AIV" |
| 162 | ``` | 171 | ``` |
| 163 | 172 | ||
| @@ -165,7 +174,10 @@ export HCCL_OP_EXPANSION_MODE="AIV" | |||
| 165 | 174 | ||
| 166 | ```bash | 175 | ```bash |
| 167 | # 进入工具安装目录 | 176 | # 进入工具安装目录 |
| 168 | -cd /home/workspace/CheckerL2/hccl_vm_install | 177 | +cd /home/workspace/hcomm/test/hccl_vm/hccl_vm_install |
| 178 | + | ||
| 179 | +# 需要进入到新的bin文件目录下执行hccl-vm | ||
| 180 | +cd ./bin | ||
| 169 | 181 | ||
| 170 | # 选择昇腾集群拓扑配置文件,启动工具,初始化集群环境,进入工具命令行 | 182 | # 选择昇腾集群拓扑配置文件,启动工具,初始化集群环境,进入工具命令行 |
| 171 | ./hccl-vm start ascend950_cluster_32_server_normal.yaml | 183 | ./hccl-vm start ascend950_cluster_32_server_normal.yaml |
| @@ -373,7 +385,7 @@ server_list: | |||
| 373 | 385 | ||
| 374 | 用户在昇腾集群环境中,需要根据待执行算子所需的通信域不同,选择不同的通信域配置文件。 | 386 | 用户在昇腾集群环境中,需要根据待执行算子所需的通信域不同,选择不同的通信域配置文件。 |
| 375 | 387 | ||
| 376 | -工具提供了hccl-vm mock-comm命令读取和配置算子通信域配置文件。通信域配置文件格式为yaml,路径为hccl_vm_install/cluster_model/topo_meta。若目录中没有对应的通信域配置文件,则用户需要先创建一个。 | 388 | +工具提供了hccl-vm mock-comm命令读取和配置算子通信域配置文件。通信域配置文件格式为yaml,路径为hccl_vm_install/config/topo_meta。若目录中没有对应的通信域配置文件,则用户需要先创建一个。 |
| 377 | 389 | ||
| 378 | hccl-vm工具支持非对称拓扑通信域配置。如下所示: | 390 | hccl-vm工具支持非对称拓扑通信域配置。如下所示: |
| 379 | 391 | ||
| @@ -539,19 +551,37 @@ remove_files_by_prefix() { | |||
| 539 | return 0 | 551 | return 0 |
| 540 | } | 552 | } |
| 541 | 553 | ||
| 542 | -# 清理执行目录的冗余文件 | 554 | +# 清理 data/ 目录的冗余文件(CCU 模式下生成的临时文件) |
| 543 | -remove_files_by_prefix "sqe_info_rank_" | 555 | +cd "${HCCL_VM_INSTALL_DIR}/data" 2>/dev/null && { |
| 544 | -remove_files_by_prefix "mc_instr_info_rank_" | 556 | + remove_files_by_prefix "sqe_info_rank_" |
| 545 | -rm -f "all_rank_input_output.txt" | 557 | + remove_files_by_prefix "mc_instr_info_rank_" |
| 558 | + rm -f "all_rank_input_output.txt" | ||
| 559 | + cd "${HCCL_VM_INSTALL_DIR}" | ||
| 560 | +} | ||
| 546 | 561 | ||
| 547 | # 设置CANN环境变量 | 562 | # 设置CANN环境变量 |
| 548 | source /home/Ascend/cann/set_env.sh | 563 | source /home/Ascend/cann/set_env.sh |
| 549 | 564 | ||
| 565 | +# 关闭hccl心跳功能 | ||
| 566 | +export HCCL_DFS_CONFIG=cluster_heartbeat:off | ||
| 567 | + | ||
| 568 | +# 设置 HCCL-VM 安装路径,基于脚本自身位置推断(兼容 bin/ 与 script/ 子目录) | ||
| 569 | +_INSTALL_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| 570 | +case "$(basename "${_INSTALL_SCRIPT_DIR}")" in | ||
| 571 | + bin|script) | ||
| 572 | + export HCCL_VM_INSTALL_DIR="$(dirname "${_INSTALL_SCRIPT_DIR}")" | ||
| 573 | + ;; | ||
| 574 | + *) | ||
| 575 | + export HCCL_VM_INSTALL_DIR="${_INSTALL_SCRIPT_DIR}" | ||
| 576 | + ;; | ||
| 577 | +esac | ||
| 578 | +unset _INSTALL_SCRIPT_DIR | ||
| 579 | + | ||
| 550 | # 配置LD_LIBRARY_PATH | 580 | # 配置LD_LIBRARY_PATH |
| 551 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH | 581 | export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH |
| 552 | 582 | ||
| 553 | -# 设置 ranktable.json文件路径 | 583 | +# 设置 ranktable.json文件路径 (与 mock-comm 生成路径保持一致) |
| 554 | -export RANK_TABLE_FILE=$(pwd)/ranktable.json | 584 | +export RANK_TABLE_FILE=${HCCL_VM_INSTALL_DIR}/data/ranktable.json |
| 555 | 585 | ||
| 556 | # 设置日志级别 | 586 | # 设置日志级别 |
| 557 | export ASCEND_GLOBAL_LOG_LEVEL=1 | 587 | export ASCEND_GLOBAL_LOG_LEVEL=1 |
| @@ -620,7 +650,8 @@ Checker插件,即算法分析器插件:功能是将hccl生成的所有task | |||
| 620 | Checker插件正处于新旧交替阶段,Checker V3为原Checker的重构版,主要提高了校验性能,在默认情况下将会运行新Checker(Checker V3),可以通过修改Checker的`manifest.json`文件中的配置参数进行调整。 | 650 | Checker插件正处于新旧交替阶段,Checker V3为原Checker的重构版,主要提高了校验性能,在默认情况下将会运行新Checker(Checker V3),可以通过修改Checker的`manifest.json`文件中的配置参数进行调整。 |
| 621 | 651 | ||
| 622 | ```bash | 652 | ```bash |
| 623 | -# 配置文件位于 /pathto/hccl_vm_install/plugin/validate/checker/manifest.json | 653 | + |
| 654 | +# 配置文件位于 /pathto/hccl_vm_install/plugin/checker/manifest.json | ||
| 624 | 655 | ||
| 625 | { | 656 | { |
| 626 | "name": "checker", // Checker插件名 | 657 | "name": "checker", // Checker插件名 |
| @@ -646,7 +677,7 @@ Checker插件正处于新旧交替阶段,Checker V3为原Checker的重构版 | |||
| 646 | ```json | 677 | ```json |
| 647 | { | 678 | { |
| 648 | "version": "2.0", | 679 | "version": "2.0", |
| 649 | - "topo_file_path": "/home/myuser/workspace/CheckerL2/hccl_vm_install/topo.json" | 680 | + "topo_file_path": "/home/myuser/workspace/CheckerL2/hccl_vm_install/data/topo.json" |
| 650 | } | 681 | } |
| 651 | ``` | 682 | ``` |
| 652 | 683 | ||
| @@ -711,6 +742,19 @@ data_size(Bytes): | aveg_time(us): | alg_bandwidth(GB/s): | check_result: | |||
| 711 | ``` | 742 | ``` |
| 712 | 743 | ||
| 713 | --- | 744 | --- |
| 745 | +### 4.10 大块内存复用(仅校验模式) | ||
| 746 | + | ||
| 747 | +仅校验模式用于大规模集群仅运行 Checker 校验的场景。开启后,单块 200MB 到 4GB 的大内存申请复用同一块 4GB 共享区 `HcclCommPool`,各 rank 共享、允许互相覆盖,以此大幅降低 `/dev/shm` 占用。此时大块内容不保证正确,仅适用于不读取缓冲区数据的 Checker V3 校验链路,需要数值正确的结果时请勿开启。 | ||
| 748 | + | ||
| 749 | +仅校验模式是会话级开关,在 `start` 子命令后追加 `--check-only` 显式开启;不加时为默认的普通模式,大块走真实独立分配,正确性无损。小于 200MB 的申请始终走真实分配,单块大于 4GB 在仅校验模式下直接报错拒绝。仅校验模式与 Runner 不互斥,但在仅校验模式开启时安装 Runner,大块复用仍会生效、可能覆盖 Runner 数据,工具会打印告警。 | ||
| 750 | + | ||
| 751 | +```bash | ||
| 752 | + | ||
| 753 | +# 启动工具时开启仅校验模式 | ||
| 754 | +./hccl-vm start ascend950_cluster_32_server_normal.yaml --check-only | ||
| 755 | +``` | ||
| 756 | + | ||
| 757 | +*** | ||
| 714 | 758 | ||
| 715 | ## 5 附录 | 759 | ## 5 附录 |
| 716 | 760 | ||
| @@ -742,4 +786,4 @@ data_size(Bytes): | aveg_time(us): | alg_bandwidth(GB/s): | check_result: | |||
| 742 | --- | 786 | --- |
| 743 | 787 | ||
| 744 | **文档版本**:v1.0 | 788 | **文档版本**:v1.0 |
| 745 | -**最后更新**:2026-06-22 | 789 | +**最后更新**:2026-06-26 |
| @@ -51,8 +51,8 @@ warn_msg() { | |||
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | 53 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 54 | -BASE_DIR="${SCRIPT_DIR}" | 54 | +BASE_DIR="$(dirname "${SCRIPT_DIR}")" |
| 55 | -OUTPUT_DIR="${BASE_DIR}/cluster_model/network/cluster" | 55 | +OUTPUT_DIR="${BASE_DIR}/config/network/cluster" |
| 56 | 56 | ||
| 57 | show_usage() { | 57 | show_usage() { |
| 58 | cat << EOF | 58 | cat << EOF |
The file is empty
| @@ -46,15 +46,15 @@ warn_msg() { | |||
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | 48 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 49 | -BASE_DIR="${SCRIPT_DIR}" | 49 | +BASE_DIR="$(dirname "${SCRIPT_DIR}")" |
| 50 | 50 | ||
| 51 | -CLUSTER_CONFIG_DIR="${BASE_DIR}/cluster_model/config/cluster" | 51 | +CLUSTER_CONFIG_DIR="${BASE_DIR}/config/cluster" |
| 52 | -SUPERPOD_CONFIG_DIR="${BASE_DIR}/cluster_model/config/super_pod" | 52 | +SUPERPOD_CONFIG_DIR="${BASE_DIR}/config/super_pod" |
| 53 | -SERVER_CONFIG_DIR="${BASE_DIR}/cluster_model/config/server_or_pod" | 53 | +SERVER_CONFIG_DIR="${BASE_DIR}/config/server_or_pod" |
| 54 | SERVER_TOPO_BANK_DIR="${BASE_DIR}/topo_bank/server_topo_bank" | 54 | SERVER_TOPO_BANK_DIR="${BASE_DIR}/topo_bank/server_topo_bank" |
| 55 | -GENERATE_TOPO_SCRIPT="${BASE_DIR}/generate_server_topo.sh" | 55 | +GENERATE_TOPO_SCRIPT="${SCRIPT_DIR}/generate_server_topo.sh" |
| 56 | -ALLOCATE_EID_SCRIPT="${BASE_DIR}/allocate_eid.sh" | 56 | +ALLOCATE_EID_SCRIPT="${SCRIPT_DIR}/allocate_eid.sh" |
| 57 | -DEFAULT_OUTPUT_DIR="${BASE_DIR}/cluster_model/network/cluster" | 57 | +DEFAULT_OUTPUT_DIR="${BASE_DIR}/config/network/cluster" |
| 58 | 58 | ||
| 59 | resolve_path() { | 59 | resolve_path() { |
| 60 | local input="$1" | 60 | local input="$1" |
| @@ -54,10 +54,10 @@ warn_msg() { | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | 56 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 57 | -BASE_DIR="${SCRIPT_DIR}" | 57 | +BASE_DIR="$(dirname "${SCRIPT_DIR}")" |
| 58 | 58 | ||
| 59 | -SERVER_CONFIG_DIR="${BASE_DIR}/cluster_model/config/server_or_pod" | 59 | +SERVER_CONFIG_DIR="${BASE_DIR}/config/server_or_pod" |
| 60 | -DEFAULT_OUTPUT_DIR="${BASE_DIR}/cluster_model/network/server_or_pod" | 60 | +DEFAULT_OUTPUT_DIR="${BASE_DIR}/config/network/server_or_pod" |
| 61 | 61 | ||
| 62 | resolve_path() { | 62 | resolve_path() { |
| 63 | local input="$1" | 63 | local input="$1" |
| @@ -41,14 +41,20 @@ rm -f "all_rank_input_output.txt" | |||
| 41 | # 设置CANN环境变量 | 41 | # 设置CANN环境变量 |
| 42 | source /home/teamserver/workspace/Ascend/cann/set_env.sh | 42 | source /home/teamserver/workspace/Ascend/cann/set_env.sh |
| 43 | 43 | ||
| 44 | -# 设置 HCCL-VM 安装路径 | 44 | +# 设置 HCCL-VM 安装路径,基于脚本自身位置推断(兼容 bin/ 与 script/ 子目录) |
| 45 | -export HCCL_VM_INSTALL_DIR=$(pwd) | 45 | +_INSTALL_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 46 | +case "$(basename "${_INSTALL_SCRIPT_DIR}")" in | ||
| 47 | + bin|script) | ||
| 48 | + export HCCL_VM_INSTALL_DIR="$(dirname "${_INSTALL_SCRIPT_DIR}")" | ||
| 49 | + ;; | ||
| 50 | + *) | ||
| 51 | + export HCCL_VM_INSTALL_DIR="${_INSTALL_SCRIPT_DIR}" | ||
| 52 | + ;; | ||
| 53 | +esac | ||
| 54 | +unset _INSTALL_SCRIPT_DIR | ||
| 46 | 55 | ||
| 47 | -# 配置LD_LIBRARY_PATH | 56 | +# 设置 ranktable.json文件路径 (与 mock-comm 生成路径保持一致) |
| 48 | -export LD_LIBRARY_PATH=$ASCEND_HOME_PATH/lib64:$ASCEND_HOME_PATH/devlib:$LD_LIBRARY_PATH | 57 | +export RANK_TABLE_FILE=${HCCL_VM_INSTALL_DIR}/data/ranktable.json |
| 49 | - | ||
| 50 | -# 设置 ranktable.json文件路径 | ||
| 51 | -export RANK_TABLE_FILE=${HCCL_VM_INSTALL_DIR}/ranktable.json | ||
| 52 | 58 | ||
| 53 | # 设置日志级别 | 59 | # 设置日志级别 |
| 54 | export ASCEND_GLOBAL_LOG_LEVEL=1 | 60 | export ASCEND_GLOBAL_LOG_LEVEL=1 |
| @@ -7,6 +7,8 @@ | |||
| 7 | # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 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. | 8 | # See LICENSE in the root of the software repository for the full text of the License. |
| 9 | 9 | ||
| 10 | +set -e | ||
| 11 | + | ||
| 10 | function usage() { | 12 | function usage() { |
| 11 | echo "Usage:" | 13 | echo "Usage:" |
| 12 | echo " sh build.sh [-h | --help]" | 14 | echo " sh build.sh [-h | --help]" |
| @@ -166,7 +166,7 @@ echo "正在拷贝驱动依赖库文件..." | |||
| 166 | 166 | ||
| 167 | # 1.定义源路径和目标路径 | 167 | # 1.定义源路径和目标路径 |
| 168 | SOURCE_DIR="$ASCEND_INSTALL_PATH/cann/x86_64-linux/devlib/device" | 168 | SOURCE_DIR="$ASCEND_INSTALL_PATH/cann/x86_64-linux/devlib/device" |
| 169 | -TARGET_DIR="$HCCL_VM_PATH/hccl_vm_install/device/lib64" | 169 | +TARGET_DIR="$HCCL_VM_PATH/hccl_vm_install/lib/aarch64" |
| 170 | 170 | ||
| 171 | # 2.检查目标目录是否存在,不存在则创建 | 171 | # 2.检查目标目录是否存在,不存在则创建 |
| 172 | if [ ! -d "$TARGET_DIR" ]; then | 172 | if [ ! -d "$TARGET_DIR" ]; then |
| @@ -0,0 +1,39 @@ | |||
| 1 | +hccl_vm: | ||
| 2 | + console_level: 2 | ||
| 3 | + file_level: 1 | ||
| 4 | + max_file_size: 52428800 | ||
| 5 | + max_files: 65535 | ||
| 6 | + file_path: logs | ||
| 7 | + file_base_name: app_log | ||
| 8 | + file_suffix: .log | ||
| 9 | + enable_compress: false | ||
| 10 | + | ||
| 11 | +proxy: | ||
| 12 | + console_level: 2 | ||
| 13 | + file_level: 1 | ||
| 14 | + max_file_size: 52428800 | ||
| 15 | + max_files: 65535 | ||
| 16 | + file_path: logs/proxy | ||
| 17 | + file_base_name: app_log | ||
| 18 | + file_suffix: .log | ||
| 19 | + enable_compress: false | ||
| 20 | + | ||
| 21 | +runner: | ||
| 22 | + console_level: 6 | ||
| 23 | + file_level: 2 | ||
| 24 | + max_file_size: 52428800 | ||
| 25 | + max_files: 65535 | ||
| 26 | + file_path: logs/runner | ||
| 27 | + file_base_name: app_log | ||
| 28 | + file_suffix: .log | ||
| 29 | + enable_compress: false | ||
| 30 | + | ||
| 31 | +checker: | ||
| 32 | + console_level: 2 | ||
| 33 | + file_level: 0 | ||
| 34 | + max_file_size: 52428800 | ||
| 35 | + max_files: 65535 | ||
| 36 | + file_path: logs/checker | ||
| 37 | + file_base_name: app_log | ||
| 38 | + file_suffix: .log | ||
| 39 | + enable_compress: false | ||
| @@ -0,0 +1,328 @@ | |||
| 1 | +# HVRM Insight V3 使用指南 | ||
| 2 | + | ||
| 3 | +## 1. 概述 | ||
| 4 | + | ||
| 5 | +HVRM Insight V3 当前主要支持 `DAGView` 任务图查看。本文档围绕 DAGView 介绍数据准备、页面访问、数据集选择、DAG 图浏览和节点检索等常用操作。 | ||
| 6 | + | ||
| 7 | +其他页面及高级联动能力暂未实现。 | ||
| 8 | + | ||
| 9 | +--- | ||
| 10 | + | ||
| 11 | +## 2. 前置准备 | ||
| 12 | + | ||
| 13 | +使用 Insight V3 前,请确认 Checker 已完成运行,并已生成 Insight 数据。 | ||
| 14 | + | ||
| 15 | +如需配置 Checker 数据输出,请确认 Checker 配置文件中已开启 Insight dump: | ||
| 16 | + | ||
| 17 | +```json | ||
| 18 | +# 配置文件位于 /pathto/hccl_vm_install/plugin/checker/manifest.json | ||
| 19 | + | ||
| 20 | +{ | ||
| 21 | + ... | ||
| 22 | + "setting": { // Checker插件配置项 | ||
| 23 | + ... | ||
| 24 | + "enable_insight_dump": true, // 是否启用可视化数据输出(默认为关闭状态) | ||
| 25 | + "enable_memory_snapshot_dump": false // 是否启用可视化内存快照数据输出(默认关闭,仅支持老Checker,需要先开启可视化数据输出"enable_insight_dump") | ||
| 26 | + } | ||
| 27 | +} | ||
| 28 | +``` | ||
| 29 | + | ||
| 30 | +DAGView 至少需要以下数据文件: | ||
| 31 | + | ||
| 32 | +```text | ||
| 33 | +<dataset_name>/ | ||
| 34 | +├── manifest.json | ||
| 35 | +└── graph/ | ||
| 36 | + ├── graph.msgpack | ||
| 37 | + └── layout.msgpack | ||
| 38 | +``` | ||
| 39 | + | ||
| 40 | +其中,`manifest.json` 用于读取数据集元信息,`graph.msgpack` 和 `layout.msgpack` 用于绘制 DAG 任务图。 | ||
| 41 | + | ||
| 42 | +--- | ||
| 43 | + | ||
| 44 | +## 3. 编译与安装 Insight 插件 | ||
| 45 | + | ||
| 46 | +Insight V3 当前前端源码位于: | ||
| 47 | + | ||
| 48 | +```text | ||
| 49 | +{hccl_vm目录}/src/plugin/insight/frontend_v3 | ||
| 50 | +``` | ||
| 51 | + | ||
| 52 | +在安装 Insight 插件前,请先完成前端编译,再执行 HCCL VM 的构建安装流程。 | ||
| 53 | + | ||
| 54 | +推荐步骤如下: | ||
| 55 | + | ||
| 56 | +1. 进入前端目录: | ||
| 57 | + | ||
| 58 | +```bash | ||
| 59 | +cd {hccl_vm目录}/src/plugin/insight/frontend_v3 | ||
| 60 | +``` | ||
| 61 | + | ||
| 62 | +2. 安装前端依赖: | ||
| 63 | + | ||
| 64 | +```bash | ||
| 65 | +npm install | ||
| 66 | +``` | ||
| 67 | + | ||
| 68 | +3. 编译前端产物: | ||
| 69 | + | ||
| 70 | +```bash | ||
| 71 | +npm run build | ||
| 72 | +``` | ||
| 73 | + | ||
| 74 | +前端编译完成后,会生成 `src/plugin/insight/dist/` 目录。 | ||
| 75 | + | ||
| 76 | +4. 回到 HCCL_VM 根目录,执行 `build.sh` 编译并安装 hccl-vm: | ||
| 77 | + | ||
| 78 | +```bash | ||
| 79 | +cd {HCCL_VM目录} | ||
| 80 | +bash build.sh --package-path <ASCEND_CANN_PATH> --hcomm-path <HCOMM_CODE_PATH> | ||
| 81 | +``` | ||
| 82 | + | ||
| 83 | +如需打包安装目录,可附加 `--pkg`。若当前构建场景要求 AICPU / AIV / FULL 模式,可按项目常规流程追加 `--aicpu`、`--aiv` 或 `--full` 参数。 | ||
| 84 | + | ||
| 85 | +--- | ||
| 86 | + | ||
| 87 | +## 4. Insight 插件配置与启停 | ||
| 88 | + | ||
| 89 | +Insight 插件配置文件位于: | ||
| 90 | + | ||
| 91 | +```text | ||
| 92 | +hccl_vm_install/plugin/visualization/insight/manifest.json | ||
| 93 | +``` | ||
| 94 | + | ||
| 95 | +当前默认配置如下: | ||
| 96 | + | ||
| 97 | +```json | ||
| 98 | +{ | ||
| 99 | + "name": "insight", | ||
| 100 | + "version": "1.0.0", | ||
| 101 | + "entry": "python3 server.py", | ||
| 102 | + "dependency": { | ||
| 103 | + "min_core_version": "1.0.0" | ||
| 104 | + }, | ||
| 105 | + "setting": { | ||
| 106 | + "dist_path": "./dist", | ||
| 107 | + "data_path": "../../checker/data/insight", | ||
| 108 | + "topo_config_path": "../../../../../asset/cluster_model/config/cluster", | ||
| 109 | + "port": 8080 | ||
| 110 | + } | ||
| 111 | +} | ||
| 112 | +``` | ||
| 113 | + | ||
| 114 | +常用字段说明如下: | ||
| 115 | + | ||
| 116 | +| 字段 | 说明 | | ||
| 117 | +|------|------| | ||
| 118 | +| `entry` | Insight 插件启动命令,当前通过 `python3 server.py` 启动服务 | | ||
| 119 | +| `setting.dist_path` | 前端静态资源目录,默认读取 `./dist` | | ||
| 120 | +| `setting.data_path` | Insight 数据目录,默认指向 Checker 输出的 `data/insight` | | ||
| 121 | +| `setting.topo_config_path` | 集群拓扑配置目录 | | ||
| 122 | +| `setting.port` | Insight 服务端口,默认 `8080` | | ||
| 123 | + | ||
| 124 | +若需要修改端口或数据目录,可直接编辑该 `manifest.json` 中的 `setting` 字段。 | ||
| 125 | + | ||
| 126 | +插件安装与卸载命令如下: | ||
| 127 | + | ||
| 128 | +```bash | ||
| 129 | +# 安装并启动 Insight 插件 | ||
| 130 | +hccl-vm plugin install @insight | ||
| 131 | + | ||
| 132 | +# 卸载 Insight 插件 | ||
| 133 | +hccl-vm plugin uninstall @insight | ||
| 134 | +``` | ||
| 135 | + | ||
| 136 | +--- | ||
| 137 | + | ||
| 138 | +## 5. 打开 Insight | ||
| 139 | + | ||
| 140 | +若 Insight 服务已启动,请直接在浏览器中打开服务地址,例如: | ||
| 141 | + | ||
| 142 | +```text | ||
| 143 | +http://localhost:8080 | ||
| 144 | +``` | ||
| 145 | + | ||
| 146 | +若需要通过插件启动 Insight,可执行: | ||
| 147 | + | ||
| 148 | +```bash | ||
| 149 | +hccl-vm plugin install @insight | ||
| 150 | +``` | ||
| 151 | + | ||
| 152 | +插件启动后,终端会输出访问地址。请在浏览器中打开该地址进入 Insight 页面。 | ||
| 153 | + | ||
| 154 | + | ||
| 155 | + | ||
| 156 | +--- | ||
| 157 | + | ||
| 158 | +## 6. 选择数据集 | ||
| 159 | + | ||
| 160 | +打开 Insight 后,默认进入 `总览` 页面。请按以下步骤选择需要分析的数据集: | ||
| 161 | + | ||
| 162 | +1. 在中间的数据集表格中查看数据集列表。 | ||
| 163 | +2. 点击目标数据集。 | ||
| 164 | +3. 在左侧 Rank 树中确认需要查看的 Rank。 | ||
| 165 | +4. 如 DAG 图规模较大,可先减少 Rank 选择范围。 | ||
| 166 | +5. 点击右侧 `进入关联视图`。 | ||
| 167 | + | ||
| 168 | + | ||
| 169 | + | ||
| 170 | +建议首次分析时先选择少量 Rank,确认分析方向后再逐步扩大 Rank 范围。 | ||
| 171 | + | ||
| 172 | +--- | ||
| 173 | + | ||
| 174 | +## 7. 进入 DAGView | ||
| 175 | + | ||
| 176 | +进入 `关联` 页面后,重点查看下半部分的 `DAGView 任务视图`。 | ||
| 177 | + | ||
| 178 | +页面主要区域如下: | ||
| 179 | + | ||
| 180 | +| 区域 | 功能 | | ||
| 181 | +|------|------| | ||
| 182 | +| 左侧面板 | 选择 Rank、搜索节点 | | ||
| 183 | +| 中间下方 | 展示 DAG 任务图 | | ||
| 184 | +| 右侧详情栏 | 查看当前节点详情 | | ||
| 185 | + | ||
| 186 | +若上方内存视图为空,不影响下方 DAGView 的查看和使用。 | ||
| 187 | + | ||
| 188 | +--- | ||
| 189 | + | ||
| 190 | +## 8. 查看 DAG 任务图 | ||
| 191 | + | ||
| 192 | +DAG 任务图由泳道、节点和箭头组成: | ||
| 193 | + | ||
| 194 | +| 元素 | 说明 | | ||
| 195 | +|------|------| | ||
| 196 | +| 泳道 | 表示一个执行队列,通常显示为 `Rank / Stream / Queue` | | ||
| 197 | +| 节点 | 表示一个任务,例如数据搬运、Reduce、Record、Wait 等 | | ||
| 198 | +| 箭头 | 表示任务之间的依赖关系 | | ||
| 199 | +| Loop 虚线框 | 表示一个 Loop 区域,会用虚线框圈住该 Loop 内相关节点,并在框外显示 `Loop` 标记 | | ||
| 200 | + | ||
| 201 | +常见节点类型如下: | ||
| 202 | + | ||
| 203 | +| 节点类型 | 含义 | | ||
| 204 | +|----------|------| | ||
| 205 | +| `TRANS_MEM` | 数据搬运任务 | | ||
| 206 | +| `REDUCE` | Reduce 任务 | | ||
| 207 | +| `RECORD` | Notify record 任务 | | ||
| 208 | +| `WAIT` | Notify wait 任务 | | ||
| 209 | +| `CCU_GRAPH` | CCU 图任务 | | ||
| 210 | +| `AIV_GRAPH` | AIV 图任务 | | ||
| 211 | + | ||
| 212 | +推荐查看方式: | ||
| 213 | + | ||
| 214 | +1. 按箭头方向查看任务依赖顺序。 | ||
| 215 | +2. 点击关注的任务节点。 | ||
| 216 | +3. 在右侧详情栏查看该节点所属的 Rank、Stream、Queue 及节点详细信息。 | ||
| 217 | +4. 继续查看该节点的父节点和子节点,追踪上下游依赖。 | ||
| 218 | + | ||
| 219 | +关于 Loop 展示,建议额外关注以下信息: | ||
| 220 | + | ||
| 221 | +1. 若 DAG 中存在 Loop,页面会自动在任务图上叠加 Loop 虚线框。 | ||
| 222 | +2. 虚线框会覆盖该 Loop 的起点、终点及循环体内部节点,便于快速识别循环边界。 | ||
| 223 | +3. 点击 Loop 胶囊后,可直接定位到对应的 Loop Start 节点。 | ||
| 224 | +4. 选中 Loop 内部节点后,右侧详情栏会展示该节点所属的 Loop 信息和嵌套链路。 | ||
| 225 | + | ||
| 226 | + | ||
| 227 | + | ||
| 228 | +--- | ||
| 229 | + | ||
| 230 | +## 9. 画布操作 | ||
| 231 | + | ||
| 232 | +DAGView 画布支持以下操作: | ||
| 233 | + | ||
| 234 | +| 操作 | 说明 | | ||
| 235 | +|------|------| | ||
| 236 | +| 移动画布 | 拖拽空白区域 | | ||
| 237 | +| 放大 / 缩小 | 使用鼠标滚轮,或点击右下角 `+` / `-` | | ||
| 238 | +| 重置缩放 | 点击右下角百分比按钮 | | ||
| 239 | +| 选中节点 | 点击目标节点 | | ||
| 240 | + | ||
| 241 | +当图规模较大时,建议先缩小 Rank 选择范围,再放大局部区域查看依赖。 | ||
| 242 | + | ||
| 243 | +--- | ||
| 244 | + | ||
| 245 | +## 10. 查看节点详情 | ||
| 246 | + | ||
| 247 | +点击 DAG 节点后,右侧详情栏会展示节点信息。常用信息如下: | ||
| 248 | + | ||
| 249 | +| 区块 | 说明 | | ||
| 250 | +|------|------| | ||
| 251 | +| 节点概览 | 节点 ID、任务类型、Rank、Stream、Queue | | ||
| 252 | +| Loop 信息 | 当前节点所属 Loop、Loop 次数、指令范围、Loop 边界等 | | ||
| 253 | +| 父节点 | 当前节点依赖的上游节点 | | ||
| 254 | +| 子节点 | 依赖当前节点的下游节点 | | ||
| 255 | +| 节点语义 | Notify、Task 元数据、Memory Slices 等 | | ||
| 256 | +| 原始 JSON | 当前节点的完整原始信息 | | ||
| 257 | + | ||
| 258 | +排查依赖关系时,建议优先查看 `父节点` 和 `子节点`;排查循环结构时,可重点查看 `Loop 信息`;排查数据搬运相关问题时,可重点查看 `Memory Slices`。 | ||
| 259 | + | ||
| 260 | +其中 `Memory Slices` 区块有以下展示规则: | ||
| 261 | + | ||
| 262 | +1. 普通内存 Slice 会显示 `rank / type / offset / size`。 | ||
| 263 | +2. 若 Slice 属于 `MS_CCU`,Insight V3 会优先显示 `MSID`,而不是底层抽象 offset。 | ||
| 264 | +3. 对于 batch 类任务,若存在多个 `MS_CCU` Slice,会自动合并为一个汇总卡片。 | ||
| 265 | +4. 汇总卡片会显示类似 `共计使用8个MSID` 的说明。 | ||
| 266 | +5. 展开 `MSID 明细` 后,可逐项查看每个 `MSID` 对应的 `id` 和 `size`。 | ||
| 267 | + | ||
| 268 | +--- | ||
| 269 | + | ||
| 270 | +## 11. 搜索节点 | ||
| 271 | + | ||
| 272 | +左侧 `搜索` 面板可用于快速定位 DAG 节点。 | ||
| 273 | + | ||
| 274 | +支持的搜索字段如下: | ||
| 275 | + | ||
| 276 | +| 字段 | 使用场景 | | ||
| 277 | +|------|----------| | ||
| 278 | +| `taskId` | 已知节点 ID 时使用 | | ||
| 279 | +| `taskType` | 按任务类型查找,例如 `TRANS_MEM` | | ||
| 280 | +| `notifyId` | 按 notify id 查找 | | ||
| 281 | + | ||
| 282 | +操作步骤: | ||
| 283 | + | ||
| 284 | +1. 在左侧搜索面板选择搜索字段。 | ||
| 285 | +2. 输入完整关键词。 | ||
| 286 | +3. 点击搜索结果。 | ||
| 287 | +4. DAGView 会自动定位并选中对应节点。 | ||
| 288 | + | ||
| 289 | +当前搜索为精确匹配。若未找到结果,请确认关键词是否完整,以及目标 Rank 是否已被勾选。 | ||
| 290 | + | ||
| 291 | +--- | ||
| 292 | + | ||
| 293 | +## 12. 推荐分析流程 | ||
| 294 | + | ||
| 295 | +建议按以下流程进行 DAGView 分析: | ||
| 296 | + | ||
| 297 | +1. 在 `总览` 页面选择数据集。 | ||
| 298 | +2. 在左侧 Rank 树中选择少量 Rank。 | ||
| 299 | +3. 点击 `进入关联视图`。 | ||
| 300 | +4. 在 DAGView 中查看整体节点和依赖箭头。 | ||
| 301 | +5. 点击关注节点并查看右侧详情。 | ||
| 302 | +6. 通过父节点和子节点追踪上下游依赖。 | ||
| 303 | +7. 使用搜索功能快速定位已知节点。 | ||
| 304 | + | ||
| 305 | +--- | ||
| 306 | + | ||
| 307 | +## 13. 常见问题 | ||
| 308 | + | ||
| 309 | +### 页面没有数据 | ||
| 310 | + | ||
| 311 | +请确认 Insight 服务地址是否正确,并确认 Checker 已生成 Insight 数据。 | ||
| 312 | + | ||
| 313 | +### 进入关联页后 DAG 为空 | ||
| 314 | + | ||
| 315 | +请确认数据集中存在以下文件: | ||
| 316 | + | ||
| 317 | +```text | ||
| 318 | +graph/graph.msgpack | ||
| 319 | +graph/layout.msgpack | ||
| 320 | +``` | ||
| 321 | + | ||
| 322 | +### DAG 图过于密集 | ||
| 323 | + | ||
| 324 | +建议先减少左侧 Rank 勾选数量,只查看部分 Rank,再放大局部区域进行分析。 | ||
| 325 | + | ||
| 326 | +### 搜索不到节点 | ||
| 327 | + | ||
| 328 | +请确认搜索关键词完整,并确认目标节点所在 Rank 已被勾选。 | ||
| @@ -18,7 +18,7 @@ HVRM Insight 是一个分布式算子可视化分析工具,用于对 HCCL 集 | |||
| 18 | 18 | ||
| 19 | HVRM Insight 依赖 Checker 插件输出的数据文件。使用前,请确保已完整运行过 Checker,并在 Checker 的配置文件中开启以下两个数据输出开关: | 19 | HVRM Insight 依赖 Checker 插件输出的数据文件。使用前,请确保已完整运行过 Checker,并在 Checker 的配置文件中开启以下两个数据输出开关: |
| 20 | 20 | ||
| 21 | -Checker配置文件默认位于`/path/to/hccl_vm_install/plugin/validate/checker/manifest.json` | 21 | +Checker配置文件默认位于`/path/to/hccl_vm_install/plugin/checker/manifest.json` |
| 22 | 22 | ||
| 23 | ```json | 23 | ```json |
| 24 | "setting": { | 24 | "setting": { |
| @@ -83,14 +83,20 @@ python3 serve.py | |||
| 83 | 83 | ||
| 84 | 浏览所有数据集,点击选择目标数据集,查看算子信息和统计数据,然后进入关联分析页面。 | 84 | 浏览所有数据集,点击选择目标数据集,查看算子信息和统计数据,然后进入关联分析页面。 |
| 85 | 85 | ||
| 86 | + | ||
| 87 | + | ||
| 86 | ### 场景二:联动分析内存与任务图(MemView) | 88 | ### 场景二:联动分析内存与任务图(MemView) |
| 87 | 89 | ||
| 88 | 通过内存时间线和 DAG 任务图的联动,定位某个 Step 的内存操作、查看节点详情、追溯数据来源。 | 90 | 通过内存时间线和 DAG 任务图的联动,定位某个 Step 的内存操作、查看节点详情、追溯数据来源。 |
| 89 | 91 | ||
| 92 | + | ||
| 93 | + | ||
| 90 | ### 场景三:查看报错并跳转到问题现场(Analytic) | 94 | ### 场景三:查看报错并跳转到问题现场(Analytic) |
| 91 | 95 | ||
| 92 | 在 Analytic 页面或 MemView 左侧报错列表中查看错误详情,然后一键跳转到关联的 DAG 节点或内存上下文。 | 96 | 在 Analytic 页面或 MemView 左侧报错列表中查看错误详情,然后一键跳转到关联的 DAG 节点或内存上下文。 |
| 93 | 97 | ||
| 98 | + | ||
| 99 | + | ||
| 94 | --- | 100 | --- |
| 95 | 101 | ||
| 96 | ## 页面详解 | 102 | ## 页面详解 |
| @@ -103,8 +109,12 @@ Dashboard 是使用工具的起点,页面从左到右分为三个区域: | |||
| 103 | - **中间**:数据集列表。点击某一行选中数据集,左侧和右侧同步刷新 | 109 | - **中间**:数据集列表。点击某一行选中数据集,左侧和右侧同步刷新 |
| 104 | - **右侧**:选中数据集的详情面板,展示统计信息和跳转按钮 | 110 | - **右侧**:选中数据集的详情面板,展示统计信息和跳转按钮 |
| 105 | 111 | ||
| 112 | + | ||
| 113 | + | ||
| 106 | 选中数据集后,右侧展示详细统计: | 114 | 选中数据集后,右侧展示详细统计: |
| 107 | 115 | ||
| 116 | + | ||
| 117 | + | ||
| 108 | 详情面板底部提供两个跳转入口: | 118 | 详情面板底部提供两个跳转入口: |
| 109 | 119 | ||
| 110 | - **`进入关联视图`**:跳转到 MemView,带入当前数据集和 Rank 选择 | 120 | - **`进入关联视图`**:跳转到 MemView,带入当前数据集和 Rank 选择 |
| @@ -114,6 +124,8 @@ Dashboard 是使用工具的起点,页面从左到右分为三个区域: | |||
| 114 | 124 | ||
| 115 | MemView 将内存时间线和 DAG 任务图放在同一视图中联动展示,是排查问题的核心页面。 | 125 | MemView 将内存时间线和 DAG 任务图放在同一视图中联动展示,是排查问题的核心页面。 |
| 116 | 126 | ||
| 127 | + | ||
| 128 | + | ||
| 117 | **页面布局:** | 129 | **页面布局:** |
| 118 | 130 | ||
| 119 | - **左侧**:Rank 选择树、报错列表(Issues)、搜索面板 | 131 | - **左侧**:Rank 选择树、报错列表(Issues)、搜索面板 |
| @@ -121,6 +133,8 @@ MemView 将内存时间线和 DAG 任务图放在同一视图中联动展示, | |||
| 121 | - **下半区**:DAG 任务图 —— 按 Rank / Stream 泳道展示任务节点和依赖关系 | 133 | - **下半区**:DAG 任务图 —— 按 Rank / Stream 泳道展示任务节点和依赖关系 |
| 122 | - **右侧**:详情栏 —— 展示当前选中 Step 或节点的详细信息 | 134 | - **右侧**:详情栏 —— 展示当前选中 Step 或节点的详细信息 |
| 123 | 135 | ||
| 136 | + | ||
| 137 | + | ||
| 124 | #### 核心联动机制:Step、Rank、Task 三者联动 | 138 | #### 核心联动机制:Step、Rank、Task 三者联动 |
| 125 | 139 | ||
| 126 | - 在时间线上选中一个 Step → DAG 同步高亮对应节点 | 140 | - 在时间线上选中一个 Step → DAG 同步高亮对应节点 |
| @@ -144,6 +158,8 @@ MemView 将内存时间线和 DAG 任务图放在同一视图中联动展示, | |||
| 144 | 158 | ||
| 145 | Analytic 集中展示校验过程中发现的所有错误,页面分为三个区域: | 159 | Analytic 集中展示校验过程中发现的所有错误,页面分为三个区域: |
| 146 | 160 | ||
| 161 | + | ||
| 162 | + | ||
| 147 | - **左侧**:数据集与 Rank 选择 | 163 | - **左侧**:数据集与 Rank 选择 |
| 148 | - **中间**:报错列表,每条错误展示标题、严重程度标签(颜色区分)、关键字段摘要和原始错误码 | 164 | - **中间**:报错列表,每条错误展示标题、严重程度标签(颜色区分)、关键字段摘要和原始错误码 |
| 149 | - **右侧**:选中错误的详情面板,包括错误基本信息、涉及的 Rank、关联节点信息、Slice 详情(精确定位数据不一致的内存位置)、补充信息和原始 JSON | 165 | - **右侧**:选中错误的详情面板,包括错误基本信息、涉及的 Rank、关联节点信息、Slice 详情(精确定位数据不一致的内存位置)、补充信息和原始 JSON |
| @@ -0,0 +1,3 @@ | |||
| 1 | +version https://git-lfs.github.com/spec/v1 | ||
| 2 | +oid sha256:9bd6fdabd019c274e01ca1565d627a5d2f179ad5f2f5f61e639b3685547ea47b | ||
| 3 | +size 4795196 | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | +version https://git-lfs.github.com/spec/v1 | ||
| 2 | +oid sha256:656143fa919b0da1d15929c2031d6144222afe7266a34045f0f4f8f1158a9e6e | ||
| 3 | +size 3951263 | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | +version https://git-lfs.github.com/spec/v1 | ||
| 2 | +oid sha256:6eedaa1041718bdb503535db9b47d7fe66294dc73748c0da9767e5d4b6c296d7 | ||
| 3 | +size 2843499 | ||
| @@ -35,6 +35,6 @@ uint32_t GetAICoreCount(uint64_t deviceId); | |||
| 35 | uint32_t GetVectorCoreCount(uint64_t deviceId); | 35 | 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); | 38 | +bool GetRankIdByMPI(uint32_t &rankId, uint64_t &serverId); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| @@ -89,6 +89,7 @@ private: | |||
| 89 | sim::SqliteTable<sim::RaJetty> m_raJettyTbl; | 89 | sim::SqliteTable<sim::RaJetty> m_raJettyTbl; |
| 90 | sim::SqliteTable<sim::RaJfc> m_raJfcTbl; | 90 | sim::SqliteTable<sim::RaJfc> m_raJfcTbl; |
| 91 | sim::SqliteTable<sim::RaCr> m_raCrTbl; | 91 | sim::SqliteTable<sim::RaCr> m_raCrTbl; |
| 92 | + sim::SqliteTable<sim::RunModeConfig> m_runModeConfigTbl; | ||
| 92 | 93 | ||
| 93 | std::mutex m_lazyMutex; | 94 | std::mutex m_lazyMutex; |
| 94 | std::unordered_map<std::type_index, sim::TableBase*> m_tableMap; | 95 | std::unordered_map<std::type_index, sim::TableBase*> m_tableMap; |
| @@ -154,6 +155,7 @@ public: | |||
| 154 | , m_raJettyTbl(m_db.GetDb(), "RaJetty") | 155 | , m_raJettyTbl(m_db.GetDb(), "RaJetty") |
| 155 | , m_raJfcTbl(m_db.GetDb(), "RaJfc") | 156 | , m_raJfcTbl(m_db.GetDb(), "RaJfc") |
| 156 | , m_raCrTbl(m_db.GetDb(), "RaCr") | 157 | , m_raCrTbl(m_db.GetDb(), "RaCr") |
| 158 | + , m_runModeConfigTbl(m_db.GetDb(), "RunModeConfig") | ||
| 157 | { | 159 | { |
| 158 | RegisterTable(m_serverTbl, "Server"); | 160 | RegisterTable(m_serverTbl, "Server"); |
| 159 | RegisterTable(m_hostTbl, "Host"); | 161 | RegisterTable(m_hostTbl, "Host"); |
| @@ -206,6 +208,7 @@ public: | |||
| 206 | RegisterTable(m_raJettyTbl, "RaJetty"); | 208 | RegisterTable(m_raJettyTbl, "RaJetty"); |
| 207 | RegisterTable(m_raJfcTbl, "RaJfc"); | 209 | RegisterTable(m_raJfcTbl, "RaJfc"); |
| 208 | RegisterTable(m_raCrTbl, "RaCr"); | 210 | RegisterTable(m_raCrTbl, "RaCr"); |
| 211 | + RegisterTable(m_runModeConfigTbl, "RunModeConfig"); | ||
| 209 | } | 212 | } |
| 210 | 213 | ||
| 211 | SimRunnerSqliteDB(const SimRunnerSqliteDB&) = delete; | 214 | SimRunnerSqliteDB(const SimRunnerSqliteDB&) = delete; |
| @@ -26,6 +26,11 @@ typedef struct { | |||
| 26 | char version[16]; | 26 | char version[16]; |
| 27 | } Server; | 27 | } Server; |
| 28 | 28 | ||
| 29 | +typedef struct { | ||
| 30 | + uint64_t id; // PK | ||
| 31 | + uint8_t mode; // 0=normal,1=check-only | ||
| 32 | +} RunModeConfig; | ||
| 33 | + | ||
| 29 | typedef struct { | 34 | typedef struct { |
| 30 | uint64_t id; // PK | 35 | uint64_t id; // PK |
| 31 | uint64_t server_id; | 36 | uint64_t server_id; |
| @@ -20,7 +20,7 @@ enum class DbType { | |||
| 20 | }; | 20 | }; |
| 21 | struct DBConfig { | 21 | struct DBConfig { |
| 22 | DbType type = DbType::SQLITE3; | 22 | DbType type = DbType::SQLITE3; |
| 23 | - std::string dbPath = "./hccl_vm_data.db"; | 23 | + std::string dbPath = "data/hccl_vm_data.db"; |
| 24 | std::string host; | 24 | std::string host; |
| 25 | uint16_t port = 0; | 25 | uint16_t port = 0; |
| 26 | std::string user; | 26 | std::string user; |
| @@ -0,0 +1,29 @@ | |||
| 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 | +class InstallPath { | ||
| 17 | +public: | ||
| 18 | + // 获取 hccl-vm-install 根目录的绝对路径 | ||
| 19 | + static const std::string& GetHcclVmInstallAbsPath(); | ||
| 20 | + | ||
| 21 | + // 把相对路径解析为基于 install root 的绝对路径 | ||
| 22 | + // @param relPath 相对路径(如 "data/hccl_vm_data.db") | ||
| 23 | + // @note - 已是绝对路径(以 '/' 开头)则原样返回 | ||
| 24 | + // - 以 "./" 开头也原样返回 | ||
| 25 | + // - 空字符串原样返回 | ||
| 26 | + static std::string ResolveToInstallRoot(const std::string& relPath); | ||
| 27 | +}; | ||
| 28 | + | ||
| 29 | + | ||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -75,6 +76,7 @@ struct LogConfig | |||
| 75 | bool enableCompress{false}; | 76 | bool enableCompress{false}; |
| 76 | }; | 77 | }; |
| 77 | 78 | ||
| 79 | +LogConfig LoadLogConfig(const std::string& process_name); | ||
| 78 | void InitLogger(const LogConfig& config); | 80 | void InitLogger(const LogConfig& config); |
| 79 | void FlushLog(); | 81 | void FlushLog(); |
| 80 | void DeInitLogger(); | 82 | void DeInitLogger(); |
| @@ -0,0 +1,22 @@ | |||
| 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 | +// 解析yaml文件 | ||
| 18 | +bool LoadYamlStringMap(const std::string& yamlPath, | ||
| 19 | + const std::string& nodeName, | ||
| 20 | + std::map<std::string, std::string>& out); | ||
| 21 | + | ||
| 22 | + | ||
| @@ -0,0 +1,42 @@ | |||
| 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 | +namespace sim { | ||
| 17 | +// HcclCommPool 复用区的准入策略,主机侧与设备侧共用的纯判定。阈值与上界集中在此定义。 | ||
| 18 | +struct CommPoolPolicy { | ||
| 19 | + static constexpr size_t kBigBlockThreshold = 200ULL * 1024 * 1024; // 200MB,对齐 CCL buffer 默认 | ||
| 20 | + // 复用区规格 4GB,大块可申请和可寻址的上界(含等于)。超过 4GB 由 ExceedsCeiling 报错。 | ||
| 21 | + static constexpr size_t kPoolSize = 4ULL * 1024 * 1024 * 1024; // 4GB | ||
| 22 | + | ||
| 23 | + // 复用区共享内存名。 | ||
| 24 | + static constexpr const char* kPoolName = "HcclCommPool"; | ||
| 25 | + | ||
| 26 | + // 本次申请是否应引流到复用区:仅校验模式开且 threshold <= size <= poolSize。 | ||
| 27 | + static bool ShouldRedirect(size_t size, bool checkOnlyMode, | ||
| 28 | + size_t threshold = kBigBlockThreshold, | ||
| 29 | + size_t poolSize = kPoolSize) | ||
| 30 | + { | ||
| 31 | + return checkOnlyMode && size >= threshold && size <= poolSize; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + // 本次申请是否超出复用区上界、应报错:仅仅校验模式下拦 size > poolSize。 | ||
| 35 | + static bool ExceedsCeiling(size_t size, bool checkOnlyMode, size_t poolSize = kPoolSize) | ||
| 36 | + { | ||
| 37 | + return checkOnlyMode && size > poolSize; | ||
| 38 | + } | ||
| 39 | +}; | ||
| 40 | +} // namespace sim | ||
| 41 | + | ||
| 42 | + | ||
| @@ -51,7 +51,7 @@ public: | |||
| 51 | 51 | ||
| 52 | // 获取host地址 | 52 | // 获取host地址 |
| 53 | void* GetHostPtrByDevPtr(void* devPtr); | 53 | void* GetHostPtrByDevPtr(void* devPtr); |
| 54 | - | 54 | + |
| 55 | private: | 55 | private: |
| 56 | // 私有构造函数 | 56 | // 私有构造函数 |
| 57 | DeviceMemoryManager(); | 57 | DeviceMemoryManager(); |
| @@ -0,0 +1,22 @@ | |||
| 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 | +namespace sim { | ||
| 15 | +// 读 DB 的 RunModeConfig,返回是否仅校验模式,不缓存。表为空返回 false。 | ||
| 16 | +bool ProbeCheckOnlyMode(); | ||
| 17 | + | ||
| 18 | +// 进程内只读一次并缓存结果。 | ||
| 19 | +bool IsCheckOnlyMode(); | ||
| 20 | +} // namespace sim | ||
| 21 | + | ||
| 22 | + | ||
| @@ -298,12 +298,12 @@ run_test() { | |||
| 298 | sudo bash -c "cat > /etc/hccl_rootinfo.json << EOF | 298 | sudo bash -c "cat > /etc/hccl_rootinfo.json << EOF |
| 299 | { | 299 | { |
| 300 | \"version\": \"2.0\", | 300 | \"version\": \"2.0\", |
| 301 | - \"topo_file_path\": \"${CHECKER_PATH}/hccl_vm_install/topo.json\" | 301 | + \"topo_file_path\": \"${CHECKER_PATH}/hccl_vm_install/data/topo.json\" |
| 302 | } | 302 | } |
| 303 | EOF" | 303 | EOF" |
| 304 | else | 304 | else |
| 305 | info "更新hccl_rootinfo.json文件..." | 305 | info "更新hccl_rootinfo.json文件..." |
| 306 | - sudo sed -i -E 's|"topo_file_path"\s*:\s*".*"|"topo_file_path": "${CHECKER_PATH}/hccl_vm_install/topo.json"|g' /etc/hccl_rootinfo.json | 306 | + sudo sed -i -E 's|"topo_file_path"\s*:\s*".*"|"topo_file_path": "${CHECKER_PATH}/hccl_vm_install/data/topo.json"|g' /etc/hccl_rootinfo.json |
| 307 | fi | 307 | fi |
| 308 | 308 | ||
| 309 | # 配置环境变量 | 309 | # 配置环境变量 |
| @@ -71,13 +71,22 @@ target_include_directories(hccl-vm PUBLIC | |||
| 71 | 71 | ||
| 72 | target_link_libraries(hccl-vm | 72 | target_link_libraries(hccl-vm |
| 73 | PRIVATE | 73 | PRIVATE |
| 74 | - common | 74 | + -Wl,--whole-archive |
| 75 | - runnerdb | ||
| 76 | - store | ||
| 77 | - log | ||
| 78 | cmd | 75 | cmd |
| 76 | + common | ||
| 77 | + store | ||
| 78 | + topo | ||
| 79 | + loader | ||
| 80 | + runnerdb | ||
| 79 | modeldb | 81 | modeldb |
| 82 | + log | ||
| 83 | + -Wl,--no-whole-archive | ||
| 84 | + dl | ||
| 85 | + rt | ||
| 80 | sqlite3 | 86 | sqlite3 |
| 87 | + yaml-cpp::yaml-cpp | ||
| 88 | + CLI11::CLI11 | ||
| 89 | + JSON::JSON | ||
| 81 | ) | 90 | ) |
| 82 | 91 | ||
| 83 | target_compile_options(hccl-vm PRIVATE | 92 | target_compile_options(hccl-vm PRIVATE |
| @@ -107,7 +116,7 @@ if(TARGET third_party_yaml_cpp) | |||
| 107 | endif() | 116 | endif() |
| 108 | 117 | ||
| 109 | install(TARGETS hccl-vm | 118 | install(TARGETS hccl-vm |
| 110 | - DESTINATION "." | 119 | + DESTINATION "bin" |
| 111 | # 文件的权限 (755) | 120 | # 文件的权限 (755) |
| 112 | PERMISSIONS | 121 | PERMISSIONS |
| 113 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 122 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| @@ -28,7 +28,7 @@ target_include_directories(cmd PRIVATE | |||
| 28 | ${CMAKE_CURRENT_SOURCE_DIR}/../../include/topo | 28 | ${CMAKE_CURRENT_SOURCE_DIR}/../../include/topo |
| 29 | ${CMAKE_CURRENT_SOURCE_DIR}/../../include/store | 29 | ${CMAKE_CURRENT_SOURCE_DIR}/../../include/store |
| 30 | ${CMAKE_CURRENT_SOURCE_DIR}/../../include | 30 | ${CMAKE_CURRENT_SOURCE_DIR}/../../include |
| 31 | - ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party | 31 | + ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/nlohmann_json |
| 32 | 32 | ||
| 33 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc | 33 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc |
| 34 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime | 34 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime |
| @@ -54,12 +54,11 @@ target_link_libraries(cmd PRIVATE | |||
| 54 | runnerdb | 54 | runnerdb |
| 55 | store | 55 | store |
| 56 | topo | 56 | topo |
| 57 | + CLI11::CLI11 | ||
| 58 | + yaml-cpp::yaml-cpp | ||
| 59 | + JSON::JSON | ||
| 57 | ) | 60 | ) |
| 58 | 61 | ||
| 59 | -target_link_libraries(cmd PRIVATE CLI11::CLI11) | ||
| 60 | -target_link_libraries(cmd PRIVATE yaml-cpp::yaml-cpp) | ||
| 61 | -target_link_libraries(cmd PRIVATE JSON::JSON) | ||
| 62 | - | ||
| 63 | if(TARGET third_party_yaml_cpp) | 62 | if(TARGET third_party_yaml_cpp) |
| 64 | add_dependencies(cmd third_party_yaml_cpp) | 63 | add_dependencies(cmd third_party_yaml_cpp) |
| 65 | endif() | 64 | endif() |
| @@ -30,6 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | + | ||
| 33 | 34 | ||
| 34 | 35 | ||
| 35 | 36 | ||
| @@ -41,10 +42,13 @@ | |||
| 41 | 42 | ||
| 42 | 43 | ||
| 43 | 44 | ||
| 45 | + | ||
| 46 | + | ||
| 44 | 47 | ||
| 45 | 48 | ||
| 46 | 49 | ||
| 47 | 50 | ||
| 51 | + | ||
| 48 | 52 | ||
| 49 | 53 | ||
| 50 | 54 | ||
| @@ -327,7 +331,11 @@ std::string GetBinLocation() { | |||
| 327 | if (ec) { | 331 | if (ec) { |
| 328 | throw std::runtime_error("read_symlink failed: " + ec.message()); | 332 | throw std::runtime_error("read_symlink failed: " + ec.message()); |
| 329 | } | 333 | } |
| 330 | - return exePath.parent_path().string(); | 334 | + fs::path binDir = exePath.parent_path(); |
| 335 | + if (binDir.filename() == "bin") { | ||
| 336 | + return binDir.parent_path().string(); | ||
| 337 | + } | ||
| 338 | + return binDir.string(); | ||
| 331 | } | 339 | } |
| 332 | 340 | ||
| 333 | std::string ArgvToString(int argc, char *argv[]) { | 341 | std::string ArgvToString(int argc, char *argv[]) { |
| @@ -396,7 +404,7 @@ std::string FileInModelDir(const std::string& fileName) { | |||
| 396 | } | 404 | } |
| 397 | return ""; | 405 | return ""; |
| 398 | } | 406 | } |
| 399 | - std::string filePath = GetBinLocation() + "/cluster_model/topo_meta/" + fileName + ".yaml"; | 407 | + std::string filePath = GetBinLocation() + "/config/topo_meta/" + fileName + ".yaml"; |
| 400 | auto fileExistd = [&]()->bool { | 408 | auto fileExistd = [&]()->bool { |
| 401 | std::ifstream f(filePath.c_str()); | 409 | std::ifstream f(filePath.c_str()); |
| 402 | return f.good(); | 410 | return f.good(); |
| @@ -415,12 +423,12 @@ std::string GenerateClusterTopo(const std::string& topoFileName) { | |||
| 415 | topoName.erase(topoName.find(".yaml"), 5); | 423 | topoName.erase(topoName.find(".yaml"), 5); |
| 416 | } | 424 | } |
| 417 | 425 | ||
| 418 | - std::string generateShellPath = GetBinLocation() + "/generate_cluster_topo.sh"; | 426 | + std::string generateShellPath = GetBinLocation() + "/script/generate_cluster_topo.sh"; |
| 419 | if (!fs::exists(generateShellPath)) { | 427 | if (!fs::exists(generateShellPath)) { |
| 420 | HCCL_VM_ERROR("[HVM] generate_cluster_topo.sh not found: {}", generateShellPath); | 428 | HCCL_VM_ERROR("[HVM] generate_cluster_topo.sh not found: {}", generateShellPath); |
| 421 | return "[HVM] generate_cluster_topo.sh not found: " + generateShellPath; | 429 | return "[HVM] generate_cluster_topo.sh not found: " + generateShellPath; |
| 422 | } | 430 | } |
| 423 | - std::string clusterConfigFilePath = GetBinLocation() + "/cluster_model/config/cluster/" + topoName + ".yaml"; | 431 | + std::string clusterConfigFilePath = GetBinLocation() + "/config/cluster/" + topoName + ".yaml"; |
| 424 | if (!fs::exists(clusterConfigFilePath)) { | 432 | if (!fs::exists(clusterConfigFilePath)) { |
| 425 | HCCL_VM_ERROR("[HVM] cluster config file not found: {}", clusterConfigFilePath); | 433 | HCCL_VM_ERROR("[HVM] cluster config file not found: {}", clusterConfigFilePath); |
| 426 | return "[HVM] cluster config file not found: " + clusterConfigFilePath; | 434 | return "[HVM] cluster config file not found: " + clusterConfigFilePath; |
| @@ -465,12 +473,21 @@ void ShowModel() { | |||
| 465 | return; | 473 | return; |
| 466 | } | 474 | } |
| 467 | 475 | ||
| 468 | -HcclVmResult InitHvmEnv(const std::string& configClusterDir, uint32_t level) | 476 | +HcclVmResult InitHvmEnv(const std::string& configClusterDir, uint32_t level, bool checkOnlyMode) |
| 469 | -{ | 477 | +{ |
| 470 | - HCCL_VM_INFO("Enter InitHvmEnv: {}", configClusterDir); | 478 | + HCCL_VM_INFO("Enter InitHvmEnv: {}", configClusterDir); |
| 471 | - // 启动仿真环境 | 479 | + // 启动仿真环境 |
| 472 | - // 创建用于Host-Device通信的共享内存 | 480 | + // 创建用于Host-Device通信的共享内存 |
| 473 | - void *shmptr =sim::MemoryManager::GetInstance().AllocMemByName("HcclAicpuData", sizeof(HcclAicpuData)); | 481 | + // 仅校验模式才创建大块复用区 HcclCommPool,须在其它共享内存创建前,仅一次。 |
| 482 | + if (checkOnlyMode) { | ||
| 483 | + void* commPool = sim::MemoryManager::GetInstance().AllocMemByName( | ||
| 484 | + sim::CommPoolPolicy::kPoolName, sim::CommPoolPolicy::kPoolSize); | ||
| 485 | + if (commPool == nullptr) { | ||
| 486 | + HCCL_VM_ERROR("[HVM] create HcclCommPool fail"); | ||
| 487 | + return HcclVmResult::HCCL_SIM_HOST_ERROR_CMD; | ||
| 488 | + } | ||
| 489 | + } | ||
| 490 | + void *shmptr =sim::MemoryManager::GetInstance().AllocMemByName("HcclAicpuData", sizeof(HcclAicpuData)); | ||
| 474 | if (shmptr == nullptr) { | 491 | if (shmptr == nullptr) { |
| 475 | HCCL_VM_ERROR("[HVM] Alloc Shared Memory fail "); | 492 | HCCL_VM_ERROR("[HVM] Alloc Shared Memory fail "); |
| 476 | return HcclVmResult::HCCL_SIM_HOST_ERROR_CMD; | 493 | return HcclVmResult::HCCL_SIM_HOST_ERROR_CMD; |
| @@ -498,7 +515,7 @@ HcclVmResult InitHvmCommEnv(const TopoMeta& topoMeta, const std::string& configF | |||
| 498 | { | 515 | { |
| 499 | // 通信域已初始化,则无需重复初始化 | 516 | // 通信域已初始化,则无需重复初始化 |
| 500 | if (AscendClusterTopoParser::GetInstance().GetClusterStatus() == HvmClusterStatus::COMM_DOMAIN_INIT_DONE) { | 517 | if (AscendClusterTopoParser::GetInstance().GetClusterStatus() == HvmClusterStatus::COMM_DOMAIN_INIT_DONE) { |
| 501 | - HCCL_VM_ERROR("[{}] communication domain already initialized", __func__); | 518 | + HCCL_VM_ERROR("communication domain already initialized"); |
| 502 | return HcclVmResult::HCCL_SIM_E_INTERNAL; | 519 | return HcclVmResult::HCCL_SIM_E_INTERNAL; |
| 503 | } | 520 | } |
| 504 | HcclVmResult ret; | 521 | HcclVmResult ret; |
| @@ -508,7 +525,7 @@ HcclVmResult InitHvmCommEnv(const TopoMeta& topoMeta, const std::string& configF | |||
| 508 | ret = AscendClusterTopoParser::GetInstance().InitCommunicationDomain(topoMeta, false); | 525 | ret = AscendClusterTopoParser::GetInstance().InitCommunicationDomain(topoMeta, false); |
| 509 | } else { | 526 | } else { |
| 510 | HCCL_VM_INFO("mock-comm cmd config rank table file, config by ranktable.json"); | 527 | HCCL_VM_INFO("mock-comm cmd config rank table file, config by ranktable.json"); |
| 511 | - std::string clusterInfo = GetBinLocation() + "/ranktable.json"; | 528 | + std::string clusterInfo = GetBinLocation() + "/data/ranktable.json"; |
| 512 | std::ifstream f(clusterInfo.c_str()); | 529 | std::ifstream f(clusterInfo.c_str()); |
| 513 | if (!f.good()) { | 530 | if (!f.good()) { |
| 514 | HCCL_VM_ERROR("ranktable.json file not found: {}", clusterInfo); | 531 | HCCL_VM_ERROR("ranktable.json file not found: {}", clusterInfo); |
| @@ -539,14 +556,20 @@ HcclVmResult HcclVmExit() | |||
| 539 | const fs::path backupDir = fs::path(g_binDir) / "data" / MakeDataBackupTimestamp(); | 556 | const fs::path backupDir = fs::path(g_binDir) / "data" / MakeDataBackupTimestamp(); |
| 540 | BackupAivTaskFiles(backupDir); | 557 | BackupAivTaskFiles(backupDir); |
| 541 | 558 | ||
| 542 | - HCCL_VM_INFO("start Destroy ALL Resources."); | 559 | + HCCL_VM_INFO("start Destroy ALL Resources."); |
| 543 | - int ret1 = system("sudo rm -fr /dev/shm/* 2>/dev/null"); | 560 | + // 仅校验模式才解除主进程对复用区 HcclCommPool 的映射,普通模式从未建池。 |
| 561 | + // 这里只解主进程自己这一份,共享内存文件何时真正删除由跨进程引用计数决定, | ||
| 562 | + // rank 还在用时不会删;异常退出未走到这里的,由下面的 rm 兜底删除。 | ||
| 563 | + if (sim::IsCheckOnlyMode()) { | ||
| 564 | + sim::MemoryManager::GetInstance().FreeMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 565 | + } | ||
| 566 | + int ret1 = system("sudo rm -fr /dev/shm/* 2>/dev/null"); | ||
| 544 | ret1 |= system("sudo rm -fr /tmp/hccl_sim.db* 2>/dev/null"); | 567 | ret1 |= system("sudo rm -fr /tmp/hccl_sim.db* 2>/dev/null"); |
| 545 | return ret; | 568 | return ret; |
| 546 | } | 569 | } |
| 547 | 570 | ||
| 548 | -HcclVmResult InstallUserPlugin(std::string argStr) { | 571 | +HcclVmResult InstallUserPlugin(std::string argStr) { |
| 549 | - // 处理插件tag和路径 | 572 | + // 处理插件tag和路径 |
| 550 | HcclVmResult ret {HcclVmResult::HCCL_SIM_HOST_ERROR_CMD}; | 573 | HcclVmResult ret {HcclVmResult::HCCL_SIM_HOST_ERROR_CMD}; |
| 551 | if (argStr.empty() || argStr[0] != '@') { | 574 | if (argStr.empty() || argStr[0] != '@') { |
| 552 | HCCL_VM_ERROR("[HVM] plugin tag should start with '@', invalid tag: {}", argStr); | 575 | HCCL_VM_ERROR("[HVM] plugin tag should start with '@', invalid tag: {}", argStr); |
| @@ -556,14 +579,19 @@ HcclVmResult InstallUserPlugin(std::string argStr) { | |||
| 556 | 579 | ||
| 557 | // 注册插件 | 580 | // 注册插件 |
| 558 | HcclPluginManager &pluginManager = HcclPluginManager::GetInstance(); | 581 | HcclPluginManager &pluginManager = HcclPluginManager::GetInstance(); |
| 559 | - ret = pluginManager.RegisterPlugin(argStr); | 582 | + ret = pluginManager.RegisterPlugin(argStr); |
| 560 | - if (ret != HcclVmResult::HCCL_SIM_SUCCESS) { | 583 | + if (ret != HcclVmResult::HCCL_SIM_SUCCESS) { |
| 561 | - HCCL_VM_ERROR("[HVM] Install plugin [{}] failed", argStr); | 584 | + HCCL_VM_ERROR("[HVM] Install plugin [{}] failed", argStr); |
| 562 | - return ret; | 585 | + return ret; |
| 563 | - } | 586 | + } |
| 564 | 587 | ||
| 565 | - return HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD; | 588 | + // 装 Runner 时若仅校验模式开着,复用池仍在、大块仍会引流,可能覆盖 Runner 真实数据,告警提示。 |
| 566 | -} | 589 | + if (argStr == "runner" && sim::IsCheckOnlyMode()) { |
| 590 | + HCCL_VM_WARN("[HVM] check-only mode on while runner installed; big-block contents are not guaranteed"); | ||
| 591 | + } | ||
| 592 | + | ||
| 593 | + return HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD; | ||
| 594 | +} | ||
| 567 | 595 | ||
| 568 | HcclVmResult RunUserPlugin(std::string argStr) { | 596 | HcclVmResult RunUserPlugin(std::string argStr) { |
| 569 | nlohmann::json j; | 597 | nlohmann::json j; |
| @@ -598,17 +626,18 @@ HcclVmResult UninstallUserPlugin(std::string argStr) { | |||
| 598 | lastTag.erase(lastTag.begin()); | 626 | lastTag.erase(lastTag.begin()); |
| 599 | pluginTags.push_back(lastTag); | 627 | pluginTags.push_back(lastTag); |
| 600 | 628 | ||
| 601 | - HcclPluginManager &pluginManager = HcclPluginManager::GetInstance(); | 629 | + HcclPluginManager &pluginManager = HcclPluginManager::GetInstance(); |
| 602 | - auto rets = pluginManager.StopPlugins(pluginTags); | 630 | + auto rets = pluginManager.StopPlugins(pluginTags); |
| 603 | - for (int i = 0; i < pluginTags.size(); ++i) { | ||
| 604 | - if (rets[i] != HcclVmResult::HCCL_SIM_SUCCESS) { | ||
| 605 | - HCCL_VM_ERROR("[HVM] plugin Uninstall fail : {}", pluginTags[i]); | ||
| 606 | - return rets[i]; | ||
| 607 | - } | ||
| 608 | - } | ||
| 609 | 631 | ||
| 610 | - return HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD; | 632 | + for (int i = 0; i < pluginTags.size(); ++i) { |
| 611 | -} | 633 | + if (rets[i] != HcclVmResult::HCCL_SIM_SUCCESS) { |
| 634 | + HCCL_VM_ERROR("[HVM] plugin Uninstall fail : {}", pluginTags[i]); | ||
| 635 | + return rets[i]; | ||
| 636 | + } | ||
| 637 | + } | ||
| 638 | + | ||
| 639 | + return HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD; | ||
| 640 | +} | ||
| 612 | 641 | ||
| 613 | void ShowUserPlugin() { | 642 | void ShowUserPlugin() { |
| 614 | std::vector<std::string> listPlugins{}; | 643 | std::vector<std::string> listPlugins{}; |
| @@ -654,8 +683,8 @@ HcclVmResult StartHvmCmd() { | |||
| 654 | 683 | ||
| 655 | // Child Process(Bash) | 684 | // Child Process(Bash) |
| 656 | // 劫持库存在性判断 | 685 | // 劫持库存在性判断 |
| 657 | - std::string hcclVmbin = g_binDir + "/hccl-vm"; | 686 | + std::string hcclVmbin = g_binDir + "/bin/hccl-vm"; |
| 658 | - std::string proxyPath = g_binDir + "/libhccl_proxy_level" + std::to_string(g_hcclVmLevel) + ".so"; | 687 | + std::string proxyPath = g_binDir + "/lib/x86_64/libhccl_proxy_level" + std::to_string(g_hcclVmLevel) + ".so"; |
| 659 | if (!fs::exists(proxyPath)) { | 688 | if (!fs::exists(proxyPath)) { |
| 660 | HCCL_VM_ERROR("[HVM] [ERROR] proxy hacking .so not found {}, please check your proxy hacking .so:" | 689 | HCCL_VM_ERROR("[HVM] [ERROR] proxy hacking .so not found {}, please check your proxy hacking .so:" |
| 661 | "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" | 690 | "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" |
| @@ -711,14 +740,14 @@ HcclVmResult StartHvmCmd() { | |||
| 711 | } else if (pid == 0) { | 740 | } else if (pid == 0) { |
| 712 | setenv(HVM_BASH_ENV_KEY.c_str(), g_binDir.c_str(), 1); | 741 | setenv(HVM_BASH_ENV_KEY.c_str(), g_binDir.c_str(), 1); |
| 713 | setenv("LD_PRELOAD", proxyPath.c_str(), 1); | 742 | setenv("LD_PRELOAD", proxyPath.c_str(), 1); |
| 743 | + setenv("HCCL_VM_INSTALL_ROOT", g_binDir.c_str(), 1); | ||
| 714 | execv("/bin/bash", bashArgv); | 744 | execv("/bin/bash", bashArgv); |
| 715 | - perror("bash execv failed"); | ||
| 716 | exit(1); | 745 | exit(1); |
| 717 | } else { | 746 | } else { |
| 718 | // Parent Process (Host) | 747 | // Parent Process (Host) |
| 719 | // 等待 bash 结束 (阻塞等待,保持Host存活) | 748 | // 等待 bash 结束 (阻塞等待,保持Host存活) |
| 720 | int status; | 749 | int status; |
| 721 | - waitpid(pid, &status, 0); | 750 | + waitpid(pid, &status, 0); |
| 722 | auto ret = HcclVmExit(); | 751 | auto ret = HcclVmExit(); |
| 723 | HCCL_VM_INFO("[HVM] Shell exited. Host shutting down."); | 752 | HCCL_VM_INFO("[HVM] Shell exited. Host shutting down."); |
| 724 | } | 753 | } |
| @@ -1088,7 +1117,7 @@ HcclVmResult ClearDbTables() | |||
| 1088 | const fs::path backupDir = fs::path(g_binDir) / "data" / MakeDataBackupTimestamp(); | 1117 | const fs::path backupDir = fs::path(g_binDir) / "data" / MakeDataBackupTimestamp(); |
| 1089 | BackupBinFiles(backupDir); | 1118 | BackupBinFiles(backupDir); |
| 1090 | BackupAivTaskFiles(backupDir); | 1119 | BackupAivTaskFiles(backupDir); |
| 1091 | - BackupDatabase("./hccl_vm_data.db"); | 1120 | + BackupDatabase(g_binDir + "/data/hccl_vm_data.db"); |
| 1092 | 1121 | ||
| 1093 | // 1. 清空 OpDbOps (SQLite) 中的静态表数据 | 1122 | // 1. 清空 OpDbOps (SQLite) 中的静态表数据 |
| 1094 | std::vector<std::string> staticTables = { | 1123 | std::vector<std::string> staticTables = { |
| @@ -1135,7 +1164,7 @@ HcclVmResult ClearDbTables() | |||
| 1135 | RunnerDB::DeleteAll<sim::RaSocket>(); | 1164 | RunnerDB::DeleteAll<sim::RaSocket>(); |
| 1136 | RunnerDB::DeleteAll<sim::RaSocketPair>(); | 1165 | RunnerDB::DeleteAll<sim::RaSocketPair>(); |
| 1137 | 1166 | ||
| 1138 | - CleanShmFilesByPrefix({"DEV", "ra_socket_"}); | 1167 | + CleanShmFilesByPrefix({"DEV", "ra_sock_"}); |
| 1139 | 1168 | ||
| 1140 | sim::ProcessSyncer syncer; | 1169 | sim::ProcessSyncer syncer; |
| 1141 | syncer.Reset(); | 1170 | syncer.Reset(); |
| @@ -1162,7 +1191,8 @@ HcclVmResult HcclVmResetCommDomain() | |||
| 1162 | HcclVmResult CopyFile(const std::string& clusterDir) { | 1191 | HcclVmResult CopyFile(const std::string& clusterDir) { |
| 1163 | // 1. 拼接源文件和目标文件路径 | 1192 | // 1. 拼接源文件和目标文件路径 |
| 1164 | auto srcPath = clusterDir + "/superpod0/server0/topo.json"; | 1193 | auto srcPath = clusterDir + "/superpod0/server0/topo.json"; |
| 1165 | - auto destPath = GetBinLocation() + "/topo.json"; | 1194 | + fs::create_directories(fs::path(GetBinLocation() + "/data")); |
| 1195 | + auto destPath = GetBinLocation() + "/data/topo.json"; | ||
| 1166 | 1196 | ||
| 1167 | // 显式提示:文件已存在,将覆盖 | 1197 | // 显式提示:文件已存在,将覆盖 |
| 1168 | if (fs::exists(destPath)) { | 1198 | if (fs::exists(destPath)) { |
| @@ -72,7 +72,7 @@ void RemoveFromLDPreload(const std::string& targetValue); | |||
| 72 | void ShowModel(); | 72 | void ShowModel(); |
| 73 | 73 | ||
| 74 | // init hvm env | 74 | // init hvm env |
| 75 | -HcclVmResult InitHvmEnv(const std::string& configClusterDir, uint32_t level); | 75 | +HcclVmResult InitHvmEnv(const std::string& configClusterDir, uint32_t level, bool checkOnlyMode); |
| 76 | HcclVmResult InitHvmCommEnv(const TopoMeta& topoMeta, const std::string& configFileName, uint32_t level); | 76 | HcclVmResult InitHvmCommEnv(const TopoMeta& topoMeta, const std::string& configFileName, uint32_t level); |
| 77 | HcclVmResult HcclVmExit(); | 77 | HcclVmResult HcclVmExit(); |
| 78 | HcclVmResult CopyFile(const std::string& clusterDir); | 78 | HcclVmResult CopyFile(const std::string& clusterDir); |
| @@ -38,7 +38,7 @@ bool SetEnvValue(const char* key, const std::string& value) | |||
| 38 | bool ParseYamlTopoImpl(const std::string& fileName, TopoMeta& topo) | 38 | bool ParseYamlTopoImpl(const std::string& fileName, TopoMeta& topo) |
| 39 | { | 39 | { |
| 40 | try { | 40 | try { |
| 41 | - std::string filePath = GetBinLocation() + "/cluster_model/topo_meta/" + fileName + ".yaml"; | 41 | + std::string filePath = GetBinLocation() + "/config/topo_meta/" + fileName + ".yaml"; |
| 42 | YAML::Node root = YAML::LoadFile(filePath); | 42 | YAML::Node root = YAML::LoadFile(filePath); |
| 43 | 43 | ||
| 44 | if (!root["meta"]) { | 44 | if (!root["meta"]) { |
| @@ -11,8 +11,10 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | + | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 17 | + | ||
| 16 | 18 | ||
| 17 | 19 | ||
| 18 | namespace HcclSim { | 20 | namespace HcclSim { |
| @@ -21,6 +23,8 @@ void RunCommand::Setup(CLI::App& app) { | |||
| 21 | 23 | ||
| 22 | sub_oneShot->add_option("configFile", configClusterName, "加载昇腾集群组网配置目录")->required()->check(GenerateClusterTopo); | 24 | sub_oneShot->add_option("configFile", configClusterName, "加载昇腾集群组网配置目录")->required()->check(GenerateClusterTopo); |
| 23 | sub_oneShot->add_option("--level", g_hcclVmLevel, "设置模拟等级, 当前支持等级为 1 和 2, 默认模拟等级 2 "); | 25 | sub_oneShot->add_option("--level", g_hcclVmLevel, "设置模拟等级, 当前支持等级为 1 和 2, 默认模拟等级 2 "); |
| 26 | + sub_oneShot->add_flag("--check-only", checkOnlyMode, | ||
| 27 | + "仅校验模式:大块(200MB-4GB)内存申请复用同一块 4GB 共享区,内容不保证正确,换取内存节省"); | ||
| 24 | sub_oneShot->allow_extras(true); | 28 | sub_oneShot->allow_extras(true); |
| 25 | 29 | ||
| 26 | sub_oneShot->callback([this, &app]() { Execute(app); }); | 30 | sub_oneShot->callback([this, &app]() { Execute(app); }); |
| @@ -38,8 +42,15 @@ void RunCommand::Execute(CLI::App& app) { | |||
| 38 | return; | 42 | return; |
| 39 | } | 43 | } |
| 40 | HCCL_VM_INFO("[HVM] Initializing: Model={}, Level={}", configClusterName, g_hcclVmLevel); | 44 | HCCL_VM_INFO("[HVM] Initializing: Model={}, Level={}", configClusterName, g_hcclVmLevel); |
| 41 | - auto clusterDir = GetBinLocation() + "/cluster_model/network/cluster/" + configClusterName; | 45 | + auto clusterDir = GetBinLocation() + "/config/network/cluster/" + configClusterName; |
| 42 | - auto ret = InitHvmEnv(clusterDir, g_hcclVmLevel); | 46 | + |
| 47 | + sim::RunModeConfig runMode{}; | ||
| 48 | + runMode.mode = checkOnlyMode ? 1 : 0; | ||
| 49 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 50 | + RunnerDB::Add<sim::RunModeConfig>(runMode); | ||
| 51 | + HCCL_VM_INFO("[HVM] run mode: {}", checkOnlyMode ? "check-only" : "normal"); | ||
| 52 | + | ||
| 53 | + auto ret = InitHvmEnv(clusterDir, g_hcclVmLevel, checkOnlyMode); | ||
| 43 | if (ret != HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD) { | 54 | if (ret != HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD) { |
| 44 | HCCL_VM_ERROR("[HVM] Failed to initialize simulation environment. Cleaning up environment."); | 55 | HCCL_VM_ERROR("[HVM] Failed to initialize simulation environment. Cleaning up environment."); |
| 45 | auto cleanRet = HcclVmExit(); | 56 | auto cleanRet = HcclVmExit(); |
| @@ -50,7 +61,7 @@ void RunCommand::Execute(CLI::App& app) { | |||
| 50 | } | 61 | } |
| 51 | CstyleCmd syscmd(leftargvs); | 62 | CstyleCmd syscmd(leftargvs); |
| 52 | HCCL_VM_INFO("[HVM] one_shot mode, executing: {}", syscmd.cmd()); | 63 | HCCL_VM_INFO("[HVM] one_shot mode, executing: {}", syscmd.cmd()); |
| 53 | - std::string proxyPath = GetBinLocation() + "/libhccl_proxy_level2.so"; | 64 | + std::string proxyPath = GetBinLocation() + "/lib/x86_64/libhccl_proxy_level2.so"; |
| 54 | setenv("LD_PRELOAD", proxyPath.c_str(), 1); | 65 | setenv("LD_PRELOAD", proxyPath.c_str(), 1); |
| 55 | int sysRet = std::system(syscmd.cmd().c_str()); // system() 会阻塞当前进程直到子命令结束 | 66 | int sysRet = std::system(syscmd.cmd().c_str()); // system() 会阻塞当前进程直到子命令结束 |
| 56 | if (sysRet != 0) { | 67 | if (sysRet != 0) { |
| @@ -12,8 +12,10 @@ | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | + | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 18 | + | ||
| 17 | 19 | ||
| 18 | 20 | ||
| 19 | namespace HcclSim { | 21 | namespace HcclSim { |
| @@ -22,7 +24,9 @@ void StartCommand::Setup(CLI::App& app) { | |||
| 22 | 24 | ||
| 23 | sub_start->add_option("configCluster", configClusterName, "加载昇腾集群组网配置目录")->required()->check(GenerateClusterTopo); | 25 | sub_start->add_option("configCluster", configClusterName, "加载昇腾集群组网配置目录")->required()->check(GenerateClusterTopo); |
| 24 | sub_start->add_option("--level", g_hcclVmLevel, "设置模拟等级, 当前支持等级为 1 和 2, 默认模拟等级 2 "); | 26 | sub_start->add_option("--level", g_hcclVmLevel, "设置模拟等级, 当前支持等级为 1 和 2, 默认模拟等级 2 "); |
| 25 | - | 27 | + sub_start->add_flag("--check-only", checkOnlyMode, |
| 28 | + "仅校验模式:大块(200MB-4GB)内存申请复用同一块 4GB 共享区,内容不保证正确,换取内存节省"); | ||
| 29 | + | ||
| 26 | sub_start->callback([this]() { Execute(); }); | 30 | sub_start->callback([this]() { Execute(); }); |
| 27 | } | 31 | } |
| 28 | 32 | ||
| @@ -36,16 +40,22 @@ void StartCommand::Execute() { | |||
| 36 | } | 40 | } |
| 37 | 41 | ||
| 38 | HCCL_VM_INFO("[HVM] Initializing: Model={}, Level={}", configClusterName, g_hcclVmLevel); | 42 | HCCL_VM_INFO("[HVM] Initializing: Model={}, Level={}", configClusterName, g_hcclVmLevel); |
| 39 | - auto clusterDir = GetBinLocation() + "/cluster_model/network/cluster/" + configClusterName; | 43 | + auto clusterDir = GetBinLocation() + "/config/network/cluster/" + configClusterName; |
| 40 | 44 | ||
| 41 | // 拷贝topo.json文件到执行目录 | 45 | // 拷贝topo.json文件到执行目录 |
| 42 | auto ret = CopyFile(clusterDir); | 46 | auto ret = CopyFile(clusterDir); |
| 43 | if (ret != HcclVmResult::HCCL_SIM_SUCCESS) { | 47 | if (ret != HcclVmResult::HCCL_SIM_SUCCESS) { |
| 44 | - HCCL_VM_ERROR("[{}] copy topo.json file failed", __func__); | 48 | + HCCL_VM_ERROR("copy topo.json file failed"); |
| 45 | return; | 49 | return; |
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | - ret = InitHvmEnv(clusterDir, g_hcclVmLevel); | 52 | + sim::RunModeConfig runMode{}; |
| 53 | + runMode.mode = checkOnlyMode ? 1 : 0; | ||
| 54 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 55 | + RunnerDB::Add<sim::RunModeConfig>(runMode); | ||
| 56 | + HCCL_VM_INFO("[HVM] run mode: {}", checkOnlyMode ? "check-only" : "normal"); | ||
| 57 | + | ||
| 58 | + ret = InitHvmEnv(clusterDir, g_hcclVmLevel, checkOnlyMode); | ||
| 49 | if (ret != HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD) { | 59 | if (ret != HcclVmResult::HCCL_SIM_HOST_SUCCESS_CMD) { |
| 50 | HCCL_VM_ERROR("[HVM] Failed to initialize simulation environment. Cleaning up environment."); | 60 | HCCL_VM_ERROR("[HVM] Failed to initialize simulation environment. Cleaning up environment."); |
| 51 | auto cleanRet = HcclVmExit(); | 61 | auto cleanRet = HcclVmExit(); |
| @@ -8,9 +8,10 @@ | |||
| 8 | 8 | ||
| 9 | file(GLOB_RECURSE HCCL_SOURCES "*.cc") | 9 | file(GLOB_RECURSE HCCL_SOURCES "*.cc") |
| 10 | 10 | ||
| 11 | -add_library(common SHARED ${HCCL_SOURCES}) | 11 | +add_library(common STATIC ${HCCL_SOURCES}) |
| 12 | 12 | ||
| 13 | target_compile_options(common PRIVATE | 13 | target_compile_options(common PRIVATE |
| 14 | + -fPIC | ||
| 14 | -Werror | 15 | -Werror |
| 15 | -fno-common | 16 | -fno-common |
| 16 | -fno-strict-aliasing | 17 | -fno-strict-aliasing |
| @@ -55,27 +56,3 @@ target_link_libraries(common PRIVATE | |||
| 55 | log | 56 | log |
| 56 | runnerdb | 57 | runnerdb |
| 57 | ) | 58 | ) |
| 58 | - | ||
| 59 | -install(TARGETS common | ||
| 60 | - DESTINATION "." | ||
| 61 | - PERMISSIONS | ||
| 62 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 63 | - GROUP_READ GROUP_EXECUTE | ||
| 64 | - WORLD_READ WORLD_EXECUTE | ||
| 65 | -) | ||
| 66 | - | ||
| 67 | -install(TARGETS common | ||
| 68 | - DESTINATION "plugin/validate/runner" | ||
| 69 | - PERMISSIONS | ||
| 70 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 71 | - GROUP_READ GROUP_EXECUTE | ||
| 72 | - WORLD_READ WORLD_EXECUTE | ||
| 73 | -) | ||
| 74 | - | ||
| 75 | -install(TARGETS common | ||
| 76 | - DESTINATION "plugin/validate/checker" | ||
| 77 | - PERMISSIONS | ||
| 78 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 79 | - GROUP_READ GROUP_EXECUTE | ||
| 80 | - WORLD_READ WORLD_EXECUTE | ||
| 81 | -) | ||
| @@ -49,8 +49,8 @@ target_include_directories(sqlite3 PRIVATE | |||
| 49 | ) | 49 | ) |
| 50 | install(TARGETS sqlite3 | 50 | install(TARGETS sqlite3 |
| 51 | RUNTIME DESTINATION bin | 51 | RUNTIME DESTINATION bin |
| 52 | - LIBRARY DESTINATION lib | 52 | + LIBRARY DESTINATION lib/aarch64 |
| 53 | - ARCHIVE DESTINATION lib | 53 | + ARCHIVE DESTINATION lib/aarch64 |
| 54 | ) | 54 | ) |
| 55 | 55 | ||
| 56 | add_executable(device | 56 | add_executable(device |
| @@ -62,6 +62,8 @@ add_executable(device | |||
| 62 | ${HCCL_VM_SRC}/store/store_sim_shm_ops.cc | 62 | ${HCCL_VM_SRC}/store/store_sim_shm_ops.cc |
| 63 | ${HCCL_VM_SRC}/runnerdb/tracedb/db_sim_sqlite_db.cc | 63 | ${HCCL_VM_SRC}/runnerdb/tracedb/db_sim_sqlite_db.cc |
| 64 | ${HCCL_VM_SRC}/utils/sim_log.cc | 64 | ${HCCL_VM_SRC}/utils/sim_log.cc |
| 65 | + ${HCCL_VM_SRC}/utils/sim_yaml_config.cc | ||
| 66 | + ${HCCL_VM_SRC}/utils/sim_common_api.cc | ||
| 65 | ${HCCL_VM_SRC}/proxy/log_stub.cc | 67 | ${HCCL_VM_SRC}/proxy/log_stub.cc |
| 66 | ${HCCL_VM_SRC}/runnerdb/tracedb/db_sim_op_db_ops.cc | 68 | ${HCCL_VM_SRC}/runnerdb/tracedb/db_sim_op_db_ops.cc |
| 67 | ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_op_db_ops.cc | 69 | ${HCCL_VM_SRC}/runnerdb/modeldb/db_hccl_op_db_ops.cc |
| @@ -127,6 +129,7 @@ target_compile_options(device PRIVATE | |||
| 127 | -g | 129 | -g |
| 128 | -D_GLIBCXX_USE_CXX11_ABI=0 | 130 | -D_GLIBCXX_USE_CXX11_ABI=0 |
| 129 | -DCANN_VERSION_NUM=${HCCL_CANN_VERSION_NUM} | 131 | -DCANN_VERSION_NUM=${HCCL_CANN_VERSION_NUM} |
| 132 | + -DNO_YAML_CONFIG | ||
| 130 | ) | 133 | ) |
| 131 | 134 | ||
| 132 | target_link_options(device PUBLIC "-Wl,--export-dynamic") | 135 | target_link_options(device PUBLIC "-Wl,--export-dynamic") |
| @@ -135,8 +138,8 @@ add_dependencies(device sqlite3) | |||
| 135 | 138 | ||
| 136 | install(TARGETS device | 139 | install(TARGETS device |
| 137 | RUNTIME DESTINATION bin | 140 | RUNTIME DESTINATION bin |
| 138 | - LIBRARY DESTINATION lib | 141 | + LIBRARY DESTINATION lib/aarch64 |
| 139 | - ARCHIVE DESTINATION lib | 142 | + ARCHIVE DESTINATION lib/aarch64 |
| 140 | ) | 143 | ) |
| 141 | 144 | ||
| 142 | 145 | ||
| @@ -16,9 +16,9 @@ constexpr uint32_t UNIQUEID_HEADER_OFFSET = 152; | |||
| 16 | constexpr uint32_t UNIQUEID_HEADER_SIZE = 20; | 16 | constexpr uint32_t UNIQUEID_HEADER_SIZE = 20; |
| 17 | constexpr uint32_t COMMON_DATA_SIZE = 8; | 17 | constexpr uint32_t COMMON_DATA_SIZE = 8; |
| 18 | constexpr uint32_t NOTIFY_ID_SIZE = 8; | 18 | constexpr uint32_t NOTIFY_ID_SIZE = 8; |
| 19 | -constexpr uint32_t NOTIFY_BUFFER_SIZE = 24; | 19 | +constexpr uint32_t NOTIFY_BUFFER_SIZE = 28; |
| 20 | -constexpr uint32_t LOCAL_BUFFER_SIZE = 24; | 20 | +constexpr uint32_t LOCAL_BUFFER_SIZE = 28; |
| 21 | -constexpr uint32_t REMOTE_BUFFER_SIZE = 24; | 21 | +constexpr uint32_t REMOTE_BUFFER_SIZE = 28; |
| 22 | constexpr uint32_t HCOMID_MAX_SIZE = 128; | 22 | constexpr uint32_t HCOMID_MAX_SIZE = 128; |
| 23 | 23 | ||
| 24 | struct HDCommunicateParams { | 24 | struct HDCommunicateParams { |
| @@ -210,7 +210,7 @@ void SignalHandler(int signum) | |||
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | printf("========================================\n"); | 212 | printf("========================================\n"); |
| 213 | - printf("Resolve: aarch64-linux-gnu-addr2line -e ./device/bin/device -C -f <addr>\n"); | 213 | + printf("Resolve: aarch64-linux-gnu-addr2line -e ./bin/device -C -f <addr>\n"); |
| 214 | printf("========================================\n\n"); | 214 | printf("========================================\n\n"); |
| 215 | 215 | ||
| 216 | // 4. 刷新缓冲区,确保信息在进程退出前输出 | 216 | // 4. 刷新缓冲区,确保信息在进程退出前输出 |
| @@ -126,9 +126,9 @@ bool InitKernelFuncHandle() | |||
| 126 | if (gLibsLoaded) { | 126 | if (gLibsLoaded) { |
| 127 | return true; | 127 | return true; |
| 128 | } | 128 | } |
| 129 | - std::string libDir = "./device/lib/"; // device编译产物install路径 | 129 | + const char* installDir = getenv("HCCL_VM_INSTALL_DIR"); |
| 130 | + std::string libDir = installDir ? std::string(installDir) + "/lib/aarch64/" : "./lib/aarch64/"; | ||
| 130 | gSlogHandle = LoadLibrary(libDir, "libslog.so"); | 131 | gSlogHandle = LoadLibrary(libDir, "libslog.so"); |
| 131 | - libDir = "./device/lib64/"; // device依赖库路径 | ||
| 132 | gCsecHandle = LoadLibrary(libDir, "libc_sec.so"); | 132 | gCsecHandle = LoadLibrary(libDir, "libc_sec.so"); |
| 133 | gHcclKerHandle = LoadLibrary(libDir, "libscatter_aicpu_kernel.so"); | 133 | gHcclKerHandle = LoadLibrary(libDir, "libscatter_aicpu_kernel.so"); |
| 134 | gHcommHandle = LoadLibrary(libDir, "libccl_kernel.so"); | 134 | gHcommHandle = LoadLibrary(libDir, "libccl_kernel.so"); |
| @@ -26,7 +26,7 @@ namespace sim { | |||
| 26 | 26 | ||
| 27 | int main(int argc, char *argv[]) | 27 | int main(int argc, char *argv[]) |
| 28 | { | 28 | { |
| 29 | - LogConfig config; | 29 | + LogConfig config = LoadLogConfig("device_aarch64"); |
| 30 | InitLogger(config); | 30 | InitLogger(config); |
| 31 | 31 | ||
| 32 | RegisterSignalHandler(); | 32 | RegisterSignalHandler(); |
| @@ -395,7 +395,8 @@ std::map<uint32_t, HcclDataType> DavidUbDataTypeMap = { | |||
| 395 | {0x4, HcclDataType::HCCL_DATA_TYPE_UINT16}, | 395 | {0x4, HcclDataType::HCCL_DATA_TYPE_UINT16}, |
| 396 | {0x5, HcclDataType::HCCL_DATA_TYPE_UINT32}, | 396 | {0x5, HcclDataType::HCCL_DATA_TYPE_UINT32}, |
| 397 | {0x6, HcclDataType::HCCL_DATA_TYPE_FP16}, | 397 | {0x6, HcclDataType::HCCL_DATA_TYPE_FP16}, |
| 398 | - {0x7, HcclDataType::HCCL_DATA_TYPE_FP32} | 398 | + {0x7, HcclDataType::HCCL_DATA_TYPE_FP32}, |
| 399 | + {0x8, HcclDataType::HCCL_DATA_TYPE_BFP16} | ||
| 399 | }; | 400 | }; |
| 400 | 401 | ||
| 401 | HcclDataType ParseUbDataTypeDavid(uint32_t type) | 402 | HcclDataType ParseUbDataTypeDavid(uint32_t type) |
| @@ -19,7 +19,9 @@ | |||
| 19 | 19 | ||
| 20 | void envInit() | 20 | void envInit() |
| 21 | { | 21 | { |
| 22 | - int ret3 = system("sudo rm -fr ./hccl_vm_data.db ./hccl_vm_data.db-wal ./hccl_vm_data.db-shm 2>/dev/null"); | 22 | + setenv("HCCL_VM_INSTALL_ROOT", GetBinLocation().c_str(), 1); |
| 23 | + std::string dbPrefix = GetBinLocation() + "/data/hccl_vm_data.db"; | ||
| 24 | + int ret3 = system(("sudo rm -fr " + dbPrefix + " " + dbPrefix + "-wal " + dbPrefix + "-shm 2>/dev/null").c_str()); | ||
| 23 | int ret1 = system("sudo rm -fr /dev/shm/* 2>/dev/null"); | 25 | int ret1 = system("sudo rm -fr /dev/shm/* 2>/dev/null"); |
| 24 | int ret2 = system("sudo rm -fr /tmp/hccl_sim.db* 2>/dev/null"); | 26 | int ret2 = system("sudo rm -fr /tmp/hccl_sim.db* 2>/dev/null"); |
| 25 | if (ret1 != 0 || ret2 != 0) { | 27 | if (ret1 != 0 || ret2 != 0) { |
| @@ -31,15 +33,13 @@ void envInit() | |||
| 31 | 33 | ||
| 32 | int main(int argc, char *argv[]) | 34 | int main(int argc, char *argv[]) |
| 33 | { | 35 | { |
| 34 | - LogConfig config; | ||
| 35 | - config.fileBaseName = "hccl_vm"; | ||
| 36 | - InitLogger(config); | ||
| 37 | - | ||
| 38 | const char* envCheck = std::getenv(HVM_BASH_ENV_KEY.c_str()); | 36 | const char* envCheck = std::getenv(HVM_BASH_ENV_KEY.c_str()); |
| 39 | 37 | ||
| 40 | if (envCheck != nullptr) { | 38 | if (envCheck != nullptr) { |
| 41 | StartHostClient(argc, argv); | 39 | StartHostClient(argc, argv); |
| 42 | } else { | 40 | } else { |
| 41 | + LogConfig config = LoadLogConfig("hccl_vm"); | ||
| 42 | + InitLogger(config); | ||
| 43 | envInit(); | 43 | envInit(); |
| 44 | std::string cmd = ArgvToString(argc, argv); | 44 | std::string cmd = ArgvToString(argc, argv); |
| 45 | if (argc == 1) { | 45 | if (argc == 1) { |
| @@ -26,7 +26,7 @@ add_subdirectory(checker) | |||
| 26 | #) | 26 | #) |
| 27 | 27 | ||
| 28 | install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/insight" | 28 | install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/insight" |
| 29 | - DESTINATION "plugin/visualize" | 29 | + DESTINATION "plugin/visualization" |
| 30 | # 文件的权限 (755) | 30 | # 文件的权限 (755) |
| 31 | FILE_PERMISSIONS | 31 | FILE_PERMISSIONS |
| 32 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 32 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| @@ -46,6 +46,7 @@ target_include_directories(checker PUBLIC | |||
| 46 | 46 | ||
| 47 | ${CMAKE_SOURCE_DIR}/include | 47 | ${CMAKE_SOURCE_DIR}/include |
| 48 | ${CMAKE_SOURCE_DIR}/include/runnerdb | 48 | ${CMAKE_SOURCE_DIR}/include/runnerdb |
| 49 | + ${CMAKE_SOURCE_DIR}/third_party | ||
| 49 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 50 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json |
| 50 | ) | 51 | ) |
| 51 | 52 | ||
| @@ -54,15 +55,16 @@ target_sources(checker PRIVATE | |||
| 54 | ) | 55 | ) |
| 55 | 56 | ||
| 56 | target_link_libraries(checker PRIVATE | 57 | target_link_libraries(checker PRIVATE |
| 57 | - ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.so | ||
| 58 | - pthread | ||
| 59 | log | 58 | log |
| 60 | loader | 59 | loader |
| 61 | -) | 60 | + runnerdb |
| 62 | - | 61 | + modeldb |
| 63 | -set_target_properties(checker PROPERTIES | 62 | + store |
| 64 | - INSTALL_RPATH "$ORIGIN" | 63 | + common |
| 65 | - BUILD_WITH_INSTALL_RPATH TRUE | 64 | + ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.so |
| 65 | + pthread | ||
| 66 | + yaml-cpp::yaml-cpp | ||
| 67 | + sqlite3 | ||
| 66 | ) | 68 | ) |
| 67 | 69 | ||
| 68 | set_target_properties(checker PROPERTIES POSITION_INDEPENDENT_CODE ON) | 70 | set_target_properties(checker PROPERTIES POSITION_INDEPENDENT_CODE ON) |
| @@ -81,7 +83,7 @@ target_compile_options(checker PRIVATE | |||
| 81 | ) | 83 | ) |
| 82 | 84 | ||
| 83 | install(TARGETS checker | 85 | install(TARGETS checker |
| 84 | - DESTINATION "plugin/validate/checker" | 86 | + DESTINATION "plugin/checker" |
| 85 | # 文件的权限 (755) | 87 | # 文件的权限 (755) |
| 86 | PERMISSIONS | 88 | PERMISSIONS |
| 87 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 89 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| @@ -90,7 +92,7 @@ install(TARGETS checker | |||
| 90 | ) | 92 | ) |
| 91 | 93 | ||
| 92 | install(FILES "manifest.json" | 94 | install(FILES "manifest.json" |
| 93 | - DESTINATION "plugin/validate/checker" | 95 | + DESTINATION "plugin/checker" |
| 94 | # 文件的权限 (755) | 96 | # 文件的权限 (755) |
| 95 | PERMISSIONS | 97 | PERMISSIONS |
| 96 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 98 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| @@ -546,10 +546,7 @@ void ProcessCommand(const std::string& line) { | |||
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | int main() { | 548 | int main() { |
| 549 | - LogConfig config; | 549 | + LogConfig config = LoadLogConfig("checker"); |
| 550 | - config.fileBaseName = "checker"; | ||
| 551 | - config.consoleLevel = 2; | ||
| 552 | - config.fileLevel = 0; | ||
| 553 | InitLogger(config); | 550 | InitLogger(config); |
| 554 | 551 | ||
| 555 | HCCL_VM_INFO("[Checker] Plugin process active. Listening for commands..."); | 552 | HCCL_VM_INFO("[Checker] Plugin process active. Listening for commands..."); |
| @@ -72,7 +72,7 @@ void CcuErrorHandler::GetCcuErrorMsg(int32_t deviceId, const ParaCcu &ccuTaskPar | |||
| 72 | const auto missionContext = GetCcuMissionContext(deviceId, ccuTaskParam.dieId, ccuTaskParam.execMissionId); | 72 | const auto missionContext = GetCcuMissionContext(deviceId, ccuTaskParam.dieId, ccuTaskParam.execMissionId); |
| 73 | const uint16_t missionStatus = missionContext.GetStatus(); | 73 | const uint16_t missionStatus = missionContext.GetStatus(); |
| 74 | if (missionStatus == 0) { | 74 | if (missionStatus == 0) { |
| 75 | - HCCL_INFO("[CcuErrorHandler][%s] no err found, mission status is 0, deviceId[%d], dieId[%u], execMissionId[%u]", | 75 | + HCCL_INFO("[CcuErrorHandler] no err found, mission status is 0, deviceId[%d], dieId[%u], execMissionId[%u]", |
| 76 | __func__, deviceId, static_cast<u32>(ccuTaskParam.dieId), static_cast<u32>(ccuTaskParam.execMissionId)); | 76 | __func__, deviceId, static_cast<u32>(ccuTaskParam.dieId), static_cast<u32>(ccuTaskParam.execMissionId)); |
| 77 | return; | 77 | return; |
| 78 | } | 78 | } |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/aiv_graph_generator_v3/aiv_task_transform_v3.cc+1036-4
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | + | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | 17 | ||
| @@ -19,6 +20,7 @@ | |||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 23 | + | ||
| 22 | 24 | ||
| 23 | 25 | ||
| 24 | 26 | ||
| @@ -50,9 +52,21 @@ struct AivLaunchContext { | |||
| 50 | NodeId endNodeId{INVALID_NODE_ID}; | 52 | NodeId endNodeId{INVALID_NODE_ID}; |
| 51 | std::map<uint32_t, AivNodeRecord> taskIdToNode; | 53 | std::map<uint32_t, AivNodeRecord> taskIdToNode; |
| 52 | std::vector<NodeId> internalNodeIds; | 54 | std::vector<NodeId> internalNodeIds; |
| 55 | + std::set<NodeId> inactiveNodeIds; | ||
| 56 | + std::unordered_map<NodeId, std::vector<uint32_t>> cpGmMergeSourceTaskIds; | ||
| 57 | + uint32_t nextSyntheticTaskId{0}; | ||
| 53 | size_t setWaitEdgeCount{0}; | 58 | size_t setWaitEdgeCount{0}; |
| 54 | size_t pipeBarrierMergeCount{0}; | 59 | size_t pipeBarrierMergeCount{0}; |
| 55 | size_t syncAllMergeCount{0}; | 60 | size_t syncAllMergeCount{0}; |
| 61 | + size_t taskJsonTotalTaskCount{0}; | ||
| 62 | + size_t dagNodeCountBeforeCpGmMerge{0}; | ||
| 63 | + size_t dagNodeCountAfterCpGmMerge{0}; | ||
| 64 | + size_t cpGmLoopMergeCount{0}; | ||
| 65 | + size_t cpGmMergedIterationCount{0}; | ||
| 66 | + size_t cpGmMergedOriginalNodeCount{0}; | ||
| 67 | + size_t cpGmGeneratedNodeCount{0}; | ||
| 68 | + size_t cpGmInactiveNodeCount{0}; | ||
| 69 | + size_t cpGmLoopSkipCount{0}; | ||
| 56 | }; | 70 | }; |
| 57 | 71 | ||
| 58 | struct SetWaitKey { | 72 | struct SetWaitKey { |
| @@ -116,6 +130,13 @@ struct MergeGroup { | |||
| 116 | uint32_t syncRound{std::numeric_limits<uint32_t>::max()}; | 130 | uint32_t syncRound{std::numeric_limits<uint32_t>::max()}; |
| 117 | }; | 131 | }; |
| 118 | 132 | ||
| 133 | +using CpGmIter = std::array<TaskNode *, 6>; | ||
| 134 | + | ||
| 135 | +struct CpGmLoopGather { | ||
| 136 | + std::vector<CpGmIter> templateLoop; | ||
| 137 | + std::array<TaskNode *, 6> merged{}; | ||
| 138 | +}; | ||
| 139 | + | ||
| 119 | uint64_t ElapsedNs(AivExpandClock::time_point start, AivExpandClock::time_point end) | 140 | uint64_t ElapsedNs(AivExpandClock::time_point start, AivExpandClock::time_point end) |
| 120 | { | 141 | { |
| 121 | return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count()); | 142 | return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count()); |
| @@ -278,6 +299,11 @@ HcclResult AddEdge(TaskGraphGeneratorV3 *graph, NodeId parent, NodeId child) | |||
| 278 | return graph->AddEdge(parent, child); | 299 | return graph->AddEdge(parent, child); |
| 279 | } | 300 | } |
| 280 | 301 | ||
| 302 | +bool IsInactive(const AivLaunchContext &ctx, NodeId nodeId) | ||
| 303 | +{ | ||
| 304 | + return ctx.inactiveNodeIds.count(nodeId) != 0; | ||
| 305 | +} | ||
| 306 | + | ||
| 281 | HcclResult RewireGroupMember(TaskGraphGeneratorV3 *graph, NodeId memberNodeId, NodeId mergeNodeId) | 307 | HcclResult RewireGroupMember(TaskGraphGeneratorV3 *graph, NodeId memberNodeId, NodeId mergeNodeId) |
| 282 | { | 308 | { |
| 283 | if (graph == nullptr) { | 309 | if (graph == nullptr) { |
| @@ -565,6 +591,995 @@ HcclResult AddSetWaitFlagEdges(AivLaunchContext &ctx) | |||
| 565 | return HCCL_SUCCESS; | 591 | return HCCL_SUCCESS; |
| 566 | } | 592 | } |
| 567 | 593 | ||
| 594 | +size_t CountAivSnapshotTasks(const AivRuntimeTaskSnapshotV3 &snapshot) | ||
| 595 | +{ | ||
| 596 | + size_t count = 0; | ||
| 597 | + for (const auto &block : snapshot.blocks) { | ||
| 598 | + count += block.scalarTasks.size(); | ||
| 599 | + count += block.mte2Tasks.size(); | ||
| 600 | + count += block.mte3Tasks.size(); | ||
| 601 | + } | ||
| 602 | + return count; | ||
| 603 | +} | ||
| 604 | + | ||
| 605 | +uint32_t FindMaxTaskId(const AivRuntimeTaskSnapshotV3 &snapshot) | ||
| 606 | +{ | ||
| 607 | + uint32_t maxTaskId = 0; | ||
| 608 | + for (const auto &block : snapshot.blocks) { | ||
| 609 | + auto update = [&maxTaskId](const std::vector<AivRuntimeTaskV3> &tasks) { | ||
| 610 | + for (const auto &task : tasks) { | ||
| 611 | + maxTaskId = std::max(maxTaskId, task.taskId); | ||
| 612 | + } | ||
| 613 | + }; | ||
| 614 | + update(block.scalarTasks); | ||
| 615 | + update(block.mte2Tasks); | ||
| 616 | + update(block.mte3Tasks); | ||
| 617 | + } | ||
| 618 | + return maxTaskId; | ||
| 619 | +} | ||
| 620 | + | ||
| 621 | +size_t CountReachableActiveInternalNodes(const AivLaunchContext &ctx) | ||
| 622 | +{ | ||
| 623 | + if (ctx.graph == nullptr || ctx.headNodeId == INVALID_NODE_ID) { | ||
| 624 | + return 0; | ||
| 625 | + } | ||
| 626 | + std::set<NodeId> internalSet(ctx.internalNodeIds.begin(), ctx.internalNodeIds.end()); | ||
| 627 | + std::set<NodeId> visited; | ||
| 628 | + std::queue<NodeId> nodeQueue; | ||
| 629 | + nodeQueue.push(ctx.headNodeId); | ||
| 630 | + visited.insert(ctx.headNodeId); | ||
| 631 | + | ||
| 632 | + while (!nodeQueue.empty()) { | ||
| 633 | + const NodeId nodeId = nodeQueue.front(); | ||
| 634 | + nodeQueue.pop(); | ||
| 635 | + const TaskNode *node = ctx.graph->GetNode(nodeId); | ||
| 636 | + if (node == nullptr) { | ||
| 637 | + continue; | ||
| 638 | + } | ||
| 639 | + for (const TaskNode *child : node->GetChildren()) { | ||
| 640 | + if (child == nullptr) { | ||
| 641 | + continue; | ||
| 642 | + } | ||
| 643 | + const NodeId childId = child->GetNodeId(); | ||
| 644 | + if (internalSet.count(childId) == 0 || IsInactive(ctx, childId)) { | ||
| 645 | + continue; | ||
| 646 | + } | ||
| 647 | + if (visited.insert(childId).second) { | ||
| 648 | + nodeQueue.push(childId); | ||
| 649 | + } | ||
| 650 | + } | ||
| 651 | + } | ||
| 652 | + return visited.size(); | ||
| 653 | +} | ||
| 654 | + | ||
| 655 | +bool IsCpGmExternalMemType(MemType memType) | ||
| 656 | +{ | ||
| 657 | + return memType == MemType::INPUT || memType == MemType::CCL || memType == MemType::OUTPUT || | ||
| 658 | + memType == MemType::FLAG_AIV; | ||
| 659 | +} | ||
| 660 | + | ||
| 661 | +bool SameSliceIdentity(const MemSlice &lhs, const MemSlice &rhs) | ||
| 662 | +{ | ||
| 663 | + return lhs.rankId == rhs.rankId && lhs.memType == rhs.memType; | ||
| 664 | +} | ||
| 665 | + | ||
| 666 | +bool IsContinuousAfter(const MemSlice &prev, const MemSlice &next) | ||
| 667 | +{ | ||
| 668 | + return SameSliceIdentity(prev, next) && next.offset == prev.offset + prev.len; | ||
| 669 | +} | ||
| 670 | + | ||
| 671 | +bool SliceExactEqual(const MemSlice &lhs, const MemSlice &rhs) | ||
| 672 | +{ | ||
| 673 | + return lhs.rankId == rhs.rankId && lhs.memType == rhs.memType && lhs.offset == rhs.offset && lhs.len == rhs.len; | ||
| 674 | +} | ||
| 675 | + | ||
| 676 | +bool IntervalsOverlap(const MemSlice &lhs, const MemSlice &rhs) | ||
| 677 | +{ | ||
| 678 | + if (!SameSliceIdentity(lhs, rhs)) { | ||
| 679 | + return false; | ||
| 680 | + } | ||
| 681 | + return lhs.offset < rhs.offset + rhs.len && rhs.offset < lhs.offset + lhs.len; | ||
| 682 | +} | ||
| 683 | + | ||
| 684 | +std::vector<MemSlice> MergeMemSliceIntervals(std::vector<MemSlice> slices) | ||
| 685 | +{ | ||
| 686 | + if (slices.empty()) { | ||
| 687 | + return {}; | ||
| 688 | + } | ||
| 689 | + std::sort(slices.begin(), slices.end(), [](const MemSlice &lhs, const MemSlice &rhs) { | ||
| 690 | + if (lhs.rankId != rhs.rankId) { | ||
| 691 | + return lhs.rankId < rhs.rankId; | ||
| 692 | + } | ||
| 693 | + if (lhs.memType != rhs.memType) { | ||
| 694 | + return static_cast<uint32_t>(lhs.memType) < static_cast<uint32_t>(rhs.memType); | ||
| 695 | + } | ||
| 696 | + if (lhs.offset != rhs.offset) { | ||
| 697 | + return lhs.offset < rhs.offset; | ||
| 698 | + } | ||
| 699 | + return lhs.len < rhs.len; | ||
| 700 | + }); | ||
| 701 | + | ||
| 702 | + std::vector<MemSlice> merged; | ||
| 703 | + merged.push_back(slices.front()); | ||
| 704 | + for (size_t index = 1; index < slices.size(); ++index) { | ||
| 705 | + MemSlice &last = merged.back(); | ||
| 706 | + const MemSlice &cur = slices[index]; | ||
| 707 | + if (!SameSliceIdentity(last, cur)) { | ||
| 708 | + merged.push_back(cur); | ||
| 709 | + continue; | ||
| 710 | + } | ||
| 711 | + const uint64_t lastEnd = last.offset + last.len; | ||
| 712 | + const uint64_t curEnd = cur.offset + cur.len; | ||
| 713 | + if (cur.offset <= lastEnd) { | ||
| 714 | + last.len = std::max(lastEnd, curEnd) - last.offset; | ||
| 715 | + continue; | ||
| 716 | + } | ||
| 717 | + merged.push_back(cur); | ||
| 718 | + } | ||
| 719 | + return merged; | ||
| 720 | +} | ||
| 721 | + | ||
| 722 | +bool BuildContinuousMergedSlices(const std::vector<MemSlice> &slices, std::vector<MemSlice> &merged) | ||
| 723 | +{ | ||
| 724 | + merged.clear(); | ||
| 725 | + if (slices.empty()) { | ||
| 726 | + return false; | ||
| 727 | + } | ||
| 728 | + MemSlice cur = slices.front(); | ||
| 729 | + for (size_t index = 1; index < slices.size(); ++index) { | ||
| 730 | + if (!IsContinuousAfter(cur, slices[index])) { | ||
| 731 | + return false; | ||
| 732 | + } | ||
| 733 | + cur.len += slices[index].len; | ||
| 734 | + } | ||
| 735 | + merged.push_back(cur); | ||
| 736 | + return true; | ||
| 737 | +} | ||
| 738 | + | ||
| 739 | +bool GetDataSlices(const TaskNode *node, MemSlice &src, MemSlice &dst, uint8_t &dataType, uint8_t &reduceOp) | ||
| 740 | +{ | ||
| 741 | + if (node == nullptr) { | ||
| 742 | + return false; | ||
| 743 | + } | ||
| 744 | + if (node->GetType() == TaskType::TRANS_MEM) { | ||
| 745 | + const auto *task = dynamic_cast<const TaskTransMem *>(node); | ||
| 746 | + if (task == nullptr) { | ||
| 747 | + return false; | ||
| 748 | + } | ||
| 749 | + src = task->GetSrc(); | ||
| 750 | + dst = task->GetDst(); | ||
| 751 | + dataType = 0; | ||
| 752 | + reduceOp = 0; | ||
| 753 | + return true; | ||
| 754 | + } | ||
| 755 | + if (node->GetType() == TaskType::REDUCE) { | ||
| 756 | + const auto *task = dynamic_cast<const TaskReduce *>(node); | ||
| 757 | + if (task == nullptr || task->GetSrcs().size() != 1U) { | ||
| 758 | + return false; | ||
| 759 | + } | ||
| 760 | + src = task->GetSrc(); | ||
| 761 | + dst = task->GetDst(); | ||
| 762 | + dataType = task->GetDataType(); | ||
| 763 | + reduceOp = task->GetReduceOp(); | ||
| 764 | + return true; | ||
| 765 | + } | ||
| 766 | + return false; | ||
| 767 | +} | ||
| 768 | + | ||
| 769 | +bool IsValidCpGmDataNode(const TaskNode *node, uint32_t pipe, bool ubAsDst) | ||
| 770 | +{ | ||
| 771 | + MemSlice src; | ||
| 772 | + MemSlice dst; | ||
| 773 | + uint8_t dataType = 0; | ||
| 774 | + uint8_t reduceOp = 0; | ||
| 775 | + if (!GetDataSlices(node, src, dst, dataType, reduceOp)) { | ||
| 776 | + return false; | ||
| 777 | + } | ||
| 778 | + if (node->GetPosition().pipe != pipe) { | ||
| 779 | + return false; | ||
| 780 | + } | ||
| 781 | + const MemSlice &ubSlice = ubAsDst ? dst : src; | ||
| 782 | + const MemSlice &externalSlice = ubAsDst ? src : dst; | ||
| 783 | + return ubSlice.memType == MemType::UB_AIV && IsCpGmExternalMemType(externalSlice.memType); | ||
| 784 | +} | ||
| 785 | + | ||
| 786 | +bool MatchPipeEventNode(const TaskNode *node, TaskType type, uint32_t curPipe, uint32_t srcPipe, uint32_t dstPipe) | ||
| 787 | +{ | ||
| 788 | + if (node == nullptr || node->GetType() != type || node->GetPosition().pipe != curPipe) { | ||
| 789 | + return false; | ||
| 790 | + } | ||
| 791 | + const AivPipeEvent *event = nullptr; | ||
| 792 | + if (type == TaskType::AIV_SET_FLAG) { | ||
| 793 | + const auto *setFlag = dynamic_cast<const TaskAivSetFlag *>(node); | ||
| 794 | + event = setFlag == nullptr ? nullptr : &setFlag->GetEvent(); | ||
| 795 | + } else { | ||
| 796 | + const auto *waitFlag = dynamic_cast<const TaskAivWaitFlag *>(node); | ||
| 797 | + event = waitFlag == nullptr ? nullptr : &waitFlag->GetEvent(); | ||
| 798 | + } | ||
| 799 | + return event != nullptr && event->curPipe == curPipe && event->srcPipe == srcPipe && event->dstPipe == dstPipe; | ||
| 800 | +} | ||
| 801 | + | ||
| 802 | +const AivPipeEvent *GetPipeEvent(const TaskNode *node) | ||
| 803 | +{ | ||
| 804 | + if (node == nullptr) { | ||
| 805 | + return nullptr; | ||
| 806 | + } | ||
| 807 | + if (node->GetType() == TaskType::AIV_SET_FLAG) { | ||
| 808 | + const auto *setFlag = dynamic_cast<const TaskAivSetFlag *>(node); | ||
| 809 | + return setFlag == nullptr ? nullptr : &setFlag->GetEvent(); | ||
| 810 | + } | ||
| 811 | + if (node->GetType() == TaskType::AIV_WAIT_FLAG) { | ||
| 812 | + const auto *waitFlag = dynamic_cast<const TaskAivWaitFlag *>(node); | ||
| 813 | + return waitFlag == nullptr ? nullptr : &waitFlag->GetEvent(); | ||
| 814 | + } | ||
| 815 | + return nullptr; | ||
| 816 | +} | ||
| 817 | + | ||
| 818 | +bool SamePositionScope(const TaskPosition &lhs, const TaskPosition &rhs) | ||
| 819 | +{ | ||
| 820 | + return lhs.rankId == rhs.rankId && lhs.launchIdx == rhs.launchIdx && lhs.blockId == rhs.blockId; | ||
| 821 | +} | ||
| 822 | + | ||
| 823 | +bool SameEventExceptTaskId(const TaskNode *lhsNode, const TaskNode *rhsNode) | ||
| 824 | +{ | ||
| 825 | + if (lhsNode == nullptr || rhsNode == nullptr || lhsNode->GetType() != rhsNode->GetType()) { | ||
| 826 | + return false; | ||
| 827 | + } | ||
| 828 | + const AivPipeEvent *lhs = GetPipeEvent(lhsNode); | ||
| 829 | + const AivPipeEvent *rhs = GetPipeEvent(rhsNode); | ||
| 830 | + if (lhs == nullptr || rhs == nullptr) { | ||
| 831 | + return false; | ||
| 832 | + } | ||
| 833 | + return lhs->rankId == rhs->rankId && lhs->launchIdx == rhs->launchIdx && lhs->blockId == rhs->blockId && | ||
| 834 | + lhs->curPipe == rhs->curPipe && lhs->srcPipe == rhs->srcPipe && lhs->dstPipe == rhs->dstPipe && | ||
| 835 | + lhs->eventId == rhs->eventId; | ||
| 836 | +} | ||
| 837 | + | ||
| 838 | +bool SameSetWaitEvent(const TaskNode *setNode, const TaskNode *waitNode) | ||
| 839 | +{ | ||
| 840 | + const AivPipeEvent *setEvent = GetPipeEvent(setNode); | ||
| 841 | + const AivPipeEvent *waitEvent = GetPipeEvent(waitNode); | ||
| 842 | + if (setEvent == nullptr || waitEvent == nullptr) { | ||
| 843 | + return false; | ||
| 844 | + } | ||
| 845 | + return setEvent->rankId == waitEvent->rankId && setEvent->launchIdx == waitEvent->launchIdx && | ||
| 846 | + setEvent->blockId == waitEvent->blockId && setEvent->srcPipe == waitEvent->srcPipe && | ||
| 847 | + setEvent->dstPipe == waitEvent->dstPipe && setEvent->eventId == waitEvent->eventId; | ||
| 848 | +} | ||
| 849 | + | ||
| 850 | +bool SameDataTypeAndOp(const TaskNode *lhsNode, const TaskNode *rhsNode) | ||
| 851 | +{ | ||
| 852 | + if (lhsNode == nullptr || rhsNode == nullptr || lhsNode->GetType() != rhsNode->GetType()) { | ||
| 853 | + return false; | ||
| 854 | + } | ||
| 855 | + if (lhsNode->GetType() != TaskType::REDUCE) { | ||
| 856 | + return true; | ||
| 857 | + } | ||
| 858 | + MemSlice lhsSrc; | ||
| 859 | + MemSlice lhsDst; | ||
| 860 | + uint8_t lhsDataType = 0; | ||
| 861 | + uint8_t lhsReduceOp = 0; | ||
| 862 | + MemSlice rhsSrc; | ||
| 863 | + MemSlice rhsDst; | ||
| 864 | + uint8_t rhsDataType = 0; | ||
| 865 | + uint8_t rhsReduceOp = 0; | ||
| 866 | + return GetDataSlices(lhsNode, lhsSrc, lhsDst, lhsDataType, lhsReduceOp) && | ||
| 867 | + GetDataSlices(rhsNode, rhsSrc, rhsDst, rhsDataType, rhsReduceOp) && | ||
| 868 | + lhsDataType == rhsDataType && lhsReduceOp == rhsReduceOp; | ||
| 869 | +} | ||
| 870 | + | ||
| 871 | +bool DataSliceShapeValid(const CpGmIter &iter) | ||
| 872 | +{ | ||
| 873 | + MemSlice t0Src; | ||
| 874 | + MemSlice t0Dst; | ||
| 875 | + MemSlice t3Src; | ||
| 876 | + MemSlice t3Dst; | ||
| 877 | + uint8_t dataType = 0; | ||
| 878 | + uint8_t reduceOp = 0; | ||
| 879 | + if (!GetDataSlices(iter[0], t0Src, t0Dst, dataType, reduceOp) || | ||
| 880 | + !GetDataSlices(iter[3], t3Src, t3Dst, dataType, reduceOp)) { | ||
| 881 | + return false; | ||
| 882 | + } | ||
| 883 | + if (t0Dst.memType != MemType::UB_AIV || t3Src.memType != MemType::UB_AIV) { | ||
| 884 | + return false; | ||
| 885 | + } | ||
| 886 | + if (!IsCpGmExternalMemType(t0Src.memType) || !IsCpGmExternalMemType(t3Dst.memType)) { | ||
| 887 | + return false; | ||
| 888 | + } | ||
| 889 | + if (t0Dst.len != t3Src.len) { | ||
| 890 | + return false; | ||
| 891 | + } | ||
| 892 | + return true; | ||
| 893 | +} | ||
| 894 | + | ||
| 895 | +bool SameUbLayout(const CpGmIter &iter) | ||
| 896 | +{ | ||
| 897 | + MemSlice t0Src; | ||
| 898 | + MemSlice t0Dst; | ||
| 899 | + MemSlice t3Src; | ||
| 900 | + MemSlice t3Dst; | ||
| 901 | + uint8_t dataType = 0; | ||
| 902 | + uint8_t reduceOp = 0; | ||
| 903 | + if (!GetDataSlices(iter[0], t0Src, t0Dst, dataType, reduceOp) || | ||
| 904 | + !GetDataSlices(iter[3], t3Src, t3Dst, dataType, reduceOp)) { | ||
| 905 | + return false; | ||
| 906 | + } | ||
| 907 | + return SliceExactEqual(t0Dst, t3Src); | ||
| 908 | +} | ||
| 909 | + | ||
| 910 | +bool SameExternalIdentityAsFirst(const CpGmIter &first, const CpGmIter &iter) | ||
| 911 | +{ | ||
| 912 | + MemSlice firstT0Src; | ||
| 913 | + MemSlice firstT0Dst; | ||
| 914 | + MemSlice firstT3Src; | ||
| 915 | + MemSlice firstT3Dst; | ||
| 916 | + MemSlice curT0Src; | ||
| 917 | + MemSlice curT0Dst; | ||
| 918 | + MemSlice curT3Src; | ||
| 919 | + MemSlice curT3Dst; | ||
| 920 | + uint8_t dataType = 0; | ||
| 921 | + uint8_t reduceOp = 0; | ||
| 922 | + if (!GetDataSlices(first[0], firstT0Src, firstT0Dst, dataType, reduceOp) || | ||
| 923 | + !GetDataSlices(first[3], firstT3Src, firstT3Dst, dataType, reduceOp) || | ||
| 924 | + !GetDataSlices(iter[0], curT0Src, curT0Dst, dataType, reduceOp) || | ||
| 925 | + !GetDataSlices(iter[3], curT3Src, curT3Dst, dataType, reduceOp)) { | ||
| 926 | + return false; | ||
| 927 | + } | ||
| 928 | + return SameSliceIdentity(firstT0Src, curT0Src) && SameSliceIdentity(firstT3Dst, curT3Dst); | ||
| 929 | +} | ||
| 930 | + | ||
| 931 | +bool ExternalSlicesContinuous(const CpGmLoopGather &gather) | ||
| 932 | +{ | ||
| 933 | + if (gather.templateLoop.empty()) { | ||
| 934 | + return false; | ||
| 935 | + } | ||
| 936 | + std::vector<MemSlice> t0Srcs; | ||
| 937 | + std::vector<MemSlice> t3Dsts; | ||
| 938 | + t0Srcs.reserve(gather.templateLoop.size()); | ||
| 939 | + t3Dsts.reserve(gather.templateLoop.size()); | ||
| 940 | + for (const CpGmIter &iter : gather.templateLoop) { | ||
| 941 | + MemSlice t0Src; | ||
| 942 | + MemSlice t0Dst; | ||
| 943 | + MemSlice t3Src; | ||
| 944 | + MemSlice t3Dst; | ||
| 945 | + uint8_t dataType = 0; | ||
| 946 | + uint8_t reduceOp = 0; | ||
| 947 | + if (!GetDataSlices(iter[0], t0Src, t0Dst, dataType, reduceOp) || | ||
| 948 | + !GetDataSlices(iter[3], t3Src, t3Dst, dataType, reduceOp)) { | ||
| 949 | + return false; | ||
| 950 | + } | ||
| 951 | + t0Srcs.push_back(t0Src); | ||
| 952 | + t3Dsts.push_back(t3Dst); | ||
| 953 | + } | ||
| 954 | + std::vector<MemSlice> merged; | ||
| 955 | + return BuildContinuousMergedSlices(t0Srcs, merged) && BuildContinuousMergedSlices(t3Dsts, merged); | ||
| 956 | +} | ||
| 957 | + | ||
| 958 | +bool HasValidSyntheticTaskIdBudget(const AivLaunchContext &ctx) | ||
| 959 | +{ | ||
| 960 | + const uint32_t maxTaskId = std::numeric_limits<uint32_t>::max(); | ||
| 961 | + return ctx.nextSyntheticTaskId <= maxTaskId - 6U; | ||
| 962 | +} | ||
| 963 | + | ||
| 964 | +bool CanMergeCpGmRun(const AivLaunchContext &ctx, const CpGmLoopGather &gather) | ||
| 965 | +{ | ||
| 966 | + if (!HasValidSyntheticTaskIdBudget(ctx)) { | ||
| 967 | + return false; | ||
| 968 | + } | ||
| 969 | + return ExternalSlicesContinuous(gather); | ||
| 970 | +} | ||
| 971 | + | ||
| 972 | +TaskNode *FindOnlyChildByType(const AivLaunchContext &ctx, const TaskNode *node, TaskType type) | ||
| 973 | +{ | ||
| 974 | + if (node == nullptr) { | ||
| 975 | + return nullptr; | ||
| 976 | + } | ||
| 977 | + TaskNode *matched = nullptr; | ||
| 978 | + for (TaskNode *child : node->GetChildren()) { | ||
| 979 | + if (child == nullptr || IsInactive(ctx, child->GetNodeId()) || child->GetType() != type) { | ||
| 980 | + continue; | ||
| 981 | + } | ||
| 982 | + if (matched != nullptr) { | ||
| 983 | + return nullptr; | ||
| 984 | + } | ||
| 985 | + matched = child; | ||
| 986 | + } | ||
| 987 | + return matched; | ||
| 988 | +} | ||
| 989 | + | ||
| 990 | +TaskNode *FindOnlyWaitChildForSet(const AivLaunchContext &ctx, const TaskNode *setNode) | ||
| 991 | +{ | ||
| 992 | + if (setNode == nullptr) { | ||
| 993 | + return nullptr; | ||
| 994 | + } | ||
| 995 | + TaskNode *matched = nullptr; | ||
| 996 | + for (TaskNode *child : setNode->GetChildren()) { | ||
| 997 | + if (child == nullptr || IsInactive(ctx, child->GetNodeId()) || child->GetType() != TaskType::AIV_WAIT_FLAG || | ||
| 998 | + !SameSetWaitEvent(setNode, child)) { | ||
| 999 | + continue; | ||
| 1000 | + } | ||
| 1001 | + if (matched != nullptr) { | ||
| 1002 | + return nullptr; | ||
| 1003 | + } | ||
| 1004 | + matched = child; | ||
| 1005 | + } | ||
| 1006 | + return matched; | ||
| 1007 | +} | ||
| 1008 | + | ||
| 1009 | +TaskNode *FindOnlySetParentForWait(const AivLaunchContext &ctx, const TaskNode *waitNode) | ||
| 1010 | +{ | ||
| 1011 | + if (waitNode == nullptr) { | ||
| 1012 | + return nullptr; | ||
| 1013 | + } | ||
| 1014 | + TaskNode *matched = nullptr; | ||
| 1015 | + for (TaskNode *parent : waitNode->GetParents()) { | ||
| 1016 | + if (parent == nullptr || IsInactive(ctx, parent->GetNodeId()) || parent->GetType() != TaskType::AIV_SET_FLAG || | ||
| 1017 | + !SameSetWaitEvent(parent, waitNode)) { | ||
| 1018 | + continue; | ||
| 1019 | + } | ||
| 1020 | + if (matched != nullptr) { | ||
| 1021 | + return nullptr; | ||
| 1022 | + } | ||
| 1023 | + matched = parent; | ||
| 1024 | + } | ||
| 1025 | + return matched; | ||
| 1026 | +} | ||
| 1027 | + | ||
| 1028 | +bool HasActiveChild(const AivLaunchContext &ctx, const TaskNode *parent, const TaskNode *target) | ||
| 1029 | +{ | ||
| 1030 | + if (parent == nullptr || target == nullptr) { | ||
| 1031 | + return false; | ||
| 1032 | + } | ||
| 1033 | + const NodeId targetId = target->GetNodeId(); | ||
| 1034 | + if (IsInactive(ctx, targetId)) { | ||
| 1035 | + return false; | ||
| 1036 | + } | ||
| 1037 | + for (const TaskNode *child : parent->GetChildren()) { | ||
| 1038 | + if (child != nullptr && child->GetNodeId() == targetId && !IsInactive(ctx, child->GetNodeId())) { | ||
| 1039 | + return true; | ||
| 1040 | + } | ||
| 1041 | + } | ||
| 1042 | + return false; | ||
| 1043 | +} | ||
| 1044 | + | ||
| 1045 | +bool MatchCpGmTemplateFromNode(TaskNode *start, const AivLaunchContext &ctx, CpGmIter &iter) | ||
| 1046 | +{ | ||
| 1047 | + if (start == nullptr || IsInactive(ctx, start->GetNodeId())) { | ||
| 1048 | + return false; | ||
| 1049 | + } | ||
| 1050 | + iter = CpGmIter{}; | ||
| 1051 | + iter[0] = start; | ||
| 1052 | + if (!IsValidCpGmDataNode(iter[0], PIPE_MTE2, true)) { | ||
| 1053 | + return false; | ||
| 1054 | + } | ||
| 1055 | + iter[1] = FindOnlyChildByType(ctx, iter[0], TaskType::AIV_SET_FLAG); | ||
| 1056 | + iter[2] = FindOnlyWaitChildForSet(ctx, iter[1]); | ||
| 1057 | + iter[3] = FindOnlyChildByType(ctx, iter[2], TaskType::TRANS_MEM); | ||
| 1058 | + if (iter[3] == nullptr) { | ||
| 1059 | + iter[3] = FindOnlyChildByType(ctx, iter[2], TaskType::REDUCE); | ||
| 1060 | + } | ||
| 1061 | + iter[4] = FindOnlyChildByType(ctx, iter[3], TaskType::AIV_SET_FLAG); | ||
| 1062 | + iter[5] = FindOnlyWaitChildForSet(ctx, iter[4]); | ||
| 1063 | + for (TaskNode *node : iter) { | ||
| 1064 | + if (node == nullptr || IsInactive(ctx, node->GetNodeId())) { | ||
| 1065 | + return false; | ||
| 1066 | + } | ||
| 1067 | + } | ||
| 1068 | + | ||
| 1069 | + if (!HasActiveChild(ctx, iter[1], iter[5])) { | ||
| 1070 | + return false; | ||
| 1071 | + } | ||
| 1072 | + | ||
| 1073 | + if (FindOnlySetParentForWait(ctx, iter[2]) != iter[1]) { | ||
| 1074 | + return false; | ||
| 1075 | + } | ||
| 1076 | + if (FindOnlySetParentForWait(ctx, iter[5]) != iter[4]) { | ||
| 1077 | + return false; | ||
| 1078 | + } | ||
| 1079 | + | ||
| 1080 | + if (!IsValidCpGmDataNode(iter[0], PIPE_MTE2, true) || | ||
| 1081 | + !MatchPipeEventNode(iter[1], TaskType::AIV_SET_FLAG, PIPE_MTE2, PIPE_MTE2, PIPE_MTE3) || | ||
| 1082 | + !MatchPipeEventNode(iter[2], TaskType::AIV_WAIT_FLAG, PIPE_MTE3, PIPE_MTE2, PIPE_MTE3) || | ||
| 1083 | + !IsValidCpGmDataNode(iter[3], PIPE_MTE3, false) || | ||
| 1084 | + !MatchPipeEventNode(iter[4], TaskType::AIV_SET_FLAG, PIPE_MTE3, PIPE_MTE3, PIPE_MTE2) || | ||
| 1085 | + !MatchPipeEventNode(iter[5], TaskType::AIV_WAIT_FLAG, PIPE_MTE2, PIPE_MTE3, PIPE_MTE2)) { | ||
| 1086 | + return false; | ||
| 1087 | + } | ||
| 1088 | + if (!SameSetWaitEvent(iter[1], iter[2]) || !SameSetWaitEvent(iter[4], iter[5])) { | ||
| 1089 | + return false; | ||
| 1090 | + } | ||
| 1091 | + const TaskPosition &position = iter[0]->GetPosition(); | ||
| 1092 | + for (TaskNode *node : iter) { | ||
| 1093 | + if (!SamePositionScope(position, node->GetPosition())) { | ||
| 1094 | + return false; | ||
| 1095 | + } | ||
| 1096 | + } | ||
| 1097 | + return true; | ||
| 1098 | +} | ||
| 1099 | + | ||
| 1100 | +bool ValidateCpGmRun(const CpGmLoopGather &gather) | ||
| 1101 | +{ | ||
| 1102 | + if (gather.templateLoop.size() <= 1U) { | ||
| 1103 | + return false; | ||
| 1104 | + } | ||
| 1105 | + const CpGmIter &first = gather.templateLoop.front(); | ||
| 1106 | + for (const CpGmIter &iter : gather.templateLoop) { | ||
| 1107 | + if (iter[0]->GetType() != first[0]->GetType() || iter[3]->GetType() != first[3]->GetType()) { | ||
| 1108 | + return false; | ||
| 1109 | + } | ||
| 1110 | + if (!DataSliceShapeValid(iter) || !SameUbLayout(iter) || !SameExternalIdentityAsFirst(first, iter)) { | ||
| 1111 | + return false; | ||
| 1112 | + } | ||
| 1113 | + for (size_t idx : {1U, 2U, 4U, 5U}) { | ||
| 1114 | + if (!SameEventExceptTaskId(first[idx], iter[idx])) { | ||
| 1115 | + return false; | ||
| 1116 | + } | ||
| 1117 | + } | ||
| 1118 | + for (size_t idx : {0U, 3U}) { | ||
| 1119 | + if (!SameDataTypeAndOp(first[idx], iter[idx])) { | ||
| 1120 | + return false; | ||
| 1121 | + } | ||
| 1122 | + } | ||
| 1123 | + } | ||
| 1124 | + return true; | ||
| 1125 | +} | ||
| 1126 | + | ||
| 1127 | +bool CollectCpGmBlockTopo(const AivLaunchContext &ctx, uint32_t blockId, std::vector<NodeId> &topo) | ||
| 1128 | +{ | ||
| 1129 | + topo.clear(); | ||
| 1130 | + std::set<NodeId> blockNodes; | ||
| 1131 | + for (NodeId nodeId : ctx.internalNodeIds) { | ||
| 1132 | + if (IsInactive(ctx, nodeId)) { | ||
| 1133 | + continue; | ||
| 1134 | + } | ||
| 1135 | + const TaskNode *node = ctx.graph->GetNode(nodeId); | ||
| 1136 | + if (node == nullptr || node->GetPosition().blockId != blockId) { | ||
| 1137 | + continue; | ||
| 1138 | + } | ||
| 1139 | + const uint32_t pipe = node->GetPosition().pipe; | ||
| 1140 | + if (pipe == PIPE_MTE2 || pipe == PIPE_MTE3) { | ||
| 1141 | + blockNodes.insert(nodeId); | ||
| 1142 | + } | ||
| 1143 | + } | ||
| 1144 | + if (blockNodes.empty()) { | ||
| 1145 | + return true; | ||
| 1146 | + } | ||
| 1147 | + | ||
| 1148 | + std::map<NodeId, uint32_t> indegree; | ||
| 1149 | + std::map<NodeId, std::vector<NodeId>> children; | ||
| 1150 | + for (NodeId nodeId : blockNodes) { | ||
| 1151 | + indegree[nodeId] = 0; | ||
| 1152 | + } | ||
| 1153 | + for (NodeId nodeId : blockNodes) { | ||
| 1154 | + const TaskNode *node = ctx.graph->GetNode(nodeId); | ||
| 1155 | + if (node == nullptr) { | ||
| 1156 | + return false; | ||
| 1157 | + } | ||
| 1158 | + for (const TaskNode *child : node->GetChildren()) { | ||
| 1159 | + if (child == nullptr) { | ||
| 1160 | + return false; | ||
| 1161 | + } | ||
| 1162 | + const NodeId childId = child->GetNodeId(); | ||
| 1163 | + if (blockNodes.count(childId) == 0) { | ||
| 1164 | + continue; | ||
| 1165 | + } | ||
| 1166 | + children[nodeId].push_back(childId); | ||
| 1167 | + ++indegree[childId]; | ||
| 1168 | + } | ||
| 1169 | + } | ||
| 1170 | + | ||
| 1171 | + auto lessByTaskId = [&ctx](NodeId lhs, NodeId rhs) { | ||
| 1172 | + const TaskNode *lhsNode = ctx.graph->GetNode(lhs); | ||
| 1173 | + const TaskNode *rhsNode = ctx.graph->GetNode(rhs); | ||
| 1174 | + const uint32_t lhsTaskId = lhsNode == nullptr ? std::numeric_limits<uint32_t>::max() : | ||
| 1175 | + lhsNode->GetPosition().taskId; | ||
| 1176 | + const uint32_t rhsTaskId = rhsNode == nullptr ? std::numeric_limits<uint32_t>::max() : | ||
| 1177 | + rhsNode->GetPosition().taskId; | ||
| 1178 | + if (lhsTaskId != rhsTaskId) { | ||
| 1179 | + return lhsTaskId > rhsTaskId; | ||
| 1180 | + } | ||
| 1181 | + return lhs > rhs; | ||
| 1182 | + }; | ||
| 1183 | + std::priority_queue<NodeId, std::vector<NodeId>, decltype(lessByTaskId)> ready(lessByTaskId); | ||
| 1184 | + for (const auto &entry : indegree) { | ||
| 1185 | + if (entry.second == 0) { | ||
| 1186 | + ready.push(entry.first); | ||
| 1187 | + } | ||
| 1188 | + } | ||
| 1189 | + while (!ready.empty()) { | ||
| 1190 | + const NodeId nodeId = ready.top(); | ||
| 1191 | + ready.pop(); | ||
| 1192 | + topo.push_back(nodeId); | ||
| 1193 | + for (NodeId childId : children[nodeId]) { | ||
| 1194 | + auto iter = indegree.find(childId); | ||
| 1195 | + if (iter == indegree.end()) { | ||
| 1196 | + continue; | ||
| 1197 | + } | ||
| 1198 | + if (--iter->second == 0) { | ||
| 1199 | + ready.push(childId); | ||
| 1200 | + } | ||
| 1201 | + } | ||
| 1202 | + } | ||
| 1203 | + return topo.size() == blockNodes.size(); | ||
| 1204 | +} | ||
| 1205 | + | ||
| 1206 | +uint32_t AllocateSyntheticTaskId(AivLaunchContext &ctx) | ||
| 1207 | +{ | ||
| 1208 | + return ctx.nextSyntheticTaskId++; | ||
| 1209 | +} | ||
| 1210 | + | ||
| 1211 | +TaskPosition MakeSyntheticPosition(AivLaunchContext &ctx, const TaskNode *source) | ||
| 1212 | +{ | ||
| 1213 | + TaskPosition position = source == nullptr ? TaskPosition{} : source->GetPosition(); | ||
| 1214 | + position.taskId = AllocateSyntheticTaskId(ctx); | ||
| 1215 | + return position; | ||
| 1216 | +} | ||
| 1217 | + | ||
| 1218 | +std::unique_ptr<TaskNode> CloneSyntheticSyncNode(const TaskNode *source, const TaskPosition &position) | ||
| 1219 | +{ | ||
| 1220 | + if (source == nullptr) { | ||
| 1221 | + return nullptr; | ||
| 1222 | + } | ||
| 1223 | + if (source->GetType() == TaskType::AIV_SET_FLAG) { | ||
| 1224 | + const auto *setFlag = dynamic_cast<const TaskAivSetFlag *>(source); | ||
| 1225 | + if (setFlag == nullptr) { | ||
| 1226 | + return nullptr; | ||
| 1227 | + } | ||
| 1228 | + AivPipeEvent event = setFlag->GetEvent(); | ||
| 1229 | + event.taskId = position.taskId; | ||
| 1230 | + return std::make_unique<TaskAivSetFlag>(event); | ||
| 1231 | + } | ||
| 1232 | + if (source->GetType() == TaskType::AIV_WAIT_FLAG) { | ||
| 1233 | + const auto *waitFlag = dynamic_cast<const TaskAivWaitFlag *>(source); | ||
| 1234 | + if (waitFlag == nullptr) { | ||
| 1235 | + return nullptr; | ||
| 1236 | + } | ||
| 1237 | + AivPipeEvent event = waitFlag->GetEvent(); | ||
| 1238 | + event.taskId = position.taskId; | ||
| 1239 | + return std::make_unique<TaskAivWaitFlag>(event); | ||
| 1240 | + } | ||
| 1241 | + return nullptr; | ||
| 1242 | +} | ||
| 1243 | + | ||
| 1244 | +std::vector<uint32_t> CollectSourceTaskIds(const CpGmLoopGather &gather, size_t column) | ||
| 1245 | +{ | ||
| 1246 | + std::vector<uint32_t> taskIds; | ||
| 1247 | + taskIds.reserve(gather.templateLoop.size()); | ||
| 1248 | + for (const CpGmIter &iter : gather.templateLoop) { | ||
| 1249 | + taskIds.push_back(iter[column]->GetPosition().taskId); | ||
| 1250 | + } | ||
| 1251 | + return taskIds; | ||
| 1252 | +} | ||
| 1253 | + | ||
| 1254 | +std::unique_ptr<TaskNode> BuildBatchNodeForColumn(const CpGmLoopGather &gather, size_t column) | ||
| 1255 | +{ | ||
| 1256 | + std::vector<MemSlice> srcs; | ||
| 1257 | + std::vector<MemSlice> dsts; | ||
| 1258 | + srcs.reserve(gather.templateLoop.size()); | ||
| 1259 | + dsts.reserve(gather.templateLoop.size()); | ||
| 1260 | + | ||
| 1261 | + const TaskType taskType = gather.templateLoop.front()[column]->GetType(); | ||
| 1262 | + uint8_t dataType = 0; | ||
| 1263 | + uint8_t reduceOp = 0; | ||
| 1264 | + for (const CpGmIter &iter : gather.templateLoop) { | ||
| 1265 | + MemSlice src; | ||
| 1266 | + MemSlice dst; | ||
| 1267 | + uint8_t curDataType = 0; | ||
| 1268 | + uint8_t curReduceOp = 0; | ||
| 1269 | + if (!GetDataSlices(iter[column], src, dst, curDataType, curReduceOp)) { | ||
| 1270 | + return nullptr; | ||
| 1271 | + } | ||
| 1272 | + if (iter == gather.templateLoop.front()) { | ||
| 1273 | + dataType = curDataType; | ||
| 1274 | + reduceOp = curReduceOp; | ||
| 1275 | + } | ||
| 1276 | + srcs.push_back(src); | ||
| 1277 | + dsts.push_back(dst); | ||
| 1278 | + } | ||
| 1279 | + | ||
| 1280 | + std::vector<MemSlice> mergedSrcs; | ||
| 1281 | + std::vector<MemSlice> mergedDsts; | ||
| 1282 | + const bool srcIsUb = !srcs.empty() && srcs.front().memType == MemType::UB_AIV; | ||
| 1283 | + const bool dstIsUb = !dsts.empty() && dsts.front().memType == MemType::UB_AIV; | ||
| 1284 | + if (srcIsUb) { | ||
| 1285 | + mergedSrcs = MergeMemSliceIntervals(srcs); | ||
| 1286 | + } else if (!BuildContinuousMergedSlices(srcs, mergedSrcs)) { | ||
| 1287 | + return nullptr; | ||
| 1288 | + } | ||
| 1289 | + if (dstIsUb) { | ||
| 1290 | + mergedDsts = MergeMemSliceIntervals(dsts); | ||
| 1291 | + } else if (!BuildContinuousMergedSlices(dsts, mergedDsts)) { | ||
| 1292 | + return nullptr; | ||
| 1293 | + } | ||
| 1294 | + | ||
| 1295 | + if (taskType == TaskType::TRANS_MEM) { | ||
| 1296 | + auto batch = std::make_unique<TaskBatchTransMem>(ProtocolType::SDMA); | ||
| 1297 | + batch->SetSrcMemSlices(std::move(srcs)); | ||
| 1298 | + batch->SetDstMemSlices(std::move(dsts)); | ||
| 1299 | + batch->SetMergedSrcMemSlices(std::move(mergedSrcs)); | ||
| 1300 | + batch->SetMergedDstMemSlices(std::move(mergedDsts)); | ||
| 1301 | + return batch; | ||
| 1302 | + } | ||
| 1303 | + if (taskType == TaskType::REDUCE) { | ||
| 1304 | + auto batch = std::make_unique<TaskBatchReduce>(dataType, reduceOp, ProtocolType::SDMA); | ||
| 1305 | + std::vector<std::vector<MemSlice>> srcGroups; | ||
| 1306 | + srcGroups.reserve(srcs.size()); | ||
| 1307 | + for (const MemSlice &src : srcs) { | ||
| 1308 | + srcGroups.push_back({src}); | ||
| 1309 | + } | ||
| 1310 | + std::vector<std::vector<MemSlice>> mergedSrcGroups; | ||
| 1311 | + if (mergedDsts.size() == 1U && !mergedSrcs.empty()) { | ||
| 1312 | + mergedSrcGroups.push_back(mergedSrcs); | ||
| 1313 | + } else { | ||
| 1314 | + for (const MemSlice &src : srcs) { | ||
| 1315 | + mergedSrcGroups.push_back({src}); | ||
| 1316 | + } | ||
| 1317 | + mergedDsts = dsts; | ||
| 1318 | + } | ||
| 1319 | + batch->SetSrcMemSlices(std::move(srcGroups)); | ||
| 1320 | + batch->SetDstMemSlices(std::move(dsts)); | ||
| 1321 | + batch->SetMergedSrcMemSlices(std::move(mergedSrcGroups)); | ||
| 1322 | + batch->SetMergedDstMemSlices(std::move(mergedDsts)); | ||
| 1323 | + return batch; | ||
| 1324 | + } | ||
| 1325 | + return nullptr; | ||
| 1326 | +} | ||
| 1327 | + | ||
| 1328 | +HcclResult AppendCpGmMergedNode(AivLaunchContext &ctx, CpGmLoopGather &gather, size_t column, | ||
| 1329 | + std::unique_ptr<TaskNode> node, const TaskPosition &position) | ||
| 1330 | +{ | ||
| 1331 | + if (node == nullptr) { | ||
| 1332 | + return HCCL_E_INTERNAL; | ||
| 1333 | + } | ||
| 1334 | + NodeId nodeId = INVALID_NODE_ID; | ||
| 1335 | + HcclResult ret = ctx.graph->AppendGeneratedNode(std::move(node), position, nodeId); | ||
| 1336 | + if (ret != HCCL_SUCCESS) { | ||
| 1337 | + return ret; | ||
| 1338 | + } | ||
| 1339 | + ctx.internalNodeIds.push_back(nodeId); | ||
| 1340 | + gather.merged[column] = ctx.graph->GetNode(nodeId); | ||
| 1341 | + ctx.cpGmMergeSourceTaskIds[nodeId] = CollectSourceTaskIds(gather, column); | ||
| 1342 | + ++ctx.cpGmGeneratedNodeCount; | ||
| 1343 | + return HCCL_SUCCESS; | ||
| 1344 | +} | ||
| 1345 | + | ||
| 1346 | +bool CollectCpGmBoundaryNodes(const CpGmLoopGather &gather, std::set<NodeId> &runNodes, | ||
| 1347 | + std::set<std::pair<NodeId, size_t>> &externalParentEdges, | ||
| 1348 | + std::set<std::pair<size_t, NodeId>> &externalChildEdges) | ||
| 1349 | +{ | ||
| 1350 | + runNodes.clear(); | ||
| 1351 | + externalParentEdges.clear(); | ||
| 1352 | + externalChildEdges.clear(); | ||
| 1353 | + for (const CpGmIter &iter : gather.templateLoop) { | ||
| 1354 | + for (TaskNode *node : iter) { | ||
| 1355 | + runNodes.insert(node->GetNodeId()); | ||
| 1356 | + } | ||
| 1357 | + } | ||
| 1358 | + const NodeId firstNodeId = gather.templateLoop.front()[0]->GetNodeId(); | ||
| 1359 | + const NodeId firstMte3NodeId = gather.templateLoop.front()[2]->GetNodeId(); | ||
| 1360 | + const NodeId lastMte3NodeId = gather.templateLoop.back()[4]->GetNodeId(); | ||
| 1361 | + const NodeId lastMte2NodeId = gather.templateLoop.back()[5]->GetNodeId(); | ||
| 1362 | + for (const CpGmIter &iter : gather.templateLoop) { | ||
| 1363 | + for (TaskNode *node : iter) { | ||
| 1364 | + for (TaskNode *parent : node->GetParents()) { | ||
| 1365 | + if (parent == nullptr) { | ||
| 1366 | + return false; | ||
| 1367 | + } | ||
| 1368 | + const NodeId parentId = parent->GetNodeId(); | ||
| 1369 | + if (runNodes.count(parentId) == 0) { | ||
| 1370 | + const NodeId nodeId = node->GetNodeId(); | ||
| 1371 | + if (nodeId == firstNodeId) { | ||
| 1372 | + externalParentEdges.insert({parentId, 0U}); | ||
| 1373 | + } else if (nodeId == firstMte3NodeId) { | ||
| 1374 | + externalParentEdges.insert({parentId, 2U}); | ||
| 1375 | + } else { | ||
| 1376 | + return false; | ||
| 1377 | + } | ||
| 1378 | + } | ||
| 1379 | + } | ||
| 1380 | + for (TaskNode *child : node->GetChildren()) { | ||
| 1381 | + if (child == nullptr) { | ||
| 1382 | + return false; | ||
| 1383 | + } | ||
| 1384 | + const NodeId childId = child->GetNodeId(); | ||
| 1385 | + if (runNodes.count(childId) == 0) { | ||
| 1386 | + const NodeId nodeId = node->GetNodeId(); | ||
| 1387 | + if (nodeId == lastMte3NodeId) { | ||
| 1388 | + externalChildEdges.insert({4U, childId}); | ||
| 1389 | + } else if (nodeId == lastMte2NodeId) { | ||
| 1390 | + externalChildEdges.insert({5U, childId}); | ||
| 1391 | + } else { | ||
| 1392 | + return false; | ||
| 1393 | + } | ||
| 1394 | + } | ||
| 1395 | + } | ||
| 1396 | + } | ||
| 1397 | + } | ||
| 1398 | + return true; | ||
| 1399 | +} | ||
| 1400 | + | ||
| 1401 | +HcclResult RemoveRunEdges(AivLaunchContext &ctx, const std::set<NodeId> &runNodes) | ||
| 1402 | +{ | ||
| 1403 | + std::vector<std::pair<NodeId, NodeId>> edges; | ||
| 1404 | + for (NodeId nodeId : runNodes) { | ||
| 1405 | + TaskNode *node = ctx.graph->GetNode(nodeId); | ||
| 1406 | + if (node == nullptr) { | ||
| 1407 | + return HCCL_E_PTR; | ||
| 1408 | + } | ||
| 1409 | + for (TaskNode *parent : node->GetParents()) { | ||
| 1410 | + if (parent != nullptr) { | ||
| 1411 | + edges.push_back({parent->GetNodeId(), nodeId}); | ||
| 1412 | + } | ||
| 1413 | + } | ||
| 1414 | + for (TaskNode *child : node->GetChildren()) { | ||
| 1415 | + if (child != nullptr) { | ||
| 1416 | + edges.push_back({nodeId, child->GetNodeId()}); | ||
| 1417 | + } | ||
| 1418 | + } | ||
| 1419 | + } | ||
| 1420 | + std::sort(edges.begin(), edges.end()); | ||
| 1421 | + edges.erase(std::unique(edges.begin(), edges.end()), edges.end()); | ||
| 1422 | + for (const auto &edge : edges) { | ||
| 1423 | + HcclResult ret = ctx.graph->RemoveEdge(edge.first, edge.second); | ||
| 1424 | + if (ret != HCCL_SUCCESS) { | ||
| 1425 | + return ret; | ||
| 1426 | + } | ||
| 1427 | + } | ||
| 1428 | + return HCCL_SUCCESS; | ||
| 1429 | +} | ||
| 1430 | + | ||
| 1431 | +HcclResult ReplaceCpGmRun(AivLaunchContext &ctx, CpGmLoopGather &gather) | ||
| 1432 | +{ | ||
| 1433 | + if (!ValidateCpGmRun(gather) || !CanMergeCpGmRun(ctx, gather)) { | ||
| 1434 | + ++ctx.cpGmLoopSkipCount; | ||
| 1435 | + return HCCL_SUCCESS; | ||
| 1436 | + } | ||
| 1437 | + | ||
| 1438 | + std::set<NodeId> runNodes; | ||
| 1439 | + std::set<std::pair<NodeId, size_t>> externalParentEdges; | ||
| 1440 | + std::set<std::pair<size_t, NodeId>> externalChildEdges; | ||
| 1441 | + if (!CollectCpGmBoundaryNodes(gather, runNodes, externalParentEdges, externalChildEdges)) { | ||
| 1442 | + ++ctx.cpGmLoopSkipCount; | ||
| 1443 | + return HCCL_SUCCESS; | ||
| 1444 | + } | ||
| 1445 | + | ||
| 1446 | + HcclResult ret = AppendCpGmMergedNode(ctx, gather, 0, BuildBatchNodeForColumn(gather, 0), | ||
| 1447 | + MakeSyntheticPosition(ctx, gather.templateLoop.front()[0])); | ||
| 1448 | + if (ret != HCCL_SUCCESS) { | ||
| 1449 | + return ret; | ||
| 1450 | + } | ||
| 1451 | + for (size_t column : {1U, 2U}) { | ||
| 1452 | + const TaskPosition position = MakeSyntheticPosition(ctx, gather.templateLoop.front()[column]); | ||
| 1453 | + ret = AppendCpGmMergedNode(ctx, gather, column, | ||
| 1454 | + CloneSyntheticSyncNode(gather.templateLoop.front()[column], position), position); | ||
| 1455 | + if (ret != HCCL_SUCCESS) { | ||
| 1456 | + return ret; | ||
| 1457 | + } | ||
| 1458 | + } | ||
| 1459 | + ret = AppendCpGmMergedNode(ctx, gather, 3, BuildBatchNodeForColumn(gather, 3), | ||
| 1460 | + MakeSyntheticPosition(ctx, gather.templateLoop.front()[3])); | ||
| 1461 | + if (ret != HCCL_SUCCESS) { | ||
| 1462 | + return ret; | ||
| 1463 | + } | ||
| 1464 | + for (size_t column : {4U, 5U}) { | ||
| 1465 | + const TaskPosition position = MakeSyntheticPosition(ctx, gather.templateLoop.front()[column]); | ||
| 1466 | + ret = AppendCpGmMergedNode(ctx, gather, column, | ||
| 1467 | + CloneSyntheticSyncNode(gather.templateLoop.front()[column], position), position); | ||
| 1468 | + if (ret != HCCL_SUCCESS) { | ||
| 1469 | + return ret; | ||
| 1470 | + } | ||
| 1471 | + } | ||
| 1472 | + | ||
| 1473 | + ret = RemoveRunEdges(ctx, runNodes); | ||
| 1474 | + if (ret != HCCL_SUCCESS) { | ||
| 1475 | + return ret; | ||
| 1476 | + } | ||
| 1477 | + for (const auto &edge : externalParentEdges) { | ||
| 1478 | + TaskNode *target = gather.merged[edge.second]; | ||
| 1479 | + if (target == nullptr) { | ||
| 1480 | + return HCCL_E_INTERNAL; | ||
| 1481 | + } | ||
| 1482 | + ret = AddEdge(ctx.graph, edge.first, target->GetNodeId()); | ||
| 1483 | + if (ret != HCCL_SUCCESS) { | ||
| 1484 | + return ret; | ||
| 1485 | + } | ||
| 1486 | + } | ||
| 1487 | + const std::array<std::pair<size_t, size_t>, 6> internalEdges{{{0U, 1U}, {1U, 5U}, {1U, 2U}, {2U, 3U}, | ||
| 1488 | + {3U, 4U}, {4U, 5U}}}; | ||
| 1489 | + for (const auto &edge : internalEdges) { | ||
| 1490 | + TaskNode *source = gather.merged[edge.first]; | ||
| 1491 | + TaskNode *target = gather.merged[edge.second]; | ||
| 1492 | + if (source == nullptr || target == nullptr) { | ||
| 1493 | + return HCCL_E_INTERNAL; | ||
| 1494 | + } | ||
| 1495 | + ret = AddEdge(ctx.graph, source->GetNodeId(), target->GetNodeId()); | ||
| 1496 | + if (ret != HCCL_SUCCESS) { | ||
| 1497 | + return ret; | ||
| 1498 | + } | ||
| 1499 | + } | ||
| 1500 | + for (const auto &edge : externalChildEdges) { | ||
| 1501 | + TaskNode *source = gather.merged[edge.first]; | ||
| 1502 | + if (source == nullptr) { | ||
| 1503 | + return HCCL_E_INTERNAL; | ||
| 1504 | + } | ||
| 1505 | + ret = AddEdge(ctx.graph, source->GetNodeId(), edge.second); | ||
| 1506 | + if (ret != HCCL_SUCCESS) { | ||
| 1507 | + return ret; | ||
| 1508 | + } | ||
| 1509 | + } | ||
| 1510 | + for (NodeId nodeId : runNodes) { | ||
| 1511 | + ctx.inactiveNodeIds.insert(nodeId); | ||
| 1512 | + } | ||
| 1513 | + ++ctx.cpGmLoopMergeCount; | ||
| 1514 | + ctx.cpGmMergedIterationCount += gather.templateLoop.size(); | ||
| 1515 | + ctx.cpGmMergedOriginalNodeCount += runNodes.size(); | ||
| 1516 | + ctx.cpGmInactiveNodeCount += runNodes.size(); | ||
| 1517 | + return HCCL_SUCCESS; | ||
| 1518 | +} | ||
| 1519 | + | ||
| 1520 | +HcclResult FlushCpGmGather(AivLaunchContext &ctx, CpGmLoopGather &gather) | ||
| 1521 | +{ | ||
| 1522 | + if (gather.templateLoop.size() > 1U) { | ||
| 1523 | + HcclResult ret = ReplaceCpGmRun(ctx, gather); | ||
| 1524 | + if (ret != HCCL_SUCCESS) { | ||
| 1525 | + return ret; | ||
| 1526 | + } | ||
| 1527 | + } | ||
| 1528 | + gather = CpGmLoopGather{}; | ||
| 1529 | + return HCCL_SUCCESS; | ||
| 1530 | +} | ||
| 1531 | + | ||
| 1532 | +HcclResult MergeCpGM2GMLoops(AivLaunchContext &ctx) | ||
| 1533 | +{ | ||
| 1534 | + ctx.dagNodeCountBeforeCpGmMerge = CountReachableActiveInternalNodes(ctx); | ||
| 1535 | + for (const auto &block : ctx.snapshot.blocks) { | ||
| 1536 | + std::vector<NodeId> topo; | ||
| 1537 | + if (!CollectCpGmBlockTopo(ctx, block.blockIdx, topo)) { | ||
| 1538 | + HCCL_VM_WARN("[AivTaskTransformV3][CpGM2GMMerge] Skip block due to topo failure, rank={}, launch={}, " | ||
| 1539 | + "block={}, file={}", ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(), block.blockIdx, | ||
| 1540 | + ctx.snapshot.filePath); | ||
| 1541 | + continue; | ||
| 1542 | + } | ||
| 1543 | + | ||
| 1544 | + CpGmLoopGather gather; | ||
| 1545 | + std::set<NodeId> consumed; // 记录节点已经作为某个完整模板的一部分被识别过 | ||
| 1546 | + for (size_t index = 0; index < topo.size(); ++index) { | ||
| 1547 | + CpGmIter iter{}; | ||
| 1548 | + TaskNode *node = ctx.graph->GetNode(topo[index]); | ||
| 1549 | + if (node == nullptr) { | ||
| 1550 | + continue; | ||
| 1551 | + } | ||
| 1552 | + if (consumed.count(node->GetNodeId()) != 0) { | ||
| 1553 | + continue; | ||
| 1554 | + } | ||
| 1555 | + if (MatchCpGmTemplateFromNode(node, ctx, iter)) { | ||
| 1556 | + gather.templateLoop.push_back(iter); | ||
| 1557 | + for (TaskNode *matchedNode : iter) { | ||
| 1558 | + consumed.insert(matchedNode->GetNodeId()); | ||
| 1559 | + } | ||
| 1560 | + continue; | ||
| 1561 | + } | ||
| 1562 | + HcclResult ret = FlushCpGmGather(ctx, gather); | ||
| 1563 | + if (ret != HCCL_SUCCESS) { | ||
| 1564 | + return ret; | ||
| 1565 | + } | ||
| 1566 | + } | ||
| 1567 | + HcclResult ret = FlushCpGmGather(ctx, gather); | ||
| 1568 | + if (ret != HCCL_SUCCESS) { | ||
| 1569 | + return ret; | ||
| 1570 | + } | ||
| 1571 | + } | ||
| 1572 | + ctx.dagNodeCountAfterCpGmMerge = CountReachableActiveInternalNodes(ctx); | ||
| 1573 | + HCCL_VM_INFO("[AivTaskTransformV3][CpGM2GMMerge] rank={}, launch={}, taskJsonTotalTaskCount={}, " | ||
| 1574 | + "dagNodeCountBeforeMerge={}, dagNodeCountAfterMerge={}, cpGmLoopMergeCount={}, " | ||
| 1575 | + "cpGmMergedIterationCount={}, cpGmMergedOriginalNodeCount={}, cpGmGeneratedNodeCount={}, " | ||
| 1576 | + "cpGmInactiveNodeCount={}", ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(), | ||
| 1577 | + ctx.taskJsonTotalTaskCount, ctx.dagNodeCountBeforeCpGmMerge, ctx.dagNodeCountAfterCpGmMerge, | ||
| 1578 | + ctx.cpGmLoopMergeCount, ctx.cpGmMergedIterationCount, ctx.cpGmMergedOriginalNodeCount, | ||
| 1579 | + ctx.cpGmGeneratedNodeCount, ctx.cpGmInactiveNodeCount); | ||
| 1580 | + return HCCL_SUCCESS; | ||
| 1581 | +} | ||
| 1582 | + | ||
| 568 | class DisjointSet { | 1583 | class DisjointSet { |
| 569 | public: | 1584 | public: |
| 570 | explicit DisjointSet(size_t size) : parent_(size), rank_(size, 0) | 1585 | explicit DisjointSet(size_t size) : parent_(size), rank_(size, 0) |
| @@ -781,11 +1796,11 @@ HcclResult MergeSyncAllGroups(AivLaunchContext &ctx) | |||
| 781 | group.syncRound, memberNodeId, ctx.snapshot.filePath); | 1796 | group.syncRound, memberNodeId, ctx.snapshot.filePath); |
| 782 | return HCCL_E_INTERNAL; | 1797 | return HCCL_E_INTERNAL; |
| 783 | } | 1798 | } |
| 784 | - const TaskPosition &location = syncAll->GetInfo().taskLoc; | 1799 | + const TaskPosition &taskLoc = syncAll->GetInfo().taskLoc; |
| 785 | - if (!members.insert({location.blockId, location.pipe}).second) { | 1800 | + if (!members.insert({taskLoc.blockId, taskLoc.pipe}).second) { |
| 786 | HCCL_VM_ERROR("[AivTaskTransformV3] Duplicate SyncAll member, rank={}, launch={}, syncRound={}, " | 1801 | HCCL_VM_ERROR("[AivTaskTransformV3] Duplicate SyncAll member, rank={}, launch={}, syncRound={}, " |
| 787 | "block={}, pipe={}, file={}", ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(), | 1802 | "block={}, pipe={}, file={}", ctx.placeholder->GetRankId(), ctx.placeholder->GetLaunchIdx(), |
| 788 | - group.syncRound, location.blockId, location.pipe, ctx.snapshot.filePath); | 1803 | + group.syncRound, taskLoc.blockId, taskLoc.pipe, ctx.snapshot.filePath); |
| 789 | return HCCL_E_INTERNAL; | 1804 | return HCCL_E_INTERNAL; |
| 790 | } | 1805 | } |
| 791 | } | 1806 | } |
| @@ -854,7 +1869,8 @@ HcclResult ConnectCurrentTailsToEnd(AivLaunchContext &ctx) | |||
| 854 | return HCCL_E_PTR; | 1869 | return HCCL_E_PTR; |
| 855 | } | 1870 | } |
| 856 | const NodeId childId = child->GetNodeId(); | 1871 | const NodeId childId = child->GetNodeId(); |
| 857 | - if (internalSet.count(childId) == 0 || reachableInternalNodes.count(childId) != 0) { | 1872 | + if (internalSet.count(childId) == 0 || IsInactive(ctx, childId) || |
| 1873 | + reachableInternalNodes.count(childId) != 0) { | ||
| 858 | continue; | 1874 | continue; |
| 859 | } | 1875 | } |
| 860 | reachableInternalNodes.insert(childId); | 1876 | reachableInternalNodes.insert(childId); |
| @@ -955,6 +1971,10 @@ HcclResult ExpandOneAivGraph(TaskGraphGeneratorV3 *graph, StorageManager *storag | |||
| 955 | if (ret != HCCL_SUCCESS) { | 1971 | if (ret != HCCL_SUCCESS) { |
| 956 | return ret; | 1972 | return ret; |
| 957 | } | 1973 | } |
| 1974 | + ctx.taskJsonTotalTaskCount = CountAivSnapshotTasks(ctx.snapshot); | ||
| 1975 | + const uint32_t maxTaskId = FindMaxTaskId(ctx.snapshot); | ||
| 1976 | + ctx.nextSyntheticTaskId = maxTaskId == std::numeric_limits<uint32_t>::max() ? | ||
| 1977 | + std::numeric_limits<uint32_t>::max() : maxTaskId + 1U; | ||
| 958 | 1978 | ||
| 959 | const TaskPosition basePosition = aivGraph->GetPosition(); | 1979 | const TaskPosition basePosition = aivGraph->GetPosition(); |
| 960 | ret = graph->AppendGeneratedNode(std::make_unique<TaskStart>(BoundaryType::AIV_SUB_GRAPH), basePosition, | 1980 | ret = graph->AppendGeneratedNode(std::make_unique<TaskStart>(BoundaryType::AIV_SUB_GRAPH), basePosition, |
| @@ -973,6 +1993,10 @@ HcclResult ExpandOneAivGraph(TaskGraphGeneratorV3 *graph, StorageManager *storag | |||
| 973 | if (ret != HCCL_SUCCESS) { | 1993 | if (ret != HCCL_SUCCESS) { |
| 974 | return ret; | 1994 | return ret; |
| 975 | } | 1995 | } |
| 1996 | + ret = MergeCpGM2GMLoops(ctx); | ||
| 1997 | + if (ret != HCCL_SUCCESS) { | ||
| 1998 | + return ret; | ||
| 1999 | + } | ||
| 976 | ret = MergePipeBarrierGroups(ctx); | 2000 | ret = MergePipeBarrierGroups(ctx); |
| 977 | if (ret != HCCL_SUCCESS) { | 2001 | if (ret != HCCL_SUCCESS) { |
| 978 | return ret; | 2002 | return ret; |
| @@ -1001,6 +2025,14 @@ HcclResult ExpandOneAivGraph(TaskGraphGeneratorV3 *graph, StorageManager *storag | |||
| 1001 | output.setWaitEdgeCount += ctx.setWaitEdgeCount; | 2025 | output.setWaitEdgeCount += ctx.setWaitEdgeCount; |
| 1002 | output.pipeBarrierMergeCount += ctx.pipeBarrierMergeCount; | 2026 | output.pipeBarrierMergeCount += ctx.pipeBarrierMergeCount; |
| 1003 | output.syncAllMergeCount += ctx.syncAllMergeCount; | 2027 | output.syncAllMergeCount += ctx.syncAllMergeCount; |
| 2028 | + output.taskJsonTotalTaskCount += ctx.taskJsonTotalTaskCount; | ||
| 2029 | + output.dagNodeCountBeforeCpGmMerge += ctx.dagNodeCountBeforeCpGmMerge; | ||
| 2030 | + output.dagNodeCountAfterCpGmMerge += ctx.dagNodeCountAfterCpGmMerge; | ||
| 2031 | + output.cpGmLoopMergeCount += ctx.cpGmLoopMergeCount; | ||
| 2032 | + output.cpGmMergedIterationCount += ctx.cpGmMergedIterationCount; | ||
| 2033 | + output.cpGmMergedOriginalNodeCount += ctx.cpGmMergedOriginalNodeCount; | ||
| 2034 | + output.cpGmGeneratedNodeCount += ctx.cpGmGeneratedNodeCount; | ||
| 2035 | + output.cpGmInactiveNodeCount += ctx.cpGmInactiveNodeCount; | ||
| 1004 | return HCCL_SUCCESS; | 2036 | return HCCL_SUCCESS; |
| 1005 | } | 2037 | } |
| 1006 | 2038 | ||
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/ccu_graph_generator_v3/ccu_task_transform_instruct_a5_v3.cc+1-1
| @@ -468,7 +468,7 @@ HcclResult TransformTransLocMemToLocMemInstr(const CcuRep::CcuInstr *instr, CcuG | |||
| 468 | CHK_RET(StorageManager::GetInstance().GetSlice(srcAddr, len, srcSlice)); | 468 | CHK_RET(StorageManager::GetInstance().GetSlice(srcAddr, len, srcSlice)); |
| 469 | CHK_RET(StorageManager::GetInstance().GetSlice(dstAddr, len, dstSlice)); | 469 | CHK_RET(StorageManager::GetInstance().GetSlice(dstAddr, len, dstSlice)); |
| 470 | 470 | ||
| 471 | - HCCL_VM_DEBUG("zhf-locmem2locmem: rankId={}, src={}, dst={}, size={}", | 471 | + HCCL_VM_DEBUG("locmem2locmem: rankId={}, src={}, dst={}, size={}", |
| 472 | rankId, srcSlice.Describe(), dstSlice.Describe(), len); | 472 | rankId, srcSlice.Describe(), dstSlice.Describe(), len); |
| 473 | 473 | ||
| 474 | AddLocalCopy(rankId, queId, curCcuTask, srcSlice, dstSlice); | 474 | AddLocalCopy(rankId, queId, curCcuTask, srcSlice, dstSlice); |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/ccu_graph_generator_v3/ccu_task_transform_v3.cc+3-3
| @@ -332,9 +332,9 @@ void SetNodeQueueIdV3(TaskNode *node, QueueId queueId) | |||
| 332 | return; | 332 | return; |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | - TaskLocation location = node->GetLocation(); | 335 | + TaskLocation taskLoc = node->GetLocation(); |
| 336 | - location.queueId = queueId; | 336 | + taskLoc.queueId = queueId; |
| 337 | - node->SetLocation(location); | 337 | + node->SetLocation(taskLoc); |
| 338 | 338 | ||
| 339 | if (!node->HasCcuTrace()) { | 339 | if (!node->HasCcuTrace()) { |
| 340 | return; | 340 | return; |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_generator_v3.cc+16-3
| @@ -517,14 +517,27 @@ HcclResult TaskGraphGeneratorV3::ExpandAivSubGraphs() | |||
| 517 | stats.pipeBarrierMergeCount = result.pipeBarrierMergeCount; | 517 | stats.pipeBarrierMergeCount = result.pipeBarrierMergeCount; |
| 518 | stats.syncAllMergeCount = result.syncAllMergeCount; | 518 | stats.syncAllMergeCount = result.syncAllMergeCount; |
| 519 | stats.sendRecvEdgeCount = result.sendRecvEdgeCount; | 519 | stats.sendRecvEdgeCount = result.sendRecvEdgeCount; |
| 520 | + stats.taskJsonTotalTaskCount = result.taskJsonTotalTaskCount; | ||
| 521 | + stats.dagNodeCountBeforeCpGmMerge = result.dagNodeCountBeforeCpGmMerge; | ||
| 522 | + stats.dagNodeCountAfterCpGmMerge = result.dagNodeCountAfterCpGmMerge; | ||
| 523 | + stats.cpGmLoopMergeCount = result.cpGmLoopMergeCount; | ||
| 524 | + stats.cpGmMergedIterationCount = result.cpGmMergedIterationCount; | ||
| 525 | + stats.cpGmMergedOriginalNodeCount = result.cpGmMergedOriginalNodeCount; | ||
| 526 | + stats.cpGmGeneratedNodeCount = result.cpGmGeneratedNodeCount; | ||
| 527 | + stats.cpGmInactiveNodeCount = result.cpGmInactiveNodeCount; | ||
| 520 | stats.totalExpandNs = result.expandNs; | 528 | stats.totalExpandNs = result.expandNs; |
| 521 | aivExpandStats_ = stats; | 529 | aivExpandStats_ = stats; |
| 522 | HCCL_VM_INFO("[TaskGraphGeneratorV3][ExpandAivSubGraphs] AIV subgraph expansion finished, aivGraphCount={}, " | 530 | HCCL_VM_INFO("[TaskGraphGeneratorV3][ExpandAivSubGraphs] AIV subgraph expansion finished, aivGraphCount={}, " |
| 523 | "internalNodeCount={}, setWaitEdgeCount={}, pipeBarrierMergeCount={}, syncAllMergeCount={}, " | 531 | "internalNodeCount={}, setWaitEdgeCount={}, pipeBarrierMergeCount={}, syncAllMergeCount={}, " |
| 524 | - "sendRecvEdgeCount={}, ubBufferSize={}, flagBufferSize={}, expandTotalMs={}", stats.graphCount, | 532 | + "sendRecvEdgeCount={}, taskJsonTotalTaskCount={}, dagNodeCountBeforeCpGmMerge={}, " |
| 525 | - stats.internalNodeCount, | 533 | + "dagNodeCountAfterCpGmMerge={}, cpGmLoopMergeCount={}, cpGmMergedIterationCount={}, " |
| 534 | + "cpGmMergedOriginalNodeCount={}, cpGmGeneratedNodeCount={}, cpGmInactiveNodeCount={}, " | ||
| 535 | + "ubBufferSize={}, flagBufferSize={}, expandTotalMs={}", stats.graphCount, stats.internalNodeCount, | ||
| 526 | stats.setWaitEdgeCount, stats.pipeBarrierMergeCount, stats.syncAllMergeCount, stats.sendRecvEdgeCount, | 536 | stats.setWaitEdgeCount, stats.pipeBarrierMergeCount, stats.syncAllMergeCount, stats.sendRecvEdgeCount, |
| 527 | - g_checkerAivUbBufferSize, g_checkerAivFlagBufferSize, stats.totalExpandNs / 1000000ULL); | 537 | + stats.taskJsonTotalTaskCount, stats.dagNodeCountBeforeCpGmMerge, stats.dagNodeCountAfterCpGmMerge, |
| 538 | + stats.cpGmLoopMergeCount, stats.cpGmMergedIterationCount, stats.cpGmMergedOriginalNodeCount, | ||
| 539 | + stats.cpGmGeneratedNodeCount, stats.cpGmInactiveNodeCount, g_checkerAivUbBufferSize, | ||
| 540 | + g_checkerAivFlagBufferSize, stats.totalExpandNs / 1000000ULL); | ||
| 528 | return HCCL_SUCCESS; | 541 | return HCCL_SUCCESS; |
| 529 | } | 542 | } |
| 530 | 543 | ||
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_generator_v3.h+8-0
| @@ -39,6 +39,14 @@ struct AivExpandStats { | |||
| 39 | size_t pipeBarrierMergeCount{0}; | 39 | size_t pipeBarrierMergeCount{0}; |
| 40 | size_t syncAllMergeCount{0}; | 40 | size_t syncAllMergeCount{0}; |
| 41 | size_t sendRecvEdgeCount{0}; | 41 | size_t sendRecvEdgeCount{0}; |
| 42 | + size_t taskJsonTotalTaskCount{0}; | ||
| 43 | + size_t dagNodeCountBeforeCpGmMerge{0}; | ||
| 44 | + size_t dagNodeCountAfterCpGmMerge{0}; | ||
| 45 | + size_t cpGmLoopMergeCount{0}; | ||
| 46 | + size_t cpGmMergedIterationCount{0}; | ||
| 47 | + size_t cpGmMergedOriginalNodeCount{0}; | ||
| 48 | + size_t cpGmGeneratedNodeCount{0}; | ||
| 49 | + size_t cpGmInactiveNodeCount{0}; | ||
| 42 | uint64_t totalExpandNs{0}; | 50 | uint64_t totalExpandNs{0}; |
| 43 | }; | 51 | }; |
| 44 | 52 | ||
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_semantic_check_v3.cc+33-21
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -54,6 +55,7 @@ struct SliceOpPairV3 { | |||
| 54 | SliceOpV3 op{SliceOpV3::OVERRIDE}; | 55 | SliceOpV3 op{SliceOpV3::OVERRIDE}; |
| 55 | HcclReduceOp reduceType{HCCL_REDUCE_RESERVED}; | 56 | HcclReduceOp reduceType{HCCL_REDUCE_RESERVED}; |
| 56 | u64 index{0}; | 57 | u64 index{0}; |
| 58 | + bool useBatchIndex{false}; | ||
| 57 | 59 | ||
| 58 | std::string Describe() const | 60 | std::string Describe() const |
| 59 | { | 61 | { |
| @@ -65,6 +67,7 @@ struct SliceOpPairV3 { | |||
| 65 | << ", launch=" << position.launchIdx << ", block=" << position.blockId | 67 | << ", launch=" << position.launchIdx << ", block=" << position.blockId |
| 66 | << ", pipe=" << position.pipe << ", taskId=" << position.taskId | 68 | << ", pipe=" << position.pipe << ", taskId=" << position.taskId |
| 67 | << ", index=" << index << ", op=" << static_cast<uint32_t>(op) | 69 | << ", index=" << index << ", op=" << static_cast<uint32_t>(op) |
| 70 | + << ", useBatchIndex=" << useBatchIndex | ||
| 68 | << ", reduceType=" << static_cast<uint32_t>(reduceType) << "}"; | 71 | << ", reduceType=" << static_cast<uint32_t>(reduceType) << "}"; |
| 69 | return os.str(); | 72 | return os.str(); |
| 70 | } | 73 | } |
| @@ -92,7 +95,9 @@ struct MsKey { | |||
| 92 | struct AivMemoryKey { | 95 | struct AivMemoryKey { |
| 93 | RankId rankId{INVALID_RANK_ID}; | 96 | RankId rankId{INVALID_RANK_ID}; |
| 94 | MemType memType{MemType::INVALID}; | 97 | MemType memType{MemType::INVALID}; |
| 95 | - u64 aivUbIdx{0}; | 98 | + u64 aivUBIdx{0}; |
| 99 | + u64 batchIndex{0}; | ||
| 100 | + bool isBatchUB{false}; | ||
| 96 | 101 | ||
| 97 | bool operator<(const AivMemoryKey &rhs) const | 102 | bool operator<(const AivMemoryKey &rhs) const |
| 98 | { | 103 | { |
| @@ -102,7 +107,13 @@ struct AivMemoryKey { | |||
| 102 | if (memType != rhs.memType) { | 107 | if (memType != rhs.memType) { |
| 103 | return static_cast<uint32_t>(memType) < static_cast<uint32_t>(rhs.memType); | 108 | return static_cast<uint32_t>(memType) < static_cast<uint32_t>(rhs.memType); |
| 104 | } | 109 | } |
| 105 | - return aivUbIdx < rhs.aivUbIdx; | 110 | + if (aivUBIdx != rhs.aivUBIdx) { |
| 111 | + return aivUBIdx < rhs.aivUBIdx; | ||
| 112 | + } | ||
| 113 | + if (batchIndex != rhs.batchIndex) { | ||
| 114 | + return batchIndex < rhs.batchIndex; | ||
| 115 | + } | ||
| 116 | + return isBatchUB < rhs.isBatchUB; | ||
| 106 | } | 117 | } |
| 107 | }; | 118 | }; |
| 108 | 119 | ||
| @@ -126,7 +137,7 @@ struct SemanticState { | |||
| 126 | u64 outputSize{0}; | 137 | u64 outputSize{0}; |
| 127 | std::map<RankId, InternalRankMemorySemantics> mem; | 138 | std::map<RankId, InternalRankMemorySemantics> mem; |
| 128 | std::map<MsKey, InternalBufferSemanticMap> ms; | 139 | std::map<MsKey, InternalBufferSemanticMap> ms; |
| 129 | - std::map<AivMemoryKey, InternalBufferSemanticMap> scopedMem; | 140 | + std::map<AivMemoryKey, InternalBufferSemanticMap> AivDevMem; |
| 130 | }; | 141 | }; |
| 131 | 142 | ||
| 132 | BufferType ConvertMemTypeToBufferType(MemType memType) | 143 | BufferType ConvertMemTypeToBufferType(MemType memType) |
| @@ -195,33 +206,33 @@ u64 MakeAivUbIdx(const TaskPosition &position) | |||
| 195 | return (position.launchIdx << 32U) | static_cast<u64>(position.blockId); | 206 | return (position.launchIdx << 32U) | static_cast<u64>(position.blockId); |
| 196 | } | 207 | } |
| 197 | 208 | ||
| 198 | -u64 GetSemanticIndex(const MemSlice &slice, const TaskPosition &position, u64 fallbackIndex) | 209 | +AivMemoryKey MakeAivMemoryKey(RankId rankId, MemType memType, const TaskPosition &position, u64 batchIndex, |
| 210 | + bool isBatchUB) | ||
| 199 | { | 211 | { |
| 200 | - if (slice.memType == MemType::UB_AIV) { | 212 | + if (memType == MemType::FLAG_AIV) { |
| 201 | - return MakeAivUbIdx(position); | 213 | + return AivMemoryKey{rankId, memType, 0U, 0U, false}; |
| 202 | } | 214 | } |
| 203 | - if (slice.memType == MemType::FLAG_AIV) { | 215 | + const bool effectiveIsBatchUB = memType == MemType::UB_AIV && isBatchUB; |
| 204 | - return 0; | 216 | + return AivMemoryKey{rankId, memType, MakeAivUbIdx(position), effectiveIsBatchUB ? batchIndex : 0U, |
| 205 | - } | 217 | + effectiveIsBatchUB}; |
| 206 | - return fallbackIndex; | ||
| 207 | } | 218 | } |
| 208 | 219 | ||
| 209 | // 普通内存直接按 rank/bufferType 取语义表;MS 则额外按 batch 下标拆桶, | 220 | // 普通内存直接按 rank/bufferType 取语义表;MS 则额外按 batch 下标拆桶, |
| 210 | // 从而把“同一个 ms 在不同 batch item 复用”的语义分开记录。 | 221 | // 从而把“同一个 ms 在不同 batch item 复用”的语义分开记录。 |
| 211 | InternalBufferSemanticMap &GetBufferSemanticMap(SemanticState &state, RankId rankId, MemType memType, u64 offset, | 222 | InternalBufferSemanticMap &GetBufferSemanticMap(SemanticState &state, RankId rankId, MemType memType, u64 offset, |
| 212 | - u64 index) | 223 | + const TaskPosition &position, u64 index, bool useBatchIndex) |
| 213 | { | 224 | { |
| 214 | if (memType == MemType::MS_CCU) { | 225 | if (memType == MemType::MS_CCU) { |
| 215 | return state.ms[MakeMsKey(rankId, offset, index)]; | 226 | return state.ms[MakeMsKey(rankId, offset, index)]; |
| 216 | } | 227 | } |
| 217 | if (memType == MemType::UB_AIV || memType == MemType::FLAG_AIV) { | 228 | if (memType == MemType::UB_AIV || memType == MemType::FLAG_AIV) { |
| 218 | - return state.scopedMem[AivMemoryKey{rankId, memType, index}]; | 229 | + return state.AivDevMem[MakeAivMemoryKey(rankId, memType, position, index, useBatchIndex)]; |
| 219 | } | 230 | } |
| 220 | return state.mem[rankId][ConvertMemTypeToBufferType(memType)]; | 231 | return state.mem[rankId][ConvertMemTypeToBufferType(memType)]; |
| 221 | } | 232 | } |
| 222 | 233 | ||
| 223 | const InternalBufferSemanticMap &GetBufferSemanticMap(const SemanticState &state, RankId rankId, MemType memType, | 234 | const InternalBufferSemanticMap &GetBufferSemanticMap(const SemanticState &state, RankId rankId, MemType memType, |
| 224 | - u64 offset, u64 index) | 235 | + u64 offset, const TaskPosition &position, u64 index, bool useBatchIndex) |
| 225 | { | 236 | { |
| 226 | static const InternalBufferSemanticMap empty; | 237 | static const InternalBufferSemanticMap empty; |
| 227 | if (memType == MemType::MS_CCU) { | 238 | if (memType == MemType::MS_CCU) { |
| @@ -229,8 +240,8 @@ const InternalBufferSemanticMap &GetBufferSemanticMap(const SemanticState &state | |||
| 229 | return iter == state.ms.end() ? empty : iter->second; | 240 | return iter == state.ms.end() ? empty : iter->second; |
| 230 | } | 241 | } |
| 231 | if (memType == MemType::UB_AIV || memType == MemType::FLAG_AIV) { | 242 | if (memType == MemType::UB_AIV || memType == MemType::FLAG_AIV) { |
| 232 | - const auto iter = state.scopedMem.find(AivMemoryKey{rankId, memType, index}); | 243 | + const auto iter = state.AivDevMem.find(MakeAivMemoryKey(rankId, memType, position, index, useBatchIndex)); |
| 233 | - return iter == state.scopedMem.end() ? empty : iter->second; | 244 | + return iter == state.AivDevMem.end() ? empty : iter->second; |
| 234 | } | 245 | } |
| 235 | const auto rankIter = state.mem.find(rankId); | 246 | const auto rankIter = state.mem.find(rankId); |
| 236 | if (rankIter == state.mem.end()) { | 247 | if (rankIter == state.mem.end()) { |
| @@ -556,8 +567,8 @@ void ApplyOverrideSemantics(const SliceOpPairV3 &pair, SemanticState &state, | |||
| 556 | const std::vector<const BufferSemantic *> &srcSemantics) | 567 | const std::vector<const BufferSemantic *> &srcSemantics) |
| 557 | { | 568 | { |
| 558 | InternalBufferSemanticMap &dstSemantics = | 569 | InternalBufferSemanticMap &dstSemantics = |
| 559 | - GetBufferSemanticMap(state, pair.dstRank, pair.dst.memType, pair.dst.offset, | 570 | + GetBufferSemanticMap(state, pair.dstRank, pair.dst.memType, pair.dst.offset, pair.position, pair.index, |
| 560 | - GetSemanticIndex(pair.dst, pair.position, pair.index)); | 571 | + pair.useBatchIndex); |
| 561 | const u64 dstStartAddr = pair.dst.offset; | 572 | const u64 dstStartAddr = pair.dst.offset; |
| 562 | const u64 dstEndAddr = dstStartAddr + pair.dst.len; | 573 | const u64 dstEndAddr = dstStartAddr + pair.dst.len; |
| 563 | SplitBufferSemantic(dstSemantics, dstStartAddr); | 574 | SplitBufferSemantic(dstSemantics, dstStartAddr); |
| @@ -623,8 +634,8 @@ HcclResult ApplyReduceSemantic(const SliceOpPairV3 &pair, SemanticState &state, | |||
| 623 | const u64 dstEndAddr = ApplyOffsetDelta(srcEndAddr, dstSrcOffset); | 634 | const u64 dstEndAddr = ApplyOffsetDelta(srcEndAddr, dstSrcOffset); |
| 624 | 635 | ||
| 625 | InternalBufferSemanticMap &dstSemantics = | 636 | InternalBufferSemanticMap &dstSemantics = |
| 626 | - GetBufferSemanticMap(state, pair.dstRank, pair.dst.memType, pair.dst.offset, | 637 | + GetBufferSemanticMap(state, pair.dstRank, pair.dst.memType, pair.dst.offset, pair.position, pair.index, |
| 627 | - GetSemanticIndex(pair.dst, pair.position, pair.index)); | 638 | + pair.useBatchIndex); |
| 628 | SplitBufferSemantic(dstSemantics, dstStartAddr); | 639 | SplitBufferSemantic(dstSemantics, dstStartAddr); |
| 629 | SplitBufferSemantic(dstSemantics, dstEndAddr); | 640 | SplitBufferSemantic(dstSemantics, dstEndAddr); |
| 630 | 641 | ||
| @@ -691,7 +702,7 @@ HcclResult LoadSliceOpPairSrcSemantics(const SliceOpPairV3 &pair, const Semantic | |||
| 691 | } | 702 | } |
| 692 | 703 | ||
| 693 | const InternalBufferSemanticMap &srcSemanticsMap = GetBufferSemanticMap(state, pair.srcRank, pair.src.memType, | 704 | const InternalBufferSemanticMap &srcSemanticsMap = GetBufferSemanticMap(state, pair.srcRank, pair.src.memType, |
| 694 | - pair.src.offset, GetSemanticIndex(pair.src, pair.position, pair.index)); | 705 | + pair.src.offset, pair.position, pair.index, pair.useBatchIndex); |
| 695 | std::vector<const BufferSemantic *> srcViews; | 706 | std::vector<const BufferSemantic *> srcViews; |
| 696 | CollectOverlappingBufferSemantics(srcSemanticsMap, pair.src.offset, pair.src.offset + pair.src.len, srcViews); | 707 | CollectOverlappingBufferSemantics(srcSemanticsMap, pair.src.offset, pair.src.offset + pair.src.len, srcViews); |
| 697 | 708 | ||
| @@ -787,7 +798,7 @@ void GetSliceOpPairs(const TaskNode *node, std::vector<SliceOpPairV3> &pairs) | |||
| 787 | for (size_t index = 0; index < count; ++index) { | 798 | for (size_t index = 0; index < count; ++index) { |
| 788 | pairs.push_back(SliceOpPairV3{srcs[index].rankId, dsts[index].rankId, srcs[index], dsts[index], | 799 | pairs.push_back(SliceOpPairV3{srcs[index].rankId, dsts[index].rankId, srcs[index], dsts[index], |
| 789 | node->GetPosition(), SliceOpV3::OVERRIDE, HCCL_REDUCE_RESERVED, | 800 | node->GetPosition(), SliceOpV3::OVERRIDE, HCCL_REDUCE_RESERVED, |
| 790 | - static_cast<u64>(index)}); | 801 | + static_cast<u64>(index), true}); |
| 791 | } | 802 | } |
| 792 | return; | 803 | return; |
| 793 | } | 804 | } |
| @@ -811,6 +822,7 @@ void GetSliceOpPairs(const TaskNode *node, std::vector<SliceOpPairV3> &pairs) | |||
| 811 | pair.op = SliceOpV3::REDUCE; | 822 | pair.op = SliceOpV3::REDUCE; |
| 812 | pair.reduceType = static_cast<HcclReduceOp>(task->GetReduceOp()); | 823 | pair.reduceType = static_cast<HcclReduceOp>(task->GetReduceOp()); |
| 813 | pair.index = static_cast<u64>(index); | 824 | pair.index = static_cast<u64>(index); |
| 825 | + pair.useBatchIndex = true; | ||
| 814 | pairs.push_back(std::move(pair)); | 826 | pairs.push_back(std::move(pair)); |
| 815 | } | 827 | } |
| 816 | } | 828 | } |
Mtest/hccl_vm/src/plugin/checker/src/framework/task_graph_generator_v3/task_graph_single_task_check_v3.cc+11-2
| @@ -519,15 +519,24 @@ HcclResult CheckTwoSliceOverlap(const TaskNode *node, const MemSlice &lhs, const | |||
| 519 | } | 519 | } |
| 520 | if (lhs.len > std::numeric_limits<uint64_t>::max() - lhs.offset || | 520 | if (lhs.len > std::numeric_limits<uint64_t>::max() - lhs.offset || |
| 521 | rhs.len > std::numeric_limits<uint64_t>::max() - rhs.offset) { | 521 | rhs.len > std::numeric_limits<uint64_t>::max() - rhs.offset) { |
| 522 | - HCCL_VM_ERROR("[TaskGraphSingleTaskCheckV3] Memory slice overflow, node={}, lhs={}, rhs={}", | 522 | + HCCL_VM_ERROR("[TaskGraphSingleTaskCheckV3] Memory slice overflow, node={}, sliceA={}, sliceB={}", |
| 523 | node->Describe(), DescribeMemSlice(lhs), DescribeMemSlice(rhs)); | 523 | node->Describe(), DescribeMemSlice(lhs), DescribeMemSlice(rhs)); |
| 524 | return HCCL_E_PARA; | 524 | return HCCL_E_PARA; |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | + if (node->HasCcuTrace()) { | ||
| 528 | + // CCU mode下,允许src == dst | ||
| 529 | + if (lhs.rankId == rhs.rankId && IsSameMemoryType(lhs, rhs) && lhs.offset == rhs.offset && lhs.len == rhs.len) { | ||
| 530 | + HCCL_VM_WARN("[TaskGraphSingleTaskCheckV3] MemSlice are same (src == dst), which may affect performance, {}, node={}, sliceA={}, sliceB={}", | ||
| 531 | + DescribePosition(node->GetPosition()), node->Describe(), DescribeMemSlice(lhs), DescribeMemSlice(rhs)); | ||
| 532 | + return HCCL_SUCCESS; | ||
| 533 | + } | ||
| 534 | + } | ||
| 535 | + | ||
| 527 | const bool conflictCase1 = lhs.offset >= rhs.offset && lhs.offset < (rhs.offset + rhs.len); | 536 | const bool conflictCase1 = lhs.offset >= rhs.offset && lhs.offset < (rhs.offset + rhs.len); |
| 528 | const bool conflictCase2 = rhs.offset >= lhs.offset && rhs.offset < (lhs.offset + lhs.len); | 537 | const bool conflictCase2 = rhs.offset >= lhs.offset && rhs.offset < (lhs.offset + lhs.len); |
| 529 | if (conflictCase1 || conflictCase2) { | 538 | if (conflictCase1 || conflictCase2) { |
| 530 | - HCCL_VM_ERROR("[TaskGraphSingleTaskCheckV3] Slice conflict, {}, node={}, lhs={}, rhs={}", | 539 | + HCCL_VM_ERROR("[TaskGraphSingleTaskCheckV3] Slice conflict, {}, node={}, sliceA={}, sliceB={}", |
| 531 | DescribePosition(node->GetPosition()), node->Describe(), DescribeMemSlice(lhs), DescribeMemSlice(rhs)); | 540 | DescribePosition(node->GetPosition()), node->Describe(), DescribeMemSlice(lhs), DescribeMemSlice(rhs)); |
| 532 | return HCCL_E_INTERNAL; | 541 | return HCCL_E_INTERNAL; |
| 533 | } | 542 | } |
| @@ -74,10 +74,10 @@ HcclVmResult HcclPlugin::Start() | |||
| 74 | { | 74 | { |
| 75 | std::string entryCmd = m_manifest.value(HcclPlugin::Manifest::pluginEntry, ""); | 75 | std::string entryCmd = m_manifest.value(HcclPlugin::Manifest::pluginEntry, ""); |
| 76 | if (entryCmd.empty()) { | 76 | if (entryCmd.empty()) { |
| 77 | - HCCL_VM_INFO("[HcclPlugin::{}] Empty Entry Command", __func__); | 77 | + HCCL_VM_INFO("Empty Entry Command"); |
| 78 | return HcclVmResult::HCCL_SIM_E_PARA; | 78 | return HcclVmResult::HCCL_SIM_E_PARA; |
| 79 | } | 79 | } |
| 80 | - HCCL_VM_INFO("[HcclPlugin::{}] Starting plugin [{}]", __func__, GetTag()); | 80 | + HCCL_VM_INFO("Starting plugin [{}]", GetTag()); |
| 81 | int32_t fds[2]; | 81 | int32_t fds[2]; |
| 82 | if (pipe(fds) == -1) { | 82 | if (pipe(fds) == -1) { |
| 83 | return HcclVmResult::HCCL_SIM_E_INTERNAL; | 83 | return HcclVmResult::HCCL_SIM_E_INTERNAL; |
| @@ -127,14 +127,14 @@ HcclVmResult HcclPlugin::Start() | |||
| 127 | 127 | ||
| 128 | if (res == 0) { | 128 | if (res == 0) { |
| 129 | // 情况 A: 子进程正常运行中(这是我们预期的) | 129 | // 情况 A: 子进程正常运行中(这是我们预期的) |
| 130 | - HCCL_VM_INFO("[HcclPlugin::{}] Plugin [{}] started", __func__, GetTag()); | 130 | + HCCL_VM_INFO("Plugin [{}] started", GetTag()); |
| 131 | return HcclVmResult::HCCL_SIM_SUCCESS; | 131 | return HcclVmResult::HCCL_SIM_SUCCESS; |
| 132 | } else if (res == m_pid) { | 132 | } else if (res == m_pid) { |
| 133 | // 情况 B: 子进程已经退出,通常是 execvp 失败 | 133 | // 情况 B: 子进程已经退出,通常是 execvp 失败 |
| 134 | // 检查退出码,如果是通过 _exit(EXIT_FAILURE) 退出的 | 134 | // 检查退出码,如果是通过 _exit(EXIT_FAILURE) 退出的 |
| 135 | if (WIFEXITED(status)) { | 135 | if (WIFEXITED(status)) { |
| 136 | int exitCode = WEXITSTATUS(status); | 136 | int exitCode = WEXITSTATUS(status); |
| 137 | - HCCL_VM_ERROR("[HcclPlugin::{}] Plugin [{}] failed to start with code [{}].", __func__, GetTag(), exitCode); | 137 | + HCCL_VM_ERROR("Plugin [{}] failed to start with code [{}].", GetTag(), exitCode); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | // 清理现场,防止后续逻辑误以为子进程还在 | 140 | // 清理现场,防止后续逻辑误以为子进程还在 |
| @@ -211,13 +211,13 @@ HcclVmResult HcclPlugin::Stop() | |||
| 211 | 211 | ||
| 212 | // 4. 超时后不强制 kill,而是输出告警信息 | 212 | // 4. 超时后不强制 kill,而是输出告警信息 |
| 213 | if (!exited) { | 213 | if (!exited) { |
| 214 | - HCCL_VM_ERROR("[HcclPlugin::{}] Plugin [{}] detected as not exiting normally.", __func__, GetTag()); | 214 | + HCCL_VM_ERROR("Plugin [{}] detected as not exiting normally.", GetTag()); |
| 215 | - HCCL_VM_ERROR("[HcclPlugin::{}] [ACTION REQUIRED] Please manually check or terminate PID: {:d}", __func__, m_pid); | 215 | + HCCL_VM_ERROR("[ACTION REQUIRED] Please manually check or terminate PID: {:d}", m_pid); |
| 216 | 216 | ||
| 217 | // 既然无法回收,我们将该 PID 记录在日志后放弃管理 | 217 | // 既然无法回收,我们将该 PID 记录在日志后放弃管理 |
| 218 | // 防止析构函数再次产生误判 | 218 | // 防止析构函数再次产生误判 |
| 219 | } else { | 219 | } else { |
| 220 | - HCCL_VM_INFO("[HcclPlugin::{}] [{}] exited successfully.", __func__, GetTag()); | 220 | + HCCL_VM_INFO("Plugin [{}] exited successfully.", GetTag()); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | m_pid = -1; | 223 | m_pid = -1; |
| @@ -255,10 +255,7 @@ int main(int argc, char* argv[]) | |||
| 255 | (void) argc; | 255 | (void) argc; |
| 256 | (void) argv; | 256 | (void) argv; |
| 257 | init_lock(); | 257 | init_lock(); |
| 258 | - LogConfig config; | 258 | + LogConfig config = LoadLogConfig("runner"); |
| 259 | - config.fileBaseName = "runner"; | ||
| 260 | - config.consoleLevel = 6; | ||
| 261 | - config.fileLevel = 2; | ||
| 262 | InitLogger(config); | 259 | InitLogger(config); |
| 263 | HcclSim::StorageManager& storage = HcclSim::StorageManager::GetInstance(); | 260 | HcclSim::StorageManager& storage = HcclSim::StorageManager::GetInstance(); |
| 264 | storage.SetDataId("runner"); | 261 | storage.SetDataId("runner"); |
| @@ -1,26 +1,26 @@ | |||
| 1 | <script setup> | 1 | <script setup> |
| 2 | import { computed, nextTick, onMounted, onBeforeUnmount, ref, watch } from 'vue' | 2 | import { computed, nextTick, onMounted, onBeforeUnmount, ref, watch } from 'vue' |
| 3 | -import { | 3 | +import { |
| 4 | - CaretLeft, | 4 | + CaretLeft, |
| 5 | - CaretRight, | 5 | + CaretRight, |
| 6 | - DArrowLeft, | 6 | + DArrowLeft, |
| 7 | - DArrowRight, | 7 | + DArrowRight, |
| 8 | - Search, | 8 | + Search, |
| 9 | - VideoPause, | 9 | + VideoPause, |
| 10 | - VideoPlay, | 10 | + VideoPlay, |
| 11 | - WarningFilled, | 11 | + WarningFilled, |
| 12 | -} from '@element-plus/icons-vue' | 12 | +} from '@element-plus/icons-vue' |
| 13 | import sidebarHandle from '../assets/sidebar-handle.svg' | 13 | import sidebarHandle from '../assets/sidebar-handle.svg' |
| 14 | import sidebarHandleExpand from '../assets/sidebar-handle-expand.svg' | 14 | import sidebarHandleExpand from '../assets/sidebar-handle-expand.svg' |
| 15 | import { useInsightDatasetState } from '../composables/useInsightDatasetState' | 15 | import { useInsightDatasetState } from '../composables/useInsightDatasetState' |
| 16 | import { usePageNavigationState } from '../composables/usePageNavigationState' | 16 | import { usePageNavigationState } from '../composables/usePageNavigationState' |
| 17 | import { useMemViewTimeline } from '../composables/useMemViewTimeline' | 17 | import { useMemViewTimeline } from '../composables/useMemViewTimeline' |
| 18 | -import { taskOpsAtStep } from '../utils/memviewIndex.js' | 18 | +import { taskOpsAtStep } from '../utils/memviewIndex.js' |
| 19 | -import { fetchValidationIssues } from '../utils/analyticIssues.js' | 19 | +import { fetchValidationIssues } from '../utils/analyticIssues.js' |
| 20 | -import { | 20 | +import { |
| 21 | - DEFAULT_MEMVIEW_STAGE, | 21 | + DEFAULT_MEMVIEW_STAGE, |
| 22 | - normalizeStreamCollection, | 22 | + normalizeStreamCollection, |
| 23 | -} from '../utils/memviewDag.js' | 23 | +} from '../utils/memviewDag.js' |
| 24 | import DashboardSidebar from '../components/dashboard/DashboardSidebar.vue' | 24 | import DashboardSidebar from '../components/dashboard/DashboardSidebar.vue' |
| 25 | import MemViewDagPanel from '../components/memview/MemViewDagPanel.vue' | 25 | import MemViewDagPanel from '../components/memview/MemViewDagPanel.vue' |
| 26 | import MemViewInspectorPanel from '../components/memview/MemViewInspectorPanel.vue' | 26 | import MemViewInspectorPanel from '../components/memview/MemViewInspectorPanel.vue' |
| @@ -29,57 +29,57 @@ import MemViewOverviewPanel from '../components/memview/MemViewOverviewPanel.vue | |||
| 29 | const CENTER_TOP_MIN_SIZE = 250 | 29 | const CENTER_TOP_MIN_SIZE = 250 |
| 30 | const CENTER_TOP_MAX_SIZE = 620 | 30 | const CENTER_TOP_MAX_SIZE = 620 |
| 31 | const CENTER_TOP_DEFAULT_RATIO = 0.6 | 31 | const CENTER_TOP_DEFAULT_RATIO = 0.6 |
| 32 | -const CENTER_BOTTOM_MIN_SIZE = 220 | 32 | +const CENTER_BOTTOM_MIN_SIZE = 220 |
| 33 | -const CENTER_COLLAPSED_SIZE = 36 | 33 | +const CENTER_COLLAPSED_SIZE = 36 |
| 34 | -const CENTER_COLLAPSE_THRESHOLD = 72 | 34 | +const CENTER_COLLAPSE_THRESHOLD = 72 |
| 35 | -const SEARCH_FIELD_OPTIONS = [ | 35 | +const SEARCH_FIELD_OPTIONS = [ |
| 36 | - { label: 'taskId', value: 'taskId' }, | 36 | + { label: 'taskId', value: 'taskId' }, |
| 37 | - { label: 'taskType', value: 'taskType' }, | 37 | + { label: 'taskType', value: 'taskType' }, |
| 38 | - { label: 'notifyId', value: 'notifyId' }, | 38 | + { label: 'notifyId', value: 'notifyId' }, |
| 39 | -] | 39 | +] |
| 40 | - | 40 | + |
| 41 | -const sidebarCollapsed = ref(false) | 41 | +const sidebarCollapsed = ref(false) |
| 42 | -const recordCollapsed = ref(false) | 42 | +const recordCollapsed = ref(false) |
| 43 | -const leftPanelSize = ref(376) | 43 | +const leftPanelSize = ref(376) |
| 44 | -const rightPanelSize = ref(420) | 44 | +const rightPanelSize = ref(420) |
| 45 | const centerPaneState = ref('normal') | 45 | const centerPaneState = ref('normal') |
| 46 | const centerAvailableHeight = ref(0) | 46 | const centerAvailableHeight = ref(0) |
| 47 | const centerTopSize = ref(360) | 47 | const centerTopSize = ref(360) |
| 48 | const currentGraphNodeIds = ref([]) | 48 | const currentGraphNodeIds = ref([]) |
| 49 | -const currentGraphStage = ref(DEFAULT_MEMVIEW_STAGE) | 49 | +const currentGraphStage = ref(DEFAULT_MEMVIEW_STAGE) |
| 50 | -const pendingStageNavigation = ref(null) | 50 | +const pendingStageNavigation = ref(null) |
| 51 | -const pendingExternalNavigation = ref(null) | 51 | +const pendingExternalNavigation = ref(null) |
| 52 | -const issueHighlightedNodeIds = ref(null) | 52 | +const issueHighlightedNodeIds = ref(null) |
| 53 | -const datasetIssuePayload = ref({ issueCount: 0, issues: [] }) | 53 | +const datasetIssuePayload = ref({ issueCount: 0, issues: [] }) |
| 54 | -const selectedIssueId = ref(null) | 54 | +const selectedIssueId = ref(null) |
| 55 | -const inspectorRef = ref(null) | 55 | +const inspectorRef = ref(null) |
| 56 | -const centerSplitRef = ref(null) | 56 | +const centerSplitRef = ref(null) |
| 57 | -const layoutRefreshTimers = [] | 57 | +const layoutRefreshTimers = [] |
| 58 | -const playbackPlaying = ref(false) | 58 | +const playbackPlaying = ref(false) |
| 59 | -const issuePanelSections = ref(['issues']) | 59 | +const issuePanelSections = ref(['issues']) |
| 60 | -const searchPanelSections = ref(['search']) | 60 | +const searchPanelSections = ref(['search']) |
| 61 | -const searchField = ref('taskId') | 61 | +const searchField = ref('taskId') |
| 62 | -const searchQuery = ref('') | 62 | +const searchQuery = ref('') |
| 63 | -const dagFocusStep = ref(null) | 63 | +const dagFocusStep = ref(null) |
| 64 | -let centerResizeObserver = null | 64 | +let centerResizeObserver = null |
| 65 | -let playbackTimer = 0 | 65 | +let playbackTimer = 0 |
| 66 | -let issueLoadToken = 0 | 66 | +let issueLoadToken = 0 |
| 67 | - | 67 | + |
| 68 | -const overviewEmptyText = computed(() => { | 68 | +const overviewEmptyText = computed(() => { |
| 69 | - if (loadingDetail.value) return 'Loading data...' | 69 | + if (loadingDetail.value) return 'Loading data...' |
| 70 | - if (selectedDataset.value && memorySnapshotCount.value === 0) { | 70 | + if (selectedDataset.value && memorySnapshotCount.value === 0) { |
| 71 | - return '当前数据集没有内存快照。' | 71 | + return '当前数据集没有内存快照。' |
| 72 | - } | 72 | + } |
| 73 | - return EMPTY_TEXT | 73 | + return EMPTY_TEXT |
| 74 | -}) | 74 | +}) |
| 75 | - | 75 | + |
| 76 | -const dagEmptyText = computed(() => { | 76 | +const dagEmptyText = computed(() => { |
| 77 | - if (loadingDetail.value) return 'Loading data...' | 77 | + if (loadingDetail.value) return 'Loading data...' |
| 78 | - if (selectedDataset.value && !datasetDetail.value?.graph?.length) { | 78 | + if (selectedDataset.value && !datasetDetail.value?.graph?.length) { |
| 79 | - return '当前数据集没有 DAG 数据。' | 79 | + return '当前数据集没有 DAG 数据。' |
| 80 | - } | 80 | + } |
| 81 | - return EMPTY_TEXT | 81 | + return EMPTY_TEXT |
| 82 | -}) | 82 | +}) |
| 83 | 83 | ||
| 84 | const { | 84 | const { |
| 85 | EMPTY_TEXT, | 85 | EMPTY_TEXT, |
| @@ -87,11 +87,11 @@ const { | |||
| 87 | selectedDataset, | 87 | selectedDataset, |
| 88 | selectedDatasetName, | 88 | selectedDatasetName, |
| 89 | selectedRankKeys, | 89 | selectedRankKeys, |
| 90 | - loadingList, | 90 | + loadingList, |
| 91 | - loadingDetail, | 91 | + loadingDetail, |
| 92 | - hasData, | 92 | + hasData, |
| 93 | - memorySnapshotCount, | 93 | + memorySnapshotCount, |
| 94 | - selectedRankCount, | 94 | + selectedRankCount, |
| 95 | treeData, | 95 | treeData, |
| 96 | ensureDatasetsLoaded, | 96 | ensureDatasetsLoaded, |
| 97 | selectDataset, | 97 | selectDataset, |
| @@ -99,7 +99,7 @@ const { | |||
| 99 | formatCount, | 99 | formatCount, |
| 100 | } = useInsightDatasetState() | 100 | } = useInsightDatasetState() |
| 101 | 101 | ||
| 102 | -const { pendingMemViewNavigation, clearMemViewNavigation } = usePageNavigationState() | 102 | +const { pendingMemViewNavigation, clearMemViewNavigation } = usePageNavigationState() |
| 103 | 103 | ||
| 104 | const { | 104 | const { |
| 105 | clampedCurrentStep, | 105 | clampedCurrentStep, |
| @@ -124,14 +124,14 @@ const { | |||
| 124 | 124 | ||
| 125 | const renderedLeftPanelSize = computed(() => (sidebarCollapsed.value ? 28 : leftPanelSize.value)) | 125 | const renderedLeftPanelSize = computed(() => (sidebarCollapsed.value ? 28 : leftPanelSize.value)) |
| 126 | const renderedRightPanelSize = computed(() => (recordCollapsed.value ? 28 : rightPanelSize.value)) | 126 | const renderedRightPanelSize = computed(() => (recordCollapsed.value ? 28 : rightPanelSize.value)) |
| 127 | -const topPaneCollapsed = computed(() => centerPaneState.value === 'top-collapsed') | 127 | +const topPaneCollapsed = computed(() => centerPaneState.value === 'top-collapsed') |
| 128 | -const bottomPaneCollapsed = computed(() => centerPaneState.value === 'bottom-collapsed') | 128 | +const bottomPaneCollapsed = computed(() => centerPaneState.value === 'bottom-collapsed') |
| 129 | -const issues = computed(() => datasetIssuePayload.value?.issues ?? []) | 129 | +const issues = computed(() => datasetIssuePayload.value?.issues ?? []) |
| 130 | -const issueCount = computed(() => datasetIssuePayload.value?.issueCount ?? issues.value.length) | 130 | +const issueCount = computed(() => datasetIssuePayload.value?.issueCount ?? issues.value.length) |
| 131 | -const selectedIssue = computed( | 131 | +const selectedIssue = computed( |
| 132 | - () => issues.value.find((issue) => issue.issueId === selectedIssueId.value) ?? issues.value[0] ?? null, | 132 | + () => issues.value.find((issue) => issue.issueId === selectedIssueId.value) ?? issues.value[0] ?? null, |
| 133 | -) | 133 | +) |
| 134 | -const renderedCenterTopSize = computed(() => { | 134 | +const renderedCenterTopSize = computed(() => { |
| 135 | if (topPaneCollapsed.value) return CENTER_COLLAPSED_SIZE | 135 | if (topPaneCollapsed.value) return CENTER_COLLAPSED_SIZE |
| 136 | if (bottomPaneCollapsed.value) { | 136 | if (bottomPaneCollapsed.value) { |
| 137 | return Math.max(CENTER_COLLAPSED_SIZE, resolveCenterAvailableHeight() - CENTER_COLLAPSED_SIZE) | 137 | return Math.max(CENTER_COLLAPSED_SIZE, resolveCenterAvailableHeight() - CENTER_COLLAPSED_SIZE) |
| @@ -247,9 +247,9 @@ watch( | |||
| 247 | }, | 247 | }, |
| 248 | ) | 248 | ) |
| 249 | 249 | ||
| 250 | -watch( | 250 | +watch( |
| 251 | - availableGraphStages, | 251 | + availableGraphStages, |
| 252 | - (stages) => { | 252 | + (stages) => { |
| 253 | if (!stages.length) { | 253 | if (!stages.length) { |
| 254 | currentGraphStage.value = '' | 254 | currentGraphStage.value = '' |
| 255 | return | 255 | return |
| @@ -258,45 +258,45 @@ watch( | |||
| 258 | if (stages.includes(currentGraphStage.value)) return | 258 | if (stages.includes(currentGraphStage.value)) return |
| 259 | currentGraphStage.value = stages.includes(DEFAULT_MEMVIEW_STAGE) ? DEFAULT_MEMVIEW_STAGE : stages[0] | 259 | currentGraphStage.value = stages.includes(DEFAULT_MEMVIEW_STAGE) ? DEFAULT_MEMVIEW_STAGE : stages[0] |
| 260 | }, | 260 | }, |
| 261 | - { immediate: true }, | 261 | + { immediate: true }, |
| 262 | -) | 262 | +) |
| 263 | - | 263 | + |
| 264 | -watch( | 264 | +watch( |
| 265 | - selectedDatasetName, | 265 | + selectedDatasetName, |
| 266 | - async (datasetName) => { | 266 | + async (datasetName) => { |
| 267 | - const token = ++issueLoadToken | 267 | + const token = ++issueLoadToken |
| 268 | - if (!datasetName) { | 268 | + if (!datasetName) { |
| 269 | - datasetIssuePayload.value = { issueCount: 0, issues: [] } | 269 | + datasetIssuePayload.value = { issueCount: 0, issues: [] } |
| 270 | - return | 270 | + return |
| 271 | - } | 271 | + } |
| 272 | - | 272 | + |
| 273 | - const payload = await fetchValidationIssues(datasetName) | 273 | + const payload = await fetchValidationIssues(datasetName) |
| 274 | - if (token === issueLoadToken) { | 274 | + if (token === issueLoadToken) { |
| 275 | - datasetIssuePayload.value = payload | 275 | + datasetIssuePayload.value = payload |
| 276 | - } | 276 | + } |
| 277 | - }, | 277 | + }, |
| 278 | - { immediate: true }, | 278 | + { immediate: true }, |
| 279 | -) | 279 | +) |
| 280 | - | 280 | + |
| 281 | -watch( | 281 | +watch( |
| 282 | - issues, | 282 | + issues, |
| 283 | - (nextIssues) => { | 283 | + (nextIssues) => { |
| 284 | - if (!nextIssues.length) { | 284 | + if (!nextIssues.length) { |
| 285 | - selectedIssueId.value = null | 285 | + selectedIssueId.value = null |
| 286 | - return | 286 | + return |
| 287 | - } | 287 | + } |
| 288 | - | 288 | + |
| 289 | - const currentIssueExists = nextIssues.some((issue) => issue.issueId === selectedIssueId.value) | 289 | + const currentIssueExists = nextIssues.some((issue) => issue.issueId === selectedIssueId.value) |
| 290 | - if (!currentIssueExists) { | 290 | + if (!currentIssueExists) { |
| 291 | - selectedIssueId.value = nextIssues[0].issueId | 291 | + selectedIssueId.value = nextIssues[0].issueId |
| 292 | - } | 292 | + } |
| 293 | - }, | 293 | + }, |
| 294 | - { immediate: true }, | 294 | + { immediate: true }, |
| 295 | -) | 295 | +) |
| 296 | - | 296 | + |
| 297 | -watch( | 297 | +watch( |
| 298 | - () => pendingMemViewNavigation.value?.token ?? 0, | 298 | + () => pendingMemViewNavigation.value?.token ?? 0, |
| 299 | - async () => { | 299 | + async () => { |
| 300 | const request = pendingMemViewNavigation.value | 300 | const request = pendingMemViewNavigation.value |
| 301 | if (!request) return | 301 | if (!request) return |
| 302 | 302 | ||
| @@ -334,303 +334,303 @@ watch( | |||
| 334 | { immediate: true }, | 334 | { immediate: true }, |
| 335 | ) | 335 | ) |
| 336 | 336 | ||
| 337 | -const selectedNodeStep = computed(() => { | 337 | +const selectedNodeStep = computed(() => { |
| 338 | - const node = selectedNode.value | 338 | + const node = selectedNode.value |
| 339 | - return resolveStepForNode(node) | 339 | + return resolveStepForNode(node) |
| 340 | -}) | 340 | +}) |
| 341 | - | ||
| 342 | -const selectedRankIdSet = computed(() => { | ||
| 343 | - const ids = new Set() | ||
| 344 | - for (const key of selectedRankKeys.value) { | ||
| 345 | - const match = String(key).match(/^rank-(\d+)$/) | ||
| 346 | - if (match) { | ||
| 347 | - ids.add(Number(match[1])) | ||
| 348 | - } | ||
| 349 | - } | ||
| 350 | - return ids | ||
| 351 | -}) | ||
| 352 | - | ||
| 353 | -const selectedNodeTaskOps = computed(() => { | ||
| 354 | - const node = selectedNode.value | ||
| 355 | - const step = selectedNodeStep.value | ||
| 356 | - if (!node?.id || !indexes.value || !Number.isInteger(step)) return [] | ||
| 357 | - return taskOpsAtStep(indexes.value, step).filter((op) => taskOpMatchesSelectedNode(node, op)) | ||
| 358 | -}) | ||
| 359 | - | ||
| 360 | -const selectedSearchFieldLabel = computed( | ||
| 361 | - () => SEARCH_FIELD_OPTIONS.find((option) => option.value === searchField.value)?.label ?? searchField.value, | ||
| 362 | -) | ||
| 363 | - | ||
| 364 | -const selectedRankSearchNodes = computed(() => { | ||
| 365 | - if (!selectedRankIdSet.value.size) return [] | ||
| 366 | - | ||
| 367 | - const registry = nodeRegistry.value | ||
| 368 | - if (!(registry instanceof Map) || !registry.size) return [] | ||
| 369 | - | ||
| 370 | - const seen = new Map() | ||
| 371 | - for (const node of registry.values()) { | ||
| 372 | - if (!node?.id || seen.has(node.id)) continue | ||
| 373 | - if (Number.isInteger(node.rankId) && !selectedRankIdSet.value.has(node.rankId)) { | ||
| 374 | - continue | ||
| 375 | - } | ||
| 376 | - if (!Number.isInteger(node.rankId)) { | ||
| 377 | - continue | ||
| 378 | - } | ||
| 379 | - seen.set(node.id, node) | ||
| 380 | - } | ||
| 381 | - | ||
| 382 | - return [...seen.values()].sort((left, right) => { | ||
| 383 | - const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY | ||
| 384 | - const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY | ||
| 385 | - if (leftRank !== rightRank) return leftRank - rightRank | ||
| 386 | - | ||
| 387 | - const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY | ||
| 388 | - const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY | ||
| 389 | - if (leftQueue !== rightQueue) return leftQueue - rightQueue | ||
| 390 | - | ||
| 391 | - const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 392 | - const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 393 | - if (leftPos !== rightPos) return leftPos - rightPos | ||
| 394 | - | ||
| 395 | - return String(left.id).localeCompare(String(right.id)) | ||
| 396 | - }) | ||
| 397 | -}) | ||
| 398 | - | ||
| 399 | -const normalizedSearchQuery = computed(() => searchQuery.value.trim()) | ||
| 400 | - | ||
| 401 | -function collectSearchNodesFromRegistry(registry) { | ||
| 402 | - if (!(registry instanceof Map) || !registry.size) return [] | ||
| 403 | - | ||
| 404 | - const roots = [...registry.values()].filter((node) => node?.id && !node.isPlaceholder && Number.isInteger(node.rankId)) | ||
| 405 | - | ||
| 406 | - const collected = [] | ||
| 407 | - const seenIds = new Set() | ||
| 408 | - | ||
| 409 | - const pushNode = (node, context = {}) => { | ||
| 410 | - if (!node?.id || seenIds.has(node.id)) return | ||
| 411 | - if (!Number.isInteger(node.rankId)) return | ||
| 412 | - | ||
| 413 | - seenIds.add(node.id) | ||
| 414 | - collected.push({ | ||
| 415 | - ...node, | ||
| 416 | - searchParentId: context.parentId ?? '', | ||
| 417 | - searchDepth: Number.isInteger(context.depth) ? context.depth : 0, | ||
| 418 | - searchPath: Array.isArray(context.path) ? context.path : [], | ||
| 419 | - searchRootId: context.rootId ?? node.id, | ||
| 420 | - }) | ||
| 421 | - } | ||
| 422 | - | ||
| 423 | - const walkSubgraph = (entries, context) => { | ||
| 424 | - if (!Array.isArray(entries)) return | ||
| 425 | - for (const entry of entries) { | ||
| 426 | - if (!entry || typeof entry !== 'object') continue | ||
| 427 | - const nestedNodes = normalizeStreamCollection([entry], context.rankId, { | ||
| 428 | - stageName: currentGraphStage.value || DEFAULT_MEMVIEW_STAGE, | ||
| 429 | - topLevel: false, | ||
| 430 | - }).flatMap((stream) => stream.nodes) | ||
| 431 | - | ||
| 432 | - for (const nestedNode of nestedNodes) { | ||
| 433 | - const nestedContext = { | ||
| 434 | - rootId: context.rootId, | ||
| 435 | - parentId: context.parentId, | ||
| 436 | - depth: context.depth + 1, | ||
| 437 | - path: [...context.path, entry.node_id ?? entry.id ?? entry.task_id ?? nestedNode.id], | ||
| 438 | - } | ||
| 439 | - pushNode(nestedNode, nestedContext) | ||
| 440 | - const nestedSubGraph = nestedNode?.rawNode?.task?.task_data?.sub_graph | ||
| 441 | - if (Array.isArray(nestedSubGraph) && nestedSubGraph.length) { | ||
| 442 | - walkSubgraph(nestedSubGraph.flat(), { | ||
| 443 | - rankId: nestedNode.rankId, | ||
| 444 | - rootId: context.rootId, | ||
| 445 | - parentId: nestedNode.id, | ||
| 446 | - depth: nestedContext.depth, | ||
| 447 | - path: nestedContext.path, | ||
| 448 | - }) | ||
| 449 | - } | ||
| 450 | - } | ||
| 451 | - } | ||
| 452 | - } | ||
| 453 | - | ||
| 454 | - for (const rootNode of roots) { | ||
| 455 | - pushNode(rootNode, { | ||
| 456 | - rootId: rootNode.id, | ||
| 457 | - parentId: '', | ||
| 458 | - depth: 0, | ||
| 459 | - path: [rootNode.id], | ||
| 460 | - }) | ||
| 461 | - | ||
| 462 | - const subGraph = rootNode?.rawNode?.task?.task_data?.sub_graph | ||
| 463 | - if (Array.isArray(subGraph) && subGraph.length) { | ||
| 464 | - walkSubgraph(subGraph.flat(), { | ||
| 465 | - rankId: rootNode.rankId, | ||
| 466 | - rootId: rootNode.id, | ||
| 467 | - parentId: rootNode.id, | ||
| 468 | - depth: 0, | ||
| 469 | - path: [rootNode.id], | ||
| 470 | - }) | ||
| 471 | - } | ||
| 472 | - } | ||
| 473 | - | ||
| 474 | - return collected | ||
| 475 | -} | ||
| 476 | - | ||
| 477 | -function isExactSearchMatch(node, field, query) { | ||
| 478 | - if (!node || !query) return false | ||
| 479 | - const normalizedQuery = String(query).trim().toLowerCase() | ||
| 480 | - if (!normalizedQuery) return false | ||
| 481 | - | ||
| 482 | - if (field === 'taskType') { | ||
| 483 | - const value = String(node.taskType ?? node.rawNode?.task?.task_type ?? node.rawNode?.task_type ?? '').trim().toLowerCase() | ||
| 484 | - return value === normalizedQuery | ||
| 485 | - } | ||
| 486 | - | ||
| 487 | - if (field === 'notifyId') { | ||
| 488 | - const value = normalizeSearchFieldValue( | ||
| 489 | - node.notifyId ?? | ||
| 490 | - node.notify_id ?? | ||
| 491 | - node.taskData?.notifyId ?? | ||
| 492 | - node.taskData?.notify_id ?? | ||
| 493 | - node.rawNode?.notifyId ?? | ||
| 494 | - node.rawNode?.notify_id ?? | ||
| 495 | - node.rawNode?.task?.notifyId ?? | ||
| 496 | - node.rawNode?.task?.notify_id, | ||
| 497 | - ) | ||
| 498 | - return value === normalizedQuery | ||
| 499 | - } | ||
| 500 | - | ||
| 501 | - const values = resolveSearchNodeIds(node) | ||
| 502 | - return values.some((value) => String(value).trim().toLowerCase() === normalizedQuery) | ||
| 503 | -} | ||
| 504 | - | ||
| 505 | -function resolveSearchNodeIds(node) { | ||
| 506 | - const ids = new Set() | ||
| 507 | - const push = (value) => { | ||
| 508 | - if (typeof value === 'string' && value.trim()) { | ||
| 509 | - ids.add(value.trim()) | ||
| 510 | - } | ||
| 511 | - } | ||
| 512 | - | ||
| 513 | - push(node?.id) | ||
| 514 | - push(node?.rawNode?.node_id) | ||
| 515 | - push(node?.rawNode?.id) | ||
| 516 | - push(node?.rawNode?.task_id) | ||
| 517 | - return [...ids] | ||
| 518 | -} | ||
| 519 | - | ||
| 520 | -function sortSearchNodes(nodes) { | ||
| 521 | - return [...nodes].sort((left, right) => { | ||
| 522 | - const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY | ||
| 523 | - const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY | ||
| 524 | - if (leftRank !== rightRank) return leftRank - rightRank | ||
| 525 | - | ||
| 526 | - const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY | ||
| 527 | - const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY | ||
| 528 | - if (leftQueue !== rightQueue) return leftQueue - rightQueue | ||
| 529 | - | ||
| 530 | - const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 531 | - const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 532 | - if (leftPos !== rightPos) return leftPos - rightPos | ||
| 533 | - | ||
| 534 | - return String(left.id).localeCompare(String(right.id)) | ||
| 535 | - }) | ||
| 536 | -} | ||
| 537 | - | ||
| 538 | -const searchResults = computed(() => { | ||
| 539 | - const query = normalizedSearchQuery.value | ||
| 540 | - if (!query) return [] | ||
| 541 | - | ||
| 542 | - const field = searchField.value | ||
| 543 | - const allSearchNodes = collectSearchNodesFromRegistry(nodeRegistry.value) | ||
| 544 | - const matched = allSearchNodes.filter((node) => isExactSearchMatch(node, field, query)) | ||
| 545 | - | ||
| 546 | - return sortSearchNodes(matched) | ||
| 547 | - .map((node) => ({ | ||
| 548 | - node, | ||
| 549 | - taskId: node.id, | ||
| 550 | - taskType: String(node.taskType ?? '--').replaceAll('_', ' '), | ||
| 551 | - rank: Number.isInteger(node.rankId) ? node.rankId : '--', | ||
| 552 | - queue: Number.isInteger(node.queueId) ? node.queueId : '--', | ||
| 553 | - pos: Number.isInteger(node.pos) ? node.pos : Number.isInteger(node.slotIndex) ? node.slotIndex : '--', | ||
| 554 | - location: formatSearchLocation(node), | ||
| 555 | - notifyId: resolveSearchFieldDisplayValue(node, 'notifyId'), | ||
| 556 | - })) | ||
| 557 | -}) | ||
| 558 | - | ||
| 559 | -const canResolveRelation = computed(() => (nodeId) => Boolean(resolveNodeNavigationTarget(nodeId))) | ||
| 560 | -const datasetIssueNodeIds = computed(() => { | ||
| 561 | - const issues = datasetIssuePayload.value?.issues ?? [] | ||
| 562 | - const registry = nodeRegistry.value | ||
| 563 | - if (!(registry instanceof Map) || !registry.size || !issues.length) return null | ||
| 564 | - | ||
| 565 | - const ids = new Set() | ||
| 566 | - const nodes = [...new Set([...registry.values()].filter(Boolean))] | ||
| 567 | - for (const issue of issues) { | ||
| 568 | - for (const node of nodes) { | ||
| 569 | - if (issueMatchesNode(issue, node)) { | ||
| 570 | - ids.add(node.id) | ||
| 571 | - } | ||
| 572 | - } | ||
| 573 | - } | ||
| 574 | - | ||
| 575 | - return ids.size ? ids : null | ||
| 576 | -}) | ||
| 577 | - | ||
| 578 | -const dagIssueNodeIds = computed(() => { | ||
| 579 | - const ids = new Set() | ||
| 580 | - datasetIssueNodeIds.value?.forEach((nodeId) => ids.add(nodeId)) | ||
| 581 | - issueHighlightedNodeIds.value?.forEach?.((nodeId) => ids.add(nodeId)) | ||
| 582 | - return ids.size ? ids : null | ||
| 583 | -}) | ||
| 584 | 341 | ||
| 585 | -function handleTreeCheck(checkedKeys) { | 342 | +const selectedRankIdSet = computed(() => { |
| 586 | - setSelectedRankKeys(checkedKeys) | 343 | + const ids = new Set() |
| 587 | -} | 344 | + for (const key of selectedRankKeys.value) { |
| 588 | - | 345 | + const match = String(key).match(/^rank-(\d+)$/) |
| 589 | -function issueMatchesNode(issue, node) { | 346 | + if (match) { |
| 590 | - if (!issue || !node?.id) return false | 347 | + ids.add(Number(match[1])) |
| 591 | - | 348 | + } |
| 592 | - const targetIds = issueTargetNodeIds(issue) | 349 | + } |
| 593 | - const lookupIds = new Set(resolveNodeLookupIds(node)) | 350 | + return ids |
| 594 | - if (targetIds.some((nodeId) => lookupIds.has(nodeId) || node.mappingKey === nodeId)) { | 351 | +}) |
| 595 | - return true | 352 | + |
| 596 | - } | 353 | +const selectedNodeTaskOps = computed(() => { |
| 597 | - | 354 | + const node = selectedNode.value |
| 598 | - const target = issue.dagTarget ?? {} | 355 | + const step = selectedNodeStep.value |
| 599 | - const detail = issue.rawDetail ?? {} | 356 | + if (!node?.id || !indexes.value || !Number.isInteger(step)) return [] |
| 600 | - const rankId = firstIssueInteger(target.rankId, issue.primaryRankId, detail.rank_id, detail.task_rank, detail.peer_rank) | 357 | + return taskOpsAtStep(indexes.value, step).filter((op) => taskOpMatchesSelectedNode(node, op)) |
| 601 | - const queueId = firstIssueInteger(target.queueId, issue.queueId, detail.queue_id) | 358 | +}) |
| 602 | - const slotIndex = firstIssueInteger(target.slotIndex, detail.task_pos, detail.pos) | 359 | + |
| 603 | - if (!Number.isInteger(rankId) || !Number.isInteger(queueId) || !Number.isInteger(slotIndex)) return false | 360 | +const selectedSearchFieldLabel = computed( |
| 604 | - | 361 | + () => SEARCH_FIELD_OPTIONS.find((option) => option.value === searchField.value)?.label ?? searchField.value, |
| 605 | - const nodeSlot = Number.isInteger(node.pos) ? node.pos : node.slotIndex | 362 | +) |
| 606 | - const nodeQueue = Number.isInteger(node.queueId) ? node.queueId : node.streamId | 363 | + |
| 607 | - return node.rankId === rankId && nodeQueue === queueId && nodeSlot === slotIndex | 364 | +const selectedRankSearchNodes = computed(() => { |
| 608 | -} | 365 | + if (!selectedRankIdSet.value.size) return [] |
| 609 | - | 366 | + |
| 610 | -function issueTargetNodeIds(issue) { | 367 | + const registry = nodeRegistry.value |
| 611 | - const ids = [] | 368 | + if (!(registry instanceof Map) || !registry.size) return [] |
| 612 | - const push = (value) => { | 369 | + |
| 613 | - if (typeof value === 'string' && value.trim()) ids.push(value.trim()) | 370 | + const seen = new Map() |
| 614 | - } | 371 | + for (const node of registry.values()) { |
| 615 | - | 372 | + if (!node?.id || seen.has(node.id)) continue |
| 616 | - push(issue?.dagTarget?.nodeId) | 373 | + if (Number.isInteger(node.rankId) && !selectedRankIdSet.value.has(node.rankId)) { |
| 617 | - push(issue?.taskNode?.nodeId) | 374 | + continue |
| 618 | - push(issue?.rawDetail?.task_id) | 375 | + } |
| 619 | - issue?.relatedNodeAnchors?.forEach((anchor) => push(anchor?.nodeId)) | 376 | + if (!Number.isInteger(node.rankId)) { |
| 620 | - | 377 | + continue |
| 621 | - return [...new Set(ids)] | 378 | + } |
| 622 | -} | 379 | + seen.set(node.id, node) |
| 623 | - | 380 | + } |
| 624 | -function firstIssueInteger(...values) { | 381 | + |
| 625 | - for (const value of values) { | 382 | + return [...seen.values()].sort((left, right) => { |
| 626 | - if (Number.isInteger(value)) return value | 383 | + const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY |
| 627 | - if (typeof value === 'string' && value.trim()) { | 384 | + const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY |
| 628 | - const numeric = Number(value) | 385 | + if (leftRank !== rightRank) return leftRank - rightRank |
| 629 | - if (Number.isInteger(numeric)) return numeric | 386 | + |
| 630 | - } | 387 | + const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY |
| 631 | - } | 388 | + const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY |
| 632 | - return null | 389 | + if (leftQueue !== rightQueue) return leftQueue - rightQueue |
| 633 | -} | 390 | + |
| 391 | + const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 392 | + const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 393 | + if (leftPos !== rightPos) return leftPos - rightPos | ||
| 394 | + | ||
| 395 | + return String(left.id).localeCompare(String(right.id)) | ||
| 396 | + }) | ||
| 397 | +}) | ||
| 398 | + | ||
| 399 | +const normalizedSearchQuery = computed(() => searchQuery.value.trim()) | ||
| 400 | + | ||
| 401 | +function collectSearchNodesFromRegistry(registry) { | ||
| 402 | + if (!(registry instanceof Map) || !registry.size) return [] | ||
| 403 | + | ||
| 404 | + const roots = [...registry.values()].filter((node) => node?.id && !node.isPlaceholder && Number.isInteger(node.rankId)) | ||
| 405 | + | ||
| 406 | + const collected = [] | ||
| 407 | + const seenIds = new Set() | ||
| 408 | + | ||
| 409 | + const pushNode = (node, context = {}) => { | ||
| 410 | + if (!node?.id || seenIds.has(node.id)) return | ||
| 411 | + if (!Number.isInteger(node.rankId)) return | ||
| 412 | + | ||
| 413 | + seenIds.add(node.id) | ||
| 414 | + collected.push({ | ||
| 415 | + ...node, | ||
| 416 | + searchParentId: context.parentId ?? '', | ||
| 417 | + searchDepth: Number.isInteger(context.depth) ? context.depth : 0, | ||
| 418 | + searchPath: Array.isArray(context.path) ? context.path : [], | ||
| 419 | + searchRootId: context.rootId ?? node.id, | ||
| 420 | + }) | ||
| 421 | + } | ||
| 422 | + | ||
| 423 | + const walkSubgraph = (entries, context) => { | ||
| 424 | + if (!Array.isArray(entries)) return | ||
| 425 | + for (const entry of entries) { | ||
| 426 | + if (!entry || typeof entry !== 'object') continue | ||
| 427 | + const nestedNodes = normalizeStreamCollection([entry], context.rankId, { | ||
| 428 | + stageName: currentGraphStage.value || DEFAULT_MEMVIEW_STAGE, | ||
| 429 | + topLevel: false, | ||
| 430 | + }).flatMap((stream) => stream.nodes) | ||
| 431 | + | ||
| 432 | + for (const nestedNode of nestedNodes) { | ||
| 433 | + const nestedContext = { | ||
| 434 | + rootId: context.rootId, | ||
| 435 | + parentId: context.parentId, | ||
| 436 | + depth: context.depth + 1, | ||
| 437 | + path: [...context.path, entry.node_id ?? entry.id ?? entry.task_id ?? nestedNode.id], | ||
| 438 | + } | ||
| 439 | + pushNode(nestedNode, nestedContext) | ||
| 440 | + const nestedSubGraph = nestedNode?.rawNode?.task?.task_data?.sub_graph | ||
| 441 | + if (Array.isArray(nestedSubGraph) && nestedSubGraph.length) { | ||
| 442 | + walkSubgraph(nestedSubGraph.flat(), { | ||
| 443 | + rankId: nestedNode.rankId, | ||
| 444 | + rootId: context.rootId, | ||
| 445 | + parentId: nestedNode.id, | ||
| 446 | + depth: nestedContext.depth, | ||
| 447 | + path: nestedContext.path, | ||
| 448 | + }) | ||
| 449 | + } | ||
| 450 | + } | ||
| 451 | + } | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + for (const rootNode of roots) { | ||
| 455 | + pushNode(rootNode, { | ||
| 456 | + rootId: rootNode.id, | ||
| 457 | + parentId: '', | ||
| 458 | + depth: 0, | ||
| 459 | + path: [rootNode.id], | ||
| 460 | + }) | ||
| 461 | + | ||
| 462 | + const subGraph = rootNode?.rawNode?.task?.task_data?.sub_graph | ||
| 463 | + if (Array.isArray(subGraph) && subGraph.length) { | ||
| 464 | + walkSubgraph(subGraph.flat(), { | ||
| 465 | + rankId: rootNode.rankId, | ||
| 466 | + rootId: rootNode.id, | ||
| 467 | + parentId: rootNode.id, | ||
| 468 | + depth: 0, | ||
| 469 | + path: [rootNode.id], | ||
| 470 | + }) | ||
| 471 | + } | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | + return collected | ||
| 475 | +} | ||
| 476 | + | ||
| 477 | +function isExactSearchMatch(node, field, query) { | ||
| 478 | + if (!node || !query) return false | ||
| 479 | + const normalizedQuery = String(query).trim().toLowerCase() | ||
| 480 | + if (!normalizedQuery) return false | ||
| 481 | + | ||
| 482 | + if (field === 'taskType') { | ||
| 483 | + const value = String(node.taskType ?? node.rawNode?.task?.task_type ?? node.rawNode?.task_type ?? '').trim().toLowerCase() | ||
| 484 | + return value === normalizedQuery | ||
| 485 | + } | ||
| 486 | + | ||
| 487 | + if (field === 'notifyId') { | ||
| 488 | + const value = normalizeSearchFieldValue( | ||
| 489 | + node.notifyId ?? | ||
| 490 | + node.notify_id ?? | ||
| 491 | + node.taskData?.notifyId ?? | ||
| 492 | + node.taskData?.notify_id ?? | ||
| 493 | + node.rawNode?.notifyId ?? | ||
| 494 | + node.rawNode?.notify_id ?? | ||
| 495 | + node.rawNode?.task?.notifyId ?? | ||
| 496 | + node.rawNode?.task?.notify_id, | ||
| 497 | + ) | ||
| 498 | + return value === normalizedQuery | ||
| 499 | + } | ||
| 500 | + | ||
| 501 | + const values = resolveSearchNodeIds(node) | ||
| 502 | + return values.some((value) => String(value).trim().toLowerCase() === normalizedQuery) | ||
| 503 | +} | ||
| 504 | + | ||
| 505 | +function resolveSearchNodeIds(node) { | ||
| 506 | + const ids = new Set() | ||
| 507 | + const push = (value) => { | ||
| 508 | + if (typeof value === 'string' && value.trim()) { | ||
| 509 | + ids.add(value.trim()) | ||
| 510 | + } | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + push(node?.id) | ||
| 514 | + push(node?.rawNode?.node_id) | ||
| 515 | + push(node?.rawNode?.id) | ||
| 516 | + push(node?.rawNode?.task_id) | ||
| 517 | + return [...ids] | ||
| 518 | +} | ||
| 519 | + | ||
| 520 | +function sortSearchNodes(nodes) { | ||
| 521 | + return [...nodes].sort((left, right) => { | ||
| 522 | + const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY | ||
| 523 | + const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY | ||
| 524 | + if (leftRank !== rightRank) return leftRank - rightRank | ||
| 525 | + | ||
| 526 | + const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY | ||
| 527 | + const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY | ||
| 528 | + if (leftQueue !== rightQueue) return leftQueue - rightQueue | ||
| 529 | + | ||
| 530 | + const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 531 | + const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 532 | + if (leftPos !== rightPos) return leftPos - rightPos | ||
| 533 | + | ||
| 534 | + return String(left.id).localeCompare(String(right.id)) | ||
| 535 | + }) | ||
| 536 | +} | ||
| 537 | + | ||
| 538 | +const searchResults = computed(() => { | ||
| 539 | + const query = normalizedSearchQuery.value | ||
| 540 | + if (!query) return [] | ||
| 541 | + | ||
| 542 | + const field = searchField.value | ||
| 543 | + const allSearchNodes = collectSearchNodesFromRegistry(nodeRegistry.value) | ||
| 544 | + const matched = allSearchNodes.filter((node) => isExactSearchMatch(node, field, query)) | ||
| 545 | + | ||
| 546 | + return sortSearchNodes(matched) | ||
| 547 | + .map((node) => ({ | ||
| 548 | + node, | ||
| 549 | + taskId: node.id, | ||
| 550 | + taskType: String(node.taskType ?? '--').replaceAll('_', ' '), | ||
| 551 | + rank: Number.isInteger(node.rankId) ? node.rankId : '--', | ||
| 552 | + queue: Number.isInteger(node.queueId) ? node.queueId : '--', | ||
| 553 | + pos: Number.isInteger(node.pos) ? node.pos : Number.isInteger(node.slotIndex) ? node.slotIndex : '--', | ||
| 554 | + formatLoc: formatSearchLocation(node), | ||
| 555 | + notifyId: resolveSearchFieldDisplayValue(node, 'notifyId'), | ||
| 556 | + })) | ||
| 557 | +}) | ||
| 558 | + | ||
| 559 | +const canResolveRelation = computed(() => (nodeId) => Boolean(resolveNodeNavigationTarget(nodeId))) | ||
| 560 | +const datasetIssueNodeIds = computed(() => { | ||
| 561 | + const issues = datasetIssuePayload.value?.issues ?? [] | ||
| 562 | + const registry = nodeRegistry.value | ||
| 563 | + if (!(registry instanceof Map) || !registry.size || !issues.length) return null | ||
| 564 | + | ||
| 565 | + const ids = new Set() | ||
| 566 | + const nodes = [...new Set([...registry.values()].filter(Boolean))] | ||
| 567 | + for (const issue of issues) { | ||
| 568 | + for (const node of nodes) { | ||
| 569 | + if (issueMatchesNode(issue, node)) { | ||
| 570 | + ids.add(node.id) | ||
| 571 | + } | ||
| 572 | + } | ||
| 573 | + } | ||
| 574 | + | ||
| 575 | + return ids.size ? ids : null | ||
| 576 | +}) | ||
| 577 | + | ||
| 578 | +const dagIssueNodeIds = computed(() => { | ||
| 579 | + const ids = new Set() | ||
| 580 | + datasetIssueNodeIds.value?.forEach((nodeId) => ids.add(nodeId)) | ||
| 581 | + issueHighlightedNodeIds.value?.forEach?.((nodeId) => ids.add(nodeId)) | ||
| 582 | + return ids.size ? ids : null | ||
| 583 | +}) | ||
| 584 | + | ||
| 585 | +function handleTreeCheck(checkedKeys) { | ||
| 586 | + setSelectedRankKeys(checkedKeys) | ||
| 587 | +} | ||
| 588 | + | ||
| 589 | +function issueMatchesNode(issue, node) { | ||
| 590 | + if (!issue || !node?.id) return false | ||
| 591 | + | ||
| 592 | + const targetIds = issueTargetNodeIds(issue) | ||
| 593 | + const lookupIds = new Set(resolveNodeLookupIds(node)) | ||
| 594 | + if (targetIds.some((nodeId) => lookupIds.has(nodeId) || node.mappingKey === nodeId)) { | ||
| 595 | + return true | ||
| 596 | + } | ||
| 597 | + | ||
| 598 | + const target = issue.dagTarget ?? {} | ||
| 599 | + const detail = issue.rawDetail ?? {} | ||
| 600 | + const rankId = firstIssueInteger(target.rankId, issue.primaryRankId, detail.rank_id, detail.task_rank, detail.peer_rank) | ||
| 601 | + const queueId = firstIssueInteger(target.queueId, issue.queueId, detail.queue_id) | ||
| 602 | + const slotIndex = firstIssueInteger(target.slotIndex, detail.task_pos, detail.pos) | ||
| 603 | + if (!Number.isInteger(rankId) || !Number.isInteger(queueId) || !Number.isInteger(slotIndex)) return false | ||
| 604 | + | ||
| 605 | + const nodeSlot = Number.isInteger(node.pos) ? node.pos : node.slotIndex | ||
| 606 | + const nodeQueue = Number.isInteger(node.queueId) ? node.queueId : node.streamId | ||
| 607 | + return node.rankId === rankId && nodeQueue === queueId && nodeSlot === slotIndex | ||
| 608 | +} | ||
| 609 | + | ||
| 610 | +function issueTargetNodeIds(issue) { | ||
| 611 | + const ids = [] | ||
| 612 | + const push = (value) => { | ||
| 613 | + if (typeof value === 'string' && value.trim()) ids.push(value.trim()) | ||
| 614 | + } | ||
| 615 | + | ||
| 616 | + push(issue?.dagTarget?.nodeId) | ||
| 617 | + push(issue?.taskNode?.nodeId) | ||
| 618 | + push(issue?.rawDetail?.task_id) | ||
| 619 | + issue?.relatedNodeAnchors?.forEach((anchor) => push(anchor?.nodeId)) | ||
| 620 | + | ||
| 621 | + return [...new Set(ids)] | ||
| 622 | +} | ||
| 623 | + | ||
| 624 | +function firstIssueInteger(...values) { | ||
| 625 | + for (const value of values) { | ||
| 626 | + if (Number.isInteger(value)) return value | ||
| 627 | + if (typeof value === 'string' && value.trim()) { | ||
| 628 | + const numeric = Number(value) | ||
| 629 | + if (Number.isInteger(numeric)) return numeric | ||
| 630 | + } | ||
| 631 | + } | ||
| 632 | + return null | ||
| 633 | +} | ||
| 634 | 634 | ||
| 635 | function handleLeftPanelResize(size) { | 635 | function handleLeftPanelResize(size) { |
| 636 | if (!sidebarCollapsed.value && typeof size === 'number') { | 636 | if (!sidebarCollapsed.value && typeof size === 'number') { |
| @@ -681,206 +681,206 @@ function expandCenterPane(target) { | |||
| 681 | notifyDagLayoutChange() | 681 | notifyDagLayoutChange() |
| 682 | } | 682 | } |
| 683 | 683 | ||
| 684 | -function handleNodeSelect(node) { | 684 | +function handleNodeSelect(node) { |
| 685 | - focusNode(node, { follow: true, sync: true }) | 685 | + focusNode(node, { follow: true, sync: true }) |
| 686 | -} | 686 | +} |
| 687 | - | 687 | + |
| 688 | -async function handleIssueSelect(issue) { | 688 | +async function handleIssueSelect(issue) { |
| 689 | - if (!issue) return | 689 | + if (!issue) return |
| 690 | - | 690 | + |
| 691 | - selectedIssueId.value = issue.issueId | 691 | + selectedIssueId.value = issue.issueId |
| 692 | - | 692 | + |
| 693 | - const target = resolveIssueNodeTarget(issue) | 693 | + const target = resolveIssueNodeTarget(issue) |
| 694 | - const step = resolveIssueNavigationStep(issue) | 694 | + const step = resolveIssueNavigationStep(issue) |
| 695 | - const rankIds = resolveNavigationRankIds(issue) | 695 | + const rankIds = resolveNavigationRankIds(issue) |
| 696 | - const stageName = issue?.dagTarget?.stageName ?? issue?.memTarget?.stageName ?? '' | 696 | + const stageName = issue?.dagTarget?.stageName ?? issue?.memTarget?.stageName ?? '' |
| 697 | - const hasNodeTarget = Boolean(target?.nodeId) | 697 | + const hasNodeTarget = Boolean(target?.nodeId) |
| 698 | - const hasStepTarget = Number.isInteger(step) | 698 | + const hasStepTarget = Number.isInteger(step) |
| 699 | - | 699 | + |
| 700 | - if (!hasNodeTarget && !hasStepTarget && !rankIds.length) { | 700 | + if (!hasNodeTarget && !hasStepTarget && !rankIds.length) { |
| 701 | - return | 701 | + return |
| 702 | - } | 702 | + } |
| 703 | - | 703 | + |
| 704 | - if (rankIds.length) { | 704 | + if (rankIds.length) { |
| 705 | - setSelectedRankKeys(rankIds.map((rankId) => `rank-${rankId}`)) | 705 | + setSelectedRankKeys(rankIds.map((rankId) => `rank-${rankId}`)) |
| 706 | - } | 706 | + } |
| 707 | - | 707 | + |
| 708 | - if (stageName && stageName !== currentGraphStage.value) { | 708 | + if (stageName && stageName !== currentGraphStage.value) { |
| 709 | - handleStageUpdate(stageName) | 709 | + handleStageUpdate(stageName) |
| 710 | - } | 710 | + } |
| 711 | - | 711 | + |
| 712 | - if (hasNodeTarget) { | 712 | + if (hasNodeTarget) { |
| 713 | - pendingExternalNavigation.value = { | 713 | + pendingExternalNavigation.value = { |
| 714 | - source: 'analytic', | 714 | + source: 'analytic', |
| 715 | - targetView: 'dag', | 715 | + targetView: 'dag', |
| 716 | - stageName: stageName || currentGraphStage.value, | 716 | + stageName: stageName || currentGraphStage.value, |
| 717 | - lookupId: target.nodeId, | 717 | + lookupId: target.nodeId, |
| 718 | - nodeId: target.nodeId, | 718 | + nodeId: target.nodeId, |
| 719 | - rankId: target.rankId, | 719 | + rankId: target.rankId, |
| 720 | - queueId: target.queueId, | 720 | + queueId: target.queueId, |
| 721 | - slotIndex: target.slotIndex, | 721 | + slotIndex: target.slotIndex, |
| 722 | - taskType: target.taskType, | 722 | + taskType: target.taskType, |
| 723 | - } | 723 | + } |
| 724 | - | 724 | + |
| 725 | - await nextTick() | 725 | + await nextTick() |
| 726 | - resolvePendingExternalNavigation() | 726 | + resolvePendingExternalNavigation() |
| 727 | - return | 727 | + return |
| 728 | - } | 728 | + } |
| 729 | - | 729 | + |
| 730 | - if (hasStepTarget) { | 730 | + if (hasStepTarget) { |
| 731 | - focusStep(step, { smoothScroll: false }) | 731 | + focusStep(step, { smoothScroll: false }) |
| 732 | - } | 732 | + } |
| 733 | -} | 733 | +} |
| 734 | - | 734 | + |
| 735 | -function handleSearchResultSelect(result) { | 735 | +function handleSearchResultSelect(result) { |
| 736 | - if (!result?.node) return | 736 | + if (!result?.node) return |
| 737 | - handleNavigate({ | 737 | + handleNavigate({ |
| 738 | - stageName: result.node.stageName || currentGraphStage.value || '', | 738 | + stageName: result.node.stageName || currentGraphStage.value || '', |
| 739 | - lookupId: result.node.id, | 739 | + lookupId: result.node.id, |
| 740 | - containerLookupId: | 740 | + containerLookupId: |
| 741 | - result.node.searchParentId && result.node.searchParentId !== result.node.id | 741 | + result.node.searchParentId && result.node.searchParentId !== result.node.id |
| 742 | - ? result.node.searchParentId | 742 | + ? result.node.searchParentId |
| 743 | - : result.node.searchRootId && result.node.searchRootId !== result.node.id | 743 | + : result.node.searchRootId && result.node.searchRootId !== result.node.id |
| 744 | - ? result.node.searchRootId | 744 | + ? result.node.searchRootId |
| 745 | - : '', | 745 | + : '', |
| 746 | - }) | 746 | + }) |
| 747 | -} | 747 | +} |
| 748 | - | 748 | + |
| 749 | -function resolveNavigationRankIds(issue) { | 749 | +function resolveNavigationRankIds(issue) { |
| 750 | - if (issue?.relatedRankIds?.length) { | 750 | + if (issue?.relatedRankIds?.length) { |
| 751 | - return issue.relatedRankIds | 751 | + return issue.relatedRankIds |
| 752 | - } | 752 | + } |
| 753 | - | 753 | + |
| 754 | - return selectedRankKeys.value | 754 | + return selectedRankKeys.value |
| 755 | .map((key) => { | 755 | .map((key) => { |
| 756 | const match = String(key).match(/^rank-(\d+)$/) | 756 | const match = String(key).match(/^rank-(\d+)$/) |
| 757 | return match ? Number(match[1]) : null | 757 | return match ? Number(match[1]) : null |
| 758 | }) | 758 | }) |
| 759 | .filter((rankId) => Number.isInteger(rankId)) | 759 | .filter((rankId) => Number.isInteger(rankId)) |
| 760 | -} | 760 | +} |
| 761 | - | ||
| 762 | -function resolveIssueNavigationStep(issue) { | ||
| 763 | - const primaryStep = issue?.primaryRelatedStep | ||
| 764 | - if (Number.isInteger(primaryStep?.snapshotStep)) return primaryStep.snapshotStep | ||
| 765 | - | ||
| 766 | - const taskNode = issue?.taskNode | ||
| 767 | - if (Number.isInteger(taskNode?.globalStep)) return taskNode.globalStep | ||
| 768 | - if (Number.isInteger(taskNode?.localStep)) return taskNode.localStep | ||
| 769 | - | ||
| 770 | - const stage = typeof issue?.stage === 'string' ? issue.stage : '' | ||
| 771 | - const stageMatch = stage.match(/^step_(\d+)_/) | ||
| 772 | - if (stageMatch) return Number(stageMatch[1]) | ||
| 773 | - | ||
| 774 | - return null | ||
| 775 | -} | ||
| 776 | - | ||
| 777 | -function resolveIssueNodeTarget(issue) { | ||
| 778 | - const relatedNode = issue?.primaryRelatedNode ?? issue?.taskNode | ||
| 779 | - if (relatedNode?.nodeId || (Number.isInteger(relatedNode?.rankId) && Number.isInteger(relatedNode?.queueId))) { | ||
| 780 | - return { | ||
| 781 | - nodeId: relatedNode?.nodeId ?? '', | ||
| 782 | - rankId: Number.isInteger(relatedNode?.rankId) ? relatedNode.rankId : issue?.primaryRankId ?? null, | ||
| 783 | - queueId: Number.isInteger(relatedNode?.queueId) ? relatedNode.queueId : issue?.queueId ?? null, | ||
| 784 | - slotIndex: Number.isInteger(relatedNode?.pos) ? relatedNode.pos : null, | ||
| 785 | - taskType: relatedNode?.taskType ?? issue?.taskType ?? '', | ||
| 786 | - } | ||
| 787 | - } | ||
| 788 | - | ||
| 789 | - if (!issue?.dagTarget) { | ||
| 790 | - return { | ||
| 791 | - nodeId: '', | ||
| 792 | - rankId: null, | ||
| 793 | - queueId: null, | ||
| 794 | - slotIndex: null, | ||
| 795 | - taskType: '', | ||
| 796 | - } | ||
| 797 | - } | ||
| 798 | - | ||
| 799 | - return { | ||
| 800 | - nodeId: issue.dagTarget.nodeId ?? '', | ||
| 801 | - rankId: | ||
| 802 | - Number.isInteger(issue?.dagTarget?.queueId) || Number.isInteger(issue?.dagTarget?.slotIndex) || issue?.dagTarget?.nodeId | ||
| 803 | - ? issue.dagTarget.rankId ?? issue?.primaryRankId ?? null | ||
| 804 | - : null, | ||
| 805 | - queueId: issue.dagTarget.queueId ?? issue?.queueId ?? null, | ||
| 806 | - slotIndex: issue?.dagTarget?.slotIndex ?? null, | ||
| 807 | - taskType: issue?.dagTarget?.taskType ?? issue?.taskType ?? '', | ||
| 808 | - } | ||
| 809 | -} | ||
| 810 | - | ||
| 811 | -function resolveSearchFieldValue(node, field) { | ||
| 812 | - if (!node) return '' | ||
| 813 | - const rawNode = node.rawNode ?? {} | ||
| 814 | - const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 815 | - | ||
| 816 | - switch (field) { | ||
| 817 | - case 'taskType': | ||
| 818 | - return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '').toLowerCase() | ||
| 819 | - case 'notifyId': | ||
| 820 | - return normalizeSearchFieldValue( | ||
| 821 | - node.notifyId ?? | ||
| 822 | - node.notify_id ?? | ||
| 823 | - taskData.notifyId ?? | ||
| 824 | - taskData.notify_id ?? | ||
| 825 | - rawNode.notifyId ?? | ||
| 826 | - rawNode.notify_id ?? | ||
| 827 | - rawNode?.task?.notifyId ?? | ||
| 828 | - rawNode?.task?.notify_id, | ||
| 829 | - ) | ||
| 830 | - case 'taskId': | ||
| 831 | - default: | ||
| 832 | - return String(node.id ?? rawNode?.node_id ?? rawNode?.id ?? '').toLowerCase() | ||
| 833 | - } | ||
| 834 | -} | ||
| 835 | - | ||
| 836 | -function resolveSearchFieldDisplayValue(node, field) { | ||
| 837 | - if (!node) return '--' | ||
| 838 | - const rawNode = node.rawNode ?? {} | ||
| 839 | - const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 840 | - | ||
| 841 | - switch (field) { | ||
| 842 | - case 'taskType': | ||
| 843 | - return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '--').replaceAll('_', ' ') | ||
| 844 | - case 'notifyId': | ||
| 845 | - return formatSearchFieldDisplayValue( | ||
| 846 | - node.notifyId ?? | ||
| 847 | - node.notify_id ?? | ||
| 848 | - taskData.notifyId ?? | ||
| 849 | - taskData.notify_id ?? | ||
| 850 | - rawNode.notifyId ?? | ||
| 851 | - rawNode.notify_id ?? | ||
| 852 | - rawNode?.task?.notifyId ?? | ||
| 853 | - rawNode?.task?.notify_id, | ||
| 854 | - ) | ||
| 855 | - case 'taskId': | ||
| 856 | - default: | ||
| 857 | - return formatSearchFieldDisplayValue(node.id ?? rawNode?.node_id ?? rawNode?.id) | ||
| 858 | - } | ||
| 859 | -} | ||
| 860 | - | ||
| 861 | -function formatSearchLocation(node) { | ||
| 862 | - const rank = Number.isInteger(node?.rankId) ? `rank ${node.rankId}` : 'rank --' | ||
| 863 | - const queue = Number.isInteger(node?.queueId) ? `queue ${node.queueId}` : 'queue --' | ||
| 864 | - const posValue = Number.isInteger(node?.pos) | ||
| 865 | - ? node.pos | ||
| 866 | - : Number.isInteger(node?.slotIndex) | ||
| 867 | - ? node.slotIndex | ||
| 868 | - : null | ||
| 869 | - const pos = Number.isInteger(posValue) ? `pos ${posValue}` : 'pos --' | ||
| 870 | - return `${rank} / ${queue} / ${pos}` | ||
| 871 | -} | ||
| 872 | - | ||
| 873 | -function normalizeSearchFieldValue(value) { | ||
| 874 | - if (value === null || value === undefined || value === '') return '' | ||
| 875 | - return String(value).toLowerCase() | ||
| 876 | -} | ||
| 877 | - | ||
| 878 | -function formatSearchFieldDisplayValue(value) { | ||
| 879 | - if (value === null || value === undefined || value === '') return '--' | ||
| 880 | - return String(value) | ||
| 881 | -} | ||
| 882 | 761 | ||
| 883 | -function handleStageUpdate(nextStage) { | 762 | +function resolveIssueNavigationStep(issue) { |
| 763 | + const primaryStep = issue?.primaryRelatedStep | ||
| 764 | + if (Number.isInteger(primaryStep?.snapshotStep)) return primaryStep.snapshotStep | ||
| 765 | + | ||
| 766 | + const taskNode = issue?.taskNode | ||
| 767 | + if (Number.isInteger(taskNode?.globalStep)) return taskNode.globalStep | ||
| 768 | + if (Number.isInteger(taskNode?.localStep)) return taskNode.localStep | ||
| 769 | + | ||
| 770 | + const stage = typeof issue?.stage === 'string' ? issue.stage : '' | ||
| 771 | + const stageMatch = stage.match(/^step_(\d+)_/) | ||
| 772 | + if (stageMatch) return Number(stageMatch[1]) | ||
| 773 | + | ||
| 774 | + return null | ||
| 775 | +} | ||
| 776 | + | ||
| 777 | +function resolveIssueNodeTarget(issue) { | ||
| 778 | + const relatedNode = issue?.primaryRelatedNode ?? issue?.taskNode | ||
| 779 | + if (relatedNode?.nodeId || (Number.isInteger(relatedNode?.rankId) && Number.isInteger(relatedNode?.queueId))) { | ||
| 780 | + return { | ||
| 781 | + nodeId: relatedNode?.nodeId ?? '', | ||
| 782 | + rankId: Number.isInteger(relatedNode?.rankId) ? relatedNode.rankId : issue?.primaryRankId ?? null, | ||
| 783 | + queueId: Number.isInteger(relatedNode?.queueId) ? relatedNode.queueId : issue?.queueId ?? null, | ||
| 784 | + slotIndex: Number.isInteger(relatedNode?.pos) ? relatedNode.pos : null, | ||
| 785 | + taskType: relatedNode?.taskType ?? issue?.taskType ?? '', | ||
| 786 | + } | ||
| 787 | + } | ||
| 788 | + | ||
| 789 | + if (!issue?.dagTarget) { | ||
| 790 | + return { | ||
| 791 | + nodeId: '', | ||
| 792 | + rankId: null, | ||
| 793 | + queueId: null, | ||
| 794 | + slotIndex: null, | ||
| 795 | + taskType: '', | ||
| 796 | + } | ||
| 797 | + } | ||
| 798 | + | ||
| 799 | + return { | ||
| 800 | + nodeId: issue.dagTarget.nodeId ?? '', | ||
| 801 | + rankId: | ||
| 802 | + Number.isInteger(issue?.dagTarget?.queueId) || Number.isInteger(issue?.dagTarget?.slotIndex) || issue?.dagTarget?.nodeId | ||
| 803 | + ? issue.dagTarget.rankId ?? issue?.primaryRankId ?? null | ||
| 804 | + : null, | ||
| 805 | + queueId: issue.dagTarget.queueId ?? issue?.queueId ?? null, | ||
| 806 | + slotIndex: issue?.dagTarget?.slotIndex ?? null, | ||
| 807 | + taskType: issue?.dagTarget?.taskType ?? issue?.taskType ?? '', | ||
| 808 | + } | ||
| 809 | +} | ||
| 810 | + | ||
| 811 | +function resolveSearchFieldValue(node, field) { | ||
| 812 | + if (!node) return '' | ||
| 813 | + const rawNode = node.rawNode ?? {} | ||
| 814 | + const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 815 | + | ||
| 816 | + switch (field) { | ||
| 817 | + case 'taskType': | ||
| 818 | + return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '').toLowerCase() | ||
| 819 | + case 'notifyId': | ||
| 820 | + return normalizeSearchFieldValue( | ||
| 821 | + node.notifyId ?? | ||
| 822 | + node.notify_id ?? | ||
| 823 | + taskData.notifyId ?? | ||
| 824 | + taskData.notify_id ?? | ||
| 825 | + rawNode.notifyId ?? | ||
| 826 | + rawNode.notify_id ?? | ||
| 827 | + rawNode?.task?.notifyId ?? | ||
| 828 | + rawNode?.task?.notify_id, | ||
| 829 | + ) | ||
| 830 | + case 'taskId': | ||
| 831 | + default: | ||
| 832 | + return String(node.id ?? rawNode?.node_id ?? rawNode?.id ?? '').toLowerCase() | ||
| 833 | + } | ||
| 834 | +} | ||
| 835 | + | ||
| 836 | +function resolveSearchFieldDisplayValue(node, field) { | ||
| 837 | + if (!node) return '--' | ||
| 838 | + const rawNode = node.rawNode ?? {} | ||
| 839 | + const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 840 | + | ||
| 841 | + switch (field) { | ||
| 842 | + case 'taskType': | ||
| 843 | + return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '--').replaceAll('_', ' ') | ||
| 844 | + case 'notifyId': | ||
| 845 | + return formatSearchFieldDisplayValue( | ||
| 846 | + node.notifyId ?? | ||
| 847 | + node.notify_id ?? | ||
| 848 | + taskData.notifyId ?? | ||
| 849 | + taskData.notify_id ?? | ||
| 850 | + rawNode.notifyId ?? | ||
| 851 | + rawNode.notify_id ?? | ||
| 852 | + rawNode?.task?.notifyId ?? | ||
| 853 | + rawNode?.task?.notify_id, | ||
| 854 | + ) | ||
| 855 | + case 'taskId': | ||
| 856 | + default: | ||
| 857 | + return formatSearchFieldDisplayValue(node.id ?? rawNode?.node_id ?? rawNode?.id) | ||
| 858 | + } | ||
| 859 | +} | ||
| 860 | + | ||
| 861 | +function formatSearchLocation(node) { | ||
| 862 | + const rank = Number.isInteger(node?.rankId) ? `rank ${node.rankId}` : 'rank --' | ||
| 863 | + const queue = Number.isInteger(node?.queueId) ? `queue ${node.queueId}` : 'queue --' | ||
| 864 | + const posValue = Number.isInteger(node?.pos) | ||
| 865 | + ? node.pos | ||
| 866 | + : Number.isInteger(node?.slotIndex) | ||
| 867 | + ? node.slotIndex | ||
| 868 | + : null | ||
| 869 | + const pos = Number.isInteger(posValue) ? `pos ${posValue}` : 'pos --' | ||
| 870 | + return `${rank} / ${queue} / ${pos}` | ||
| 871 | +} | ||
| 872 | + | ||
| 873 | +function normalizeSearchFieldValue(value) { | ||
| 874 | + if (value === null || value === undefined || value === '') return '' | ||
| 875 | + return String(value).toLowerCase() | ||
| 876 | +} | ||
| 877 | + | ||
| 878 | +function formatSearchFieldDisplayValue(value) { | ||
| 879 | + if (value === null || value === undefined || value === '') return '--' | ||
| 880 | + return String(value) | ||
| 881 | +} | ||
| 882 | + | ||
| 883 | +function handleStageUpdate(nextStage) { | ||
| 884 | if (typeof nextStage !== 'string' || !nextStage || nextStage === currentGraphStage.value) return | 884 | if (typeof nextStage !== 'string' || !nextStage || nextStage === currentGraphStage.value) return |
| 885 | 885 | ||
| 886 | const mappedTarget = selectedNode.value?.nodeMappings?.find((item) => item?.stageName === nextStage) ?? null | 886 | const mappedTarget = selectedNode.value?.nodeMappings?.find((item) => item?.stageName === nextStage) ?? null |
| @@ -937,55 +937,55 @@ function handleNavigate(target) { | |||
| 937 | return | 937 | return |
| 938 | } | 938 | } |
| 939 | 939 | ||
| 940 | - if (resolvedTarget.containerNode) { | 940 | + if (resolvedTarget.containerNode) { |
| 941 | - enterSubgraph(resolvedTarget.containerNode) | 941 | + enterSubgraph(resolvedTarget.containerNode) |
| 942 | - } else if (subgraphNode.value) { | 942 | + } else if (subgraphNode.value) { |
| 943 | - exitSubgraph() | 943 | + exitSubgraph() |
| 944 | - } | 944 | + } |
| 945 | 945 | ||
| 946 | registerNodes([...resolvedTarget.path, resolvedTarget.node]) | 946 | registerNodes([...resolvedTarget.path, resolvedTarget.node]) |
| 947 | focusNode(resolvedTarget.node, { follow: true, sync: true }) | 947 | focusNode(resolvedTarget.node, { follow: true, sync: true }) |
| 948 | -} | 948 | +} |
| 949 | - | 949 | + |
| 950 | -function handleFocusStep(step) { | 950 | +function handleFocusStep(step) { |
| 951 | - enterDagFocus(step) | 951 | + enterDagFocus(step) |
| 952 | - focusStep(step, { smoothScroll: true }) | 952 | + focusStep(step, { smoothScroll: true }) |
| 953 | -} | 953 | +} |
| 954 | - | 954 | + |
| 955 | -function handleStepUpdate(step) { | 955 | +function handleStepUpdate(step) { |
| 956 | - if (!Number.isFinite(step)) return | 956 | + if (!Number.isFinite(step)) return |
| 957 | - enterDagFocus(step) | 957 | + enterDagFocus(step) |
| 958 | - focusStep(step, { smoothScroll: false }) | 958 | + focusStep(step, { smoothScroll: false }) |
| 959 | -} | 959 | +} |
| 960 | - | 960 | + |
| 961 | -function handleOverviewStepUpdate(step) { | 961 | +function handleOverviewStepUpdate(step) { |
| 962 | - if (!Number.isFinite(step)) return | 962 | + if (!Number.isFinite(step)) return |
| 963 | - selectedNode.value = null | 963 | + selectedNode.value = null |
| 964 | - enterDagFocus(step) | 964 | + enterDagFocus(step) |
| 965 | - focusStep(step, { smoothScroll: false }) | 965 | + focusStep(step, { smoothScroll: false }) |
| 966 | -} | 966 | +} |
| 967 | - | 967 | + |
| 968 | -async function handleBufferSelect(selection) { | 968 | +async function handleBufferSelect(selection) { |
| 969 | - const step = Number(selection?.step) | 969 | + const step = Number(selection?.step) |
| 970 | const rankId = Number(selection?.rankId) | 970 | const rankId = Number(selection?.rankId) |
| 971 | const bufferId = Number(selection?.bufferId) | 971 | const bufferId = Number(selection?.bufferId) |
| 972 | - if (!Number.isInteger(step) || !Number.isInteger(rankId) || !Number.isInteger(bufferId)) return | 972 | + if (!Number.isInteger(step) || !Number.isInteger(rankId) || !Number.isInteger(bufferId)) return |
| 973 | - | 973 | + |
| 974 | - selectedNode.value = null | 974 | + selectedNode.value = null |
| 975 | - enterDagFocus(step) | 975 | + enterDagFocus(step) |
| 976 | - focusStep(step, { smoothScroll: false }) | 976 | + focusStep(step, { smoothScroll: false }) |
| 977 | - await nextTick() | 977 | + await nextTick() |
| 978 | - inspectorRef.value?.selectLayout?.(rankId, bufferId) | 978 | + inspectorRef.value?.selectLayout?.(rankId, bufferId) |
| 979 | -} | 979 | +} |
| 980 | - | 980 | + |
| 981 | -function enterDagFocus(step) { | 981 | +function enterDagFocus(step) { |
| 982 | - if (!Number.isFinite(step)) return | 982 | + if (!Number.isFinite(step)) return |
| 983 | - dagFocusStep.value = Math.max(0, Math.floor(step)) | 983 | + dagFocusStep.value = Math.max(0, Math.floor(step)) |
| 984 | -} | 984 | +} |
| 985 | - | 985 | + |
| 986 | -function exitDagFocus() { | 986 | +function exitDagFocus() { |
| 987 | - dagFocusStep.value = null | 987 | + dagFocusStep.value = null |
| 988 | -} | 988 | +} |
| 989 | 989 | ||
| 990 | function handleTotalStepsUpdate(total) { | 990 | function handleTotalStepsUpdate(total) { |
| 991 | setTotalSteps(total) | 991 | setTotalSteps(total) |
| @@ -1392,19 +1392,19 @@ function findNodeInDescendants(rootNode, targetId, visited, path = []) { | |||
| 1392 | return null | 1392 | return null |
| 1393 | } | 1393 | } |
| 1394 | 1394 | ||
| 1395 | -function iterateSubgraphEntries(streamCollection, fallbackRankId) { | 1395 | +function iterateSubgraphEntries(streamCollection, fallbackRankId) { |
| 1396 | - return normalizeStreamCollection(streamCollection, fallbackRankId, { | 1396 | + return normalizeStreamCollection(streamCollection, fallbackRankId, { |
| 1397 | - stageName: DEFAULT_MEMVIEW_STAGE, | 1397 | + stageName: DEFAULT_MEMVIEW_STAGE, |
| 1398 | - topLevel: false, | 1398 | + topLevel: false, |
| 1399 | - }).flatMap((stream) => | 1399 | + }).flatMap((stream) => |
| 1400 | - stream.nodes.map((node) => ({ | 1400 | + stream.nodes.map((node) => ({ |
| 1401 | - rawNode: node.rawNode, | 1401 | + rawNode: node.rawNode, |
| 1402 | - node, | 1402 | + node, |
| 1403 | - })), | 1403 | + })), |
| 1404 | - ) | 1404 | + ) |
| 1405 | -} | 1405 | +} |
| 1406 | - | 1406 | + |
| 1407 | -watch( | 1407 | +watch( |
| 1408 | () => [selectedDatasetName.value, selectedRankKeys.value.join(',')], | 1408 | () => [selectedDatasetName.value, selectedRankKeys.value.join(',')], |
| 1409 | () => { | 1409 | () => { |
| 1410 | resetTimeline() | 1410 | resetTimeline() |
| @@ -1436,35 +1436,35 @@ watch( | |||
| 1436 | }, | 1436 | }, |
| 1437 | ) | 1437 | ) |
| 1438 | 1438 | ||
| 1439 | -watch( | 1439 | +watch( |
| 1440 | - () => [playbackVisibleSteps.value.length, playbackVisibleIndex.value], | 1440 | + () => [playbackVisibleSteps.value.length, playbackVisibleIndex.value], |
| 1441 | - ([stepCount, currentIndex]) => { | 1441 | + ([stepCount, currentIndex]) => { |
| 1442 | - if (!playbackPlaying.value) return | 1442 | + if (!playbackPlaying.value) return |
| 1443 | - if (!stepCount || currentIndex >= stepCount - 1) { | 1443 | + if (!stepCount || currentIndex >= stepCount - 1) { |
| 1444 | - stopPlayback() | 1444 | + stopPlayback() |
| 1445 | - } | 1445 | + } |
| 1446 | - }, | 1446 | + }, |
| 1447 | -) | 1447 | +) |
| 1448 | - | 1448 | + |
| 1449 | -watch( | 1449 | +watch( |
| 1450 | - () => [selectedDatasetName.value, selectedRankKeys.value.join(','), currentGraphStage.value], | 1450 | + () => [selectedDatasetName.value, selectedRankKeys.value.join(','), currentGraphStage.value], |
| 1451 | - () => { | 1451 | + () => { |
| 1452 | - if (Number.isInteger(dagFocusStep.value)) { | 1452 | + if (Number.isInteger(dagFocusStep.value)) { |
| 1453 | - exitDagFocus() | 1453 | + exitDagFocus() |
| 1454 | - } | 1454 | + } |
| 1455 | - }, | 1455 | + }, |
| 1456 | -) | 1456 | +) |
| 1457 | - | 1457 | + |
| 1458 | -watch( | 1458 | +watch( |
| 1459 | - clampedCurrentStep, | 1459 | + clampedCurrentStep, |
| 1460 | - (step) => { | 1460 | + (step) => { |
| 1461 | - if (!Number.isInteger(dagFocusStep.value)) return | 1461 | + if (!Number.isInteger(dagFocusStep.value)) return |
| 1462 | - if (dagFocusStep.value !== step) { | 1462 | + if (dagFocusStep.value !== step) { |
| 1463 | - dagFocusStep.value = step | 1463 | + dagFocusStep.value = step |
| 1464 | - } | 1464 | + } |
| 1465 | - }, | 1465 | + }, |
| 1466 | - { immediate: true }, | 1466 | + { immediate: true }, |
| 1467 | -) | 1467 | +) |
| 1468 | 1468 | ||
| 1469 | onMounted(() => { | 1469 | onMounted(() => { |
| 1470 | centerTopSize.value = resolveDefaultCenterTopSize() | 1470 | centerTopSize.value = resolveDefaultCenterTopSize() |
| @@ -1499,190 +1499,190 @@ onBeforeUnmount(() => { | |||
| 1499 | :resizable="!sidebarCollapsed" | 1499 | :resizable="!sidebarCollapsed" |
| 1500 | @update:size="handleLeftPanelResize" | 1500 | @update:size="handleLeftPanelResize" |
| 1501 | > | 1501 | > |
| 1502 | - <aside class="dashboard-sidebar-shell" :class="{ 'is-collapsed': sidebarCollapsed }"> | 1502 | + <aside class="dashboard-sidebar-shell" :class="{ 'is-collapsed': sidebarCollapsed }"> |
| 1503 | - <DashboardSidebar | 1503 | + <DashboardSidebar |
| 1504 | - :selected-rank-count="selectedRankCount" | 1504 | + :selected-rank-count="selectedRankCount" |
| 1505 | - :selected-dataset="selectedDataset" | 1505 | + :selected-dataset="selectedDataset" |
| 1506 | - :tree-data="treeData" | 1506 | + :tree-data="treeData" |
| 1507 | - :checked-keys="selectedRankKeys" | 1507 | + :checked-keys="selectedRankKeys" |
| 1508 | - :format-count="formatCount" | 1508 | + :format-count="formatCount" |
| 1509 | - :empty-text="loadingList ? 'Loading...' : EMPTY_TEXT" | 1509 | + :empty-text="loadingList ? 'Loading...' : EMPTY_TEXT" |
| 1510 | - @tree-check="handleTreeCheck" | 1510 | + @tree-check="handleTreeCheck" |
| 1511 | - > | 1511 | + > |
| 1512 | - <template #after-rank> | 1512 | + <template #after-rank> |
| 1513 | - <el-collapse | 1513 | + <el-collapse |
| 1514 | - v-model="issuePanelSections" | 1514 | + v-model="issuePanelSections" |
| 1515 | - class="dashboard-sidebar-collapse memview-issue-collapse" | 1515 | + class="dashboard-sidebar-collapse memview-issue-collapse" |
| 1516 | - > | 1516 | + > |
| 1517 | - <el-collapse-item name="issues" class="dashboard-subpanel analytic-list-panel"> | 1517 | + <el-collapse-item name="issues" class="dashboard-subpanel analytic-list-panel"> |
| 1518 | - <template #title> | 1518 | + <template #title> |
| 1519 | - <div class="dashboard-panel-toggle"> | 1519 | + <div class="dashboard-panel-toggle"> |
| 1520 | - <span class="dashboard-panel-toggle__title"> | 1520 | + <span class="dashboard-panel-toggle__title"> |
| 1521 | - <el-icon><WarningFilled /></el-icon> | 1521 | + <el-icon><WarningFilled /></el-icon> |
| 1522 | - <span>报错列表</span> | 1522 | + <span>报错列表</span> |
| 1523 | - </span> | 1523 | + </span> |
| 1524 | - <span class="dashboard-panel-toggle__meta"> | 1524 | + <span class="dashboard-panel-toggle__meta"> |
| 1525 | - <el-tag size="small" type="danger">{{ issueCount }} 条</el-tag> | 1525 | + <el-tag size="small" type="danger">{{ issueCount }} 条</el-tag> |
| 1526 | - </span> | 1526 | + </span> |
| 1527 | - </div> | 1527 | + </div> |
| 1528 | - </template> | 1528 | + </template> |
| 1529 | - | 1529 | + |
| 1530 | - <div v-if="loadingIssues" class="dashboard-empty-wrap analytic-list-empty"> | 1530 | + <div v-if="loadingIssues" class="dashboard-empty-wrap analytic-list-empty"> |
| 1531 | - <el-empty description="正在读取 issues.msgpack..." /> | 1531 | + <el-empty description="正在读取 issues.msgpack..." /> |
| 1532 | - </div> | 1532 | + </div> |
| 1533 | - | 1533 | + |
| 1534 | - <div v-else-if="issues.length" class="analytic-issue-list"> | 1534 | + <div v-else-if="issues.length" class="analytic-issue-list"> |
| 1535 | - <button | 1535 | + <button |
| 1536 | - v-for="issue in issues" | 1536 | + v-for="issue in issues" |
| 1537 | - :key="issue.issueId" | 1537 | + :key="issue.issueId" |
| 1538 | - type="button" | 1538 | + type="button" |
| 1539 | - class="analytic-issue-row" | 1539 | + class="analytic-issue-row" |
| 1540 | - :class="{ 'is-active': selectedIssue?.issueId === issue.issueId }" | 1540 | + :class="{ 'is-active': selectedIssue?.issueId === issue.issueId }" |
| 1541 | - @click="handleIssueSelect(issue)" | 1541 | + @click="handleIssueSelect(issue)" |
| 1542 | - > | 1542 | + > |
| 1543 | - <span class="analytic-issue-row__icon" :class="`is-${issue.severityType}`"> | 1543 | + <span class="analytic-issue-row__icon" :class="`is-${issue.severityType}`"> |
| 1544 | - <el-icon><WarningFilled /></el-icon> | 1544 | + <el-icon><WarningFilled /></el-icon> |
| 1545 | - </span> | 1545 | + </span> |
| 1546 | - <div class="analytic-issue-row__content"> | 1546 | + <div class="analytic-issue-row__content"> |
| 1547 | - <div class="analytic-issue-row__head"> | 1547 | + <div class="analytic-issue-row__head"> |
| 1548 | - <strong>{{ issue.title }}</strong> | 1548 | + <strong>{{ issue.title }}</strong> |
| 1549 | - <div class="analytic-issue-row__head-tags"> | 1549 | + <div class="analytic-issue-row__head-tags"> |
| 1550 | - <el-tag size="small" :type="issue.severityType">{{ issue.severityLabel }}</el-tag> | 1550 | + <el-tag size="small" :type="issue.severityType">{{ issue.severityLabel }}</el-tag> |
| 1551 | - </div> | 1551 | + </div> |
| 1552 | - </div> | 1552 | + </div> |
| 1553 | - <div class="analytic-issue-row__body"> | 1553 | + <div class="analytic-issue-row__body"> |
| 1554 | - <div v-if="issue.listFieldRows.primaryRow.length" class="analytic-issue-row__field-stack"> | 1554 | + <div v-if="issue.listFieldRows.primaryRow.length" class="analytic-issue-row__field-stack"> |
| 1555 | - <div | 1555 | + <div |
| 1556 | - v-for="field in issue.listFieldRows.primaryRow" | 1556 | + v-for="field in issue.listFieldRows.primaryRow" |
| 1557 | - :key="`primary-${issue.issueId}-${field.label}`" | 1557 | + :key="`primary-${issue.issueId}-${field.label}`" |
| 1558 | - class="analytic-issue-row__field" | 1558 | + class="analytic-issue-row__field" |
| 1559 | - > | 1559 | + > |
| 1560 | - <span>{{ field.label }}</span> | 1560 | + <span>{{ field.label }}</span> |
| 1561 | - <strong>{{ field.value }}</strong> | 1561 | + <strong>{{ field.value }}</strong> |
| 1562 | - </div> | 1562 | + </div> |
| 1563 | - </div> | 1563 | + </div> |
| 1564 | - <div | 1564 | + <div |
| 1565 | - v-if="issue.listFieldRows.secondaryRow.length" | 1565 | + v-if="issue.listFieldRows.secondaryRow.length" |
| 1566 | - class="analytic-issue-row__field-stack is-secondary" | 1566 | + class="analytic-issue-row__field-stack is-secondary" |
| 1567 | - > | 1567 | + > |
| 1568 | - <div | 1568 | + <div |
| 1569 | - v-for="field in issue.listFieldRows.secondaryRow" | 1569 | + v-for="field in issue.listFieldRows.secondaryRow" |
| 1570 | - :key="`secondary-${issue.issueId}-${field.label}`" | 1570 | + :key="`secondary-${issue.issueId}-${field.label}`" |
| 1571 | - class="analytic-issue-row__field" | 1571 | + class="analytic-issue-row__field" |
| 1572 | - > | 1572 | + > |
| 1573 | - <span>{{ field.label }}</span> | 1573 | + <span>{{ field.label }}</span> |
| 1574 | - <strong>{{ field.value }}</strong> | 1574 | + <strong>{{ field.value }}</strong> |
| 1575 | - </div> | 1575 | + </div> |
| 1576 | - </div> | 1576 | + </div> |
| 1577 | - </div> | 1577 | + </div> |
| 1578 | - <span class="analytic-issue-row__code">{{ issue.code }}</span> | 1578 | + <span class="analytic-issue-row__code">{{ issue.code }}</span> |
| 1579 | - </div> | 1579 | + </div> |
| 1580 | - </button> | 1580 | + </button> |
| 1581 | - </div> | 1581 | + </div> |
| 1582 | - | 1582 | + |
| 1583 | - <div v-else class="dashboard-empty-wrap analytic-list-empty"> | 1583 | + <div v-else class="dashboard-empty-wrap analytic-list-empty"> |
| 1584 | - <el-empty description="当前数据集没有 issue 记录。" /> | 1584 | + <el-empty description="当前数据集没有 issue 记录。" /> |
| 1585 | - </div> | 1585 | + </div> |
| 1586 | - </el-collapse-item> | 1586 | + </el-collapse-item> |
| 1587 | - </el-collapse> | 1587 | + </el-collapse> |
| 1588 | - | 1588 | + |
| 1589 | - <el-collapse | 1589 | + <el-collapse |
| 1590 | - v-model="searchPanelSections" | 1590 | + v-model="searchPanelSections" |
| 1591 | - class="dashboard-sidebar-collapse memview-search-collapse" | 1591 | + class="dashboard-sidebar-collapse memview-search-collapse" |
| 1592 | - > | 1592 | + > |
| 1593 | - <el-collapse-item name="search" class="dashboard-subpanel memview-search-panel"> | 1593 | + <el-collapse-item name="search" class="dashboard-subpanel memview-search-panel"> |
| 1594 | - <template #title> | 1594 | + <template #title> |
| 1595 | - <div class="dashboard-panel-toggle"> | 1595 | + <div class="dashboard-panel-toggle"> |
| 1596 | - <span class="dashboard-panel-toggle__title"> | 1596 | + <span class="dashboard-panel-toggle__title"> |
| 1597 | - <el-icon><Search /></el-icon> | 1597 | + <el-icon><Search /></el-icon> |
| 1598 | - <span>搜索</span> | 1598 | + <span>搜索</span> |
| 1599 | - </span> | 1599 | + </span> |
| 1600 | - <span class="dashboard-panel-toggle__meta"> | 1600 | + <span class="dashboard-panel-toggle__meta"> |
| 1601 | - <el-tag size="small" type="info">{{ selectedSearchFieldLabel }}</el-tag> | 1601 | + <el-tag size="small" type="info">{{ selectedSearchFieldLabel }}</el-tag> |
| 1602 | - <el-tag size="small" type="success"> | 1602 | + <el-tag size="small" type="success"> |
| 1603 | - {{ normalizedSearchQuery ? `${searchResults.length} results` : `${selectedRankCount} ranks` }} | 1603 | + {{ normalizedSearchQuery ? `${searchResults.length} results` : `${selectedRankCount} ranks` }} |
| 1604 | - </el-tag> | 1604 | + </el-tag> |
| 1605 | - </span> | 1605 | + </span> |
| 1606 | - </div> | 1606 | + </div> |
| 1607 | - </template> | 1607 | + </template> |
| 1608 | - | 1608 | + |
| 1609 | - <section class="memview-sidebar-search"> | 1609 | + <section class="memview-sidebar-search"> |
| 1610 | - <div class="memview-sidebar-search__controls"> | 1610 | + <div class="memview-sidebar-search__controls"> |
| 1611 | - <el-select | 1611 | + <el-select |
| 1612 | - v-model="searchField" | 1612 | + v-model="searchField" |
| 1613 | - class="memview-sidebar-search__field-select" | 1613 | + class="memview-sidebar-search__field-select" |
| 1614 | - aria-label="Search field" | 1614 | + aria-label="Search field" |
| 1615 | - > | 1615 | + > |
| 1616 | - <el-option | 1616 | + <el-option |
| 1617 | - v-for="option in SEARCH_FIELD_OPTIONS" | 1617 | + v-for="option in SEARCH_FIELD_OPTIONS" |
| 1618 | - :key="option.value" | 1618 | + :key="option.value" |
| 1619 | - :label="option.label" | 1619 | + :label="option.label" |
| 1620 | - :value="option.value" | 1620 | + :value="option.value" |
| 1621 | - /> | 1621 | + /> |
| 1622 | - </el-select> | 1622 | + </el-select> |
| 1623 | - | 1623 | + |
| 1624 | - <el-input | 1624 | + <el-input |
| 1625 | - v-model="searchQuery" | 1625 | + v-model="searchQuery" |
| 1626 | - class="memview-sidebar-search__input" | 1626 | + class="memview-sidebar-search__input" |
| 1627 | - clearable | 1627 | + clearable |
| 1628 | - placeholder="Enter keyword" | 1628 | + placeholder="Enter keyword" |
| 1629 | - aria-label="Search keyword" | 1629 | + aria-label="Search keyword" |
| 1630 | - /> | 1630 | + /> |
| 1631 | - </div> | 1631 | + </div> |
| 1632 | - | 1632 | + |
| 1633 | - <div class="memview-sidebar-search__meta"> | 1633 | + <div class="memview-sidebar-search__meta"> |
| 1634 | - <span>Selected ranks: {{ selectedRankCount }}</span> | 1634 | + <span>Selected ranks: {{ selectedRankCount }}</span> |
| 1635 | - <span>Results: {{ searchResults.length }}</span> | 1635 | + <span>Results: {{ searchResults.length }}</span> |
| 1636 | - </div> | 1636 | + </div> |
| 1637 | - | 1637 | + |
| 1638 | - <div | 1638 | + <div |
| 1639 | - v-if="normalizedSearchQuery && searchResults.length" | 1639 | + v-if="normalizedSearchQuery && searchResults.length" |
| 1640 | - class="memview-sidebar-search__results" | 1640 | + class="memview-sidebar-search__results" |
| 1641 | - > | 1641 | + > |
| 1642 | - <button | 1642 | + <button |
| 1643 | - v-for="result in searchResults" | 1643 | + v-for="result in searchResults" |
| 1644 | - :key="result.node.id" | 1644 | + :key="result.node.id" |
| 1645 | - type="button" | 1645 | + type="button" |
| 1646 | - class="memview-sidebar-search-card" | 1646 | + class="memview-sidebar-search-card" |
| 1647 | - :class="{ 'is-active': selectedNode?.id === result.node.id }" | 1647 | + :class="{ 'is-active': selectedNode?.id === result.node.id }" |
| 1648 | - @click="handleSearchResultSelect(result)" | 1648 | + @click="handleSearchResultSelect(result)" |
| 1649 | - > | 1649 | + > |
| 1650 | - <div class="memview-sidebar-search-card__head"> | 1650 | + <div class="memview-sidebar-search-card__head"> |
| 1651 | - <strong>{{ result.taskId }}</strong> | 1651 | + <strong>{{ result.taskId }}</strong> |
| 1652 | - <el-tag size="small" type="info">{{ result.taskType }}</el-tag> | 1652 | + <el-tag size="small" type="info">{{ result.taskType }}</el-tag> |
| 1653 | - </div> | 1653 | + </div> |
| 1654 | - | 1654 | + |
| 1655 | - <div class="memview-sidebar-search-card__grid"> | 1655 | + <div class="memview-sidebar-search-card__grid"> |
| 1656 | - <div class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide"> | 1656 | + <div class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide"> |
| 1657 | - <span>rank / queue / pos</span> | 1657 | + <span>rank / queue / pos</span> |
| 1658 | - <strong>{{ result.location }}</strong> | 1658 | + <strong>{{ result.formatLoc }}</strong> |
| 1659 | - </div> | 1659 | + </div> |
| 1660 | - <div | 1660 | + <div |
| 1661 | - v-if="searchField === 'notifyId'" | 1661 | + v-if="searchField === 'notifyId'" |
| 1662 | - class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide" | 1662 | + class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide" |
| 1663 | - > | 1663 | + > |
| 1664 | - <span>notifyId</span> | 1664 | + <span>notifyId</span> |
| 1665 | - <strong>{{ result.notifyId }}</strong> | 1665 | + <strong>{{ result.notifyId }}</strong> |
| 1666 | - </div> | 1666 | + </div> |
| 1667 | - </div> | 1667 | + </div> |
| 1668 | - </button> | 1668 | + </button> |
| 1669 | - </div> | 1669 | + </div> |
| 1670 | - | 1670 | + |
| 1671 | - <div v-else-if="normalizedSearchQuery" class="memview-sidebar-search__empty"> | 1671 | + <div v-else-if="normalizedSearchQuery" class="memview-sidebar-search__empty"> |
| 1672 | - <el-empty description="No matching tasks" :image-size="72" /> | 1672 | + <el-empty description="No matching tasks" :image-size="72" /> |
| 1673 | - </div> | 1673 | + </div> |
| 1674 | - | 1674 | + |
| 1675 | - <div v-else class="memview-sidebar-search__hint"> | 1675 | + <div v-else class="memview-sidebar-search__hint"> |
| 1676 | - Choose taskId, taskType, or notifyId and enter a keyword to search within the selected ranks. | 1676 | + Choose taskId, taskType, or notifyId and enter a keyword to search within the selected ranks. |
| 1677 | - </div> | 1677 | + </div> |
| 1678 | - </section> | 1678 | + </section> |
| 1679 | - </el-collapse-item> | 1679 | + </el-collapse-item> |
| 1680 | - </el-collapse> | 1680 | + </el-collapse> |
| 1681 | - </template> | 1681 | + </template> |
| 1682 | - </DashboardSidebar> | 1682 | + </DashboardSidebar> |
| 1683 | - | 1683 | + |
| 1684 | - <button | 1684 | + <button |
| 1685 | - v-if="!sidebarCollapsed" | 1685 | + v-if="!sidebarCollapsed" |
| 1686 | type="button" | 1686 | type="button" |
| 1687 | class="dashboard-sidebar-toggle dashboard-sidebar-toggle--collapse" | 1687 | class="dashboard-sidebar-toggle dashboard-sidebar-toggle--collapse" |
| 1688 | aria-label="Collapse sidebar" | 1688 | aria-label="Collapse sidebar" |
| @@ -1727,7 +1727,7 @@ onBeforeUnmount(() => { | |||
| 1727 | :selected-rank-keys="selectedRankKeys" | 1727 | :selected-rank-keys="selectedRankKeys" |
| 1728 | :current-step="clampedCurrentStep" | 1728 | :current-step="clampedCurrentStep" |
| 1729 | :display-step-items="displayStepItems" | 1729 | :display-step-items="displayStepItems" |
| 1730 | - :empty-text="overviewEmptyText" | 1730 | + :empty-text="overviewEmptyText" |
| 1731 | @update:current-step="handleOverviewStepUpdate" | 1731 | @update:current-step="handleOverviewStepUpdate" |
| 1732 | @update:total-steps="handleTotalStepsUpdate" | 1732 | @update:total-steps="handleTotalStepsUpdate" |
| 1733 | @buffer-select="handleBufferSelect" | 1733 | @buffer-select="handleBufferSelect" |
| @@ -1743,28 +1743,28 @@ onBeforeUnmount(() => { | |||
| 1743 | > | 1743 | > |
| 1744 | DAGView 任务视图 | 1744 | DAGView 任务视图 |
| 1745 | </button> | 1745 | </button> |
| 1746 | - <MemViewDagPanel | 1746 | + <MemViewDagPanel |
| 1747 | - v-else | 1747 | + v-else |
| 1748 | - :dataset-name="selectedDatasetName" | 1748 | + :dataset-name="selectedDatasetName" |
| 1749 | - :graph-groups="datasetDetail?.graph ?? []" | 1749 | + :graph-groups="datasetDetail?.graph ?? []" |
| 1750 | - :stage-name="currentGraphStage" | 1750 | + :stage-name="currentGraphStage" |
| 1751 | - :selected-rank-keys="selectedRankKeys" | 1751 | + :selected-rank-keys="selectedRankKeys" |
| 1752 | - :selected-node-id="selectedNode?.id ?? ''" | 1752 | + :selected-node-id="selectedNode?.id ?? ''" |
| 1753 | - :focus-step="dagFocusStep" | 1753 | + :focus-step="dagFocusStep" |
| 1754 | - :issue-node-ids="dagIssueNodeIds" | 1754 | + :issue-node-ids="dagIssueNodeIds" |
| 1755 | - :subgraph-node="subgraphNode" | 1755 | + :subgraph-node="subgraphNode" |
| 1756 | - :current-step="clampedCurrentStep" | 1756 | + :current-step="clampedCurrentStep" |
| 1757 | - :total-steps="totalSteps" | 1757 | + :total-steps="totalSteps" |
| 1758 | - :display-step-items="displayStepItems" | 1758 | + :display-step-items="displayStepItems" |
| 1759 | - :empty-text="dagEmptyText" | 1759 | + :empty-text="dagEmptyText" |
| 1760 | @node-select="handleNodeSelect" | 1760 | @node-select="handleNodeSelect" |
| 1761 | @update:stage-name="handleStageUpdate" | 1761 | @update:stage-name="handleStageUpdate" |
| 1762 | @update:current-step="handleStepUpdate" | 1762 | @update:current-step="handleStepUpdate" |
| 1763 | - @update:total-steps="handleTotalStepsUpdate" | 1763 | + @update:total-steps="handleTotalStepsUpdate" |
| 1764 | - @nodes-loaded="handleNodesLoaded" | 1764 | + @nodes-loaded="handleNodesLoaded" |
| 1765 | - @graph-node-ids-change="handleGraphNodeIdsChange" | 1765 | + @graph-node-ids-change="handleGraphNodeIdsChange" |
| 1766 | - @close-focus-view="exitDagFocus" | 1766 | + @close-focus-view="exitDagFocus" |
| 1767 | - /> | 1767 | + /> |
| 1768 | </el-splitter-panel> | 1768 | </el-splitter-panel> |
| 1769 | </el-splitter> | 1769 | </el-splitter> |
| 1770 | </div> | 1770 | </div> |
| @@ -1,26 +1,26 @@ | |||
| 1 | <script setup> | 1 | <script setup> |
| 2 | import { computed, nextTick, onMounted, onBeforeUnmount, ref, watch } from 'vue' | 2 | import { computed, nextTick, onMounted, onBeforeUnmount, ref, watch } from 'vue' |
| 3 | -import { | 3 | +import { |
| 4 | - CaretLeft, | 4 | + CaretLeft, |
| 5 | - CaretRight, | 5 | + CaretRight, |
| 6 | - DArrowLeft, | 6 | + DArrowLeft, |
| 7 | - DArrowRight, | 7 | + DArrowRight, |
| 8 | - Search, | 8 | + Search, |
| 9 | - VideoPause, | 9 | + VideoPause, |
| 10 | - VideoPlay, | 10 | + VideoPlay, |
| 11 | - WarningFilled, | 11 | + WarningFilled, |
| 12 | -} from '@element-plus/icons-vue' | 12 | +} from '@element-plus/icons-vue' |
| 13 | import sidebarHandle from '../assets/sidebar-handle.svg' | 13 | import sidebarHandle from '../assets/sidebar-handle.svg' |
| 14 | import sidebarHandleExpand from '../assets/sidebar-handle-expand.svg' | 14 | import sidebarHandleExpand from '../assets/sidebar-handle-expand.svg' |
| 15 | import { useInsightDatasetState } from '../composables/useInsightDatasetState' | 15 | import { useInsightDatasetState } from '../composables/useInsightDatasetState' |
| 16 | import { usePageNavigationState } from '../composables/usePageNavigationState' | 16 | import { usePageNavigationState } from '../composables/usePageNavigationState' |
| 17 | import { useMemViewTimeline } from '../composables/useMemViewTimeline' | 17 | import { useMemViewTimeline } from '../composables/useMemViewTimeline' |
| 18 | -import { taskOpsAtStep } from '../utils/memviewIndex.js' | 18 | +import { taskOpsAtStep } from '../utils/memviewIndex.js' |
| 19 | -import { fetchValidationIssues } from '../utils/analyticIssues.js' | 19 | +import { fetchValidationIssues } from '../utils/analyticIssues.js' |
| 20 | -import { | 20 | +import { |
| 21 | - DEFAULT_MEMVIEW_STAGE, | 21 | + DEFAULT_MEMVIEW_STAGE, |
| 22 | - normalizeStreamCollection, | 22 | + normalizeStreamCollection, |
| 23 | -} from '../utils/memviewDag.js' | 23 | +} from '../utils/memviewDag.js' |
| 24 | import DashboardSidebar from '../components/dashboard/DashboardSidebar.vue' | 24 | import DashboardSidebar from '../components/dashboard/DashboardSidebar.vue' |
| 25 | import MemViewDagPanel from '../components/memview/MemViewDagPanel.vue' | 25 | import MemViewDagPanel from '../components/memview/MemViewDagPanel.vue' |
| 26 | import MemViewInspectorPanel from '../components/memview/MemViewInspectorPanel.vue' | 26 | import MemViewInspectorPanel from '../components/memview/MemViewInspectorPanel.vue' |
| @@ -29,58 +29,58 @@ import MemViewOverviewPanel from '../components/memview/MemViewOverviewPanel.vue | |||
| 29 | const CENTER_TOP_MIN_SIZE = 250 | 29 | const CENTER_TOP_MIN_SIZE = 250 |
| 30 | const CENTER_TOP_MAX_SIZE = 620 | 30 | const CENTER_TOP_MAX_SIZE = 620 |
| 31 | const CENTER_TOP_DEFAULT_RATIO = 0.6 | 31 | const CENTER_TOP_DEFAULT_RATIO = 0.6 |
| 32 | -const CENTER_BOTTOM_MIN_SIZE = 220 | 32 | +const CENTER_BOTTOM_MIN_SIZE = 220 |
| 33 | -const CENTER_COLLAPSED_SIZE = 36 | 33 | +const CENTER_COLLAPSED_SIZE = 36 |
| 34 | -const CENTER_COLLAPSE_THRESHOLD = 72 | 34 | +const CENTER_COLLAPSE_THRESHOLD = 72 |
| 35 | -const SEARCH_FIELD_OPTIONS = [ | 35 | +const SEARCH_FIELD_OPTIONS = [ |
| 36 | - { label: 'taskId', value: 'taskId' }, | 36 | + { label: 'taskId', value: 'taskId' }, |
| 37 | - { label: 'taskType', value: 'taskType' }, | 37 | + { label: 'taskType', value: 'taskType' }, |
| 38 | - { label: 'notifyId', value: 'notifyId' }, | 38 | + { label: 'notifyId', value: 'notifyId' }, |
| 39 | -] | 39 | +] |
| 40 | - | 40 | + |
| 41 | -const sidebarCollapsed = ref(false) | 41 | +const sidebarCollapsed = ref(false) |
| 42 | -const recordCollapsed = ref(false) | 42 | +const recordCollapsed = ref(false) |
| 43 | -const leftPanelSize = ref(376) | 43 | +const leftPanelSize = ref(376) |
| 44 | -const rightPanelSize = ref(420) | 44 | +const rightPanelSize = ref(420) |
| 45 | const centerPaneState = ref('normal') | 45 | const centerPaneState = ref('normal') |
| 46 | const centerAvailableHeight = ref(0) | 46 | const centerAvailableHeight = ref(0) |
| 47 | const centerTopSize = ref(360) | 47 | const centerTopSize = ref(360) |
| 48 | const currentGraphNodeIds = ref([]) | 48 | const currentGraphNodeIds = ref([]) |
| 49 | -const currentGraphStage = ref(DEFAULT_MEMVIEW_STAGE) | 49 | +const currentGraphStage = ref(DEFAULT_MEMVIEW_STAGE) |
| 50 | -const pendingStageNavigation = ref(null) | 50 | +const pendingStageNavigation = ref(null) |
| 51 | -const pendingExternalNavigation = ref(null) | 51 | +const pendingExternalNavigation = ref(null) |
| 52 | -const issueHighlightedNodeIds = ref(null) | 52 | +const issueHighlightedNodeIds = ref(null) |
| 53 | -const datasetIssuePayload = ref({ issueCount: 0, issues: [] }) | 53 | +const datasetIssuePayload = ref({ issueCount: 0, issues: [] }) |
| 54 | -const selectedIssueId = ref(null) | 54 | +const selectedIssueId = ref(null) |
| 55 | -const inspectorRef = ref(null) | 55 | +const inspectorRef = ref(null) |
| 56 | -const centerSplitRef = ref(null) | 56 | +const centerSplitRef = ref(null) |
| 57 | -const layoutRefreshTimers = [] | 57 | +const layoutRefreshTimers = [] |
| 58 | -const playbackPlaying = ref(false) | 58 | +const playbackPlaying = ref(false) |
| 59 | -const issuePanelSections = ref(['issues']) | 59 | +const issuePanelSections = ref(['issues']) |
| 60 | -const searchPanelSections = ref(['search']) | 60 | +const searchPanelSections = ref(['search']) |
| 61 | -const searchField = ref('taskId') | 61 | +const searchField = ref('taskId') |
| 62 | -const searchQuery = ref('') | 62 | +const searchQuery = ref('') |
| 63 | -let centerResizeObserver = null | 63 | +let centerResizeObserver = null |
| 64 | -let playbackTimer = 0 | 64 | +let playbackTimer = 0 |
| 65 | -let issueLoadToken = 0 | 65 | +let issueLoadToken = 0 |
| 66 | - | 66 | + |
| 67 | -const hasMemoryData = computed(() => (datasetDetail.value?.memory?.length ?? 0) > 0) | 67 | +const hasMemoryData = computed(() => (datasetDetail.value?.memory?.length ?? 0) > 0) |
| 68 | - | 68 | + |
| 69 | -const overviewEmptyText = computed(() => { | 69 | +const overviewEmptyText = computed(() => { |
| 70 | - if (loadingDetail.value) return 'Loading data...' | 70 | + if (loadingDetail.value) return 'Loading data...' |
| 71 | - if (selectedDataset.value && !hasMemoryData.value) { | 71 | + if (selectedDataset.value && !hasMemoryData.value) { |
| 72 | - return '当前数据集只有 DAG 数据,内存时间线暂不可用。' | 72 | + return '当前数据集只有 DAG 数据,内存时间线暂不可用。' |
| 73 | - } | 73 | + } |
| 74 | - return EMPTY_TEXT | 74 | + return EMPTY_TEXT |
| 75 | -}) | 75 | +}) |
| 76 | - | 76 | + |
| 77 | -const dagEmptyText = computed(() => { | 77 | +const dagEmptyText = computed(() => { |
| 78 | - if (loadingDetail.value) return 'Loading data...' | 78 | + if (loadingDetail.value) return 'Loading data...' |
| 79 | - if (selectedDataset.value && !datasetDetail.value?.graph?.length) { | 79 | + if (selectedDataset.value && !datasetDetail.value?.graph?.length) { |
| 80 | - return '当前数据集没有 DAG 数据。' | 80 | + return '当前数据集没有 DAG 数据。' |
| 81 | - } | 81 | + } |
| 82 | - return EMPTY_TEXT | 82 | + return EMPTY_TEXT |
| 83 | -}) | 83 | +}) |
| 84 | 84 | ||
| 85 | const { | 85 | const { |
| 86 | EMPTY_TEXT, | 86 | EMPTY_TEXT, |
| @@ -88,18 +88,18 @@ const { | |||
| 88 | selectedDataset, | 88 | selectedDataset, |
| 89 | selectedDatasetName, | 89 | selectedDatasetName, |
| 90 | selectedRankKeys, | 90 | selectedRankKeys, |
| 91 | - loadingList, | 91 | + loadingList, |
| 92 | - loadingDetail, | 92 | + loadingDetail, |
| 93 | - hasData, | 93 | + hasData, |
| 94 | - memorySnapshotCount, | 94 | + memorySnapshotCount, |
| 95 | - selectedRankCount, | 95 | + selectedRankCount, |
| 96 | - treeData, | 96 | + treeData, |
| 97 | - ensureDatasetsLoaded, | 97 | + ensureDatasetsLoaded, |
| 98 | - selectDataset, | 98 | + selectDataset, |
| 99 | - setSelectedRankKeys, | 99 | + setSelectedRankKeys, |
| 100 | -} = useInsightDatasetState() | 100 | +} = useInsightDatasetState() |
| 101 | 101 | ||
| 102 | -const { pendingMemViewNavigation, clearMemViewNavigation } = usePageNavigationState() | 102 | +const { pendingMemViewNavigation, clearMemViewNavigation } = usePageNavigationState() |
| 103 | 103 | ||
| 104 | const { | 104 | const { |
| 105 | clampedCurrentStep, | 105 | clampedCurrentStep, |
| @@ -124,14 +124,14 @@ const { | |||
| 124 | 124 | ||
| 125 | const renderedLeftPanelSize = computed(() => (sidebarCollapsed.value ? 28 : leftPanelSize.value)) | 125 | const renderedLeftPanelSize = computed(() => (sidebarCollapsed.value ? 28 : leftPanelSize.value)) |
| 126 | const renderedRightPanelSize = computed(() => (recordCollapsed.value ? 28 : rightPanelSize.value)) | 126 | const renderedRightPanelSize = computed(() => (recordCollapsed.value ? 28 : rightPanelSize.value)) |
| 127 | -const topPaneCollapsed = computed(() => centerPaneState.value === 'top-collapsed') | 127 | +const topPaneCollapsed = computed(() => centerPaneState.value === 'top-collapsed') |
| 128 | -const bottomPaneCollapsed = computed(() => centerPaneState.value === 'bottom-collapsed') | 128 | +const bottomPaneCollapsed = computed(() => centerPaneState.value === 'bottom-collapsed') |
| 129 | -const issues = computed(() => datasetIssuePayload.value?.issues ?? []) | 129 | +const issues = computed(() => datasetIssuePayload.value?.issues ?? []) |
| 130 | -const issueCount = computed(() => datasetIssuePayload.value?.issueCount ?? issues.value.length) | 130 | +const issueCount = computed(() => datasetIssuePayload.value?.issueCount ?? issues.value.length) |
| 131 | -const selectedIssue = computed( | 131 | +const selectedIssue = computed( |
| 132 | - () => issues.value.find((issue) => issue.issueId === selectedIssueId.value) ?? issues.value[0] ?? null, | 132 | + () => issues.value.find((issue) => issue.issueId === selectedIssueId.value) ?? issues.value[0] ?? null, |
| 133 | -) | 133 | +) |
| 134 | -const renderedCenterTopSize = computed(() => { | 134 | +const renderedCenterTopSize = computed(() => { |
| 135 | if (topPaneCollapsed.value) return CENTER_COLLAPSED_SIZE | 135 | if (topPaneCollapsed.value) return CENTER_COLLAPSED_SIZE |
| 136 | if (bottomPaneCollapsed.value) { | 136 | if (bottomPaneCollapsed.value) { |
| 137 | return Math.max(CENTER_COLLAPSED_SIZE, resolveCenterAvailableHeight() - CENTER_COLLAPSED_SIZE) | 137 | return Math.max(CENTER_COLLAPSED_SIZE, resolveCenterAvailableHeight() - CENTER_COLLAPSED_SIZE) |
| @@ -247,9 +247,9 @@ watch( | |||
| 247 | }, | 247 | }, |
| 248 | ) | 248 | ) |
| 249 | 249 | ||
| 250 | -watch( | 250 | +watch( |
| 251 | - availableGraphStages, | 251 | + availableGraphStages, |
| 252 | - (stages) => { | 252 | + (stages) => { |
| 253 | if (!stages.length) { | 253 | if (!stages.length) { |
| 254 | currentGraphStage.value = '' | 254 | currentGraphStage.value = '' |
| 255 | return | 255 | return |
| @@ -258,45 +258,45 @@ watch( | |||
| 258 | if (stages.includes(currentGraphStage.value)) return | 258 | if (stages.includes(currentGraphStage.value)) return |
| 259 | currentGraphStage.value = stages.includes(DEFAULT_MEMVIEW_STAGE) ? DEFAULT_MEMVIEW_STAGE : stages[0] | 259 | currentGraphStage.value = stages.includes(DEFAULT_MEMVIEW_STAGE) ? DEFAULT_MEMVIEW_STAGE : stages[0] |
| 260 | }, | 260 | }, |
| 261 | - { immediate: true }, | 261 | + { immediate: true }, |
| 262 | -) | 262 | +) |
| 263 | - | 263 | + |
| 264 | -watch( | 264 | +watch( |
| 265 | - selectedDatasetName, | 265 | + selectedDatasetName, |
| 266 | - async (datasetName) => { | 266 | + async (datasetName) => { |
| 267 | - const token = ++issueLoadToken | 267 | + const token = ++issueLoadToken |
| 268 | - if (!datasetName) { | 268 | + if (!datasetName) { |
| 269 | - datasetIssuePayload.value = { issueCount: 0, issues: [] } | 269 | + datasetIssuePayload.value = { issueCount: 0, issues: [] } |
| 270 | - return | 270 | + return |
| 271 | - } | 271 | + } |
| 272 | - | 272 | + |
| 273 | - const payload = await fetchValidationIssues(datasetName) | 273 | + const payload = await fetchValidationIssues(datasetName) |
| 274 | - if (token === issueLoadToken) { | 274 | + if (token === issueLoadToken) { |
| 275 | - datasetIssuePayload.value = payload | 275 | + datasetIssuePayload.value = payload |
| 276 | - } | 276 | + } |
| 277 | - }, | 277 | + }, |
| 278 | - { immediate: true }, | 278 | + { immediate: true }, |
| 279 | -) | 279 | +) |
| 280 | - | 280 | + |
| 281 | -watch( | 281 | +watch( |
| 282 | - issues, | 282 | + issues, |
| 283 | - (nextIssues) => { | 283 | + (nextIssues) => { |
| 284 | - if (!nextIssues.length) { | 284 | + if (!nextIssues.length) { |
| 285 | - selectedIssueId.value = null | 285 | + selectedIssueId.value = null |
| 286 | - return | 286 | + return |
| 287 | - } | 287 | + } |
| 288 | - | 288 | + |
| 289 | - const currentIssueExists = nextIssues.some((issue) => issue.issueId === selectedIssueId.value) | 289 | + const currentIssueExists = nextIssues.some((issue) => issue.issueId === selectedIssueId.value) |
| 290 | - if (!currentIssueExists) { | 290 | + if (!currentIssueExists) { |
| 291 | - selectedIssueId.value = nextIssues[0].issueId | 291 | + selectedIssueId.value = nextIssues[0].issueId |
| 292 | - } | 292 | + } |
| 293 | - }, | 293 | + }, |
| 294 | - { immediate: true }, | 294 | + { immediate: true }, |
| 295 | -) | 295 | +) |
| 296 | - | 296 | + |
| 297 | -watch( | 297 | +watch( |
| 298 | - () => pendingMemViewNavigation.value?.token ?? 0, | 298 | + () => pendingMemViewNavigation.value?.token ?? 0, |
| 299 | - async () => { | 299 | + async () => { |
| 300 | const request = pendingMemViewNavigation.value | 300 | const request = pendingMemViewNavigation.value |
| 301 | if (!request) return | 301 | if (!request) return |
| 302 | 302 | ||
| @@ -334,314 +334,314 @@ watch( | |||
| 334 | { immediate: true }, | 334 | { immediate: true }, |
| 335 | ) | 335 | ) |
| 336 | 336 | ||
| 337 | -const selectedNodeStep = computed(() => { | 337 | +const selectedNodeStep = computed(() => { |
| 338 | - const node = selectedNode.value | 338 | + const node = selectedNode.value |
| 339 | - return resolveStepForNode(node) | 339 | + return resolveStepForNode(node) |
| 340 | -}) | 340 | +}) |
| 341 | - | ||
| 342 | -const selectedRankIdSet = computed(() => { | ||
| 343 | - const ids = new Set() | ||
| 344 | - for (const key of selectedRankKeys.value) { | ||
| 345 | - const match = String(key).match(/^rank-(\d+)$/) | ||
| 346 | - if (match) { | ||
| 347 | - ids.add(Number(match[1])) | ||
| 348 | - } | ||
| 349 | - } | ||
| 350 | - return ids | ||
| 351 | -}) | ||
| 352 | - | ||
| 353 | -const selectedNodeTaskOps = computed(() => { | ||
| 354 | - const node = selectedNode.value | ||
| 355 | - const step = selectedNodeStep.value | ||
| 356 | - if (!node?.id || !indexes.value || !Number.isInteger(step)) return [] | ||
| 357 | - return taskOpsAtStep(indexes.value, step).filter((op) => taskOpMatchesSelectedNode(node, op)) | ||
| 358 | -}) | ||
| 359 | - | ||
| 360 | -const selectedSearchFieldLabel = computed( | ||
| 361 | - () => SEARCH_FIELD_OPTIONS.find((option) => option.value === searchField.value)?.label ?? searchField.value, | ||
| 362 | -) | ||
| 363 | - | ||
| 364 | -const selectedRankSearchNodes = computed(() => { | ||
| 365 | - if (!selectedRankIdSet.value.size) return [] | ||
| 366 | - | ||
| 367 | - const registry = nodeRegistry.value | ||
| 368 | - if (!(registry instanceof Map) || !registry.size) return [] | ||
| 369 | - | ||
| 370 | - const seen = new Map() | ||
| 371 | - for (const node of registry.values()) { | ||
| 372 | - if (!node?.id || seen.has(node.id)) continue | ||
| 373 | - if (Number.isInteger(node.rankId) && !selectedRankIdSet.value.has(node.rankId)) { | ||
| 374 | - continue | ||
| 375 | - } | ||
| 376 | - if (!Number.isInteger(node.rankId)) { | ||
| 377 | - continue | ||
| 378 | - } | ||
| 379 | - seen.set(node.id, node) | ||
| 380 | - } | ||
| 381 | - | ||
| 382 | - return [...seen.values()].sort((left, right) => { | ||
| 383 | - const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY | ||
| 384 | - const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY | ||
| 385 | - if (leftRank !== rightRank) return leftRank - rightRank | ||
| 386 | - | ||
| 387 | - const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY | ||
| 388 | - const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY | ||
| 389 | - if (leftQueue !== rightQueue) return leftQueue - rightQueue | ||
| 390 | - | ||
| 391 | - const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 392 | - const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 393 | - if (leftPos !== rightPos) return leftPos - rightPos | ||
| 394 | - | ||
| 395 | - return String(left.id).localeCompare(String(right.id)) | ||
| 396 | - }) | ||
| 397 | -}) | ||
| 398 | - | ||
| 399 | -const normalizedSearchQuery = computed(() => searchQuery.value.trim()) | ||
| 400 | - | ||
| 401 | -function collectSearchNodesFromRegistry(registry) { | ||
| 402 | - if (!(registry instanceof Map) || !registry.size) return [] | ||
| 403 | - | ||
| 404 | - const roots = [...registry.values()].filter((node) => node?.id && !node.isPlaceholder && Number.isInteger(node.rankId)) | ||
| 405 | - | ||
| 406 | - const collected = [] | ||
| 407 | - const seenIds = new Set() | ||
| 408 | - | ||
| 409 | - const pushNode = (node, context = {}) => { | ||
| 410 | - if (!node?.id || seenIds.has(node.id)) return | ||
| 411 | - if (!Number.isInteger(node.rankId)) return | ||
| 412 | - | ||
| 413 | - seenIds.add(node.id) | ||
| 414 | - collected.push({ | ||
| 415 | - ...node, | ||
| 416 | - searchParentId: context.parentId ?? '', | ||
| 417 | - searchDepth: Number.isInteger(context.depth) ? context.depth : 0, | ||
| 418 | - searchPath: Array.isArray(context.path) ? context.path : [], | ||
| 419 | - searchRootId: context.rootId ?? node.id, | ||
| 420 | - }) | ||
| 421 | - } | ||
| 422 | - | ||
| 423 | - const walkSubgraph = (entries, context) => { | ||
| 424 | - if (!Array.isArray(entries)) return | ||
| 425 | - for (const entry of entries) { | ||
| 426 | - if (!entry || typeof entry !== 'object') continue | ||
| 427 | - const nestedNodes = normalizeStreamCollection([entry], context.rankId, { | ||
| 428 | - stageName: currentGraphStage.value || DEFAULT_MEMVIEW_STAGE, | ||
| 429 | - topLevel: false, | ||
| 430 | - }).flatMap((stream) => stream.nodes) | ||
| 431 | - | ||
| 432 | - for (const nestedNode of nestedNodes) { | ||
| 433 | - const nestedContext = { | ||
| 434 | - rootId: context.rootId, | ||
| 435 | - parentId: context.parentId, | ||
| 436 | - depth: context.depth + 1, | ||
| 437 | - path: [...context.path, entry.node_id ?? entry.id ?? entry.task_id ?? nestedNode.id], | ||
| 438 | - } | ||
| 439 | - pushNode(nestedNode, nestedContext) | ||
| 440 | - const nestedSubGraph = nestedNode?.rawNode?.task?.task_data?.sub_graph | ||
| 441 | - if (Array.isArray(nestedSubGraph) && nestedSubGraph.length) { | ||
| 442 | - walkSubgraph(nestedSubGraph.flat(), { | ||
| 443 | - rankId: nestedNode.rankId, | ||
| 444 | - rootId: context.rootId, | ||
| 445 | - parentId: nestedNode.id, | ||
| 446 | - depth: nestedContext.depth, | ||
| 447 | - path: nestedContext.path, | ||
| 448 | - }) | ||
| 449 | - } | ||
| 450 | - } | ||
| 451 | - } | ||
| 452 | - } | ||
| 453 | - | ||
| 454 | - for (const rootNode of roots) { | ||
| 455 | - pushNode(rootNode, { | ||
| 456 | - rootId: rootNode.id, | ||
| 457 | - parentId: '', | ||
| 458 | - depth: 0, | ||
| 459 | - path: [rootNode.id], | ||
| 460 | - }) | ||
| 461 | - | ||
| 462 | - const subGraph = rootNode?.rawNode?.task?.task_data?.sub_graph | ||
| 463 | - if (Array.isArray(subGraph) && subGraph.length) { | ||
| 464 | - walkSubgraph(subGraph.flat(), { | ||
| 465 | - rankId: rootNode.rankId, | ||
| 466 | - rootId: rootNode.id, | ||
| 467 | - parentId: rootNode.id, | ||
| 468 | - depth: 0, | ||
| 469 | - path: [rootNode.id], | ||
| 470 | - }) | ||
| 471 | - } | ||
| 472 | - } | ||
| 473 | - | ||
| 474 | - return collected | ||
| 475 | -} | ||
| 476 | - | ||
| 477 | -function isExactSearchMatch(node, field, query) { | ||
| 478 | - if (!node || !query) return false | ||
| 479 | - const normalizedQuery = String(query).trim().toLowerCase() | ||
| 480 | - if (!normalizedQuery) return false | ||
| 481 | - | ||
| 482 | - if (field === 'taskType') { | ||
| 483 | - const value = String(node.taskType ?? node.rawNode?.task?.task_type ?? node.rawNode?.task_type ?? '').trim().toLowerCase() | ||
| 484 | - return value === normalizedQuery | ||
| 485 | - } | ||
| 486 | - | ||
| 487 | - if (field === 'notifyId') { | ||
| 488 | - const value = normalizeSearchFieldValue( | ||
| 489 | - node.notifyId ?? | ||
| 490 | - node.notify_id ?? | ||
| 491 | - node.taskData?.notifyId ?? | ||
| 492 | - node.taskData?.notify_id ?? | ||
| 493 | - node.rawNode?.notifyId ?? | ||
| 494 | - node.rawNode?.notify_id ?? | ||
| 495 | - node.rawNode?.task?.notifyId ?? | ||
| 496 | - node.rawNode?.task?.notify_id, | ||
| 497 | - ) | ||
| 498 | - return value === normalizedQuery | ||
| 499 | - } | ||
| 500 | - | ||
| 501 | - const values = resolveSearchNodeIds(node) | ||
| 502 | - return values.some((value) => String(value).trim().toLowerCase() === normalizedQuery) | ||
| 503 | -} | ||
| 504 | - | ||
| 505 | -function resolveSearchNodeIds(node) { | ||
| 506 | - const ids = new Set() | ||
| 507 | - const push = (value) => { | ||
| 508 | - if (typeof value === 'string' && value.trim()) { | ||
| 509 | - ids.add(value.trim()) | ||
| 510 | - } | ||
| 511 | - } | ||
| 512 | - | ||
| 513 | - push(node?.id) | ||
| 514 | - push(node?.rawNode?.node_id) | ||
| 515 | - push(node?.rawNode?.id) | ||
| 516 | - push(node?.rawNode?.task_id) | ||
| 517 | - return [...ids] | ||
| 518 | -} | ||
| 519 | - | ||
| 520 | -function sortSearchNodes(nodes) { | ||
| 521 | - return [...nodes].sort((left, right) => { | ||
| 522 | - const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY | ||
| 523 | - const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY | ||
| 524 | - if (leftRank !== rightRank) return leftRank - rightRank | ||
| 525 | - | ||
| 526 | - const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY | ||
| 527 | - const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY | ||
| 528 | - if (leftQueue !== rightQueue) return leftQueue - rightQueue | ||
| 529 | - | ||
| 530 | - const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 531 | - const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 532 | - if (leftPos !== rightPos) return leftPos - rightPos | ||
| 533 | - | ||
| 534 | - return String(left.id).localeCompare(String(right.id)) | ||
| 535 | - }) | ||
| 536 | -} | ||
| 537 | - | ||
| 538 | -const searchResults = computed(() => { | ||
| 539 | - const query = normalizedSearchQuery.value | ||
| 540 | - if (!query) return [] | ||
| 541 | - | ||
| 542 | - const field = searchField.value | ||
| 543 | - const allSearchNodes = collectSearchNodesFromRegistry(nodeRegistry.value) | ||
| 544 | - const matched = allSearchNodes.filter((node) => isExactSearchMatch(node, field, query)) | ||
| 545 | - | ||
| 546 | - return sortSearchNodes(matched) | ||
| 547 | - .map((node) => ({ | ||
| 548 | - node, | ||
| 549 | - taskId: node.id, | ||
| 550 | - taskType: String(node.taskType ?? '--').replaceAll('_', ' '), | ||
| 551 | - rank: Number.isInteger(node.rankId) ? node.rankId : '--', | ||
| 552 | - queue: Number.isInteger(node.queueId) ? node.queueId : '--', | ||
| 553 | - pos: Number.isInteger(node.pos) ? node.pos : Number.isInteger(node.slotIndex) ? node.slotIndex : '--', | ||
| 554 | - location: formatSearchLocation(node), | ||
| 555 | - notifyId: resolveSearchFieldDisplayValue(node, 'notifyId'), | ||
| 556 | - })) | ||
| 557 | -}) | ||
| 558 | - | ||
| 559 | -const canResolveRelation = computed(() => (nodeId) => Boolean(resolveNodeNavigationTarget(nodeId))) | ||
| 560 | -const resolveRelationMeta = computed(() => (nodeId) => { | ||
| 561 | - if (typeof nodeId !== 'string' || !nodeId) return null | ||
| 562 | - | ||
| 563 | - const resolvedTarget = resolveNodeNavigationTarget(nodeId) | ||
| 564 | - const node = resolvedTarget?.node ?? nodeRegistry.value?.get(nodeId) ?? null | ||
| 565 | - if (!node) return null | ||
| 566 | - | ||
| 567 | - return { | ||
| 568 | - taskType: typeof node.taskType === 'string' ? node.taskType.replaceAll('_', ' ') : '', | ||
| 569 | - } | ||
| 570 | -}) | ||
| 571 | -const datasetIssueNodeIds = computed(() => { | ||
| 572 | - const issues = datasetIssuePayload.value?.issues ?? [] | ||
| 573 | - const registry = nodeRegistry.value | ||
| 574 | - if (!(registry instanceof Map) || !registry.size || !issues.length) return null | ||
| 575 | - | ||
| 576 | - const ids = new Set() | ||
| 577 | - const nodes = [...new Set([...registry.values()].filter(Boolean))] | ||
| 578 | - for (const issue of issues) { | ||
| 579 | - for (const node of nodes) { | ||
| 580 | - if (issueMatchesNode(issue, node)) { | ||
| 581 | - ids.add(node.id) | ||
| 582 | - } | ||
| 583 | - } | ||
| 584 | - } | ||
| 585 | - | ||
| 586 | - return ids.size ? ids : null | ||
| 587 | -}) | ||
| 588 | - | ||
| 589 | -const dagIssueNodeIds = computed(() => { | ||
| 590 | - const ids = new Set() | ||
| 591 | - datasetIssueNodeIds.value?.forEach((nodeId) => ids.add(nodeId)) | ||
| 592 | - issueHighlightedNodeIds.value?.forEach?.((nodeId) => ids.add(nodeId)) | ||
| 593 | - return ids.size ? ids : null | ||
| 594 | -}) | ||
| 595 | 341 | ||
| 596 | -function handleTreeCheck(checkedKeys) { | 342 | +const selectedRankIdSet = computed(() => { |
| 597 | - setSelectedRankKeys(checkedKeys) | 343 | + const ids = new Set() |
| 598 | -} | 344 | + for (const key of selectedRankKeys.value) { |
| 599 | - | 345 | + const match = String(key).match(/^rank-(\d+)$/) |
| 600 | -function issueMatchesNode(issue, node) { | 346 | + if (match) { |
| 601 | - if (!issue || !node?.id) return false | 347 | + ids.add(Number(match[1])) |
| 602 | - | 348 | + } |
| 603 | - const targetIds = issueTargetNodeIds(issue) | 349 | + } |
| 604 | - const lookupIds = new Set(resolveNodeLookupIds(node)) | 350 | + return ids |
| 605 | - if (targetIds.some((nodeId) => lookupIds.has(nodeId) || node.mappingKey === nodeId)) { | 351 | +}) |
| 606 | - return true | 352 | + |
| 607 | - } | 353 | +const selectedNodeTaskOps = computed(() => { |
| 608 | - | 354 | + const node = selectedNode.value |
| 609 | - const target = issue.dagTarget ?? {} | 355 | + const step = selectedNodeStep.value |
| 610 | - const detail = issue.rawDetail ?? {} | 356 | + if (!node?.id || !indexes.value || !Number.isInteger(step)) return [] |
| 611 | - const rankId = firstIssueInteger(target.rankId, issue.primaryRankId, detail.rank_id, detail.task_rank, detail.peer_rank) | 357 | + return taskOpsAtStep(indexes.value, step).filter((op) => taskOpMatchesSelectedNode(node, op)) |
| 612 | - const queueId = firstIssueInteger(target.queueId, issue.queueId, detail.queue_id) | 358 | +}) |
| 613 | - const slotIndex = firstIssueInteger(target.slotIndex, detail.task_pos, detail.pos) | 359 | + |
| 614 | - if (!Number.isInteger(rankId) || !Number.isInteger(queueId) || !Number.isInteger(slotIndex)) return false | 360 | +const selectedSearchFieldLabel = computed( |
| 615 | - | 361 | + () => SEARCH_FIELD_OPTIONS.find((option) => option.value === searchField.value)?.label ?? searchField.value, |
| 616 | - const nodeSlot = Number.isInteger(node.pos) ? node.pos : node.slotIndex | 362 | +) |
| 617 | - const nodeQueue = Number.isInteger(node.queueId) ? node.queueId : node.streamId | 363 | + |
| 618 | - return node.rankId === rankId && nodeQueue === queueId && nodeSlot === slotIndex | 364 | +const selectedRankSearchNodes = computed(() => { |
| 619 | -} | 365 | + if (!selectedRankIdSet.value.size) return [] |
| 620 | - | 366 | + |
| 621 | -function issueTargetNodeIds(issue) { | 367 | + const registry = nodeRegistry.value |
| 622 | - const ids = [] | 368 | + if (!(registry instanceof Map) || !registry.size) return [] |
| 623 | - const push = (value) => { | 369 | + |
| 624 | - if (typeof value === 'string' && value.trim()) ids.push(value.trim()) | 370 | + const seen = new Map() |
| 625 | - } | 371 | + for (const node of registry.values()) { |
| 626 | - | 372 | + if (!node?.id || seen.has(node.id)) continue |
| 627 | - push(issue?.dagTarget?.nodeId) | 373 | + if (Number.isInteger(node.rankId) && !selectedRankIdSet.value.has(node.rankId)) { |
| 628 | - push(issue?.taskNode?.nodeId) | 374 | + continue |
| 629 | - push(issue?.rawDetail?.task_id) | 375 | + } |
| 630 | - issue?.relatedNodeAnchors?.forEach((anchor) => push(anchor?.nodeId)) | 376 | + if (!Number.isInteger(node.rankId)) { |
| 631 | - | 377 | + continue |
| 632 | - return [...new Set(ids)] | 378 | + } |
| 633 | -} | 379 | + seen.set(node.id, node) |
| 634 | - | 380 | + } |
| 635 | -function firstIssueInteger(...values) { | 381 | + |
| 636 | - for (const value of values) { | 382 | + return [...seen.values()].sort((left, right) => { |
| 637 | - if (Number.isInteger(value)) return value | 383 | + const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY |
| 638 | - if (typeof value === 'string' && value.trim()) { | 384 | + const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY |
| 639 | - const numeric = Number(value) | 385 | + if (leftRank !== rightRank) return leftRank - rightRank |
| 640 | - if (Number.isInteger(numeric)) return numeric | 386 | + |
| 641 | - } | 387 | + const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY |
| 642 | - } | 388 | + const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY |
| 643 | - return null | 389 | + if (leftQueue !== rightQueue) return leftQueue - rightQueue |
| 644 | -} | 390 | + |
| 391 | + const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 392 | + const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 393 | + if (leftPos !== rightPos) return leftPos - rightPos | ||
| 394 | + | ||
| 395 | + return String(left.id).localeCompare(String(right.id)) | ||
| 396 | + }) | ||
| 397 | +}) | ||
| 398 | + | ||
| 399 | +const normalizedSearchQuery = computed(() => searchQuery.value.trim()) | ||
| 400 | + | ||
| 401 | +function collectSearchNodesFromRegistry(registry) { | ||
| 402 | + if (!(registry instanceof Map) || !registry.size) return [] | ||
| 403 | + | ||
| 404 | + const roots = [...registry.values()].filter((node) => node?.id && !node.isPlaceholder && Number.isInteger(node.rankId)) | ||
| 405 | + | ||
| 406 | + const collected = [] | ||
| 407 | + const seenIds = new Set() | ||
| 408 | + | ||
| 409 | + const pushNode = (node, context = {}) => { | ||
| 410 | + if (!node?.id || seenIds.has(node.id)) return | ||
| 411 | + if (!Number.isInteger(node.rankId)) return | ||
| 412 | + | ||
| 413 | + seenIds.add(node.id) | ||
| 414 | + collected.push({ | ||
| 415 | + ...node, | ||
| 416 | + searchParentId: context.parentId ?? '', | ||
| 417 | + searchDepth: Number.isInteger(context.depth) ? context.depth : 0, | ||
| 418 | + searchPath: Array.isArray(context.path) ? context.path : [], | ||
| 419 | + searchRootId: context.rootId ?? node.id, | ||
| 420 | + }) | ||
| 421 | + } | ||
| 422 | + | ||
| 423 | + const walkSubgraph = (entries, context) => { | ||
| 424 | + if (!Array.isArray(entries)) return | ||
| 425 | + for (const entry of entries) { | ||
| 426 | + if (!entry || typeof entry !== 'object') continue | ||
| 427 | + const nestedNodes = normalizeStreamCollection([entry], context.rankId, { | ||
| 428 | + stageName: currentGraphStage.value || DEFAULT_MEMVIEW_STAGE, | ||
| 429 | + topLevel: false, | ||
| 430 | + }).flatMap((stream) => stream.nodes) | ||
| 431 | + | ||
| 432 | + for (const nestedNode of nestedNodes) { | ||
| 433 | + const nestedContext = { | ||
| 434 | + rootId: context.rootId, | ||
| 435 | + parentId: context.parentId, | ||
| 436 | + depth: context.depth + 1, | ||
| 437 | + path: [...context.path, entry.node_id ?? entry.id ?? entry.task_id ?? nestedNode.id], | ||
| 438 | + } | ||
| 439 | + pushNode(nestedNode, nestedContext) | ||
| 440 | + const nestedSubGraph = nestedNode?.rawNode?.task?.task_data?.sub_graph | ||
| 441 | + if (Array.isArray(nestedSubGraph) && nestedSubGraph.length) { | ||
| 442 | + walkSubgraph(nestedSubGraph.flat(), { | ||
| 443 | + rankId: nestedNode.rankId, | ||
| 444 | + rootId: context.rootId, | ||
| 445 | + parentId: nestedNode.id, | ||
| 446 | + depth: nestedContext.depth, | ||
| 447 | + path: nestedContext.path, | ||
| 448 | + }) | ||
| 449 | + } | ||
| 450 | + } | ||
| 451 | + } | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + for (const rootNode of roots) { | ||
| 455 | + pushNode(rootNode, { | ||
| 456 | + rootId: rootNode.id, | ||
| 457 | + parentId: '', | ||
| 458 | + depth: 0, | ||
| 459 | + path: [rootNode.id], | ||
| 460 | + }) | ||
| 461 | + | ||
| 462 | + const subGraph = rootNode?.rawNode?.task?.task_data?.sub_graph | ||
| 463 | + if (Array.isArray(subGraph) && subGraph.length) { | ||
| 464 | + walkSubgraph(subGraph.flat(), { | ||
| 465 | + rankId: rootNode.rankId, | ||
| 466 | + rootId: rootNode.id, | ||
| 467 | + parentId: rootNode.id, | ||
| 468 | + depth: 0, | ||
| 469 | + path: [rootNode.id], | ||
| 470 | + }) | ||
| 471 | + } | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | + return collected | ||
| 475 | +} | ||
| 476 | + | ||
| 477 | +function isExactSearchMatch(node, field, query) { | ||
| 478 | + if (!node || !query) return false | ||
| 479 | + const normalizedQuery = String(query).trim().toLowerCase() | ||
| 480 | + if (!normalizedQuery) return false | ||
| 481 | + | ||
| 482 | + if (field === 'taskType') { | ||
| 483 | + const value = String(node.taskType ?? node.rawNode?.task?.task_type ?? node.rawNode?.task_type ?? '').trim().toLowerCase() | ||
| 484 | + return value === normalizedQuery | ||
| 485 | + } | ||
| 486 | + | ||
| 487 | + if (field === 'notifyId') { | ||
| 488 | + const value = normalizeSearchFieldValue( | ||
| 489 | + node.notifyId ?? | ||
| 490 | + node.notify_id ?? | ||
| 491 | + node.taskData?.notifyId ?? | ||
| 492 | + node.taskData?.notify_id ?? | ||
| 493 | + node.rawNode?.notifyId ?? | ||
| 494 | + node.rawNode?.notify_id ?? | ||
| 495 | + node.rawNode?.task?.notifyId ?? | ||
| 496 | + node.rawNode?.task?.notify_id, | ||
| 497 | + ) | ||
| 498 | + return value === normalizedQuery | ||
| 499 | + } | ||
| 500 | + | ||
| 501 | + const values = resolveSearchNodeIds(node) | ||
| 502 | + return values.some((value) => String(value).trim().toLowerCase() === normalizedQuery) | ||
| 503 | +} | ||
| 504 | + | ||
| 505 | +function resolveSearchNodeIds(node) { | ||
| 506 | + const ids = new Set() | ||
| 507 | + const push = (value) => { | ||
| 508 | + if (typeof value === 'string' && value.trim()) { | ||
| 509 | + ids.add(value.trim()) | ||
| 510 | + } | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + push(node?.id) | ||
| 514 | + push(node?.rawNode?.node_id) | ||
| 515 | + push(node?.rawNode?.id) | ||
| 516 | + push(node?.rawNode?.task_id) | ||
| 517 | + return [...ids] | ||
| 518 | +} | ||
| 519 | + | ||
| 520 | +function sortSearchNodes(nodes) { | ||
| 521 | + return [...nodes].sort((left, right) => { | ||
| 522 | + const leftRank = Number.isInteger(left.rankId) ? left.rankId : Number.POSITIVE_INFINITY | ||
| 523 | + const rightRank = Number.isInteger(right.rankId) ? right.rankId : Number.POSITIVE_INFINITY | ||
| 524 | + if (leftRank !== rightRank) return leftRank - rightRank | ||
| 525 | + | ||
| 526 | + const leftQueue = Number.isInteger(left.queueId) ? left.queueId : Number.POSITIVE_INFINITY | ||
| 527 | + const rightQueue = Number.isInteger(right.queueId) ? right.queueId : Number.POSITIVE_INFINITY | ||
| 528 | + if (leftQueue !== rightQueue) return leftQueue - rightQueue | ||
| 529 | + | ||
| 530 | + const leftPos = Number.isInteger(left.pos) ? left.pos : Number.isInteger(left.slotIndex) ? left.slotIndex : Number.POSITIVE_INFINITY | ||
| 531 | + const rightPos = Number.isInteger(right.pos) ? right.pos : Number.isInteger(right.slotIndex) ? right.slotIndex : Number.POSITIVE_INFINITY | ||
| 532 | + if (leftPos !== rightPos) return leftPos - rightPos | ||
| 533 | + | ||
| 534 | + return String(left.id).localeCompare(String(right.id)) | ||
| 535 | + }) | ||
| 536 | +} | ||
| 537 | + | ||
| 538 | +const searchResults = computed(() => { | ||
| 539 | + const query = normalizedSearchQuery.value | ||
| 540 | + if (!query) return [] | ||
| 541 | + | ||
| 542 | + const field = searchField.value | ||
| 543 | + const allSearchNodes = collectSearchNodesFromRegistry(nodeRegistry.value) | ||
| 544 | + const matched = allSearchNodes.filter((node) => isExactSearchMatch(node, field, query)) | ||
| 545 | + | ||
| 546 | + return sortSearchNodes(matched) | ||
| 547 | + .map((node) => ({ | ||
| 548 | + node, | ||
| 549 | + taskId: node.id, | ||
| 550 | + taskType: String(node.taskType ?? '--').replaceAll('_', ' '), | ||
| 551 | + rank: Number.isInteger(node.rankId) ? node.rankId : '--', | ||
| 552 | + queue: Number.isInteger(node.queueId) ? node.queueId : '--', | ||
| 553 | + pos: Number.isInteger(node.pos) ? node.pos : Number.isInteger(node.slotIndex) ? node.slotIndex : '--', | ||
| 554 | + formatLoc: formatSearchLocation(node), | ||
| 555 | + notifyId: resolveSearchFieldDisplayValue(node, 'notifyId'), | ||
| 556 | + })) | ||
| 557 | +}) | ||
| 558 | + | ||
| 559 | +const canResolveRelation = computed(() => (nodeId) => Boolean(resolveNodeNavigationTarget(nodeId))) | ||
| 560 | +const resolveRelationMeta = computed(() => (nodeId) => { | ||
| 561 | + if (typeof nodeId !== 'string' || !nodeId) return null | ||
| 562 | + | ||
| 563 | + const resolvedTarget = resolveNodeNavigationTarget(nodeId) | ||
| 564 | + const node = resolvedTarget?.node ?? nodeRegistry.value?.get(nodeId) ?? null | ||
| 565 | + if (!node) return null | ||
| 566 | + | ||
| 567 | + return { | ||
| 568 | + taskType: typeof node.taskType === 'string' ? node.taskType.replaceAll('_', ' ') : '', | ||
| 569 | + } | ||
| 570 | +}) | ||
| 571 | +const datasetIssueNodeIds = computed(() => { | ||
| 572 | + const issues = datasetIssuePayload.value?.issues ?? [] | ||
| 573 | + const registry = nodeRegistry.value | ||
| 574 | + if (!(registry instanceof Map) || !registry.size || !issues.length) return null | ||
| 575 | + | ||
| 576 | + const ids = new Set() | ||
| 577 | + const nodes = [...new Set([...registry.values()].filter(Boolean))] | ||
| 578 | + for (const issue of issues) { | ||
| 579 | + for (const node of nodes) { | ||
| 580 | + if (issueMatchesNode(issue, node)) { | ||
| 581 | + ids.add(node.id) | ||
| 582 | + } | ||
| 583 | + } | ||
| 584 | + } | ||
| 585 | + | ||
| 586 | + return ids.size ? ids : null | ||
| 587 | +}) | ||
| 588 | + | ||
| 589 | +const dagIssueNodeIds = computed(() => { | ||
| 590 | + const ids = new Set() | ||
| 591 | + datasetIssueNodeIds.value?.forEach((nodeId) => ids.add(nodeId)) | ||
| 592 | + issueHighlightedNodeIds.value?.forEach?.((nodeId) => ids.add(nodeId)) | ||
| 593 | + return ids.size ? ids : null | ||
| 594 | +}) | ||
| 595 | + | ||
| 596 | +function handleTreeCheck(checkedKeys) { | ||
| 597 | + setSelectedRankKeys(checkedKeys) | ||
| 598 | +} | ||
| 599 | + | ||
| 600 | +function issueMatchesNode(issue, node) { | ||
| 601 | + if (!issue || !node?.id) return false | ||
| 602 | + | ||
| 603 | + const targetIds = issueTargetNodeIds(issue) | ||
| 604 | + const lookupIds = new Set(resolveNodeLookupIds(node)) | ||
| 605 | + if (targetIds.some((nodeId) => lookupIds.has(nodeId) || node.mappingKey === nodeId)) { | ||
| 606 | + return true | ||
| 607 | + } | ||
| 608 | + | ||
| 609 | + const target = issue.dagTarget ?? {} | ||
| 610 | + const detail = issue.rawDetail ?? {} | ||
| 611 | + const rankId = firstIssueInteger(target.rankId, issue.primaryRankId, detail.rank_id, detail.task_rank, detail.peer_rank) | ||
| 612 | + const queueId = firstIssueInteger(target.queueId, issue.queueId, detail.queue_id) | ||
| 613 | + const slotIndex = firstIssueInteger(target.slotIndex, detail.task_pos, detail.pos) | ||
| 614 | + if (!Number.isInteger(rankId) || !Number.isInteger(queueId) || !Number.isInteger(slotIndex)) return false | ||
| 615 | + | ||
| 616 | + const nodeSlot = Number.isInteger(node.pos) ? node.pos : node.slotIndex | ||
| 617 | + const nodeQueue = Number.isInteger(node.queueId) ? node.queueId : node.streamId | ||
| 618 | + return node.rankId === rankId && nodeQueue === queueId && nodeSlot === slotIndex | ||
| 619 | +} | ||
| 620 | + | ||
| 621 | +function issueTargetNodeIds(issue) { | ||
| 622 | + const ids = [] | ||
| 623 | + const push = (value) => { | ||
| 624 | + if (typeof value === 'string' && value.trim()) ids.push(value.trim()) | ||
| 625 | + } | ||
| 626 | + | ||
| 627 | + push(issue?.dagTarget?.nodeId) | ||
| 628 | + push(issue?.taskNode?.nodeId) | ||
| 629 | + push(issue?.rawDetail?.task_id) | ||
| 630 | + issue?.relatedNodeAnchors?.forEach((anchor) => push(anchor?.nodeId)) | ||
| 631 | + | ||
| 632 | + return [...new Set(ids)] | ||
| 633 | +} | ||
| 634 | + | ||
| 635 | +function firstIssueInteger(...values) { | ||
| 636 | + for (const value of values) { | ||
| 637 | + if (Number.isInteger(value)) return value | ||
| 638 | + if (typeof value === 'string' && value.trim()) { | ||
| 639 | + const numeric = Number(value) | ||
| 640 | + if (Number.isInteger(numeric)) return numeric | ||
| 641 | + } | ||
| 642 | + } | ||
| 643 | + return null | ||
| 644 | +} | ||
| 645 | 645 | ||
| 646 | function handleLeftPanelResize(size) { | 646 | function handleLeftPanelResize(size) { |
| 647 | if (!sidebarCollapsed.value && typeof size === 'number') { | 647 | if (!sidebarCollapsed.value && typeof size === 'number') { |
| @@ -692,206 +692,206 @@ function expandCenterPane(target) { | |||
| 692 | notifyDagLayoutChange() | 692 | notifyDagLayoutChange() |
| 693 | } | 693 | } |
| 694 | 694 | ||
| 695 | -function handleNodeSelect(node) { | 695 | +function handleNodeSelect(node) { |
| 696 | - focusNode(node, { follow: true, sync: true }) | 696 | + focusNode(node, { follow: true, sync: true }) |
| 697 | -} | 697 | +} |
| 698 | - | 698 | + |
| 699 | -async function handleIssueSelect(issue) { | 699 | +async function handleIssueSelect(issue) { |
| 700 | - if (!issue) return | 700 | + if (!issue) return |
| 701 | - | 701 | + |
| 702 | - selectedIssueId.value = issue.issueId | 702 | + selectedIssueId.value = issue.issueId |
| 703 | - | 703 | + |
| 704 | - const target = resolveIssueNodeTarget(issue) | 704 | + const target = resolveIssueNodeTarget(issue) |
| 705 | - const step = resolveIssueNavigationStep(issue) | 705 | + const step = resolveIssueNavigationStep(issue) |
| 706 | - const rankIds = resolveNavigationRankIds(issue) | 706 | + const rankIds = resolveNavigationRankIds(issue) |
| 707 | - const stageName = issue?.dagTarget?.stageName ?? issue?.memTarget?.stageName ?? '' | 707 | + const stageName = issue?.dagTarget?.stageName ?? issue?.memTarget?.stageName ?? '' |
| 708 | - const hasNodeTarget = Boolean(target?.nodeId) | 708 | + const hasNodeTarget = Boolean(target?.nodeId) |
| 709 | - const hasStepTarget = Number.isInteger(step) | 709 | + const hasStepTarget = Number.isInteger(step) |
| 710 | - | 710 | + |
| 711 | - if (!hasNodeTarget && !hasStepTarget && !rankIds.length) { | 711 | + if (!hasNodeTarget && !hasStepTarget && !rankIds.length) { |
| 712 | - return | 712 | + return |
| 713 | - } | 713 | + } |
| 714 | - | 714 | + |
| 715 | - if (rankIds.length) { | 715 | + if (rankIds.length) { |
| 716 | - setSelectedRankKeys(rankIds.map((rankId) => `rank-${rankId}`)) | 716 | + setSelectedRankKeys(rankIds.map((rankId) => `rank-${rankId}`)) |
| 717 | - } | 717 | + } |
| 718 | - | 718 | + |
| 719 | - if (stageName && stageName !== currentGraphStage.value) { | 719 | + if (stageName && stageName !== currentGraphStage.value) { |
| 720 | - handleStageUpdate(stageName) | 720 | + handleStageUpdate(stageName) |
| 721 | - } | 721 | + } |
| 722 | - | 722 | + |
| 723 | - if (hasNodeTarget) { | 723 | + if (hasNodeTarget) { |
| 724 | - pendingExternalNavigation.value = { | 724 | + pendingExternalNavigation.value = { |
| 725 | - source: 'analytic', | 725 | + source: 'analytic', |
| 726 | - targetView: 'dag', | 726 | + targetView: 'dag', |
| 727 | - stageName: stageName || currentGraphStage.value, | 727 | + stageName: stageName || currentGraphStage.value, |
| 728 | - lookupId: target.nodeId, | 728 | + lookupId: target.nodeId, |
| 729 | - nodeId: target.nodeId, | 729 | + nodeId: target.nodeId, |
| 730 | - rankId: target.rankId, | 730 | + rankId: target.rankId, |
| 731 | - queueId: target.queueId, | 731 | + queueId: target.queueId, |
| 732 | - slotIndex: target.slotIndex, | 732 | + slotIndex: target.slotIndex, |
| 733 | - taskType: target.taskType, | 733 | + taskType: target.taskType, |
| 734 | - } | 734 | + } |
| 735 | - | 735 | + |
| 736 | - await nextTick() | 736 | + await nextTick() |
| 737 | - resolvePendingExternalNavigation() | 737 | + resolvePendingExternalNavigation() |
| 738 | - return | 738 | + return |
| 739 | - } | 739 | + } |
| 740 | - | 740 | + |
| 741 | - if (hasStepTarget) { | 741 | + if (hasStepTarget) { |
| 742 | - focusStep(step, { smoothScroll: false }) | 742 | + focusStep(step, { smoothScroll: false }) |
| 743 | - } | 743 | + } |
| 744 | -} | 744 | +} |
| 745 | - | 745 | + |
| 746 | -function handleSearchResultSelect(result) { | 746 | +function handleSearchResultSelect(result) { |
| 747 | - if (!result?.node) return | 747 | + if (!result?.node) return |
| 748 | - handleNavigate({ | 748 | + handleNavigate({ |
| 749 | - stageName: result.node.stageName || currentGraphStage.value || '', | 749 | + stageName: result.node.stageName || currentGraphStage.value || '', |
| 750 | - lookupId: result.node.id, | 750 | + lookupId: result.node.id, |
| 751 | - containerLookupId: | 751 | + containerLookupId: |
| 752 | - result.node.searchParentId && result.node.searchParentId !== result.node.id | 752 | + result.node.searchParentId && result.node.searchParentId !== result.node.id |
| 753 | - ? result.node.searchParentId | 753 | + ? result.node.searchParentId |
| 754 | - : result.node.searchRootId && result.node.searchRootId !== result.node.id | 754 | + : result.node.searchRootId && result.node.searchRootId !== result.node.id |
| 755 | - ? result.node.searchRootId | 755 | + ? result.node.searchRootId |
| 756 | - : '', | 756 | + : '', |
| 757 | - }) | 757 | + }) |
| 758 | -} | 758 | +} |
| 759 | - | 759 | + |
| 760 | -function resolveNavigationRankIds(issue) { | 760 | +function resolveNavigationRankIds(issue) { |
| 761 | - if (issue?.relatedRankIds?.length) { | 761 | + if (issue?.relatedRankIds?.length) { |
| 762 | - return issue.relatedRankIds | 762 | + return issue.relatedRankIds |
| 763 | - } | 763 | + } |
| 764 | - | 764 | + |
| 765 | - return selectedRankKeys.value | 765 | + return selectedRankKeys.value |
| 766 | .map((key) => { | 766 | .map((key) => { |
| 767 | const match = String(key).match(/^rank-(\d+)$/) | 767 | const match = String(key).match(/^rank-(\d+)$/) |
| 768 | return match ? Number(match[1]) : null | 768 | return match ? Number(match[1]) : null |
| 769 | }) | 769 | }) |
| 770 | .filter((rankId) => Number.isInteger(rankId)) | 770 | .filter((rankId) => Number.isInteger(rankId)) |
| 771 | -} | 771 | +} |
| 772 | - | ||
| 773 | -function resolveIssueNavigationStep(issue) { | ||
| 774 | - const primaryStep = issue?.primaryRelatedStep | ||
| 775 | - if (Number.isInteger(primaryStep?.snapshotStep)) return primaryStep.snapshotStep | ||
| 776 | - | ||
| 777 | - const taskNode = issue?.taskNode | ||
| 778 | - if (Number.isInteger(taskNode?.globalStep)) return taskNode.globalStep | ||
| 779 | - if (Number.isInteger(taskNode?.localStep)) return taskNode.localStep | ||
| 780 | - | ||
| 781 | - const stage = typeof issue?.stage === 'string' ? issue.stage : '' | ||
| 782 | - const stageMatch = stage.match(/^step_(\d+)_/) | ||
| 783 | - if (stageMatch) return Number(stageMatch[1]) | ||
| 784 | - | ||
| 785 | - return null | ||
| 786 | -} | ||
| 787 | - | ||
| 788 | -function resolveIssueNodeTarget(issue) { | ||
| 789 | - const relatedNode = issue?.primaryRelatedNode ?? issue?.taskNode | ||
| 790 | - if (relatedNode?.nodeId || (Number.isInteger(relatedNode?.rankId) && Number.isInteger(relatedNode?.queueId))) { | ||
| 791 | - return { | ||
| 792 | - nodeId: relatedNode?.nodeId ?? '', | ||
| 793 | - rankId: Number.isInteger(relatedNode?.rankId) ? relatedNode.rankId : issue?.primaryRankId ?? null, | ||
| 794 | - queueId: Number.isInteger(relatedNode?.queueId) ? relatedNode.queueId : issue?.queueId ?? null, | ||
| 795 | - slotIndex: Number.isInteger(relatedNode?.pos) ? relatedNode.pos : null, | ||
| 796 | - taskType: relatedNode?.taskType ?? issue?.taskType ?? '', | ||
| 797 | - } | ||
| 798 | - } | ||
| 799 | - | ||
| 800 | - if (!issue?.dagTarget) { | ||
| 801 | - return { | ||
| 802 | - nodeId: '', | ||
| 803 | - rankId: null, | ||
| 804 | - queueId: null, | ||
| 805 | - slotIndex: null, | ||
| 806 | - taskType: '', | ||
| 807 | - } | ||
| 808 | - } | ||
| 809 | - | ||
| 810 | - return { | ||
| 811 | - nodeId: issue.dagTarget.nodeId ?? '', | ||
| 812 | - rankId: | ||
| 813 | - Number.isInteger(issue?.dagTarget?.queueId) || Number.isInteger(issue?.dagTarget?.slotIndex) || issue?.dagTarget?.nodeId | ||
| 814 | - ? issue.dagTarget.rankId ?? issue?.primaryRankId ?? null | ||
| 815 | - : null, | ||
| 816 | - queueId: issue.dagTarget.queueId ?? issue?.queueId ?? null, | ||
| 817 | - slotIndex: issue?.dagTarget?.slotIndex ?? null, | ||
| 818 | - taskType: issue?.dagTarget?.taskType ?? issue?.taskType ?? '', | ||
| 819 | - } | ||
| 820 | -} | ||
| 821 | - | ||
| 822 | -function resolveSearchFieldValue(node, field) { | ||
| 823 | - if (!node) return '' | ||
| 824 | - const rawNode = node.rawNode ?? {} | ||
| 825 | - const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 826 | - | ||
| 827 | - switch (field) { | ||
| 828 | - case 'taskType': | ||
| 829 | - return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '').toLowerCase() | ||
| 830 | - case 'notifyId': | ||
| 831 | - return normalizeSearchFieldValue( | ||
| 832 | - node.notifyId ?? | ||
| 833 | - node.notify_id ?? | ||
| 834 | - taskData.notifyId ?? | ||
| 835 | - taskData.notify_id ?? | ||
| 836 | - rawNode.notifyId ?? | ||
| 837 | - rawNode.notify_id ?? | ||
| 838 | - rawNode?.task?.notifyId ?? | ||
| 839 | - rawNode?.task?.notify_id, | ||
| 840 | - ) | ||
| 841 | - case 'taskId': | ||
| 842 | - default: | ||
| 843 | - return String(node.id ?? rawNode?.node_id ?? rawNode?.id ?? '').toLowerCase() | ||
| 844 | - } | ||
| 845 | -} | ||
| 846 | - | ||
| 847 | -function resolveSearchFieldDisplayValue(node, field) { | ||
| 848 | - if (!node) return '--' | ||
| 849 | - const rawNode = node.rawNode ?? {} | ||
| 850 | - const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 851 | - | ||
| 852 | - switch (field) { | ||
| 853 | - case 'taskType': | ||
| 854 | - return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '--').replaceAll('_', ' ') | ||
| 855 | - case 'notifyId': | ||
| 856 | - return formatSearchFieldDisplayValue( | ||
| 857 | - node.notifyId ?? | ||
| 858 | - node.notify_id ?? | ||
| 859 | - taskData.notifyId ?? | ||
| 860 | - taskData.notify_id ?? | ||
| 861 | - rawNode.notifyId ?? | ||
| 862 | - rawNode.notify_id ?? | ||
| 863 | - rawNode?.task?.notifyId ?? | ||
| 864 | - rawNode?.task?.notify_id, | ||
| 865 | - ) | ||
| 866 | - case 'taskId': | ||
| 867 | - default: | ||
| 868 | - return formatSearchFieldDisplayValue(node.id ?? rawNode?.node_id ?? rawNode?.id) | ||
| 869 | - } | ||
| 870 | -} | ||
| 871 | - | ||
| 872 | -function formatSearchLocation(node) { | ||
| 873 | - const rank = Number.isInteger(node?.rankId) ? `rank ${node.rankId}` : 'rank --' | ||
| 874 | - const queue = Number.isInteger(node?.queueId) ? `queue ${node.queueId}` : 'queue --' | ||
| 875 | - const posValue = Number.isInteger(node?.pos) | ||
| 876 | - ? node.pos | ||
| 877 | - : Number.isInteger(node?.slotIndex) | ||
| 878 | - ? node.slotIndex | ||
| 879 | - : null | ||
| 880 | - const pos = Number.isInteger(posValue) ? `pos ${posValue}` : 'pos --' | ||
| 881 | - return `${rank} / ${queue} / ${pos}` | ||
| 882 | -} | ||
| 883 | - | ||
| 884 | -function normalizeSearchFieldValue(value) { | ||
| 885 | - if (value === null || value === undefined || value === '') return '' | ||
| 886 | - return String(value).toLowerCase() | ||
| 887 | -} | ||
| 888 | - | ||
| 889 | -function formatSearchFieldDisplayValue(value) { | ||
| 890 | - if (value === null || value === undefined || value === '') return '--' | ||
| 891 | - return String(value) | ||
| 892 | -} | ||
| 893 | 772 | ||
| 894 | -function handleStageUpdate(nextStage) { | 773 | +function resolveIssueNavigationStep(issue) { |
| 774 | + const primaryStep = issue?.primaryRelatedStep | ||
| 775 | + if (Number.isInteger(primaryStep?.snapshotStep)) return primaryStep.snapshotStep | ||
| 776 | + | ||
| 777 | + const taskNode = issue?.taskNode | ||
| 778 | + if (Number.isInteger(taskNode?.globalStep)) return taskNode.globalStep | ||
| 779 | + if (Number.isInteger(taskNode?.localStep)) return taskNode.localStep | ||
| 780 | + | ||
| 781 | + const stage = typeof issue?.stage === 'string' ? issue.stage : '' | ||
| 782 | + const stageMatch = stage.match(/^step_(\d+)_/) | ||
| 783 | + if (stageMatch) return Number(stageMatch[1]) | ||
| 784 | + | ||
| 785 | + return null | ||
| 786 | +} | ||
| 787 | + | ||
| 788 | +function resolveIssueNodeTarget(issue) { | ||
| 789 | + const relatedNode = issue?.primaryRelatedNode ?? issue?.taskNode | ||
| 790 | + if (relatedNode?.nodeId || (Number.isInteger(relatedNode?.rankId) && Number.isInteger(relatedNode?.queueId))) { | ||
| 791 | + return { | ||
| 792 | + nodeId: relatedNode?.nodeId ?? '', | ||
| 793 | + rankId: Number.isInteger(relatedNode?.rankId) ? relatedNode.rankId : issue?.primaryRankId ?? null, | ||
| 794 | + queueId: Number.isInteger(relatedNode?.queueId) ? relatedNode.queueId : issue?.queueId ?? null, | ||
| 795 | + slotIndex: Number.isInteger(relatedNode?.pos) ? relatedNode.pos : null, | ||
| 796 | + taskType: relatedNode?.taskType ?? issue?.taskType ?? '', | ||
| 797 | + } | ||
| 798 | + } | ||
| 799 | + | ||
| 800 | + if (!issue?.dagTarget) { | ||
| 801 | + return { | ||
| 802 | + nodeId: '', | ||
| 803 | + rankId: null, | ||
| 804 | + queueId: null, | ||
| 805 | + slotIndex: null, | ||
| 806 | + taskType: '', | ||
| 807 | + } | ||
| 808 | + } | ||
| 809 | + | ||
| 810 | + return { | ||
| 811 | + nodeId: issue.dagTarget.nodeId ?? '', | ||
| 812 | + rankId: | ||
| 813 | + Number.isInteger(issue?.dagTarget?.queueId) || Number.isInteger(issue?.dagTarget?.slotIndex) || issue?.dagTarget?.nodeId | ||
| 814 | + ? issue.dagTarget.rankId ?? issue?.primaryRankId ?? null | ||
| 815 | + : null, | ||
| 816 | + queueId: issue.dagTarget.queueId ?? issue?.queueId ?? null, | ||
| 817 | + slotIndex: issue?.dagTarget?.slotIndex ?? null, | ||
| 818 | + taskType: issue?.dagTarget?.taskType ?? issue?.taskType ?? '', | ||
| 819 | + } | ||
| 820 | +} | ||
| 821 | + | ||
| 822 | +function resolveSearchFieldValue(node, field) { | ||
| 823 | + if (!node) return '' | ||
| 824 | + const rawNode = node.rawNode ?? {} | ||
| 825 | + const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 826 | + | ||
| 827 | + switch (field) { | ||
| 828 | + case 'taskType': | ||
| 829 | + return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '').toLowerCase() | ||
| 830 | + case 'notifyId': | ||
| 831 | + return normalizeSearchFieldValue( | ||
| 832 | + node.notifyId ?? | ||
| 833 | + node.notify_id ?? | ||
| 834 | + taskData.notifyId ?? | ||
| 835 | + taskData.notify_id ?? | ||
| 836 | + rawNode.notifyId ?? | ||
| 837 | + rawNode.notify_id ?? | ||
| 838 | + rawNode?.task?.notifyId ?? | ||
| 839 | + rawNode?.task?.notify_id, | ||
| 840 | + ) | ||
| 841 | + case 'taskId': | ||
| 842 | + default: | ||
| 843 | + return String(node.id ?? rawNode?.node_id ?? rawNode?.id ?? '').toLowerCase() | ||
| 844 | + } | ||
| 845 | +} | ||
| 846 | + | ||
| 847 | +function resolveSearchFieldDisplayValue(node, field) { | ||
| 848 | + if (!node) return '--' | ||
| 849 | + const rawNode = node.rawNode ?? {} | ||
| 850 | + const taskData = node.taskData ?? rawNode?.task?.task_data ?? rawNode?.task_data ?? {} | ||
| 851 | + | ||
| 852 | + switch (field) { | ||
| 853 | + case 'taskType': | ||
| 854 | + return String(node.taskType ?? rawNode?.task?.task_type ?? rawNode?.task_type ?? '--').replaceAll('_', ' ') | ||
| 855 | + case 'notifyId': | ||
| 856 | + return formatSearchFieldDisplayValue( | ||
| 857 | + node.notifyId ?? | ||
| 858 | + node.notify_id ?? | ||
| 859 | + taskData.notifyId ?? | ||
| 860 | + taskData.notify_id ?? | ||
| 861 | + rawNode.notifyId ?? | ||
| 862 | + rawNode.notify_id ?? | ||
| 863 | + rawNode?.task?.notifyId ?? | ||
| 864 | + rawNode?.task?.notify_id, | ||
| 865 | + ) | ||
| 866 | + case 'taskId': | ||
| 867 | + default: | ||
| 868 | + return formatSearchFieldDisplayValue(node.id ?? rawNode?.node_id ?? rawNode?.id) | ||
| 869 | + } | ||
| 870 | +} | ||
| 871 | + | ||
| 872 | +function formatSearchLocation(node) { | ||
| 873 | + const rank = Number.isInteger(node?.rankId) ? `rank ${node.rankId}` : 'rank --' | ||
| 874 | + const queue = Number.isInteger(node?.queueId) ? `queue ${node.queueId}` : 'queue --' | ||
| 875 | + const posValue = Number.isInteger(node?.pos) | ||
| 876 | + ? node.pos | ||
| 877 | + : Number.isInteger(node?.slotIndex) | ||
| 878 | + ? node.slotIndex | ||
| 879 | + : null | ||
| 880 | + const pos = Number.isInteger(posValue) ? `pos ${posValue}` : 'pos --' | ||
| 881 | + return `${rank} / ${queue} / ${pos}` | ||
| 882 | +} | ||
| 883 | + | ||
| 884 | +function normalizeSearchFieldValue(value) { | ||
| 885 | + if (value === null || value === undefined || value === '') return '' | ||
| 886 | + return String(value).toLowerCase() | ||
| 887 | +} | ||
| 888 | + | ||
| 889 | +function formatSearchFieldDisplayValue(value) { | ||
| 890 | + if (value === null || value === undefined || value === '') return '--' | ||
| 891 | + return String(value) | ||
| 892 | +} | ||
| 893 | + | ||
| 894 | +function handleStageUpdate(nextStage) { | ||
| 895 | if (typeof nextStage !== 'string' || !nextStage || nextStage === currentGraphStage.value) return | 895 | if (typeof nextStage !== 'string' || !nextStage || nextStage === currentGraphStage.value) return |
| 896 | 896 | ||
| 897 | const mappedTarget = selectedNode.value?.nodeMappings?.find((item) => item?.stageName === nextStage) ?? null | 897 | const mappedTarget = selectedNode.value?.nodeMappings?.find((item) => item?.stageName === nextStage) ?? null |
| @@ -948,42 +948,42 @@ function handleNavigate(target) { | |||
| 948 | return | 948 | return |
| 949 | } | 949 | } |
| 950 | 950 | ||
| 951 | - if (resolvedTarget.containerNode) { | 951 | + if (resolvedTarget.containerNode) { |
| 952 | - enterSubgraph(resolvedTarget.containerNode) | 952 | + enterSubgraph(resolvedTarget.containerNode) |
| 953 | - } else if (subgraphNode.value) { | 953 | + } else if (subgraphNode.value) { |
| 954 | - exitSubgraph() | 954 | + exitSubgraph() |
| 955 | - } | 955 | + } |
| 956 | 956 | ||
| 957 | registerNodes([...resolvedTarget.path, resolvedTarget.node]) | 957 | registerNodes([...resolvedTarget.path, resolvedTarget.node]) |
| 958 | focusNode(resolvedTarget.node, { follow: true, sync: true }) | 958 | focusNode(resolvedTarget.node, { follow: true, sync: true }) |
| 959 | -} | 959 | +} |
| 960 | - | 960 | + |
| 961 | -function handleFocusStep(step) { | 961 | +function handleFocusStep(step) { |
| 962 | - focusStep(step, { smoothScroll: true }) | 962 | + focusStep(step, { smoothScroll: true }) |
| 963 | -} | 963 | +} |
| 964 | - | 964 | + |
| 965 | -function handleStepUpdate(step) { | 965 | +function handleStepUpdate(step) { |
| 966 | - if (!Number.isFinite(step)) return | 966 | + if (!Number.isFinite(step)) return |
| 967 | - focusStep(step, { smoothScroll: false }) | 967 | + focusStep(step, { smoothScroll: false }) |
| 968 | -} | 968 | +} |
| 969 | - | 969 | + |
| 970 | -function handleOverviewStepUpdate(step) { | 970 | +function handleOverviewStepUpdate(step) { |
| 971 | - if (!Number.isFinite(step)) return | 971 | + if (!Number.isFinite(step)) return |
| 972 | - selectedNode.value = null | 972 | + selectedNode.value = null |
| 973 | - focusStep(step, { smoothScroll: false }) | 973 | + focusStep(step, { smoothScroll: false }) |
| 974 | -} | 974 | +} |
| 975 | - | 975 | + |
| 976 | -async function handleBufferSelect(selection) { | 976 | +async function handleBufferSelect(selection) { |
| 977 | - const step = Number(selection?.step) | 977 | + const step = Number(selection?.step) |
| 978 | const rankId = Number(selection?.rankId) | 978 | const rankId = Number(selection?.rankId) |
| 979 | const bufferId = Number(selection?.bufferId) | 979 | const bufferId = Number(selection?.bufferId) |
| 980 | - if (!Number.isInteger(step) || !Number.isInteger(rankId) || !Number.isInteger(bufferId)) return | 980 | + if (!Number.isInteger(step) || !Number.isInteger(rankId) || !Number.isInteger(bufferId)) return |
| 981 | - | 981 | + |
| 982 | - selectedNode.value = null | 982 | + selectedNode.value = null |
| 983 | - focusStep(step, { smoothScroll: false }) | 983 | + focusStep(step, { smoothScroll: false }) |
| 984 | - await nextTick() | 984 | + await nextTick() |
| 985 | - inspectorRef.value?.selectLayout?.(rankId, bufferId) | 985 | + inspectorRef.value?.selectLayout?.(rankId, bufferId) |
| 986 | -} | 986 | +} |
| 987 | 987 | ||
| 988 | function handleTotalStepsUpdate(total) { | 988 | function handleTotalStepsUpdate(total) { |
| 989 | setTotalSteps(total) | 989 | setTotalSteps(total) |
| @@ -1390,19 +1390,19 @@ function findNodeInDescendants(rootNode, targetId, visited, path = []) { | |||
| 1390 | return null | 1390 | return null |
| 1391 | } | 1391 | } |
| 1392 | 1392 | ||
| 1393 | -function iterateSubgraphEntries(streamCollection, fallbackRankId) { | 1393 | +function iterateSubgraphEntries(streamCollection, fallbackRankId) { |
| 1394 | - return normalizeStreamCollection(streamCollection, fallbackRankId, { | 1394 | + return normalizeStreamCollection(streamCollection, fallbackRankId, { |
| 1395 | - stageName: DEFAULT_MEMVIEW_STAGE, | 1395 | + stageName: DEFAULT_MEMVIEW_STAGE, |
| 1396 | - topLevel: false, | 1396 | + topLevel: false, |
| 1397 | - }).flatMap((stream) => | 1397 | + }).flatMap((stream) => |
| 1398 | - stream.nodes.map((node) => ({ | 1398 | + stream.nodes.map((node) => ({ |
| 1399 | - rawNode: node.rawNode, | 1399 | + rawNode: node.rawNode, |
| 1400 | - node, | 1400 | + node, |
| 1401 | - })), | 1401 | + })), |
| 1402 | - ) | 1402 | + ) |
| 1403 | -} | 1403 | +} |
| 1404 | - | 1404 | + |
| 1405 | -watch( | 1405 | +watch( |
| 1406 | () => [selectedDatasetName.value, selectedRankKeys.value.join(',')], | 1406 | () => [selectedDatasetName.value, selectedRankKeys.value.join(',')], |
| 1407 | () => { | 1407 | () => { |
| 1408 | resetTimeline() | 1408 | resetTimeline() |
| @@ -1434,17 +1434,17 @@ watch( | |||
| 1434 | }, | 1434 | }, |
| 1435 | ) | 1435 | ) |
| 1436 | 1436 | ||
| 1437 | -watch( | 1437 | +watch( |
| 1438 | - () => [playbackVisibleSteps.value.length, playbackVisibleIndex.value], | 1438 | + () => [playbackVisibleSteps.value.length, playbackVisibleIndex.value], |
| 1439 | - ([stepCount, currentIndex]) => { | 1439 | + ([stepCount, currentIndex]) => { |
| 1440 | - if (!playbackPlaying.value) return | 1440 | + if (!playbackPlaying.value) return |
| 1441 | - if (!stepCount || currentIndex >= stepCount - 1) { | 1441 | + if (!stepCount || currentIndex >= stepCount - 1) { |
| 1442 | - stopPlayback() | 1442 | + stopPlayback() |
| 1443 | - } | 1443 | + } |
| 1444 | - }, | 1444 | + }, |
| 1445 | -) | 1445 | +) |
| 1446 | - | 1446 | + |
| 1447 | -onMounted(() => { | 1447 | +onMounted(() => { |
| 1448 | centerTopSize.value = resolveDefaultCenterTopSize() | 1448 | centerTopSize.value = resolveDefaultCenterTopSize() |
| 1449 | ensureDatasetsLoaded() | 1449 | ensureDatasetsLoaded() |
| 1450 | updateCenterAvailableHeight() | 1450 | updateCenterAvailableHeight() |
| @@ -1477,190 +1477,190 @@ onBeforeUnmount(() => { | |||
| 1477 | :resizable="!sidebarCollapsed" | 1477 | :resizable="!sidebarCollapsed" |
| 1478 | @update:size="handleLeftPanelResize" | 1478 | @update:size="handleLeftPanelResize" |
| 1479 | > | 1479 | > |
| 1480 | - <aside class="dashboard-sidebar-shell" :class="{ 'is-collapsed': sidebarCollapsed }"> | 1480 | + <aside class="dashboard-sidebar-shell" :class="{ 'is-collapsed': sidebarCollapsed }"> |
| 1481 | - <DashboardSidebar | 1481 | + <DashboardSidebar |
| 1482 | - :selected-rank-count="selectedRankCount" | 1482 | + :selected-rank-count="selectedRankCount" |
| 1483 | - :dataset-detail="datasetDetail" | 1483 | + :dataset-detail="datasetDetail" |
| 1484 | - :selected-dataset="selectedDataset" | 1484 | + :selected-dataset="selectedDataset" |
| 1485 | - :tree-data="treeData" | 1485 | + :tree-data="treeData" |
| 1486 | - :checked-keys="selectedRankKeys" | 1486 | + :checked-keys="selectedRankKeys" |
| 1487 | - :empty-text="loadingList ? 'Loading...' : EMPTY_TEXT" | 1487 | + :empty-text="loadingList ? 'Loading...' : EMPTY_TEXT" |
| 1488 | - @tree-check="handleTreeCheck" | 1488 | + @tree-check="handleTreeCheck" |
| 1489 | - > | 1489 | + > |
| 1490 | - <template #after-rank> | 1490 | + <template #after-rank> |
| 1491 | - <el-collapse | 1491 | + <el-collapse |
| 1492 | - v-model="issuePanelSections" | 1492 | + v-model="issuePanelSections" |
| 1493 | - class="dashboard-sidebar-collapse memview-issue-collapse" | 1493 | + class="dashboard-sidebar-collapse memview-issue-collapse" |
| 1494 | - > | 1494 | + > |
| 1495 | - <el-collapse-item name="issues" class="dashboard-subpanel analytic-list-panel"> | 1495 | + <el-collapse-item name="issues" class="dashboard-subpanel analytic-list-panel"> |
| 1496 | - <template #title> | 1496 | + <template #title> |
| 1497 | - <div class="dashboard-panel-toggle"> | 1497 | + <div class="dashboard-panel-toggle"> |
| 1498 | - <span class="dashboard-panel-toggle__title"> | 1498 | + <span class="dashboard-panel-toggle__title"> |
| 1499 | - <el-icon><WarningFilled /></el-icon> | 1499 | + <el-icon><WarningFilled /></el-icon> |
| 1500 | - <span>报错列表</span> | 1500 | + <span>报错列表</span> |
| 1501 | - </span> | 1501 | + </span> |
| 1502 | - <span class="dashboard-panel-toggle__meta"> | 1502 | + <span class="dashboard-panel-toggle__meta"> |
| 1503 | - <el-tag size="small" type="danger">{{ issueCount }} 条</el-tag> | 1503 | + <el-tag size="small" type="danger">{{ issueCount }} 条</el-tag> |
| 1504 | - </span> | 1504 | + </span> |
| 1505 | - </div> | 1505 | + </div> |
| 1506 | - </template> | 1506 | + </template> |
| 1507 | - | 1507 | + |
| 1508 | - <div v-if="loadingIssues" class="dashboard-empty-wrap analytic-list-empty"> | 1508 | + <div v-if="loadingIssues" class="dashboard-empty-wrap analytic-list-empty"> |
| 1509 | - <el-empty description="正在读取 issues.msgpack..." /> | 1509 | + <el-empty description="正在读取 issues.msgpack..." /> |
| 1510 | - </div> | 1510 | + </div> |
| 1511 | - | 1511 | + |
| 1512 | - <div v-else-if="issues.length" class="analytic-issue-list"> | 1512 | + <div v-else-if="issues.length" class="analytic-issue-list"> |
| 1513 | - <button | 1513 | + <button |
| 1514 | - v-for="issue in issues" | 1514 | + v-for="issue in issues" |
| 1515 | - :key="issue.issueId" | 1515 | + :key="issue.issueId" |
| 1516 | - type="button" | 1516 | + type="button" |
| 1517 | - class="analytic-issue-row" | 1517 | + class="analytic-issue-row" |
| 1518 | - :class="{ 'is-active': selectedIssue?.issueId === issue.issueId }" | 1518 | + :class="{ 'is-active': selectedIssue?.issueId === issue.issueId }" |
| 1519 | - @click="handleIssueSelect(issue)" | 1519 | + @click="handleIssueSelect(issue)" |
| 1520 | - > | 1520 | + > |
| 1521 | - <span class="analytic-issue-row__icon" :class="`is-${issue.severityType}`"> | 1521 | + <span class="analytic-issue-row__icon" :class="`is-${issue.severityType}`"> |
| 1522 | - <el-icon><WarningFilled /></el-icon> | 1522 | + <el-icon><WarningFilled /></el-icon> |
| 1523 | - </span> | 1523 | + </span> |
| 1524 | - <div class="analytic-issue-row__content"> | 1524 | + <div class="analytic-issue-row__content"> |
| 1525 | - <div class="analytic-issue-row__head"> | 1525 | + <div class="analytic-issue-row__head"> |
| 1526 | - <strong>{{ issue.title }}</strong> | 1526 | + <strong>{{ issue.title }}</strong> |
| 1527 | - <div class="analytic-issue-row__head-tags"> | 1527 | + <div class="analytic-issue-row__head-tags"> |
| 1528 | - <el-tag size="small" :type="issue.severityType">{{ issue.severityLabel }}</el-tag> | 1528 | + <el-tag size="small" :type="issue.severityType">{{ issue.severityLabel }}</el-tag> |
| 1529 | - </div> | 1529 | + </div> |
| 1530 | - </div> | 1530 | + </div> |
| 1531 | - <div class="analytic-issue-row__body"> | 1531 | + <div class="analytic-issue-row__body"> |
| 1532 | - <div v-if="issue.listFieldRows.primaryRow.length" class="analytic-issue-row__field-stack"> | 1532 | + <div v-if="issue.listFieldRows.primaryRow.length" class="analytic-issue-row__field-stack"> |
| 1533 | - <div | 1533 | + <div |
| 1534 | - v-for="field in issue.listFieldRows.primaryRow" | 1534 | + v-for="field in issue.listFieldRows.primaryRow" |
| 1535 | - :key="`primary-${issue.issueId}-${field.label}`" | 1535 | + :key="`primary-${issue.issueId}-${field.label}`" |
| 1536 | - class="analytic-issue-row__field" | 1536 | + class="analytic-issue-row__field" |
| 1537 | - > | 1537 | + > |
| 1538 | - <span>{{ field.label }}</span> | 1538 | + <span>{{ field.label }}</span> |
| 1539 | - <strong>{{ field.value }}</strong> | 1539 | + <strong>{{ field.value }}</strong> |
| 1540 | - </div> | 1540 | + </div> |
| 1541 | - </div> | 1541 | + </div> |
| 1542 | - <div | 1542 | + <div |
| 1543 | - v-if="issue.listFieldRows.secondaryRow.length" | 1543 | + v-if="issue.listFieldRows.secondaryRow.length" |
| 1544 | - class="analytic-issue-row__field-stack is-secondary" | 1544 | + class="analytic-issue-row__field-stack is-secondary" |
| 1545 | - > | 1545 | + > |
| 1546 | - <div | 1546 | + <div |
| 1547 | - v-for="field in issue.listFieldRows.secondaryRow" | 1547 | + v-for="field in issue.listFieldRows.secondaryRow" |
| 1548 | - :key="`secondary-${issue.issueId}-${field.label}`" | 1548 | + :key="`secondary-${issue.issueId}-${field.label}`" |
| 1549 | - class="analytic-issue-row__field" | 1549 | + class="analytic-issue-row__field" |
| 1550 | - > | 1550 | + > |
| 1551 | - <span>{{ field.label }}</span> | 1551 | + <span>{{ field.label }}</span> |
| 1552 | - <strong>{{ field.value }}</strong> | 1552 | + <strong>{{ field.value }}</strong> |
| 1553 | - </div> | 1553 | + </div> |
| 1554 | - </div> | 1554 | + </div> |
| 1555 | - </div> | 1555 | + </div> |
| 1556 | - <span class="analytic-issue-row__code">{{ issue.code }}</span> | 1556 | + <span class="analytic-issue-row__code">{{ issue.code }}</span> |
| 1557 | - </div> | 1557 | + </div> |
| 1558 | - </button> | 1558 | + </button> |
| 1559 | - </div> | 1559 | + </div> |
| 1560 | - | 1560 | + |
| 1561 | - <div v-else class="dashboard-empty-wrap analytic-list-empty"> | 1561 | + <div v-else class="dashboard-empty-wrap analytic-list-empty"> |
| 1562 | - <el-empty description="当前数据集没有 issue 记录。" /> | 1562 | + <el-empty description="当前数据集没有 issue 记录。" /> |
| 1563 | - </div> | 1563 | + </div> |
| 1564 | - </el-collapse-item> | 1564 | + </el-collapse-item> |
| 1565 | - </el-collapse> | 1565 | + </el-collapse> |
| 1566 | - | 1566 | + |
| 1567 | - <el-collapse | 1567 | + <el-collapse |
| 1568 | - v-model="searchPanelSections" | 1568 | + v-model="searchPanelSections" |
| 1569 | - class="dashboard-sidebar-collapse memview-search-collapse" | 1569 | + class="dashboard-sidebar-collapse memview-search-collapse" |
| 1570 | - > | 1570 | + > |
| 1571 | - <el-collapse-item name="search" class="dashboard-subpanel memview-search-panel"> | 1571 | + <el-collapse-item name="search" class="dashboard-subpanel memview-search-panel"> |
| 1572 | - <template #title> | 1572 | + <template #title> |
| 1573 | - <div class="dashboard-panel-toggle"> | 1573 | + <div class="dashboard-panel-toggle"> |
| 1574 | - <span class="dashboard-panel-toggle__title"> | 1574 | + <span class="dashboard-panel-toggle__title"> |
| 1575 | - <el-icon><Search /></el-icon> | 1575 | + <el-icon><Search /></el-icon> |
| 1576 | - <span>搜索</span> | 1576 | + <span>搜索</span> |
| 1577 | - </span> | 1577 | + </span> |
| 1578 | - <span class="dashboard-panel-toggle__meta"> | 1578 | + <span class="dashboard-panel-toggle__meta"> |
| 1579 | - <el-tag size="small" type="info">{{ selectedSearchFieldLabel }}</el-tag> | 1579 | + <el-tag size="small" type="info">{{ selectedSearchFieldLabel }}</el-tag> |
| 1580 | - <el-tag size="small" type="success"> | 1580 | + <el-tag size="small" type="success"> |
| 1581 | - {{ normalizedSearchQuery ? `${searchResults.length} results` : `${selectedRankCount} ranks` }} | 1581 | + {{ normalizedSearchQuery ? `${searchResults.length} results` : `${selectedRankCount} ranks` }} |
| 1582 | - </el-tag> | 1582 | + </el-tag> |
| 1583 | - </span> | 1583 | + </span> |
| 1584 | - </div> | 1584 | + </div> |
| 1585 | - </template> | 1585 | + </template> |
| 1586 | - | 1586 | + |
| 1587 | - <section class="memview-sidebar-search"> | 1587 | + <section class="memview-sidebar-search"> |
| 1588 | - <div class="memview-sidebar-search__controls"> | 1588 | + <div class="memview-sidebar-search__controls"> |
| 1589 | - <el-select | 1589 | + <el-select |
| 1590 | - v-model="searchField" | 1590 | + v-model="searchField" |
| 1591 | - class="memview-sidebar-search__field-select" | 1591 | + class="memview-sidebar-search__field-select" |
| 1592 | - aria-label="Search field" | 1592 | + aria-label="Search field" |
| 1593 | - > | 1593 | + > |
| 1594 | - <el-option | 1594 | + <el-option |
| 1595 | - v-for="option in SEARCH_FIELD_OPTIONS" | 1595 | + v-for="option in SEARCH_FIELD_OPTIONS" |
| 1596 | - :key="option.value" | 1596 | + :key="option.value" |
| 1597 | - :label="option.label" | 1597 | + :label="option.label" |
| 1598 | - :value="option.value" | 1598 | + :value="option.value" |
| 1599 | - /> | 1599 | + /> |
| 1600 | - </el-select> | 1600 | + </el-select> |
| 1601 | - | 1601 | + |
| 1602 | - <el-input | 1602 | + <el-input |
| 1603 | - v-model="searchQuery" | 1603 | + v-model="searchQuery" |
| 1604 | - class="memview-sidebar-search__input" | 1604 | + class="memview-sidebar-search__input" |
| 1605 | - clearable | 1605 | + clearable |
| 1606 | - placeholder="Enter keyword" | 1606 | + placeholder="Enter keyword" |
| 1607 | - aria-label="Search keyword" | 1607 | + aria-label="Search keyword" |
| 1608 | - /> | 1608 | + /> |
| 1609 | - </div> | 1609 | + </div> |
| 1610 | - | 1610 | + |
| 1611 | - <div class="memview-sidebar-search__meta"> | 1611 | + <div class="memview-sidebar-search__meta"> |
| 1612 | - <span>Selected ranks: {{ selectedRankCount }}</span> | 1612 | + <span>Selected ranks: {{ selectedRankCount }}</span> |
| 1613 | - <span>Results: {{ searchResults.length }}</span> | 1613 | + <span>Results: {{ searchResults.length }}</span> |
| 1614 | - </div> | 1614 | + </div> |
| 1615 | - | 1615 | + |
| 1616 | - <div | 1616 | + <div |
| 1617 | - v-if="normalizedSearchQuery && searchResults.length" | 1617 | + v-if="normalizedSearchQuery && searchResults.length" |
| 1618 | - class="memview-sidebar-search__results" | 1618 | + class="memview-sidebar-search__results" |
| 1619 | - > | 1619 | + > |
| 1620 | - <button | 1620 | + <button |
| 1621 | - v-for="result in searchResults" | 1621 | + v-for="result in searchResults" |
| 1622 | - :key="result.node.id" | 1622 | + :key="result.node.id" |
| 1623 | - type="button" | 1623 | + type="button" |
| 1624 | - class="memview-sidebar-search-card" | 1624 | + class="memview-sidebar-search-card" |
| 1625 | - :class="{ 'is-active': selectedNode?.id === result.node.id }" | 1625 | + :class="{ 'is-active': selectedNode?.id === result.node.id }" |
| 1626 | - @click="handleSearchResultSelect(result)" | 1626 | + @click="handleSearchResultSelect(result)" |
| 1627 | - > | 1627 | + > |
| 1628 | - <div class="memview-sidebar-search-card__head"> | 1628 | + <div class="memview-sidebar-search-card__head"> |
| 1629 | - <strong>{{ result.taskId }}</strong> | 1629 | + <strong>{{ result.taskId }}</strong> |
| 1630 | - <el-tag size="small" type="info">{{ result.taskType }}</el-tag> | 1630 | + <el-tag size="small" type="info">{{ result.taskType }}</el-tag> |
| 1631 | - </div> | 1631 | + </div> |
| 1632 | - | 1632 | + |
| 1633 | - <div class="memview-sidebar-search-card__grid"> | 1633 | + <div class="memview-sidebar-search-card__grid"> |
| 1634 | - <div class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide"> | 1634 | + <div class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide"> |
| 1635 | - <span>rank / queue / pos</span> | 1635 | + <span>rank / queue / pos</span> |
| 1636 | - <strong>{{ result.location }}</strong> | 1636 | + <strong>{{ result.formatLoc }}</strong> |
| 1637 | - </div> | 1637 | + </div> |
| 1638 | - <div | 1638 | + <div |
| 1639 | - v-if="searchField === 'notifyId'" | 1639 | + v-if="searchField === 'notifyId'" |
| 1640 | - class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide" | 1640 | + class="memview-sidebar-search-card__field memview-sidebar-search-card__field--wide" |
| 1641 | - > | 1641 | + > |
| 1642 | - <span>notifyId</span> | 1642 | + <span>notifyId</span> |
| 1643 | - <strong>{{ result.notifyId }}</strong> | 1643 | + <strong>{{ result.notifyId }}</strong> |
| 1644 | - </div> | 1644 | + </div> |
| 1645 | - </div> | 1645 | + </div> |
| 1646 | - </button> | 1646 | + </button> |
| 1647 | - </div> | 1647 | + </div> |
| 1648 | - | 1648 | + |
| 1649 | - <div v-else-if="normalizedSearchQuery" class="memview-sidebar-search__empty"> | 1649 | + <div v-else-if="normalizedSearchQuery" class="memview-sidebar-search__empty"> |
| 1650 | - <el-empty description="No matching tasks" :image-size="72" /> | 1650 | + <el-empty description="No matching tasks" :image-size="72" /> |
| 1651 | - </div> | 1651 | + </div> |
| 1652 | - | 1652 | + |
| 1653 | - <div v-else class="memview-sidebar-search__hint"> | 1653 | + <div v-else class="memview-sidebar-search__hint"> |
| 1654 | - Choose taskId, taskType, or notifyId and enter a keyword to search within the selected ranks. | 1654 | + Choose taskId, taskType, or notifyId and enter a keyword to search within the selected ranks. |
| 1655 | - </div> | 1655 | + </div> |
| 1656 | - </section> | 1656 | + </section> |
| 1657 | - </el-collapse-item> | 1657 | + </el-collapse-item> |
| 1658 | - </el-collapse> | 1658 | + </el-collapse> |
| 1659 | - </template> | 1659 | + </template> |
| 1660 | - </DashboardSidebar> | 1660 | + </DashboardSidebar> |
| 1661 | - | 1661 | + |
| 1662 | - <button | 1662 | + <button |
| 1663 | - v-if="!sidebarCollapsed" | 1663 | + v-if="!sidebarCollapsed" |
| 1664 | type="button" | 1664 | type="button" |
| 1665 | class="dashboard-sidebar-toggle dashboard-sidebar-toggle--collapse" | 1665 | class="dashboard-sidebar-toggle dashboard-sidebar-toggle--collapse" |
| 1666 | aria-label="Collapse sidebar" | 1666 | aria-label="Collapse sidebar" |
| @@ -1699,14 +1699,14 @@ onBeforeUnmount(() => { | |||
| 1699 | > | 1699 | > |
| 1700 | MemView 内存视图 | 1700 | MemView 内存视图 |
| 1701 | </button> | 1701 | </button> |
| 1702 | - <MemViewOverviewPanel | 1702 | + <MemViewOverviewPanel |
| 1703 | - v-else | 1703 | + v-else |
| 1704 | - :dataset-name="selectedDatasetName" | 1704 | + :dataset-name="selectedDatasetName" |
| 1705 | - :enabled="hasMemoryData" | 1705 | + :enabled="hasMemoryData" |
| 1706 | - :selected-rank-keys="selectedRankKeys" | 1706 | + :selected-rank-keys="selectedRankKeys" |
| 1707 | - :current-step="clampedCurrentStep" | 1707 | + :current-step="clampedCurrentStep" |
| 1708 | - :display-step-items="displayStepItems" | 1708 | + :display-step-items="displayStepItems" |
| 1709 | - :empty-text="overviewEmptyText" | 1709 | + :empty-text="overviewEmptyText" |
| 1710 | @update:current-step="handleOverviewStepUpdate" | 1710 | @update:current-step="handleOverviewStepUpdate" |
| 1711 | @update:total-steps="handleTotalStepsUpdate" | 1711 | @update:total-steps="handleTotalStepsUpdate" |
| 1712 | @buffer-select="handleBufferSelect" | 1712 | @buffer-select="handleBufferSelect" |
| @@ -1722,23 +1722,23 @@ onBeforeUnmount(() => { | |||
| 1722 | > | 1722 | > |
| 1723 | DAGView 任务视图 | 1723 | DAGView 任务视图 |
| 1724 | </button> | 1724 | </button> |
| 1725 | - <MemViewDagPanel | 1725 | + <MemViewDagPanel |
| 1726 | - v-else | 1726 | + v-else |
| 1727 | - :dataset-name="selectedDatasetName" | 1727 | + :dataset-name="selectedDatasetName" |
| 1728 | - :selected-rank-keys="selectedRankKeys" | 1728 | + :selected-rank-keys="selectedRankKeys" |
| 1729 | - :selected-node-id="selectedNode?.id ?? ''" | 1729 | + :selected-node-id="selectedNode?.id ?? ''" |
| 1730 | - :issue-node-ids="dagIssueNodeIds" | 1730 | + :issue-node-ids="dagIssueNodeIds" |
| 1731 | - :subgraph-node="subgraphNode" | 1731 | + :subgraph-node="subgraphNode" |
| 1732 | - :current-step="clampedCurrentStep" | 1732 | + :current-step="clampedCurrentStep" |
| 1733 | - :total-steps="totalSteps" | 1733 | + :total-steps="totalSteps" |
| 1734 | - :display-step-items="displayStepItems" | 1734 | + :display-step-items="displayStepItems" |
| 1735 | - :empty-text="dagEmptyText" | 1735 | + :empty-text="dagEmptyText" |
| 1736 | - @node-select="handleNodeSelect" | 1736 | + @node-select="handleNodeSelect" |
| 1737 | - @update:current-step="handleStepUpdate" | 1737 | + @update:current-step="handleStepUpdate" |
| 1738 | - @update:total-steps="handleTotalStepsUpdate" | 1738 | + @update:total-steps="handleTotalStepsUpdate" |
| 1739 | - @nodes-loaded="handleNodesLoaded" | 1739 | + @nodes-loaded="handleNodesLoaded" |
| 1740 | - @graph-node-ids-change="handleGraphNodeIdsChange" | 1740 | + @graph-node-ids-change="handleGraphNodeIdsChange" |
| 1741 | - /> | 1741 | + /> |
| 1742 | </el-splitter-panel> | 1742 | </el-splitter-panel> |
| 1743 | </el-splitter> | 1743 | </el-splitter> |
| 1744 | </div> | 1744 | </div> |
| @@ -1798,14 +1798,14 @@ onBeforeUnmount(() => { | |||
| 1798 | :node-task-ops="selectedNodeTaskOps" | 1798 | :node-task-ops="selectedNodeTaskOps" |
| 1799 | :step-buffer-ops="activeStepBufferOps" | 1799 | :step-buffer-ops="activeStepBufferOps" |
| 1800 | :step-task-ops="activeStepTaskOps" | 1800 | :step-task-ops="activeStepTaskOps" |
| 1801 | - :step-layout-buffers="activeStepLayoutBuffers" | 1801 | + :step-layout-buffers="activeStepLayoutBuffers" |
| 1802 | - :selected-rank-keys="selectedRankKeys" | 1802 | + :selected-rank-keys="selectedRankKeys" |
| 1803 | - :can-resolve-relation="canResolveRelation" | 1803 | + :can-resolve-relation="canResolveRelation" |
| 1804 | - :resolve-relation-meta="resolveRelationMeta" | 1804 | + :resolve-relation-meta="resolveRelationMeta" |
| 1805 | - :empty-text="hasData ? 'Select a node to inspect.' : EMPTY_TEXT" | 1805 | + :empty-text="hasData ? 'Select a node to inspect.' : EMPTY_TEXT" |
| 1806 | - @enter-subgraph="handleEnterSubgraph" | 1806 | + @enter-subgraph="handleEnterSubgraph" |
| 1807 | - @exit-subgraph="handleExitSubgraph" | 1807 | + @exit-subgraph="handleExitSubgraph" |
| 1808 | - @navigate="handleNavigate" | 1808 | + @navigate="handleNavigate" |
| 1809 | @focus-step="handleFocusStep" | 1809 | @focus-step="handleFocusStep" |
| 1810 | /> | 1810 | /> |
| 1811 | 1811 | ||
| @@ -28,6 +28,7 @@ file(GLOB_RECURSE VR_LIB_SOURCES | |||
| 28 | # 添加插件库 | 28 | # 添加插件库 |
| 29 | add_executable(runner ${VR_LIB_SOURCES}) | 29 | add_executable(runner ${VR_LIB_SOURCES}) |
| 30 | 30 | ||
| 31 | + | ||
| 31 | target_compile_options(runner PRIVATE | 32 | target_compile_options(runner PRIVATE |
| 32 | -g | 33 | -g |
| 33 | -O0 | 34 | -O0 |
| @@ -56,17 +57,23 @@ target_include_directories(runner PRIVATE | |||
| 56 | ) | 57 | ) |
| 57 | 58 | ||
| 58 | target_link_libraries(runner PRIVATE | 59 | target_link_libraries(runner PRIVATE |
| 60 | + -Wl,--whole-archive | ||
| 59 | aiv_executor | 61 | aiv_executor |
| 60 | store | 62 | store |
| 63 | + loader | ||
| 61 | runnerdb | 64 | runnerdb |
| 65 | + modeldb | ||
| 62 | ccu_executor | 66 | ccu_executor |
| 63 | log | 67 | log |
| 68 | + -Wl,--no-whole-archive | ||
| 64 | rt | 69 | rt |
| 65 | JSON::JSON | 70 | JSON::JSON |
| 66 | - loader | 71 | + |
| 72 | + yaml-cpp::yaml-cpp | ||
| 73 | + sqlite3 | ||
| 67 | ) | 74 | ) |
| 68 | install(TARGETS runner | 75 | install(TARGETS runner |
| 69 | - DESTINATION "plugin/validate/runner" | 76 | + DESTINATION "plugin/runner" |
| 70 | # 文件的权限 (755) | 77 | # 文件的权限 (755) |
| 71 | PERMISSIONS | 78 | PERMISSIONS |
| 72 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 79 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| @@ -75,7 +82,7 @@ install(TARGETS runner | |||
| 75 | ) | 82 | ) |
| 76 | 83 | ||
| 77 | install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../manifest.json" | 84 | install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../manifest.json" |
| 78 | - DESTINATION "plugin/validate/runner" | 85 | + DESTINATION "plugin/runner" |
| 79 | # 文件的权限 (755) | 86 | # 文件的权限 (755) |
| 80 | PERMISSIONS | 87 | PERMISSIONS |
| 81 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 88 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| @@ -46,7 +46,6 @@ target_include_directories(aiv_executor | |||
| 46 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime | 46 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime |
| 47 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/profiling | 47 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/profiling |
| 48 | 48 | ||
| 49 | - ${THRID_PARTY_DIR} | ||
| 50 | ${THRID_PARTY_DIR}/nlohmann_json | 49 | ${THRID_PARTY_DIR}/nlohmann_json |
| 51 | ${THRID_PARTY_DIR}/dbg_macro # for debug | 50 | ${THRID_PARTY_DIR}/dbg_macro # for debug |
| 52 | ) | 51 | ) |
| @@ -23,9 +23,9 @@ namespace { | |||
| 23 | constexpr uint8_t INPUT_BUFFER_TYPE = 0; | 23 | constexpr uint8_t INPUT_BUFFER_TYPE = 0; |
| 24 | constexpr uint8_t OUTPUT_BUFFER_TYPE = 1; | 24 | constexpr uint8_t OUTPUT_BUFFER_TYPE = 1; |
| 25 | constexpr uint8_t CCL_BUFFER_TYPE = 2; | 25 | constexpr uint8_t CCL_BUFFER_TYPE = 2; |
| 26 | -constexpr uint64_t AIV_COMM_INFO_SIZE = 33ULL * 1024ULL * 1024ULL; | 26 | +constexpr uint64_t AIV_COMM_INFO_SIZE = 65ULL * 1024ULL * 1024ULL; |
| 27 | -constexpr uint64_t AIV_FLAG_ADDR_OFFSET = 40ULL * 1024ULL; | 27 | +constexpr uint64_t AIV_FLAG1_OFFSET = 1ULL * 1024ULL * 1024ULL; |
| 28 | -constexpr uint64_t AIV_FLAG_BUFFER_SIZE = AIV_COMM_INFO_SIZE - AIV_FLAG_ADDR_OFFSET; | 28 | +constexpr uint64_t AIV_FLAG_BUFFER_SIZE = AIV_COMM_INFO_SIZE - AIV_FLAG1_OFFSET; |
| 29 | 29 | ||
| 30 | const char *GetBufferTypeName(uint8_t bufferType) | 30 | const char *GetBufferTypeName(uint8_t bufferType) |
| 31 | { | 31 | { |
| @@ -8,8 +8,9 @@ | |||
| 8 | 8 | ||
| 9 | file(GLOB_RECURSE HCCL_SOURCES "*.cc") | 9 | file(GLOB_RECURSE HCCL_SOURCES "*.cc") |
| 10 | 10 | ||
| 11 | -# 添加共享库 | 11 | +# 添加静态库 |
| 12 | -add_library(ccu_executor SHARED ${HCCL_SOURCES}) | 12 | +add_library(ccu_executor STATIC ${HCCL_SOURCES}) |
| 13 | + | ||
| 13 | target_compile_options(ccu_executor PRIVATE | 14 | target_compile_options(ccu_executor PRIVATE |
| 14 | -fPIC | 15 | -fPIC |
| 15 | -g | 16 | -g |
| @@ -41,12 +42,3 @@ target_link_libraries(ccu_executor PRIVATE | |||
| 41 | log | 42 | log |
| 42 | rt | 43 | rt |
| 43 | ) | 44 | ) |
| 44 | - | ||
| 45 | -install(TARGETS ccu_executor | ||
| 46 | - DESTINATION "plugin/validate/runner" | ||
| 47 | - # 文件的权限 (755) | ||
| 48 | - PERMISSIONS | ||
| 49 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 50 | - GROUP_READ GROUP_EXECUTE | ||
| 51 | - WORLD_READ WORLD_EXECUTE | ||
| 52 | -) | ||
| @@ -11,6 +11,8 @@ cmake_minimum_required(VERSION 3.10) | |||
| 11 | message(STATUS "TOP_DIR: ${TOP_DIR}") | 11 | message(STATUS "TOP_DIR: ${TOP_DIR}") |
| 12 | message(STATUS "ASCEND_CANN_PACKAGE_PATH: ${ASCEND_CANN_PACKAGE_PATH}") | 12 | message(STATUS "ASCEND_CANN_PACKAGE_PATH: ${ASCEND_CANN_PACKAGE_PATH}") |
| 13 | 13 | ||
| 14 | +find_package(SQLite3 REQUIRED) | ||
| 15 | + | ||
| 14 | add_library(hccl_proxy_level2 SHARED "") | 16 | add_library(hccl_proxy_level2 SHARED "") |
| 15 | 17 | ||
| 16 | target_include_directories(hccl_proxy_level2 PRIVATE | 18 | target_include_directories(hccl_proxy_level2 PRIVATE |
| @@ -121,18 +123,22 @@ target_compile_options(hccl_proxy_level2 PRIVATE | |||
| 121 | ) | 123 | ) |
| 122 | 124 | ||
| 123 | target_link_libraries(hccl_proxy_level2 PRIVATE | 125 | target_link_libraries(hccl_proxy_level2 PRIVATE |
| 124 | - dl | 126 | + -Wl,--whole-archive |
| 125 | - rt | ||
| 126 | log | 127 | log |
| 127 | runnerdb | 128 | runnerdb |
| 129 | + modeldb | ||
| 128 | store | 130 | store |
| 129 | cmd | 131 | cmd |
| 132 | + -Wl,--no-whole-archive | ||
| 133 | + dl | ||
| 134 | + rt | ||
| 135 | + SQLite::SQLite3 | ||
| 130 | JSON::JSON | 136 | JSON::JSON |
| 131 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.a | 137 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/lib64/libc_sec.a |
| 132 | ) | 138 | ) |
| 133 | 139 | ||
| 134 | install(TARGETS hccl_proxy_level2 | 140 | install(TARGETS hccl_proxy_level2 |
| 135 | - DESTINATION "." | 141 | + DESTINATION "lib/x86_64" |
| 136 | # 文件的权限 (755) | 142 | # 文件的权限 (755) |
| 137 | PERMISSIONS | 143 | PERMISSIONS |
| 138 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 144 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
Dtest/hccl_vm/src/proxy/README.md+0-17
| @@ -1,17 +0,0 @@ | |||
| 1 | -# 编译 hccl_proxy | ||
| 2 | - | ||
| 3 | -1. 安装CANN包 | ||
| 4 | - | ||
| 5 | - ```bash | ||
| 6 | - # install-path参数写自己期望的安装路径 | ||
| 7 | - ./Ascend-cann-toolkit_8.5.0_linux-x86_64.run --full --install-path=/home/l30069909/Ascend | ||
| 8 | - ``` | ||
| 9 | - | ||
| 10 | -2. 在海思极速空间代码根目录`work_code`下拉HCCL_Checker_L2代码 | ||
| 11 | -3. 将 `hccl_vm/hccl_proxy/CMakeLists.txt` 中的 `ASCEND_CANN_PACKAGE_PATH` 参数修改为自己本机CANN包的安装路径 | ||
| 12 | -4. 进入hccl_vm目录 `cd .../work_code/HCCL_Checker_L2/hccl_vm`, 执行以下命令 | ||
| 13 | - | ||
| 14 | - ```bash | ||
| 15 | - cmake -S . -B build | ||
| 16 | - cmake --build build --target hccl_proxy | ||
| 17 | - ``` | ||
| @@ -34,7 +34,7 @@ aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId) | |||
| 34 | return d.logic_id == (uint32_t)deviceId; | 34 | return d.logic_id == (uint32_t)deviceId; |
| 35 | }); | 35 | }); |
| 36 | if (!ret.second) { | 36 | if (!ret.second) { |
| 37 | - HCCL_VM_ERROR("[{}] cannot find device: {:d}", __func__, deviceId); | 37 | + HCCL_VM_ERROR("cannot find device: {:d}", deviceId); |
| 38 | return HcclResult::HCCL_E_NOT_FOUND; | 38 | return HcclResult::HCCL_E_NOT_FOUND; |
| 39 | } | 39 | } |
| 40 | // 找不到context,则默认新增一个context | 40 | // 找不到context,则默认新增一个context |
| @@ -61,7 +61,7 @@ aclError aclrtDestroyContext(aclrtContext context) | |||
| 61 | return stm.ctx_id == ctxId && stm.is_primary_default == 1; | 61 | return stm.ctx_id == ctxId && stm.is_primary_default == 1; |
| 62 | }); | 62 | }); |
| 63 | if (!ret.second) { | 63 | if (!ret.second) { |
| 64 | - HCCL_VM_ERROR("[{}] cannot find stream by ctx: {:d}", __func__, ctxId); | 64 | + HCCL_VM_ERROR("cannot find stream by ctx: {:d}", ctxId); |
| 65 | return HcclResult::HCCL_E_NOT_FOUND; | 65 | return HcclResult::HCCL_E_NOT_FOUND; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| @@ -98,7 +98,7 @@ aclError aclrtCtxGetCurrentDefaultStream(aclrtStream *stream) | |||
| 98 | return stm.ctx_id == curCtxId && stm.is_primary_default == 1; | 98 | return stm.ctx_id == curCtxId && stm.is_primary_default == 1; |
| 99 | }); | 99 | }); |
| 100 | if (!stm.second) { | 100 | if (!stm.second) { |
| 101 | - HCCL_VM_ERROR("[{}] cannot find stream by ctx: {:d}", __func__, curCtxId); | 101 | + HCCL_VM_ERROR("cannot find stream by ctx: {:d}", curCtxId); |
| 102 | return HcclResult::HCCL_E_NOT_FOUND; | 102 | return HcclResult::HCCL_E_NOT_FOUND; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| @@ -117,7 +117,7 @@ aclError aclrtGetPrimaryCtxState(int32_t deviceId, uint32_t *flags, int32_t *act | |||
| 117 | auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id); | 117 | auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id); |
| 118 | if (!currCtx.has_value()) { | 118 | if (!currCtx.has_value()) { |
| 119 | // not find | 119 | // not find |
| 120 | - HCCL_VM_ERROR("[{}] can not get currContext: {:d}", __func__, runner.current_ctx_id); | 120 | + HCCL_VM_ERROR("can not get currContext: {:d}", runner.current_ctx_id); |
| 121 | return ACL_ERROR_INVALID_PARAM; | 121 | return ACL_ERROR_INVALID_PARAM; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| @@ -67,21 +67,35 @@ aclError aclrtSetDevice(int32_t deviceId) | |||
| 67 | try { | 67 | try { |
| 68 | HCCL_VM_DEBUG("[aclrtSetDevice] start set device {:d}", deviceId); | 68 | HCCL_VM_DEBUG("[aclrtSetDevice] start set device {:d}", deviceId); |
| 69 | uint32_t rankId; | 69 | uint32_t rankId; |
| 70 | - if (!sim::GetRankIdByMPI(rankId)) { | 70 | + uint64_t serverId = 0; |
| 71 | - HCCL_VM_ERROR("[aclrtSetDevice] cannot get rank id by MPI."); | 71 | + if (!sim::GetRankIdByMPI(rankId, serverId)) { |
| 72 | + HCCL_VM_ERROR("[aclrtSetDevice] cannot get rank id by MPI, serverId is {:d}", serverId); | ||
| 72 | return ACL_ERROR_INVALID_PARAM; | 73 | return ACL_ERROR_INVALID_PARAM; |
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | sim::Device device{}; | 76 | sim::Device device{}; |
| 76 | - auto devRet = sim::GetDeviceByRankId(rankId, device); | 77 | + if (serverId == 0) { |
| 77 | - if (devRet != ACL_SUCCESS) { | 78 | + auto devRet = sim::GetDeviceByRankId(rankId, device); |
| 78 | - HCCL_VM_ERROR("[aclrtSetDevice] cannot find device by rank id {:d}", rankId); | 79 | + if (devRet != ACL_SUCCESS) { |
| 79 | - return devRet; | 80 | + HCCL_VM_ERROR("[aclrtSetDevice] cannot find device by rank id {:d}", rankId); |
| 81 | + return devRet; | ||
| 82 | + } | ||
| 83 | + serverId = device.server_id; | ||
| 84 | + HCCL_VM_DEBUG("[aclrtSetDevice] device logic id: {:d}, rank id: {:d}, device key: {:d}", device.logic_id, rankId, device.id); | ||
| 85 | + } else { | ||
| 86 | + auto ret = RunnerDB::GetOneByPred<sim::Device>([serverId, deviceId](const sim::Device &d) { | ||
| 87 | + return d.server_id == serverId && d.logic_id == (uint32_t)deviceId; | ||
| 88 | + }); | ||
| 89 | + if (!ret.second) { | ||
| 90 | + HCCL_VM_ERROR("[aclrtSetDevice] cannot find device by logic id {:d} in server id {:d}", deviceId, serverId); | ||
| 91 | + return ACL_ERROR_INVALID_PARAM; | ||
| 92 | + } | ||
| 93 | + device = ret.first; | ||
| 94 | + HCCL_VM_DEBUG("[aclrtSetDevice] device logic id: {:d}, server id: {:d}, device key: {:d}", device.logic_id, serverId, device.id); | ||
| 80 | } | 95 | } |
| 81 | - HCCL_VM_DEBUG("[aclrtSetDevice] device logic id: {:d}, rank id: {:d}, device key: {:d}", device.logic_id, rankId, device.id); | ||
| 82 | 96 | ||
| 83 | sim::Runner runner{}; | 97 | sim::Runner runner{}; |
| 84 | - if (!sim::GetCurrRunnerTls(device.server_id, runner)) { | 98 | + if (!sim::GetCurrRunnerTls(serverId, runner)) { |
| 85 | return ACL_ERROR_INVALID_PARAM; | 99 | return ACL_ERROR_INVALID_PARAM; |
| 86 | } | 100 | } |
| 87 | auto curRunnerId = runner.id; | 101 | auto curRunnerId = runner.id; |
| @@ -327,30 +341,12 @@ aclError aclrtQueryDeviceStatus(int32_t deviceId, aclrtDeviceStatus *deviceStatu | |||
| 327 | const char *aclrtGetSocName() | 341 | const char *aclrtGetSocName() |
| 328 | { | 342 | { |
| 329 | try { | 343 | try { |
| 330 | - sim::Runner runner{}; | 344 | + // GetSocName接口根据获取server内任意一个device的soc_version |
| 331 | - if (!sim::GetCurrRunnerTls(0, runner)) { | 345 | + auto devRes = RunnerDB::GetOneByPred<sim::Device>([](const sim::Device& d) { |
| 332 | - return "invalid param"; | 346 | + return d.server_id == 1; |
| 333 | - } | ||
| 334 | - auto hostId = runner.host_id; | ||
| 335 | - if (hostId == 0) { | ||
| 336 | - HCCL_VM_ERROR("[aclrtGetSocName] wrong host id: {:d}", hostId); | ||
| 337 | - return "invalid param"; | ||
| 338 | - } | ||
| 339 | - | ||
| 340 | - auto host = RunnerDB::GetOneByPred<sim::Host>([hostId](const sim::Host& h) { | ||
| 341 | - return h.id == hostId; | ||
| 342 | - }); | ||
| 343 | - if (!host.second) { | ||
| 344 | - HCCL_VM_ERROR("[aclrtResetDevice] can not find host by key {:d}", hostId); | ||
| 345 | - return ""; | ||
| 346 | - } | ||
| 347 | - | ||
| 348 | - auto serverId = host.first.server_id; | ||
| 349 | - auto devRes = RunnerDB::GetOneByPred<sim::Device>([serverId](const sim::Device& d) { | ||
| 350 | - return d.server_id == serverId; | ||
| 351 | }); | 347 | }); |
| 352 | if (!devRes.second) { | 348 | if (!devRes.second) { |
| 353 | - HCCL_VM_ERROR("[aclrtResetDevice] can not find device by server id {:d}", serverId); | 349 | + HCCL_VM_ERROR("[aclrtGetSocName] can not find device by server id 1"); |
| 354 | return ""; | 350 | return ""; |
| 355 | } | 351 | } |
| 356 | 352 | ||
| @@ -706,7 +702,7 @@ aclError aclrtDevicePeerAccessStatus(int32_t deviceId, int32_t peerDeviceId, int | |||
| 706 | aclError aclInit(const char *configPath) | 702 | aclError aclInit(const char *configPath) |
| 707 | { | 703 | { |
| 708 | (void) configPath; | 704 | (void) configPath; |
| 709 | - HCCL_VM_DEBUG("[{0}] Success", __func__); | 705 | + HCCL_VM_DEBUG("aclInit Success"); |
| 710 | return ACL_SUCCESS; | 706 | return ACL_SUCCESS; |
| 711 | } | 707 | } |
| 712 | 708 | ||
| @@ -715,7 +711,7 @@ aclError aclFinalize() | |||
| 715 | if (g_devicePid != 0) { | 711 | if (g_devicePid != 0) { |
| 716 | kill(g_devicePid, SIGKILL); | 712 | kill(g_devicePid, SIGKILL); |
| 717 | } | 713 | } |
| 718 | - HCCL_VM_DEBUG("[{0}] Success", __func__); | 714 | + HCCL_VM_DEBUG("aclFinalize Success"); |
| 719 | return ACL_SUCCESS; | 715 | return ACL_SUCCESS; |
| 720 | } | 716 | } |
| 721 | 717 | ||
| @@ -34,7 +34,7 @@ aclError aclrtCreateEventWithFlag(aclrtEvent *event, uint32_t flag) | |||
| 34 | auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id); | 34 | auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id); |
| 35 | if (!currCtx.has_value()) { | 35 | if (!currCtx.has_value()) { |
| 36 | // not find | 36 | // not find |
| 37 | - HCCL_VM_ERROR("[{}] can not get CurrContext:{:d}", __func__, runner.current_ctx_id); | 37 | + HCCL_VM_ERROR("can not get CurrContext:{:d}", runner.current_ctx_id); |
| 38 | return ACL_ERROR_INVALID_PARAM; | 38 | return ACL_ERROR_INVALID_PARAM; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| @@ -51,7 +51,7 @@ aclError aclrtCreateEventWithFlag(aclrtEvent *event, uint32_t flag) | |||
| 51 | auto res = RunnerDB::Add<sim::Event>(tmp); | 51 | auto res = RunnerDB::Add<sim::Event>(tmp); |
| 52 | 52 | ||
| 53 | *event = (aclrtEvent)res; | 53 | *event = (aclrtEvent)res; |
| 54 | - HCCL_VM_INFO("[{}] event: {:d}", __func__, res); | 54 | + HCCL_VM_INFO("event: {:d}", res); |
| 55 | return ACL_SUCCESS; | 55 | return ACL_SUCCESS; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| @@ -68,7 +68,7 @@ aclError aclrtCreateEvent(aclrtEvent *event) | |||
| 68 | aclError aclrtDestroyEvent(aclrtEvent event) | 68 | aclError aclrtDestroyEvent(aclrtEvent event) |
| 69 | { | 69 | { |
| 70 | uint64_t eventId = (uint32_t)(uintptr_t)event; | 70 | uint64_t eventId = (uint32_t)(uintptr_t)event; |
| 71 | - HCCL_VM_INFO("[{}] event: {:d}", __func__, eventId); | 71 | + HCCL_VM_INFO("event: {:d}", eventId); |
| 72 | RunnerDB::Delete<sim::Event>(eventId); | 72 | RunnerDB::Delete<sim::Event>(eventId); |
| 73 | return ACL_SUCCESS; | 73 | return ACL_SUCCESS; |
| 74 | } | 74 | } |
| @@ -81,14 +81,14 @@ aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stream) | |||
| 81 | auto currEvent = RunnerDB::GetById<sim::Event>(eventIdx); | 81 | auto currEvent = RunnerDB::GetById<sim::Event>(eventIdx); |
| 82 | if (!currEvent.has_value()) { | 82 | if (!currEvent.has_value()) { |
| 83 | // not find | 83 | // not find |
| 84 | - HCCL_VM_ERROR("[{}] can not get Event: {:d}", __func__, eventIdx); | 84 | + HCCL_VM_ERROR("can not get Event: {:d}", eventIdx); |
| 85 | return ACL_ERROR_INVALID_PARAM; | 85 | return ACL_ERROR_INVALID_PARAM; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | auto currStm = RunnerDB::GetById<sim::Stream>(streamIdx); | 88 | auto currStm = RunnerDB::GetById<sim::Stream>(streamIdx); |
| 89 | if (!currStm.has_value()) { | 89 | if (!currStm.has_value()) { |
| 90 | // not find | 90 | // not find |
| 91 | - HCCL_VM_ERROR("[{}] can not get stream:{:d}", __func__, streamIdx); | 91 | + HCCL_VM_ERROR("can not get stream:{:d}", streamIdx); |
| 92 | return ACL_ERROR_INVALID_PARAM; | 92 | return ACL_ERROR_INVALID_PARAM; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| @@ -104,7 +104,7 @@ aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream) | |||
| 104 | uint64_t eventIdx = (uint32_t)(uintptr_t)event; | 104 | uint64_t eventIdx = (uint32_t)(uintptr_t)event; |
| 105 | auto currEvent = RunnerDB::GetById<sim::Event>(eventIdx); | 105 | auto currEvent = RunnerDB::GetById<sim::Event>(eventIdx); |
| 106 | if (!currEvent.has_value()) { | 106 | if (!currEvent.has_value()) { |
| 107 | - HCCL_VM_ERROR("[{}] can not get Event:{:d}", __func__, eventIdx); | 107 | + HCCL_VM_ERROR("can not get Event:{:d}", eventIdx); |
| 108 | return ACL_ERROR_INVALID_PARAM; | 108 | return ACL_ERROR_INVALID_PARAM; |
| 109 | } | 109 | } |
| 110 | RunnerDB::Update<sim::Event>(eventIdx, [](sim::Event &evt) { evt.status = ACL_EVENT_RECORDED_STATUS_COMPLETE;}); | 110 | RunnerDB::Update<sim::Event>(eventIdx, [](sim::Event &evt) { evt.status = ACL_EVENT_RECORDED_STATUS_COMPLETE;}); |
| @@ -116,7 +116,7 @@ aclError aclrtQueryEventStatus(aclrtEvent event, aclrtEventRecordedStatus *statu | |||
| 116 | uint64_t eventId = (uint32_t)(uintptr_t)event; | 116 | uint64_t eventId = (uint32_t)(uintptr_t)event; |
| 117 | auto res = RunnerDB::GetById<sim::Event>(eventId); | 117 | auto res = RunnerDB::GetById<sim::Event>(eventId); |
| 118 | if (!res.has_value()) { | 118 | if (!res.has_value()) { |
| 119 | - HCCL_VM_ERROR("[{}] can not get event:{:d}", __func__, eventId); | 119 | + HCCL_VM_ERROR("can not get event:{:d}", eventId); |
| 120 | return ACL_ERROR_INVALID_PARAM; | 120 | return ACL_ERROR_INVALID_PARAM; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| @@ -191,7 +191,7 @@ aclError aclrtGetEventAvailNum(uint32_t *eventCount) | |||
| 191 | auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id); | 191 | auto currCtx = RunnerDB::GetById<sim::Context>(runner.current_ctx_id); |
| 192 | if (!currCtx.has_value()) { | 192 | if (!currCtx.has_value()) { |
| 193 | // not find | 193 | // not find |
| 194 | - HCCL_VM_ERROR("[{}] can not get CurrContext:{:d}", __func__, runner.current_ctx_id); | 194 | + HCCL_VM_ERROR("can not get CurrContext:{:d}", runner.current_ctx_id); |
| 195 | return ACL_ERROR_INVALID_PARAM; | 195 | return ACL_ERROR_INVALID_PARAM; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| @@ -199,7 +199,7 @@ aclError aclrtGetEventAvailNum(uint32_t *eventCount) | |||
| 199 | 199 | ||
| 200 | auto device = RunnerDB::GetById<sim::Device>(devId); | 200 | auto device = RunnerDB::GetById<sim::Device>(devId); |
| 201 | if (!device.has_value()) { | 201 | if (!device.has_value()) { |
| 202 | - HCCL_VM_ERROR("[{}] can not get device:{:d}", __func__, devId); | 202 | + HCCL_VM_ERROR("can not get device:{:d}", devId); |
| 203 | return ACL_ERROR_INVALID_PARAM; | 203 | return ACL_ERROR_INVALID_PARAM; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| @@ -28,42 +28,56 @@ extern "C" { | |||
| 28 | aclError aclrtSetExceptionInfoCallback(aclrtExceptionInfoCallback callback) | 28 | aclError aclrtSetExceptionInfoCallback(aclrtExceptionInfoCallback callback) |
| 29 | { | 29 | { |
| 30 | (void) callback; | 30 | (void) callback; |
| 31 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 31 | + HCCL_VM_TRACE("not supported"); |
| 32 | - return ACL_SUCCESS; | ||
| 33 | -} | ||
| 34 | - | ||
| 35 | -uint32_t aclrtGetErrorCodeFromExceptionInfo(const aclrtExceptionInfo *info) | ||
| 36 | -{ | ||
| 37 | - (void) info; | ||
| 38 | - HCCL_VM_TRACE("[{}] not supported", __func__); | ||
| 39 | - return ACL_SUCCESS; | ||
| 40 | -} | ||
| 41 | - | ||
| 42 | -aclError aclrtPeekAtLastError(aclrtLastErrLevel level) | ||
| 43 | -{ | ||
| 44 | - (void) level; | ||
| 45 | - HCCL_VM_TRACE("[{}] not supported", __func__); | ||
| 46 | return ACL_SUCCESS; | 32 | return ACL_SUCCESS; |
| 47 | } | 33 | } |
| 48 | 34 | ||
| 49 | uint32_t aclrtGetTaskIdFromExceptionInfo(const aclrtExceptionInfo *info) | 35 | uint32_t aclrtGetTaskIdFromExceptionInfo(const aclrtExceptionInfo *info) |
| 50 | { | 36 | { |
| 51 | (void) info; | 37 | (void) info; |
| 52 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 38 | + HCCL_VM_TRACE("not supported"); |
| 53 | return ACL_SUCCESS; | 39 | return ACL_SUCCESS; |
| 54 | } | 40 | } |
| 55 | 41 | ||
| 56 | -aclError aclrtGetLastError(aclrtLastErrLevel level) | 42 | +uint32_t aclrtGetStreamIdFromExceptionInfo(const aclrtExceptionInfo *info) |
| 57 | { | 43 | { |
| 58 | - (void) level; | 44 | + (void) info; |
| 59 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 45 | + HCCL_VM_TRACE("not supported"); |
| 60 | return ACL_SUCCESS; | 46 | return ACL_SUCCESS; |
| 61 | } | 47 | } |
| 62 | 48 | ||
| 63 | uint32_t aclrtGetThreadIdFromExceptionInfo(const aclrtExceptionInfo *info) | 49 | uint32_t aclrtGetThreadIdFromExceptionInfo(const aclrtExceptionInfo *info) |
| 64 | { | 50 | { |
| 65 | (void) info; | 51 | (void) info; |
| 66 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 52 | + HCCL_VM_TRACE("not supported"); |
| 53 | + return ACL_SUCCESS; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +uint32_t aclrtGetDeviceIdFromExceptionInfo(const aclrtExceptionInfo *info) | ||
| 57 | +{ | ||
| 58 | + (void) info; | ||
| 59 | + HCCL_VM_TRACE("not supported"); | ||
| 60 | + return ACL_SUCCESS; | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +uint32_t aclrtGetErrorCodeFromExceptionInfo(const aclrtExceptionInfo *info) | ||
| 64 | +{ | ||
| 65 | + (void) info; | ||
| 66 | + HCCL_VM_TRACE("not supported"); | ||
| 67 | + return ACL_SUCCESS; | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +aclError aclrtPeekAtLastError(aclrtLastErrLevel level) | ||
| 71 | +{ | ||
| 72 | + (void) level; | ||
| 73 | + HCCL_VM_TRACE("not supported"); | ||
| 74 | + return ACL_SUCCESS; | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +aclError aclrtGetLastError(aclrtLastErrLevel level) | ||
| 78 | +{ | ||
| 79 | + (void) level; | ||
| 80 | + HCCL_VM_TRACE("not supported"); | ||
| 67 | return ACL_SUCCESS; | 81 | return ACL_SUCCESS; |
| 68 | } | 82 | } |
| 69 | 83 | ||
| @@ -73,14 +87,7 @@ aclError aclrtGetMemUceInfo(int32_t deviceId, aclrtMemUceInfo *memUceInfoArray, | |||
| 73 | (void) memUceInfoArray; | 87 | (void) memUceInfoArray; |
| 74 | (void) arraySize; | 88 | (void) arraySize; |
| 75 | (void) retSize; | 89 | (void) retSize; |
| 76 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 90 | + HCCL_VM_TRACE("not supported"); |
| 77 | - return ACL_SUCCESS; | ||
| 78 | -} | ||
| 79 | - | ||
| 80 | -uint32_t aclrtGetDeviceIdFromExceptionInfo(const aclrtExceptionInfo *info) | ||
| 81 | -{ | ||
| 82 | - (void) info; | ||
| 83 | - HCCL_VM_TRACE("[{}] not supported", __func__); | ||
| 84 | return ACL_SUCCESS; | 91 | return ACL_SUCCESS; |
| 85 | } | 92 | } |
| 86 | 93 | ||
| @@ -89,14 +96,7 @@ aclError aclrtMemUceRepair(int32_t deviceId, aclrtMemUceInfo *memUceInfoArray, s | |||
| 89 | (void) deviceId; | 96 | (void) deviceId; |
| 90 | (void) memUceInfoArray; | 97 | (void) memUceInfoArray; |
| 91 | (void) arraySize; | 98 | (void) arraySize; |
| 92 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 99 | + HCCL_VM_TRACE("not supported"); |
| 93 | - return ACL_SUCCESS; | ||
| 94 | -} | ||
| 95 | - | ||
| 96 | -uint32_t aclrtGetStreamIdFromExceptionInfo(const aclrtExceptionInfo *info) | ||
| 97 | -{ | ||
| 98 | - (void) info; | ||
| 99 | - HCCL_VM_TRACE("[{}] not supported", __func__); | ||
| 100 | return ACL_SUCCESS; | 100 | return ACL_SUCCESS; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| @@ -104,14 +104,14 @@ aclError aclrtDeviceTaskAbort(int32_t deviceId, uint32_t timeout) | |||
| 104 | { | 104 | { |
| 105 | (void) deviceId; | 105 | (void) deviceId; |
| 106 | (void) timeout; | 106 | (void) timeout; |
| 107 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 107 | + HCCL_VM_TRACE("not supported"); |
| 108 | return ACL_SUCCESS; | 108 | return ACL_SUCCESS; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | aclError aclRecoverAllHcclTasks(int32_t deviceId) | 111 | aclError aclRecoverAllHcclTasks(int32_t deviceId) |
| 112 | { | 112 | { |
| 113 | (void) deviceId; | 113 | (void) deviceId; |
| 114 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 114 | + HCCL_VM_TRACE("not supported"); |
| 115 | return ACL_SUCCESS; | 115 | return ACL_SUCCESS; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| @@ -119,7 +119,7 @@ aclError aclrtGetErrorVerbose(int32_t deviceId, aclrtErrorInfo *errorInfo) | |||
| 119 | { | 119 | { |
| 120 | (void) deviceId; | 120 | (void) deviceId; |
| 121 | (void) errorInfo; | 121 | (void) errorInfo; |
| 122 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 122 | + HCCL_VM_TRACE("not supported"); |
| 123 | return ACL_SUCCESS; | 123 | return ACL_SUCCESS; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| @@ -127,7 +127,7 @@ aclError aclrtRepairError(int32_t deviceId, const aclrtErrorInfo *errorInfo) | |||
| 127 | { | 127 | { |
| 128 | (void) deviceId; | 128 | (void) deviceId; |
| 129 | (void) errorInfo; | 129 | (void) errorInfo; |
| 130 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 130 | + HCCL_VM_TRACE("not supported"); |
| 131 | return ACL_SUCCESS; | 131 | return ACL_SUCCESS; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| @@ -31,7 +31,7 @@ aclError aclrtLaunchCallback(aclrtCallback fn, void *userData, aclrtCallbackBloc | |||
| 31 | (void) userData; | 31 | (void) userData; |
| 32 | (void) blockType; | 32 | (void) blockType; |
| 33 | (void) stream; | 33 | (void) stream; |
| 34 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 34 | + HCCL_VM_TRACE("not supported"); |
| 35 | return ACL_SUCCESS; | 35 | return ACL_SUCCESS; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| @@ -39,14 +39,14 @@ aclError aclrtSubscribeReport(uint64_t threadId, aclrtStream stream) | |||
| 39 | { | 39 | { |
| 40 | (void) threadId; | 40 | (void) threadId; |
| 41 | (void) stream; | 41 | (void) stream; |
| 42 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 42 | + HCCL_VM_TRACE("not supported"); |
| 43 | return ACL_SUCCESS; | 43 | return ACL_SUCCESS; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | aclError aclrtProcessReport(int32_t timeout) | 46 | aclError aclrtProcessReport(int32_t timeout) |
| 47 | { | 47 | { |
| 48 | (void) timeout; | 48 | (void) timeout; |
| 49 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 49 | + HCCL_VM_TRACE("not supported"); |
| 50 | return ACL_SUCCESS; | 50 | return ACL_SUCCESS; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| @@ -54,7 +54,7 @@ aclError aclrtUnSubscribeReport(uint64_t threadId, aclrtStream stream) | |||
| 54 | { | 54 | { |
| 55 | (void) threadId; | 55 | (void) threadId; |
| 56 | (void) stream; | 56 | (void) stream; |
| 57 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 57 | + HCCL_VM_TRACE("not supported"); |
| 58 | return ACL_SUCCESS; | 58 | return ACL_SUCCESS; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| @@ -62,14 +62,14 @@ aclError aclrtSubscribeHostFunc(uint64_t hostFuncThreadId, aclrtStream exeStream | |||
| 62 | { | 62 | { |
| 63 | (void) hostFuncThreadId; | 63 | (void) hostFuncThreadId; |
| 64 | (void) exeStream; | 64 | (void) exeStream; |
| 65 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 65 | + HCCL_VM_TRACE("not supported"); |
| 66 | return ACL_SUCCESS; | 66 | return ACL_SUCCESS; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | aclError aclrtProcessHostFunc(int32_t timeout) | 69 | aclError aclrtProcessHostFunc(int32_t timeout) |
| 70 | { | 70 | { |
| 71 | (void) timeout; | 71 | (void) timeout; |
| 72 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 72 | + HCCL_VM_TRACE("not supported"); |
| 73 | return ACL_SUCCESS; | 73 | return ACL_SUCCESS; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| @@ -77,21 +77,21 @@ aclError aclrtUnSubscribeHostFunc(uint64_t hostFuncThreadId, aclrtStream exeStre | |||
| 77 | { | 77 | { |
| 78 | (void) hostFuncThreadId; | 78 | (void) hostFuncThreadId; |
| 79 | (void) exeStream; | 79 | (void) exeStream; |
| 80 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 80 | + HCCL_VM_TRACE("not supported"); |
| 81 | return ACL_SUCCESS; | 81 | return ACL_SUCCESS; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | aclError aclrtGetOpTimeoutInterval(uint64_t *interval) | 84 | aclError aclrtGetOpTimeoutInterval(uint64_t *interval) |
| 85 | { | 85 | { |
| 86 | (void) interval; | 86 | (void) interval; |
| 87 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 87 | + HCCL_VM_TRACE("not supported"); |
| 88 | return ACL_SUCCESS; | 88 | return ACL_SUCCESS; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | aclError aclrtSetOpExecuteTimeOut(uint32_t timeout) | 91 | aclError aclrtSetOpExecuteTimeOut(uint32_t timeout) |
| 92 | { | 92 | { |
| 93 | (void) timeout; | 93 | (void) timeout; |
| 94 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 94 | + HCCL_VM_TRACE("not supported"); |
| 95 | return ACL_SUCCESS; | 95 | return ACL_SUCCESS; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| @@ -99,21 +99,21 @@ aclError aclrtSetOpExecuteTimeOutV2(uint64_t timeout, uint64_t *actualTimeout) | |||
| 99 | { | 99 | { |
| 100 | (void) timeout; | 100 | (void) timeout; |
| 101 | (void) actualTimeout; | 101 | (void) actualTimeout; |
| 102 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 102 | + HCCL_VM_TRACE("not supported"); |
| 103 | return ACL_SUCCESS; | 103 | return ACL_SUCCESS; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | aclError aclrtSetOpExecuteTimeOutWithMs(uint32_t timeout) | 106 | aclError aclrtSetOpExecuteTimeOutWithMs(uint32_t timeout) |
| 107 | { | 107 | { |
| 108 | (void) timeout; | 108 | (void) timeout; |
| 109 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 109 | + HCCL_VM_TRACE("not supported"); |
| 110 | return ACL_SUCCESS; | 110 | return ACL_SUCCESS; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | aclError aclrtGetThreadLastTaskId(uint32_t *taskId) | 113 | aclError aclrtGetThreadLastTaskId(uint32_t *taskId) |
| 114 | { | 114 | { |
| 115 | (void) taskId; | 115 | (void) taskId; |
| 116 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 116 | + HCCL_VM_TRACE("not supported"); |
| 117 | return ACL_SUCCESS; | 117 | return ACL_SUCCESS; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| @@ -122,7 +122,7 @@ aclError aclrtLaunchHostFunc(aclrtStream stream, aclrtHostFunc fn, void *args) | |||
| 122 | (void) stream; | 122 | (void) stream; |
| 123 | (void) fn; | 123 | (void) fn; |
| 124 | (void) args; | 124 | (void) args; |
| 125 | - HCCL_VM_TRACE("[{}] not supported", __func__); | 125 | + HCCL_VM_TRACE("not supported"); |
| 126 | return ACL_SUCCESS; | 126 | return ACL_SUCCESS; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| @@ -7,7 +7,10 @@ | |||
| 7 | * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 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. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | - | 10 | +#include <errno.h> |
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 11 | 14 | ||
| 12 | 15 | ||
| 13 | 16 | ||
| @@ -36,6 +39,31 @@ struct ArgsBuffer { | |||
| 36 | 39 | ||
| 37 | pid_t g_devicePid = 0; | 40 | pid_t g_devicePid = 0; |
| 38 | 41 | ||
| 42 | +static bool CheckDeviceProcStatus() | ||
| 43 | +{ | ||
| 44 | + if (g_devicePid == 0) { | ||
| 45 | + return false; | ||
| 46 | + } | ||
| 47 | + int status = 0; | ||
| 48 | + pid_t result = waitpid(g_devicePid, &status, WNOHANG); | ||
| 49 | + if (result == 0) { | ||
| 50 | + return true; | ||
| 51 | + } | ||
| 52 | + if (result == g_devicePid) { | ||
| 53 | + if (WIFSIGNALED(status)) { | ||
| 54 | + HCCL_VM_ERROR("device process[{}] killed by signal {}", g_devicePid, WTERMSIG(status)); | ||
| 55 | + } else { | ||
| 56 | + HCCL_VM_ERROR("device process[{}] exited with status {}", g_devicePid, WEXITSTATUS(status)); | ||
| 57 | + } | ||
| 58 | + } else { | ||
| 59 | + HCCL_VM_ERROR("waitpid failed for pid {}, errno: {} ({})", g_devicePid, errno, strerror(errno)); | ||
| 60 | + } | ||
| 61 | + FlushLog(); | ||
| 62 | + exit(EXIT_FAILURE); | ||
| 63 | + g_devicePid = 0; | ||
| 64 | + return false; | ||
| 65 | +} | ||
| 66 | + | ||
| 39 | namespace sim { | 67 | namespace sim { |
| 40 | constexpr size_t MAX_ARGS_BUFF_SIZE = 64 * 1024U; | 68 | constexpr size_t MAX_ARGS_BUFF_SIZE = 64 * 1024U; |
| 41 | 69 | ||
| @@ -396,18 +424,23 @@ void ForkAndStartAicpuProcess(int32_t rankId, uint8_t* devState) | |||
| 396 | exit(EXIT_FAILURE); | 424 | exit(EXIT_FAILURE); |
| 397 | } | 425 | } |
| 398 | 426 | ||
| 427 | + const char* installDir = getenv("HCCL_VM_INSTALL_DIR"); | ||
| 428 | + std::string args = std::to_string(rankId); | ||
| 429 | + std::string devicePath = installDir ? std::string(installDir) + "/bin/device" : "./bin/device"; | ||
| 430 | + std::string libPath = installDir ? std::string(installDir) + "/lib/aarch64" : "./lib/aarch64"; | ||
| 431 | + std::string preloadPath = libPath + "/libhccl-device-proxy.so"; | ||
| 399 | if (pid == 0) { | 432 | if (pid == 0) { |
| 400 | - std::string args = std::to_string(rankId); | 433 | + g_logger = nullptr; |
| 401 | - HCCL_VM_INFO("rankId[{}] aicpu process start.", rankId); | ||
| 402 | setenv("QEMU_LD_PREFIX", "/usr/aarch64-linux-gnu", 1); | 434 | setenv("QEMU_LD_PREFIX", "/usr/aarch64-linux-gnu", 1); |
| 403 | - setenv("LD_PRELOAD", "./device/lib/libhccl-device-proxy.so", 1); | 435 | + setenv("LD_PRELOAD", preloadPath.c_str(), 1); |
| 404 | - setenv("LD_LIBRARY_PATH", "./device/lib64:./device/lib", 1); | 436 | + setenv("LD_LIBRARY_PATH", libPath.c_str(), 1); |
| 405 | - execlp("qemu-aarch64-static", "qemu-aarch64-static", "./device/bin/device", args.c_str(), nullptr); | 437 | + execlp("qemu-aarch64-static", "qemu-aarch64-static", devicePath.c_str(), args.c_str(), nullptr); |
| 406 | HCCL_VM_ERROR("[ForkAndStartAicpuProcess] execlp aicpu process failed."); | 438 | HCCL_VM_ERROR("[ForkAndStartAicpuProcess] execlp aicpu process failed."); |
| 407 | exit(EXIT_FAILURE); | 439 | exit(EXIT_FAILURE); |
| 408 | } else { | 440 | } else { |
| 409 | g_devicePid = pid; // 记录device进程id用于host结束时杀掉device进程 | 441 | g_devicePid = pid; // 记录device进程id用于host结束时杀掉device进程 |
| 410 | while (*devState == DEVICE_RUN) { | 442 | while (*devState == DEVICE_RUN) { |
| 443 | + CheckDeviceProcStatus(); | ||
| 411 | sleep(1); | 444 | sleep(1); |
| 412 | } | 445 | } |
| 413 | } | 446 | } |
| @@ -456,6 +489,7 @@ void LaunchAICPUKernelFunc(std::string kernelName, aclrtArgsHandle argsHandle) | |||
| 456 | std::atomic_thread_fence(std::memory_order_release); // 内存屏障强制内存操作的顺序性 | 489 | std::atomic_thread_fence(std::memory_order_release); // 内存屏障强制内存操作的顺序性 |
| 457 | aicpuData->task[rankId].devState = DEVICE_RUN; | 490 | aicpuData->task[rankId].devState = DEVICE_RUN; |
| 458 | while (aicpuData->task[rankId].devState == DEVICE_RUN) { | 491 | while (aicpuData->task[rankId].devState == DEVICE_RUN) { |
| 492 | + CheckDeviceProcStatus(); | ||
| 459 | sleep(1); | 493 | sleep(1); |
| 460 | } | 494 | } |
| 461 | } | 495 | } |
| @@ -20,14 +20,38 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | + | ||
| 23 | 24 | ||
| 25 | + | ||
| 26 | + | ||
| 24 | 27 | ||
| 25 | 28 | ||
| 26 | 29 | ||
| 30 | +// rank 进程加载本库时先于 main 预热仅校验模式缓存,使后续引流判定拿到确定值。 | ||
| 31 | +// 只读 DB、不打日志(此刻日志组件可能尚未初始化)。 | ||
| 27 | 32 | ||
| 28 | extern "C" { | 33 | extern "C" { |
| 29 | 34 | ||
| 30 | 35 | ||
| 36 | +// 主机侧大块复用区句柄(懒加载缓存,与设备侧共用同一块 HcclCommPool) | ||
| 37 | +static std::atomic<void*> g_commPoolBase{nullptr}; | ||
| 38 | + | ||
| 39 | +// 记下复用区在本进程的地址,首个大块申请时由 CAS 保证只有一个线程写入。 | ||
| 40 | +// 首次记录时多 acquire 一次复用区且进程内不释放,使复用区在进程退出前保持映射、地址不变, | ||
| 41 | +// 后续用地址判断一块内存是否在复用区时地址不会失效。 | ||
| 42 | +static void CacheCommPoolBase(void* base) | ||
| 43 | +{ | ||
| 44 | + if (base == nullptr) { | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + void* expected = nullptr; | ||
| 48 | + // 写入用 release、IsInCommPool 读取用 acquire 配对,保证其它线程读到的地址是有效的。 | ||
| 49 | + if (g_commPoolBase.compare_exchange_strong(expected, base, | ||
| 50 | + std::memory_order_release, std::memory_order_relaxed)) { | ||
| 51 | + sim::MemoryManager::GetInstance().AcquireMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 52 | + } | ||
| 53 | +} | ||
| 54 | + | ||
| 31 | std::string GenDevMemName(int deviceId) | 55 | std::string GenDevMemName(int deviceId) |
| 32 | { | 56 | { |
| 33 | std::ostringstream oss; | 57 | std::ostringstream oss; |
| @@ -101,10 +125,42 @@ void* GetRealPtrByAddr(const void* virPtr) | |||
| 101 | return hostPtr; | 125 | return hostPtr; |
| 102 | } | 126 | } |
| 103 | 127 | ||
| 128 | +// 判断一个真实内存地址是否落在复用区内,主机侧和设备侧共用。 | ||
| 129 | +// 设备侧传进来的是设备指针对应的真实地址(用 GetHostPtrByDevPtr 取得)。 | ||
| 130 | +// 地址在 [基址, 基址+kPoolSize) 范围内,说明这块内存是引流到复用区的大块。 | ||
| 131 | +static bool IsInCommPool(const void* ptr) | ||
| 132 | +{ | ||
| 133 | + void* base = g_commPoolBase.load(std::memory_order_acquire); | ||
| 134 | + return base != nullptr && | ||
| 135 | + ptr >= base && | ||
| 136 | + ptr < static_cast<char *>(base) + sim::CommPoolPolicy::kPoolSize; | ||
| 137 | +} | ||
| 138 | + | ||
| 104 | aclError aclrtMallocHost(void **hostPtr, size_t size) | 139 | aclError aclrtMallocHost(void **hostPtr, size_t size) |
| 105 | { | 140 | { |
| 106 | - *hostPtr = malloc(size); | 141 | + bool checkOnlyMode = sim::IsCheckOnlyMode(); |
| 107 | - HCCL_VM_INFO("[MEM] malloc host addr:{:p}, size:{:d}", *hostPtr, size); | 142 | + // 超过复用区上界直接报错,不回退真实分配。 |
| 143 | + if (sim::CommPoolPolicy::ExceedsCeiling(size, checkOnlyMode)) { | ||
| 144 | + HCCL_VM_ERROR("[MEM] malloc host size:{:d} exceeds pool ceiling, reject", size); | ||
| 145 | + return ACL_ERROR_INTERNAL_ERROR; | ||
| 146 | + } | ||
| 147 | + // 仅校验模式下大块引流到共享复用区 HcclCommPool | ||
| 148 | + if (sim::CommPoolPolicy::ShouldRedirect(size, checkOnlyMode)) { | ||
| 149 | + void* base = g_commPoolBase.load(std::memory_order_acquire); | ||
| 150 | + if (base == nullptr) { | ||
| 151 | + base = sim::MemoryManager::GetInstance().AcquireMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 152 | + if (base == nullptr) { | ||
| 153 | + HCCL_VM_ERROR("[MEM] malloc host acquire HcclCommPool failed, size:{:d}", size); | ||
| 154 | + return ACL_ERROR_INTERNAL_ERROR; | ||
| 155 | + } | ||
| 156 | + CacheCommPoolBase(base); | ||
| 157 | + } | ||
| 158 | + *hostPtr = base; | ||
| 159 | + HCCL_VM_INFO("[MEM] malloc host (SHM) addr:{:p}, size:{:d}", *hostPtr, size); | ||
| 160 | + } else { | ||
| 161 | + *hostPtr = malloc(size); | ||
| 162 | + HCCL_VM_INFO("[MEM] malloc host addr:{:p}, size:{:d}", *hostPtr, size); | ||
| 163 | + } | ||
| 108 | return ACL_SUCCESS; | 164 | return ACL_SUCCESS; |
| 109 | } | 165 | } |
| 110 | 166 | ||
| @@ -117,6 +173,11 @@ aclError aclrtMallocHostWithCfg(void **ptr, uint64_t size, aclrtMallocConfig *cf | |||
| 117 | aclError aclrtFreeHost(void *hostPtr) | 173 | aclError aclrtFreeHost(void *hostPtr) |
| 118 | { | 174 | { |
| 119 | HCCL_VM_INFO("[MEM] free host addr:{:p}", hostPtr); | 175 | HCCL_VM_INFO("[MEM] free host addr:{:p}", hostPtr); |
| 176 | + // 池内地址:空操作(复用区生命周期由主进程管理,不在此 free) | ||
| 177 | + if (IsInCommPool(hostPtr)) { | ||
| 178 | + HCCL_VM_INFO("[MEM] free host (SHM noop) addr:{:p}", hostPtr); | ||
| 179 | + return ACL_SUCCESS; | ||
| 180 | + } | ||
| 120 | free(hostPtr); | 181 | free(hostPtr); |
| 121 | return ACL_SUCCESS; | 182 | return ACL_SUCCESS; |
| 122 | } | 183 | } |
| @@ -156,6 +217,10 @@ aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy) | |||
| 156 | HCCL_VM_ERROR("can not alloc phy mem deviceId:{:d}, size:{:d}", deviceId, size); | 217 | HCCL_VM_ERROR("can not alloc phy mem deviceId:{:d}, size:{:d}", deviceId, size); |
| 157 | return ACL_ERROR_INTERNAL_ERROR; | 218 | return ACL_ERROR_INTERNAL_ERROR; |
| 158 | } | 219 | } |
| 220 | + // 大块引流到复用区时缓存池基址,供 IsInCommPool 判定(与主机侧共用同一基址)。 | ||
| 221 | + if (sim::CommPoolPolicy::ShouldRedirect(size, sim::IsCheckOnlyMode())) { | ||
| 222 | + CacheCommPoolBase(hostPtr); | ||
| 223 | + } | ||
| 159 | 224 | ||
| 160 | // 记录物理内存信息到数据库 | 225 | // 记录物理内存信息到数据库 |
| 161 | sim::PhyMemBlock phyMem{}; | 226 | sim::PhyMemBlock phyMem{}; |
| @@ -247,12 +312,20 @@ aclError aclrtFree(void* devPtr) | |||
| 247 | 312 | ||
| 248 | auto devPhyId = dev->physical_id; | 313 | auto devPhyId = dev->physical_id; |
| 249 | 314 | ||
| 315 | + // 先取这块内存的真实地址,判断它是否在复用区(必须在 Unmap 之前取)。 | ||
| 316 | + // 第二次释放时映射已删、取不到地址,就按非复用区处理,天然幂等。 | ||
| 317 | + void* backing = sim::DeviceMemoryManager::GetInstance().GetHostPtrByDevPtr(devPtr); | ||
| 318 | + | ||
| 250 | // 去缓存设备地址到host地址 | 319 | // 去缓存设备地址到host地址 |
| 251 | sim::DeviceMemoryManager::GetInstance().UnmapDevPtrHostPtr(devPtr); | 320 | sim::DeviceMemoryManager::GetInstance().UnmapDevPtrHostPtr(devPtr); |
| 252 | 321 | ||
| 253 | // 删除内存 | 322 | // 删除内存 |
| 254 | sim::DeviceMemoryManager::GetInstance().FreeVirMem(devPhyId, devPtr); | 323 | sim::DeviceMemoryManager::GetInstance().FreeVirMem(devPhyId, devPtr); |
| 255 | - sim::DeviceMemoryManager::GetInstance().FreePhyMem(phyMemRes->name, deviceId); | 324 | + if (IsInCommPool(backing)) { |
| 325 | + sim::MemoryManager::GetInstance().ReleaseMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 326 | + } else { | ||
| 327 | + sim::DeviceMemoryManager::GetInstance().FreePhyMem(phyMemRes->name, deviceId); | ||
| 328 | + } | ||
| 256 | 329 | ||
| 257 | // 更新数据库记录,标记为已释放 | 330 | // 更新数据库记录,标记为已释放 |
| 258 | RunnerDB::Update<sim::PhyMemBlock>(phyMemId, [](sim::PhyMemBlock &memBlock) { memBlock.is_freed = 1; }); | 331 | RunnerDB::Update<sim::PhyMemBlock>(phyMemId, [](sim::PhyMemBlock &memBlock) { memBlock.is_freed = 1; }); |
| @@ -278,8 +351,18 @@ aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t value, size_t count) | |||
| 278 | return ACL_ERROR_INTERNAL_ERROR; | 351 | return ACL_ERROR_INTERNAL_ERROR; |
| 279 | } | 352 | } |
| 280 | 353 | ||
| 281 | - memset(hostPtr + offset, value, count); | 354 | + // 目的设备块按 size 判是否在复用区,与申请一致,命中则跳过实际写入并按池释放。 |
| 282 | - sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(phyMem.name, phyMem.device_id); | 355 | + bool pooled = sim::CommPoolPolicy::ShouldRedirect(phyMem.size, sim::IsCheckOnlyMode()); |
| 356 | + if (pooled) { | ||
| 357 | + HCCL_VM_INFO("[MEM] memset skip (pool) ptr:{:p}, size:{:d}, count:{:d}", devPtr, phyMem.size, count); | ||
| 358 | + } else { | ||
| 359 | + memset(hostPtr + offset, value, count); | ||
| 360 | + } | ||
| 361 | + if (pooled) { | ||
| 362 | + sim::MemoryManager::GetInstance().ReleaseMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 363 | + } else { | ||
| 364 | + sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(phyMem.name, phyMem.device_id); | ||
| 365 | + } | ||
| 283 | HCCL_VM_INFO("[MEM] dev mem memset ptr:{:p}, memName:{}, count: {:d}", devPtr, phyMem.name, count); | 366 | HCCL_VM_INFO("[MEM] dev mem memset ptr:{:p}, memName:{}, count: {:d}", devPtr, phyMem.name, count); |
| 284 | return ACL_SUCCESS; | 367 | return ACL_SUCCESS; |
| 285 | } | 368 | } |
| @@ -316,7 +399,12 @@ aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, a | |||
| 316 | HCCL_VM_WARN("[aclrtMemcpy D2D] only support self D2D memcpy"); | 399 | HCCL_VM_WARN("[aclrtMemcpy D2D] only support self D2D memcpy"); |
| 317 | return ACL_ERROR_RT_FEATURE_NOT_SUPPORT; | 400 | return ACL_ERROR_RT_FEATURE_NOT_SUPPORT; |
| 318 | } | 401 | } |
| 319 | - memcpy(dstAddr, srcAddr, count); | 402 | + // 目的地址在复用区(dst 是引流过来的大块):跳过实际拷贝。 |
| 403 | + if (IsInCommPool(dstAddr)) { | ||
| 404 | + HCCL_VM_INFO("[MEM] memcpy D2D skip (dst big->pool) count:{:d}", count); | ||
| 405 | + } else { | ||
| 406 | + memcpy(dstAddr, srcAddr, count); | ||
| 407 | + } | ||
| 320 | return ACL_SUCCESS; | 408 | return ACL_SUCCESS; |
| 321 | } else { | 409 | } else { |
| 322 | HCCL_VM_INFO("src:{:p} to dst:{:p}, size:{:d} type: {:d} not support", src, dst, count, (int)kind); | 410 | HCCL_VM_INFO("src:{:p} to dst:{:p}, size:{:d} type: {:d} not support", src, dst, count, (int)kind); |
| @@ -337,13 +425,28 @@ aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, a | |||
| 337 | return ACL_ERROR_INTERNAL_ERROR; | 425 | return ACL_ERROR_INTERNAL_ERROR; |
| 338 | } | 426 | } |
| 339 | 427 | ||
| 428 | + // 目的设备块按 size 判是否在复用区,与申请一致,命中则跳过实际拷贝并按池释放。 | ||
| 429 | + // D2H 的目的是主机缓冲,仍按地址判断主机缓冲是否在复用区。 | ||
| 430 | + bool devPooled = sim::CommPoolPolicy::ShouldRedirect(phyMem.size, sim::IsCheckOnlyMode()); | ||
| 340 | if (kind == ACL_MEMCPY_HOST_TO_DEVICE) { | 431 | if (kind == ACL_MEMCPY_HOST_TO_DEVICE) { |
| 341 | - memcpy(hostDevPtr + offset, hostPtr, count); | 432 | + if (devPooled) { |
| 433 | + HCCL_VM_INFO("[MEM] memcpy H2D skip (dst big->pool) count:{:d}", count); | ||
| 434 | + } else { | ||
| 435 | + memcpy(hostDevPtr + offset, hostPtr, count); | ||
| 436 | + } | ||
| 342 | } else if (kind == ACL_MEMCPY_DEVICE_TO_HOST) { | 437 | } else if (kind == ACL_MEMCPY_DEVICE_TO_HOST) { |
| 343 | - memcpy(hostPtr, hostDevPtr + offset, count); | 438 | + if (IsInCommPool(hostPtr)) { |
| 439 | + HCCL_VM_INFO("[MEM] memcpy D2H skip (dst host pool) count:{:d}", count); | ||
| 440 | + } else { | ||
| 441 | + memcpy(hostPtr, hostDevPtr + offset, count); | ||
| 442 | + } | ||
| 344 | } | 443 | } |
| 345 | 444 | ||
| 346 | - sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(phyMem.name, phyMem.device_id); | 445 | + if (devPooled) { |
| 446 | + sim::MemoryManager::GetInstance().ReleaseMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 447 | + } else { | ||
| 448 | + sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(phyMem.name, phyMem.device_id); | ||
| 449 | + } | ||
| 347 | 450 | ||
| 348 | return ACL_SUCCESS; | 451 | return ACL_SUCCESS; |
| 349 | } | 452 | } |
| @@ -411,13 +514,28 @@ aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t cou | |||
| 411 | return ACL_ERROR_INTERNAL_ERROR; | 514 | return ACL_ERROR_INTERNAL_ERROR; |
| 412 | } | 515 | } |
| 413 | 516 | ||
| 517 | + // 目的设备块按 size 判是否在复用区,与申请一致,命中则跳过实际拷贝并按池释放。 | ||
| 518 | + // D2H 的目的是主机缓冲,仍按地址判断主机缓冲是否在复用区。 | ||
| 519 | + bool devPooled = sim::CommPoolPolicy::ShouldRedirect(phyMem.size, sim::IsCheckOnlyMode()); | ||
| 414 | if (kind == ACL_MEMCPY_HOST_TO_DEVICE) { | 520 | if (kind == ACL_MEMCPY_HOST_TO_DEVICE) { |
| 415 | - memcpy(hostDevPtr + offset, hostPtr, count); | 521 | + if (devPooled) { |
| 522 | + HCCL_VM_INFO("[MEM] memcpy H2D skip (dst big->pool) count:{:d}", count); | ||
| 523 | + } else { | ||
| 524 | + memcpy(hostDevPtr + offset, hostPtr, count); | ||
| 525 | + } | ||
| 416 | } else if (kind == ACL_MEMCPY_DEVICE_TO_HOST) { | 526 | } else if (kind == ACL_MEMCPY_DEVICE_TO_HOST) { |
| 417 | - memcpy(hostPtr, hostDevPtr + offset, count); | 527 | + if (IsInCommPool(hostPtr)) { |
| 528 | + HCCL_VM_INFO("[MEM] memcpy D2H skip (dst host pool) count:{:d}", count); | ||
| 529 | + } else { | ||
| 530 | + memcpy(hostPtr, hostDevPtr + offset, count); | ||
| 531 | + } | ||
| 418 | } | 532 | } |
| 419 | 533 | ||
| 420 | - sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(phyMem.name, phyMem.device_id); | 534 | + if (devPooled) { |
| 535 | + sim::MemoryManager::GetInstance().ReleaseMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 536 | + } else { | ||
| 537 | + sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(phyMem.name, phyMem.device_id); | ||
| 538 | + } | ||
| 421 | 539 | ||
| 422 | return ACL_SUCCESS; | 540 | return ACL_SUCCESS; |
| 423 | } | 541 | } |
| @@ -529,6 +647,10 @@ aclError aclrtMallocPhysical(aclrtDrvMemHandle *handle, size_t size, const aclrt | |||
| 529 | HCCL_VM_ERROR("can not alloc phy mem deviceId:{:d}, size:{:d}", deviceId, size); | 647 | HCCL_VM_ERROR("can not alloc phy mem deviceId:{:d}, size:{:d}", deviceId, size); |
| 530 | return ACL_ERROR_INTERNAL_ERROR; | 648 | return ACL_ERROR_INTERNAL_ERROR; |
| 531 | } | 649 | } |
| 650 | + // 大块物理内存同样引流到复用区,缓存池基址,使其被 map 后的 memcpy/memset 能按地址判定。 | ||
| 651 | + if (sim::CommPoolPolicy::ShouldRedirect(size, sim::IsCheckOnlyMode())) { | ||
| 652 | + CacheCommPoolBase(hostPtr); | ||
| 653 | + } | ||
| 532 | 654 | ||
| 533 | // 记录物理内存信息到数据库 | 655 | // 记录物理内存信息到数据库 |
| 534 | sim::PhyMemBlock phyMem{}; | 656 | sim::PhyMemBlock phyMem{}; |
| @@ -552,8 +674,12 @@ aclError aclrtFreePhysical(aclrtDrvMemHandle handle) | |||
| 552 | return ACL_ERROR_INTERNAL_ERROR; | 674 | return ACL_ERROR_INTERNAL_ERROR; |
| 553 | }; | 675 | }; |
| 554 | 676 | ||
| 555 | - // 删除内存 | 677 | + // 物理内存无 devPtr→host 映射,按 size 判定是否走了复用区(与申请同一判据) |
| 556 | - sim::DeviceMemoryManager::GetInstance().FreePhyMem(phyMemRes->name, phyMemRes->device_id); | 678 | + if (sim::CommPoolPolicy::ShouldRedirect(phyMemRes->size, sim::IsCheckOnlyMode())) { |
| 679 | + sim::MemoryManager::GetInstance().ReleaseMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 680 | + } else { | ||
| 681 | + sim::DeviceMemoryManager::GetInstance().FreePhyMem(phyMemRes->name, phyMemRes->device_id); | ||
| 682 | + } | ||
| 557 | // 删除数据库记录 | 683 | // 删除数据库记录 |
| 558 | RunnerDB::Delete<sim::PhyMemBlock>(phyMemId); | 684 | RunnerDB::Delete<sim::PhyMemBlock>(phyMemId); |
| 559 | HCCL_VM_INFO("free phy mem, id:{:d}", phyMemId); | 685 | HCCL_VM_INFO("free phy mem, id:{:d}", phyMemId); |
| @@ -1083,7 +1209,7 @@ aclError aclrtReduceAsync(void *dst, const void *src, uint64_t count, aclrtReduc | |||
| 1083 | HCCL_VM_DEBUG("[aclstub][aclrtReduceAsync] Get reduce task, streamId={:d}", streamId); | 1209 | HCCL_VM_DEBUG("[aclstub][aclrtReduceAsync] Get reduce task, streamId={:d}", streamId); |
| 1084 | auto ret = InsertTaskToCollection(&taskMetaData, &index); | 1210 | auto ret = InsertTaskToCollection(&taskMetaData, &index); |
| 1085 | if (ret != HcclSim::HcclVmResult::HCCL_SIM_SUCCESS) { | 1211 | if (ret != HcclSim::HcclVmResult::HCCL_SIM_SUCCESS) { |
| 1086 | - HCCL_VM_ERROR("[{}] InsertTaskToCollection fail", __func__); | 1212 | + HCCL_VM_ERROR("[aclstub] InsertTaskToCollection fail"); |
| 1087 | return ACL_ERROR_INTERNAL_ERROR; | 1213 | return ACL_ERROR_INTERNAL_ERROR; |
| 1088 | } | 1214 | } |
| 1089 | 1215 | ||
| @@ -37,16 +37,16 @@ HcclResult hrtGetDeviceType(DevType &devType) | |||
| 37 | auto device = RunnerDB::GetById<sim::Device>(devKey); | 37 | auto device = RunnerDB::GetById<sim::Device>(devKey); |
| 38 | if (!device.has_value()) { | 38 | if (!device.has_value()) { |
| 39 | // not find | 39 | // not find |
| 40 | - HCCL_VM_ERROR("[{}] can not get current device type: {:d}", __func__, devKey); | 40 | + HCCL_VM_ERROR("[aclstub] can not get current device type: {:d}", devKey); |
| 41 | return HCCL_E_NOT_FOUND; | 41 | return HCCL_E_NOT_FOUND; |
| 42 | } | 42 | } |
| 43 | if (strcmp(device->soc_version, "Ascend950") == 0) { | 43 | if (strcmp(device->soc_version, "Ascend950") == 0) { |
| 44 | devType = DevType::DEV_TYPE_950; | 44 | devType = DevType::DEV_TYPE_950; |
| 45 | } else { | 45 | } else { |
| 46 | - HCCL_VM_ERROR("[{}] not support device soc version: {:s}", __func__, device->soc_version); | 46 | + HCCL_VM_ERROR("[aclstub] not support device soc version: {:s}", device->soc_version); |
| 47 | return HCCL_E_NOT_SUPPORT; | 47 | return HCCL_E_NOT_SUPPORT; |
| 48 | } | 48 | } |
| 49 | - HCCL_VM_TRACE("[{}] Get current device type: {}", __func__, static_cast<int>(devType)); | 49 | + HCCL_VM_TRACE("[aclstub] Get current device type: {}", static_cast<int>(devType)); |
| 50 | return HCCL_SUCCESS; | 50 | return HCCL_SUCCESS; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| @@ -119,7 +119,7 @@ aclError aclrtRecordNotify(aclrtNotify notify, aclrtStream stream) | |||
| 119 | HCCL_VM_DEBUG("[aclstub][aclrtRecordNotify] Get notify task, id={:d}, streamId={:d}", notifyId, streamId); | 119 | HCCL_VM_DEBUG("[aclstub][aclrtRecordNotify] Get notify task, id={:d}, streamId={:d}", notifyId, streamId); |
| 120 | auto ret = InsertTaskToCollection(&taskMetaData, &index); | 120 | auto ret = InsertTaskToCollection(&taskMetaData, &index); |
| 121 | if (ret != HcclSim::HcclVmResult::HCCL_SIM_SUCCESS) { | 121 | if (ret != HcclSim::HcclVmResult::HCCL_SIM_SUCCESS) { |
| 122 | - HCCL_VM_ERROR("[{}] InsertTaskToCollection fail", __func__); | 122 | + HCCL_VM_ERROR("[aclstub] InsertTaskToCollection fail"); |
| 123 | return ACL_ERROR_INTERNAL_ERROR; | 123 | return ACL_ERROR_INTERNAL_ERROR; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| @@ -156,7 +156,7 @@ aclError aclrtWaitAndResetNotify(aclrtNotify notify, aclrtStream stream, uint32_ | |||
| 156 | HCCL_VM_DEBUG("[aclstub][aclrtWaitAndResetNotify] Get notify task, id={:d}, streamId={:d}", notifyId, streamId); | 156 | HCCL_VM_DEBUG("[aclstub][aclrtWaitAndResetNotify] Get notify task, id={:d}, streamId={:d}", notifyId, streamId); |
| 157 | auto ret = InsertTaskToCollection(&taskMetaData, &index); | 157 | auto ret = InsertTaskToCollection(&taskMetaData, &index); |
| 158 | if (ret != HcclSim::HcclVmResult::HCCL_SIM_SUCCESS) { | 158 | if (ret != HcclSim::HcclVmResult::HCCL_SIM_SUCCESS) { |
| 159 | - HCCL_VM_ERROR("[{}] InsertTaskToCollection fail", __func__); | 159 | + HCCL_VM_ERROR("[aclstub] InsertTaskToCollection fail"); |
| 160 | return ACL_ERROR_INTERNAL_ERROR; | 160 | return ACL_ERROR_INTERNAL_ERROR; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| @@ -31,7 +31,7 @@ aclError aclrtSetSysParamOpt(aclSysParamOpt opt, int64_t value) | |||
| 31 | { | 31 | { |
| 32 | (void) opt; | 32 | (void) opt; |
| 33 | (void) value; | 33 | (void) value; |
| 34 | - HCCL_VM_WARN("[{}] not support", __func__); | 34 | + HCCL_VM_WARN("[aclstub] not support"); |
| 35 | return ACL_SUCCESS; | 35 | return ACL_SUCCESS; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| @@ -39,7 +39,7 @@ aclError aclrtGetSysParamOpt(aclSysParamOpt opt, int64_t *value) | |||
| 39 | { | 39 | { |
| 40 | (void) opt; | 40 | (void) opt; |
| 41 | (void) value; | 41 | (void) value; |
| 42 | - HCCL_VM_WARN("[{}] not support", __func__); | 42 | + HCCL_VM_WARN("[aclstub] not support"); |
| 43 | return ACL_SUCCESS; | 43 | return ACL_SUCCESS; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| @@ -48,7 +48,7 @@ aclError aclrtGetDeviceResLimit(int32_t deviceId, aclrtDevResLimitType type, uin | |||
| 48 | (void) deviceId; | 48 | (void) deviceId; |
| 49 | (void) type; | 49 | (void) type; |
| 50 | (void) value; | 50 | (void) value; |
| 51 | - HCCL_VM_WARN("[{}] not support", __func__); | 51 | + HCCL_VM_WARN("[aclstub] not support"); |
| 52 | return ACL_SUCCESS; | 52 | return ACL_SUCCESS; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| @@ -57,14 +57,14 @@ aclError aclrtSetDeviceResLimit(int32_t deviceId, aclrtDevResLimitType type, uin | |||
| 57 | (void) deviceId; | 57 | (void) deviceId; |
| 58 | (void) type; | 58 | (void) type; |
| 59 | (void) value; | 59 | (void) value; |
| 60 | - HCCL_VM_WARN("[{}] not support", __func__); | 60 | + HCCL_VM_WARN("[aclstub] not support"); |
| 61 | return ACL_SUCCESS; | 61 | return ACL_SUCCESS; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | aclError aclrtResetDeviceResLimit(int32_t deviceId) | 64 | aclError aclrtResetDeviceResLimit(int32_t deviceId) |
| 65 | { | 65 | { |
| 66 | (void) deviceId; | 66 | (void) deviceId; |
| 67 | - HCCL_VM_WARN("[{}] not support", __func__); | 67 | + HCCL_VM_WARN("[aclstub] not support"); |
| 68 | return ACL_SUCCESS; | 68 | return ACL_SUCCESS; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| @@ -73,7 +73,7 @@ aclError aclrtGetStreamResLimit(aclrtStream stream, aclrtDevResLimitType type, u | |||
| 73 | (void) stream; | 73 | (void) stream; |
| 74 | (void) type; | 74 | (void) type; |
| 75 | (void) value; | 75 | (void) value; |
| 76 | - HCCL_VM_WARN("[{}] not support", __func__); | 76 | + HCCL_VM_WARN("[aclstub] not support"); |
| 77 | return ACL_SUCCESS; | 77 | return ACL_SUCCESS; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| @@ -82,28 +82,28 @@ aclError aclrtSetStreamResLimit(aclrtStream stream, aclrtDevResLimitType type, u | |||
| 82 | (void) stream; | 82 | (void) stream; |
| 83 | (void) type; | 83 | (void) type; |
| 84 | (void) value; | 84 | (void) value; |
| 85 | - HCCL_VM_WARN("[{}] not support", __func__); | 85 | + HCCL_VM_WARN("[aclstub] not support"); |
| 86 | return ACL_SUCCESS; | 86 | return ACL_SUCCESS; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | aclError aclrtResetStreamResLimit(aclrtStream stream) | 89 | aclError aclrtResetStreamResLimit(aclrtStream stream) |
| 90 | { | 90 | { |
| 91 | (void) stream; | 91 | (void) stream; |
| 92 | - HCCL_VM_WARN("[{}] not support", __func__); | 92 | + HCCL_VM_WARN("[aclstub] not support"); |
| 93 | return ACL_SUCCESS; | 93 | return ACL_SUCCESS; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) | 96 | aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) |
| 97 | { | 97 | { |
| 98 | (void) stream; | 98 | (void) stream; |
| 99 | - HCCL_VM_WARN("[{}] not support", __func__); | 99 | + HCCL_VM_WARN("[aclstub] not support"); |
| 100 | return ACL_SUCCESS; | 100 | return ACL_SUCCESS; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | aclError aclrtUnuseStreamResInCurrentThread(aclrtStream stream) | 103 | aclError aclrtUnuseStreamResInCurrentThread(aclrtStream stream) |
| 104 | { | 104 | { |
| 105 | (void) stream; | 105 | (void) stream; |
| 106 | - HCCL_VM_WARN("[{}] not support", __func__); | 106 | + HCCL_VM_WARN("[aclstub] not support"); |
| 107 | return ACL_SUCCESS; | 107 | return ACL_SUCCESS; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| @@ -114,6 +114,15 @@ aclError aclrtGetResInCurrentThread(aclrtDevResLimitType type, uint32_t *value) | |||
| 114 | return ACL_SUCCESS; | 114 | return ACL_SUCCESS; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | +aclError aclrtGetOpTimeOutInterval(uint64_t *interval) | ||
| 118 | +{ | ||
| 119 | + if (interval == nullptr) { | ||
| 120 | + return ACL_ERROR_INVALID_PARAM; | ||
| 121 | + } | ||
| 122 | + *interval = 5ULL * 1000ULL * 1000ULL; // 模拟赋值 | ||
| 123 | + return ACL_SUCCESS; | ||
| 124 | +} | ||
| 125 | + | ||
| 117 | 126 | ||
| 118 | } | 127 | } |
| 119 | 128 | ||
| @@ -34,6 +34,8 @@ extern "C" { | |||
| 34 | 34 | ||
| 35 | aclError aclrtCreateStreamWithConfig(aclrtStream *stream, uint32_t priority, uint32_t flag) | 35 | aclError aclrtCreateStreamWithConfig(aclrtStream *stream, uint32_t priority, uint32_t flag) |
| 36 | { | 36 | { |
| 37 | + (void) flag; | ||
| 38 | + (void) priority; | ||
| 37 | sim::Runner runner; | 39 | sim::Runner runner; |
| 38 | if (!sim::GetCurrRunnerTls(0, runner)) { | 40 | if (!sim::GetCurrRunnerTls(0, runner)) { |
| 39 | return ACL_ERROR_INVALID_PARAM; | 41 | return ACL_ERROR_INVALID_PARAM; |
| @@ -200,6 +202,7 @@ aclError aclrtStreamQuery(aclrtStream stream, aclrtStreamStatus *status) | |||
| 200 | 202 | ||
| 201 | aclError aclrtGetStreamAvailableNum(uint32_t *streamCount) | 203 | aclError aclrtGetStreamAvailableNum(uint32_t *streamCount) |
| 202 | { | 204 | { |
| 205 | + (void) streamCount; | ||
| 203 | sim::Runner runner; | 206 | sim::Runner runner; |
| 204 | if (!sim::GetCurrRunnerTls(0, runner)) { | 207 | if (!sim::GetCurrRunnerTls(0, runner)) { |
| 205 | return ACL_ERROR_INVALID_PARAM; | 208 | return ACL_ERROR_INVALID_PARAM; |
| @@ -44,14 +44,14 @@ extern "C" { | |||
| 44 | int RaIsFirstUsed(int insId) | 44 | int RaIsFirstUsed(int insId) |
| 45 | { | 45 | { |
| 46 | (void) insId; | 46 | (void) insId; |
| 47 | - HCCL_VM_ERROR("[HCCP] [{}] stub", __func__); | 47 | + HCCL_VM_ERROR("[HCCP] stub"); |
| 48 | return 0; | 48 | return 0; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | int RaIsLastUsed(int insId) | 51 | int RaIsLastUsed(int insId) |
| 52 | { | 52 | { |
| 53 | (void) insId; | 53 | (void) insId; |
| 54 | - HCCL_VM_ERROR("[HCCP] [{}] stub", __func__); | 54 | + HCCL_VM_ERROR("[HCCP] stub"); |
| 55 | return 0; | 55 | return 0; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| @@ -59,7 +59,7 @@ int ibv_get_cq_event_stub(struct ibv_comp_channel *channel, struct ibv_cq **cq, | |||
| 59 | { | 59 | { |
| 60 | (void) cq; | 60 | (void) cq; |
| 61 | (void) cq_context; | 61 | (void) cq_context; |
| 62 | - HCCL_VM_TRACE("[{}] Stub", __func__); | 62 | + HCCL_VM_TRACE("[HCCP] Stub"); |
| 63 | if (!channel) { | 63 | if (!channel) { |
| 64 | return -1; | 64 | return -1; |
| 65 | } | 65 | } |
| @@ -70,7 +70,7 @@ void ibv_ack_cq_events_stub(struct ibv_cq *cq, unsigned int nevents) | |||
| 70 | { | 70 | { |
| 71 | (void) cq; | 71 | (void) cq; |
| 72 | (void) nevents; | 72 | (void) nevents; |
| 73 | - HCCL_VM_TRACE("[{}] Stub", __func__); | 73 | + HCCL_VM_TRACE("[HCCP] Stub"); |
| 74 | return; | 74 | return; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| @@ -80,7 +80,7 @@ void ibv_query_qp_stub(struct ibv_qp *qp, struct ibv_qp_attr *attr, int attr_mas | |||
| 80 | (void) attr; | 80 | (void) attr; |
| 81 | (void) attr_mask; | 81 | (void) attr_mask; |
| 82 | (void) init_attr; | 82 | (void) init_attr; |
| 83 | - HCCL_VM_TRACE("[{}] Stub", __func__); | 83 | + HCCL_VM_TRACE("[HCCP] Stub"); |
| 84 | return; | 84 | return; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| @@ -46,8 +46,7 @@ add_library(hccl_aiv_kernel SHARED | |||
| 46 | target_link_libraries(hccl_aiv_kernel PRIVATE log) | 46 | target_link_libraries(hccl_aiv_kernel PRIVATE log) |
| 47 | 47 | ||
| 48 | install(TARGETS hccl_aiv_kernel | 48 | install(TARGETS hccl_aiv_kernel |
| 49 | - DESTINATION "." | 49 | + DESTINATION "lib/x86_64" |
| 50 | - # 文件的权限 (755) | ||
| 51 | PERMISSIONS | 50 | PERMISSIONS |
| 52 | OWNER_READ OWNER_WRITE OWNER_EXECUTE | 51 | OWNER_READ OWNER_WRITE OWNER_EXECUTE |
| 53 | GROUP_READ GROUP_EXECUTE | 52 | GROUP_READ GROUP_EXECUTE |
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | - * Copyright (c) 2026 Huawei Technologies Co., Ltd. | 2 | + * Copyright (c) 2025 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. You may not use this file except in compliance with the License. | 5 | * Please refer to the License for details. You may not use this file except in compliance with the License. |
| @@ -11,7 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | - | ||
| 15 | 14 | ||
| 16 | 15 | ||
| 17 | 16 | ||
| @@ -22,26 +21,22 @@ static const struct FunLevelKType kernel_name##_kernel_type_section __attribute_ | |||
| 22 | ((used, section (".ascend.meta." #kernel_name))) \ | 21 | ((used, section (".ascend.meta." #kernel_name))) \ |
| 23 | = {{F_TYPE_KTYPE, sizeof(unsigned int), K_TYPE_AIV}} | 22 | = {{F_TYPE_KTYPE, sizeof(unsigned int), K_TYPE_AIV}} |
| 24 | 23 | ||
| 25 | -constexpr uint32_t MAX_RANK_SIZE = 128; // server内最大卡数 | 24 | +constexpr uint32_t MAX_RANK_SIZE = 512; // server内最大卡数 |
| 25 | +constexpr uint32_t MAX_RANK_SIZE_V = 64; | ||
| 26 | constexpr uint64_t BUFFER_OUT_ADDR_OFFSET = 16 * 1024; | 26 | constexpr uint64_t BUFFER_OUT_ADDR_OFFSET = 16 * 1024; |
| 27 | -constexpr uint64_t TOPO_ADDR_OFFSET = 32 * 1024; | ||
| 28 | -constexpr uint64_t FLAG_ADDR_OFFSET = 40 * 1024; | ||
| 29 | -constexpr uint64_t TOPO_LEN = 128; | ||
| 30 | constexpr uint64_t TOPO_LEN_Y_OFFSET = 8; | 27 | constexpr uint64_t TOPO_LEN_Y_OFFSET = 8; |
| 31 | constexpr uint64_t TOPO_LEN_Z_OFFSET = 16; | 28 | constexpr uint64_t TOPO_LEN_Z_OFFSET = 16; |
| 32 | -constexpr uint64_t IPC_SYNC_OFFSET = 500 * 1024; | ||
| 33 | -constexpr uint64_t BARRIER_OFFSET = 900 * 1024; | ||
| 34 | -constexpr uint64_t SYNC_CORE_OFFSET = 950 * 1024; | ||
| 35 | constexpr uint64_t LOCAL_FLAG_BUF_LEN = 2560; | 29 | constexpr uint64_t LOCAL_FLAG_BUF_LEN = 2560; |
| 36 | constexpr uint64_t AIV_TAG_MOVE_RIGHT_BITS = 16; | 30 | constexpr uint64_t AIV_TAG_MOVE_RIGHT_BITS = 16; |
| 37 | constexpr uint64_t LOW_16_BITS = 0xFFFF; | 31 | constexpr uint64_t LOW_16_BITS = 0xFFFF; |
| 38 | constexpr uint64_t DATA_LIMIT = 512 * 1024; | 32 | constexpr uint64_t DATA_LIMIT = 512 * 1024; |
| 33 | +constexpr uint32_t PING_PONG = 2; | ||
| 39 | 34 | ||
| 40 | struct ExtraArgs { | 35 | struct ExtraArgs { |
| 41 | - uint64_t sendCounts[MAX_RANK_SIZE] = {}; | 36 | + uint64_t sendCounts[MAX_RANK_SIZE_V] = {}; |
| 42 | - uint64_t sendDispls[MAX_RANK_SIZE] = {}; | 37 | + uint64_t sendDispls[MAX_RANK_SIZE_V] = {}; |
| 43 | - uint64_t recvCounts[MAX_RANK_SIZE] = {}; | 38 | + uint64_t recvCounts[MAX_RANK_SIZE_V] = {}; |
| 44 | - uint64_t recvDispls[MAX_RANK_SIZE] = {}; | 39 | + uint64_t recvDispls[MAX_RANK_SIZE_V] = {}; |
| 45 | }; | 40 | }; |
| 46 | 41 | ||
| 47 | using AivSuperKernelArgs = struct AivSuperKernelArgsDef { | 42 | using AivSuperKernelArgs = struct AivSuperKernelArgsDef { |
| @@ -83,7 +78,7 @@ GM_ADDR buffIn, \ | |||
| 83 | uint64_t input, uint64_t output, uint32_t rank, uint32_t sendRecvRemoteRank, uint32_t rankSize, uint64_t xRankSize, uint64_t yRankSize, uint64_t zRankSize, uint64_t len, \ | 78 | uint64_t input, uint64_t output, uint32_t rank, uint32_t sendRecvRemoteRank, uint32_t rankSize, uint64_t xRankSize, uint64_t yRankSize, uint64_t zRankSize, uint64_t len, \ |
| 84 | uint32_t dataType, uint32_t reduceOp, uint32_t root, uint32_t sliceId, \ | 79 | uint32_t dataType, uint32_t reduceOp, uint32_t root, uint32_t sliceId, \ |
| 85 | uint64_t inputSliceStride, uint64_t outputSliceStride, uint64_t repeatNum, uint64_t inputRepeatStride, uint64_t outputRepeatStride, \ | 80 | uint64_t inputSliceStride, uint64_t outputSliceStride, uint64_t repeatNum, uint64_t inputRepeatStride, uint64_t outputRepeatStride, \ |
| 86 | -bool isOpBase, \ | 81 | +uint32_t numBlocks, bool isOpBase, \ |
| 87 | GM_ADDR headCountMem, \ | 82 | GM_ADDR headCountMem, \ |
| 88 | GM_ADDR tailCountMem, GM_ADDR addOneMem, uint32_t counterMemSize, bool isEnableCounter | 83 | GM_ADDR tailCountMem, GM_ADDR addOneMem, uint32_t counterMemSize, bool isEnableCounter |
| 89 | 84 | ||
| @@ -94,7 +89,7 @@ KERNEL_ARGS_DEF, ExtraArgs extraArgs | |||
| 94 | buffIn, \ | 89 | buffIn, \ |
| 95 | input, output, rank, sendRecvRemoteRank, rankSize, xRankSize, yRankSize, zRankSize, len, dataType, reduceOp, root, sliceId, \ | 90 | input, output, rank, sendRecvRemoteRank, rankSize, xRankSize, yRankSize, zRankSize, len, dataType, reduceOp, root, sliceId, \ |
| 96 | inputSliceStride, outputSliceStride, repeatNum, inputRepeatStride, outputRepeatStride, \ | 91 | inputSliceStride, outputSliceStride, repeatNum, inputRepeatStride, outputRepeatStride, \ |
| 97 | -isOpBase, \ | 92 | +numBlocks, isOpBase, \ |
| 98 | headCountMem, tailCountMem, addOneMem, counterMemSize, isEnableCounter | 93 | headCountMem, tailCountMem, addOneMem, counterMemSize, isEnableCounter |
| 99 | 94 | ||
| 100 | 95 | ||
| @@ -104,7 +99,7 @@ KERNEL_ARGS_CALL, extraArgs | |||
| 104 | buffIn, input, output,\ | 99 | buffIn, input, output,\ |
| 105 | rank, sendRecvRemoteRank, rankSize, xRankSize, yRankSize, zRankSize, len, dataType, reduceOp, root, \ | 100 | rank, sendRecvRemoteRank, rankSize, xRankSize, yRankSize, zRankSize, len, dataType, reduceOp, root, \ |
| 106 | inputSliceStride, outputSliceStride, repeatNum, inputRepeatStride, outputRepeatStride, \ | 101 | inputSliceStride, outputSliceStride, repeatNum, inputRepeatStride, outputRepeatStride, \ |
| 107 | -headCountMem, tailCountMem, addOneMem, counterMemSize, isEnableCounter | 102 | +headCountMem, tailCountMem, addOneMem, counterMemSize, isEnableCounter, numBlocks |
| 108 | 103 | ||
| 109 | 104 | ||
| 110 | uint64_t args_offset | 105 | uint64_t args_offset |
| @@ -124,27 +119,7 @@ hiddenInput, input, output | |||
| 124 | 119 | ||
| 125 | hiddenInput, input, output | 120 | hiddenInput, input, output |
| 126 | 121 | ||
| 127 | -#define SUPERKERNEL_LITE_ARGS_DEF \ | 122 | +constexpr uint64_t AIV_FLAG_BUFFER_SIZE = 3 * 1024 * 1024; // aiv算子的flag区域大小 |
| 128 | -uint64_t args_offset | ||
| 129 | - | ||
| 130 | - | ||
| 131 | - GM_ADDR *param_base = (GM_ADDR *)get_para_base();\ | ||
| 132 | - GM_ADDR hiddenInput = param_base[args_offset++];\ | ||
| 133 | - GM_ADDR input = param_base[args_offset++];\ | ||
| 134 | - GM_ADDR output = param_base[args_offset++] | ||
| 135 | - | ||
| 136 | - | ||
| 137 | -GM_ADDR hiddenInput, GM_ADDR input, GM_ADDR output | ||
| 138 | - | ||
| 139 | - | ||
| 140 | -hiddenInput, input, output | ||
| 141 | - | ||
| 142 | - | ||
| 143 | -hiddenInput, input, output | ||
| 144 | - | ||
| 145 | -constexpr uint64_t AIV_COMM_INFO_SIZE = 33 * 1024 * 1024; // aiv算子的通信信息区大小 | ||
| 146 | -constexpr uint64_t AIV_FLAG_BUFFER_SIZE = AIV_COMM_INFO_SIZE - FLAG_ADDR_OFFSET; // aiv算子的flag区域大小 | ||
| 147 | -constexpr uint64_t CLEAR_BUFFER_OFFSET = 1024 * 1024; // 用于清空的aiv buffer的偏移 | ||
| 148 | constexpr uint64_t SYNC_BUFFER_OFFSET = 2 * 1024 * 1024; // 用于sync的aiv buffer的偏移 | 123 | constexpr uint64_t SYNC_BUFFER_OFFSET = 2 * 1024 * 1024; // 用于sync的aiv buffer的偏移 |
| 149 | constexpr uint64_t BUFFER_AREA = 1024 * 1024; // aiv算子的单独功能flag区域大小 | 124 | constexpr uint64_t BUFFER_AREA = 1024 * 1024; // aiv算子的单独功能flag区域大小 |
| 150 | 125 | ||
| @@ -175,15 +150,21 @@ constexpr uint64_t CHUNK_SIZE = 2048; | |||
| 175 | 150 | ||
| 176 | constexpr int32_t TAG_INIT_VALUE = 1; | 151 | constexpr int32_t TAG_INIT_VALUE = 1; |
| 177 | constexpr int32_t TAG_RESET_COUNT = 1000; | 152 | constexpr int32_t TAG_RESET_COUNT = 1000; |
| 178 | -constexpr uint32_t AIV_FLAG_CLEAR_OFFSET = 16 * 1024 * 1024; | 153 | +constexpr uint32_t AIV_FLAG_CLEAR_OFFSET = 512 * 1024; |
| 179 | -constexpr uint32_t AIV_FLAG_EMPTY_OFFSET = 17 * 1024 * 1024; | 154 | +// 相对于GM_OUT,前同步、尾同步使用的同步标记区的偏移,也是普通标记区的大小 |
| 155 | +constexpr uint32_t FLAG1_OFFSET = 1 * 1024 * 1024; | ||
| 156 | +constexpr uint32_t FLAG2_OFFSET = 5 * 1024 * 1024; | ||
| 157 | +constexpr uint32_t BASE_FLAG_OFFSET = 9 * 1024 * 1024; | ||
| 158 | +constexpr uint32_t AIV_FLAG_EMPTY_OFFSET = 10 * 1024 * 1024; | ||
| 159 | +constexpr uint32_t GM_OUT_PING_OFFSET = 18 * 1024 * 1024; | ||
| 160 | +constexpr uint32_t GM_OUT_PONG_OFFSET = 34 * 1024 * 1024; | ||
| 180 | 161 | ||
| 181 | /** | 162 | /** |
| 182 | - * GM_OUT BarrierBase(大小n*FLAG_SIZE) Tag(大小4) Clear | 163 | + * ccl buffers GM_OUT Tag(大小4) flag1 flag2 BarrierBase Clear data1 data2 |
| 183 | - * 0 | 40K(FLAG_ADDR_OFFSET) | 16M(AIV_FLAG_CLEAR_OFFSET)-n*FLAG_SIZE | 16M(AIV_FLAG_CLEAR_OFFSET) | 17M(AIV_FLAG_EMPTY_OFFSET) | 164 | + * 0 | 16K | 512K | 1M | 5M | 9M | 10M | 18M | 34M |
| 165 | + * BUFFER_OUT_ADDR_OFFSET | AIV_FLAG_CLEAR_OFFSET | FLAG1_OFFSET| FLAG2_OFFSET | BASE_FLAG_OFFSET | AIV_FLAG_EMPTY_OFFSET |GM_OUT_PING_OFFSET | GM_OUT_PONG_OFFSET | ||
| 184 | */ | 166 | */ |
| 185 | -// 相对于GM_OUT,前同步、尾同步使用的同步标记区的偏移,也是普通标记区的大小 | 167 | + |
| 186 | -constexpr uint32_t BASE_FLAG_OFFSET = (AIV_FLAG_CLEAR_OFFSET - FLAG_ADDR_OFFSET) - MAX_RANK_SIZE * FLAG_SIZE; | ||
| 187 | 168 | ||
| 188 | class AivCommBase { | 169 | class AivCommBase { |
| 189 | public: | 170 | public: |
| @@ -195,8 +176,8 @@ public: | |||
| 195 | uint32_t dataType, uint32_t reduceOp, uint32_t root, | 176 | uint32_t dataType, uint32_t reduceOp, uint32_t root, |
| 196 | uint64_t inputSliceStride, uint64_t outputSliceStride, uint64_t repeatNum, uint64_t inputRepeatStride, uint64_t outputRepeatStride, | 177 | uint64_t inputSliceStride, uint64_t outputSliceStride, uint64_t repeatNum, uint64_t inputRepeatStride, uint64_t outputRepeatStride, |
| 197 | GM_ADDR headCountMem, | 178 | GM_ADDR headCountMem, |
| 198 | - GM_ADDR tailCountMem, GM_ADDR addOneMem, uint32_t counterMemSize, bool isEnableCounter, | 179 | + GM_ADDR tailCountMem, GM_ADDR addOneMem, uint32_t counterMemSize, bool isEnableCounter, uint32_t numBlocks, |
| 199 | - bool useDoubleBuffer) | 180 | + bool useDoubleBuffer, bool pingpong = false) |
| 200 | { | 181 | { |
| 201 | rank_ = rank; | 182 | rank_ = rank; |
| 202 | sendRecvRemoteRank_ = sendRecvRemoteRank; | 183 | sendRecvRemoteRank_ = sendRecvRemoteRank; |
| @@ -211,7 +192,7 @@ public: | |||
| 211 | output_ = output; | 192 | output_ = output; |
| 212 | dataType_ = dataType; | 193 | dataType_ = dataType; |
| 213 | useDoubleBuffer_ = useDoubleBuffer; | 194 | useDoubleBuffer_ = useDoubleBuffer; |
| 214 | - numBlocks_ = block_num; | 195 | + numBlocks_ = numBlocks; |
| 215 | 196 | ||
| 216 | inputSliceStride_ = inputSliceStride; | 197 | inputSliceStride_ = inputSliceStride; |
| 217 | outputSliceStride_ = outputSliceStride; | 198 | outputSliceStride_ = outputSliceStride; |
| @@ -219,8 +200,6 @@ public: | |||
| 219 | inputRepeatStride_ = inputRepeatStride; | 200 | inputRepeatStride_ = inputRepeatStride; |
| 220 | outputRepeatStride_ = outputRepeatStride; | 201 | outputRepeatStride_ = outputRepeatStride; |
| 221 | 202 | ||
| 222 | - InitBuffArray(buffIn); | ||
| 223 | - | ||
| 224 | localOffset = (rankSize_ * NUM_BLOCKS_FOUR_PER_RANK_A3 * FLAG_BUF_NUM) * FLAG_SIZE; | 203 | localOffset = (rankSize_ * NUM_BLOCKS_FOUR_PER_RANK_A3 * FLAG_BUF_NUM) * FLAG_SIZE; |
| 225 | multiOffset = MAX_NUM_BLOCKS * DOUBLE * FLAG_SIZE+ localOffset; | 204 | multiOffset = MAX_NUM_BLOCKS * DOUBLE * FLAG_SIZE+ localOffset; |
| 226 | pingpongOffset = multiOffset + DOUBLE * DOUBLE * NUM_BLOCKS_FOUR_PER_RANK_A3 * ATOMIC_FLAG_SIZE * DOUBLE; | 205 | pingpongOffset = multiOffset + DOUBLE * DOUBLE * NUM_BLOCKS_FOUR_PER_RANK_A3 * ATOMIC_FLAG_SIZE * DOUBLE; |
| @@ -241,24 +220,33 @@ public: | |||
| 241 | pipe.InitBuffer(outQueueZ, 1, chunkSize); | 220 | pipe.InitBuffer(outQueueZ, 1, chunkSize); |
| 242 | 221 | ||
| 243 | GetTag(buffIn); | 222 | GetTag(buffIn); |
| 223 | + InitBuffArray(buffIn, pingpong); | ||
| 244 | } | 224 | } |
| 245 | 225 | ||
| 246 | - __aicore__ inline void Init(GM_ADDR hiddenInput, GM_ADDR input, GM_ADDR output) | 226 | + __aicore__ inline void Init(GM_ADDR hiddenInput, GM_ADDR input, GM_ADDR output, bool pingpong = false) |
| 247 | { | 227 | { |
| 248 | // SuperKernel 当前不支持 | 228 | // SuperKernel 当前不支持 |
| 249 | HCCL_VM_ERROR("Not support yet!"); | 229 | HCCL_VM_ERROR("Not support yet!"); |
| 250 | } | 230 | } |
| 251 | 231 | ||
| 252 | - __aicore__ inline void InitBuffArray(GM_ADDR buffIn) | 232 | + __aicore__ inline void InitBuffArray(GM_ADDR buffIn, bool pingpong = false) |
| 253 | { | 233 | { |
| 254 | GlobalTensor<uint64_t> ipcBufferGlobal; | 234 | GlobalTensor<uint64_t> ipcBufferGlobal; |
| 255 | ipcBufferGlobal.SetGlobalBuffer((__gm__ uint64_t*)(buffIn)); | 235 | ipcBufferGlobal.SetGlobalBuffer((__gm__ uint64_t*)(buffIn)); |
| 256 | - for(int i=0; i<rankSize_;i++){ | 236 | + if(!pingpong){ |
| 257 | - GM_IN[i] = (GM_ADDR)ipcBufferGlobal.GetValue(i); | 237 | + for(int i=0; i<rankSize_;i++){ |
| 258 | - GM_OUT[i] = (GM_ADDR)ipcBufferGlobal.GetValue(BUFFER_OUT_ADDR_OFFSET / sizeof(uint64_t) + i) + FLAG_ADDR_OFFSET; | 238 | + GM_IN[i] = (GM_ADDR)ipcBufferGlobal.GetValue(i); |
| 259 | - } | 239 | + GM_OUT[i] = (GM_ADDR)ipcBufferGlobal.GetValue(BUFFER_OUT_ADDR_OFFSET / sizeof(uint64_t) + i) + FLAG1_OFFSET; |
| 260 | - for(int i=0; i< TOPO_LEN ;i++){ | 240 | + gmOutOffset = FLAG1_OFFSET; |
| 261 | - TOPO_[i] = (uint64_t)ipcBufferGlobal.GetValue(TOPO_ADDR_OFFSET / sizeof(uint64_t) + i); | 241 | + } |
| 242 | + } else { | ||
| 243 | + for(int i=0; i<rankSize_;i++){ | ||
| 244 | + GM_IN[i] = tag_ % 2 == 0 ? (GM_ADDR)ipcBufferGlobal.GetValue(BUFFER_OUT_ADDR_OFFSET / sizeof(uint64_t) + i) + GM_OUT_PING_OFFSET : | ||
| 245 | + (GM_ADDR)ipcBufferGlobal.GetValue(BUFFER_OUT_ADDR_OFFSET / sizeof(uint64_t) + i) + GM_OUT_PONG_OFFSET; | ||
| 246 | + GM_OUT[i] = tag_ % 2 == 0 ? (GM_ADDR)ipcBufferGlobal.GetValue(BUFFER_OUT_ADDR_OFFSET / sizeof(uint64_t) + i) + FLAG1_OFFSET: | ||
| 247 | + (GM_ADDR)ipcBufferGlobal.GetValue(BUFFER_OUT_ADDR_OFFSET / sizeof(uint64_t) + i) + FLAG2_OFFSET; | ||
| 248 | + gmOutOffset = tag_ % 2 == 0 ? FLAG1_OFFSET : FLAG2_OFFSET; | ||
| 249 | + } | ||
| 262 | } | 250 | } |
| 263 | pipe_barrier(PIPE_ALL); | 251 | pipe_barrier(PIPE_ALL); |
| 264 | } | 252 | } |
| @@ -290,22 +278,34 @@ public: | |||
| 290 | template<typename T> | 278 | template<typename T> |
| 291 | __aicore__ inline void Reduce64(__gm__ T *outputGM, __gm__ T *inputGM, uint64_t count, uint32_t reduceOp); | 279 | __aicore__ inline void Reduce64(__gm__ T *outputGM, __gm__ T *inputGM, uint64_t count, uint32_t reduceOp); |
| 292 | 280 | ||
| 281 | + __aicore__ inline void BarrierForFirstOPInner(uint32_t barrierStage) | ||
| 282 | + { | ||
| 283 | + uint32_t perCoreRankNum = rankSize_ / numBlocks_; | ||
| 284 | + uint32_t remainRankNum = rankSize_ % numBlocks_; | ||
| 285 | + uint32_t curCoreRankNum = blockIdx_ < remainRankNum ? perCoreRankNum + 1 : perCoreRankNum; | ||
| 286 | + uint32_t startRank = blockIdx_ < remainRankNum | ||
| 287 | + ? (perCoreRankNum + 1) * blockIdx_ | ||
| 288 | + : perCoreRankNum * blockIdx_ + remainRankNum; | ||
| 289 | + for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 290 | + uint64_t flag_offset = BASE_FLAG_OFFSET - gmOutOffset + rank * FLAG_SIZE + barrierStage * rankSize_ * FLAG_SIZE; | ||
| 291 | + Record(rank_, flag_offset / FLAG_SIZE, DOUBLE); | ||
| 292 | + } | ||
| 293 | + PipeBarrier<PIPE_ALL>(); | ||
| 294 | + uint64_t flag_offset = BASE_FLAG_OFFSET - gmOutOffset + rank_ * FLAG_SIZE + barrierStage * rankSize_ * FLAG_SIZE; | ||
| 295 | + for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 296 | + WaitFlag(rank, flag_offset / FLAG_SIZE, DOUBLE); | ||
| 297 | + Record(rank_, flag_offset / FLAG_SIZE, 0); | ||
| 298 | + } | ||
| 299 | + } | ||
| 300 | + | ||
| 293 | __aicore__ inline void BarrierAll(); | 301 | __aicore__ inline void BarrierAll(); |
| 294 | 302 | ||
| 295 | - __aicore__ inline void SubBarrierAllForAlltoAllV(uint32_t (&sendRecvRank)[MAX_RANK_SIZE], uint64_t loop); | ||
| 296 | - | ||
| 297 | - __aicore__ inline void PreBarrierAllForAlltoAllV(uint32_t tag, uint64_t loopTimes); | ||
| 298 | - | ||
| 299 | - __aicore__ inline void PostBarrierAllForAlltoAllV(uint32_t tag); | ||
| 300 | - | ||
| 301 | __aicore__ inline void SendRecvBarrierAll(uint32_t myRank, uint32_t remoteRank); | 303 | __aicore__ inline void SendRecvBarrierAll(uint32_t myRank, uint32_t remoteRank); |
| 302 | 304 | ||
| 303 | __aicore__ inline bool IsFirstOP(int32_t sliceId); | 305 | __aicore__ inline bool IsFirstOP(int32_t sliceId); |
| 304 | 306 | ||
| 305 | __aicore__ inline void ClearGM(); | 307 | __aicore__ inline void ClearGM(); |
| 306 | 308 | ||
| 307 | - __aicore__ inline void BarrierForFirstOP(); | ||
| 308 | - | ||
| 309 | __aicore__ inline void SendRecvBarrierForFirstOP(uint32_t myRank, uint32_t remoteRank); | 309 | __aicore__ inline void SendRecvBarrierForFirstOP(uint32_t myRank, uint32_t remoteRank); |
| 310 | 310 | ||
| 311 | __aicore__ inline void WaitFlag(uint32_t targetRank, uint64_t flag_offset, int32_t curTag); | 311 | __aicore__ inline void WaitFlag(uint32_t targetRank, uint64_t flag_offset, int32_t curTag); |
| @@ -316,13 +316,20 @@ public: | |||
| 316 | 316 | ||
| 317 | __aicore__ inline void ClearFlag(); | 317 | __aicore__ inline void ClearFlag(); |
| 318 | 318 | ||
| 319 | - __aicore__ inline void BlockSync(); | ||
| 320 | - | ||
| 321 | __aicore__ inline void ClearSyncBuf(); | 319 | __aicore__ inline void ClearSyncBuf(); |
| 322 | 320 | ||
| 321 | + __aicore__ inline void BarrierForFirstOP() | ||
| 322 | + { | ||
| 323 | + BarrierForFirstOPInner(0); | ||
| 324 | + SyncAll<true>(); | ||
| 325 | + ClearGM(); | ||
| 326 | + SyncAll<true>(); | ||
| 327 | + BarrierForFirstOPInner(1); | ||
| 328 | + SyncAll<true>(); | ||
| 329 | + } | ||
| 330 | + | ||
| 323 | GM_ADDR GM_IN[MAX_RANK_SIZE]; | 331 | GM_ADDR GM_IN[MAX_RANK_SIZE]; |
| 324 | GM_ADDR GM_OUT[MAX_RANK_SIZE]; | 332 | GM_ADDR GM_OUT[MAX_RANK_SIZE]; |
| 325 | - uint64_t TOPO_[TOPO_LEN]; | ||
| 326 | uint32_t rank_; | 333 | uint32_t rank_; |
| 327 | uint32_t sendRecvRemoteRank_; | 334 | uint32_t sendRecvRemoteRank_; |
| 328 | uint32_t root_; | 335 | uint32_t root_; |
| @@ -337,11 +344,13 @@ public: | |||
| 337 | uint64_t input_; | 344 | uint64_t input_; |
| 338 | uint64_t output_; | 345 | uint64_t output_; |
| 339 | uint64_t cclBufferSize_; | 346 | uint64_t cclBufferSize_; |
| 347 | + uint64_t gmOutOffset; | ||
| 340 | 348 | ||
| 341 | uint64_t len_; | 349 | uint64_t len_; |
| 342 | uint32_t tag_; | 350 | uint32_t tag_; |
| 343 | uint32_t curTag_{0}; | 351 | uint32_t curTag_{0}; |
| 344 | int32_t numBlocks_; | 352 | int32_t numBlocks_; |
| 353 | + uint32_t blockIdx_ = GetBlockIdx(); // 在构造函数中初始化,以免漏初始化 | ||
| 345 | 354 | ||
| 346 | uint64_t inputSliceStride_; | 355 | uint64_t inputSliceStride_; |
| 347 | uint64_t outputSliceStride_; | 356 | uint64_t outputSliceStride_; |
| @@ -373,6 +382,7 @@ public: | |||
| 373 | uint32_t seperateOffset; | 382 | uint32_t seperateOffset; |
| 374 | }; | 383 | }; |
| 375 | 384 | ||
| 385 | + | ||
| 376 | __aicore__ inline void AivCommBase::Record(uint32_t targetRank, uint64_t flag_offset, int32_t curTag) | 386 | __aicore__ inline void AivCommBase::Record(uint32_t targetRank, uint64_t flag_offset, int32_t curTag) |
| 377 | { | 387 | { |
| 378 | send_flag(targetRank, flag_offset, curTag); | 388 | send_flag(targetRank, flag_offset, curTag); |
| @@ -398,12 +408,6 @@ __aicore__ inline void AivCommBase::ClearFlag() | |||
| 398 | HCCL_VM_ERROR("Not support yet!"); | 408 | HCCL_VM_ERROR("Not support yet!"); |
| 399 | } | 409 | } |
| 400 | 410 | ||
| 401 | -__aicore__ inline void AivCommBase::BlockSync() | ||
| 402 | -{ | ||
| 403 | - // SuperKernel 当前不支持 | ||
| 404 | - HCCL_VM_ERROR("Not support yet!"); | ||
| 405 | -} | ||
| 406 | - | ||
| 407 | __aicore__ inline void AivCommBase::WaitFlag(uint32_t targetRank, uint64_t flag_offset, int32_t curTag) | 411 | __aicore__ inline void AivCommBase::WaitFlag(uint32_t targetRank, uint64_t flag_offset, int32_t curTag) |
| 408 | { | 412 | { |
| 409 | recv_flag(targetRank, flag_offset, curTag); | 413 | recv_flag(targetRank, flag_offset, curTag); |
| @@ -415,40 +419,14 @@ __aicore__ inline bool AivCommBase::IsFirstOP(int32_t sliceId) | |||
| 415 | return sliceId == 1 && tag_ == 1; | 419 | return sliceId == 1 && tag_ == 1; |
| 416 | } | 420 | } |
| 417 | 421 | ||
| 418 | -__aicore__ inline void AivCommBase::ClearGM() // todo | 422 | +__aicore__ inline void AivCommBase::ClearGM() |
| 419 | { | 423 | { |
| 420 | - uint32_t emptyOffset = AIV_FLAG_EMPTY_OFFSET - FLAG_ADDR_OFFSET; | 424 | + uint32_t emptyOffset = AIV_FLAG_EMPTY_OFFSET - gmOutOffset; |
| 421 | - uint32_t blockCount = BASE_FLAG_OFFSET / numBlocks_; | 425 | + uint32_t blockCount = (BASE_FLAG_OFFSET - FLAG1_OFFSET) / numBlocks_; |
| 422 | - uint32_t blockOffset = blockCount * block_idx; | 426 | + uint32_t blockOffset = blockCount * blockIdx_; |
| 423 | CpGM2GM(GM_OUT[rank_] + blockOffset, GM_OUT[rank_] + blockOffset + emptyOffset, blockCount); | 427 | CpGM2GM(GM_OUT[rank_] + blockOffset, GM_OUT[rank_] + blockOffset + emptyOffset, blockCount); |
| 424 | } | 428 | } |
| 425 | 429 | ||
| 426 | -__aicore__ inline void AivCommBase::BarrierForFirstOP() | ||
| 427 | -{ | ||
| 428 | - // 清零标记区 | ||
| 429 | - ClearGM(); | ||
| 430 | - SyncAll<true>(); | ||
| 431 | - | ||
| 432 | - // 每个核分配多个rank | ||
| 433 | - uint32_t perCoreRankNum = rankSize_ / numBlocks_; | ||
| 434 | - uint32_t remainRankNum = rankSize_ % numBlocks_; | ||
| 435 | - uint32_t curCoreRankNum = block_idx < remainRankNum ? perCoreRankNum + 1 : perCoreRankNum; | ||
| 436 | - uint32_t startRank = block_idx < remainRankNum | ||
| 437 | - ? (perCoreRankNum + 1) * block_idx | ||
| 438 | - : perCoreRankNum * block_idx + remainRankNum; | ||
| 439 | - for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 440 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank * FLAG_SIZE; | ||
| 441 | - Record(rank_, flag_offset / FLAG_SIZE, DOUBLE); | ||
| 442 | - } | ||
| 443 | - PipeBarrier<PIPE_ALL>(); | ||
| 444 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank_ * FLAG_SIZE; | ||
| 445 | - for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 446 | - WaitFlag(rank, flag_offset / FLAG_SIZE, DOUBLE); | ||
| 447 | - } | ||
| 448 | - | ||
| 449 | - SyncAll<true>(); | ||
| 450 | -} | ||
| 451 | - | ||
| 452 | // 为sendRecv单独设计 | 430 | // 为sendRecv单独设计 |
| 453 | __aicore__ inline void AivCommBase::SendRecvBarrierForFirstOP(uint32_t myRank, uint32_t remoteRank) | 431 | __aicore__ inline void AivCommBase::SendRecvBarrierForFirstOP(uint32_t myRank, uint32_t remoteRank) |
| 454 | { | 432 | { |
| @@ -463,96 +441,22 @@ __aicore__ inline void AivCommBase::BarrierAll() | |||
| 463 | // 每个核分配多个rank | 441 | // 每个核分配多个rank |
| 464 | uint32_t perCoreRankNum = rankSize_ / numBlocks_; | 442 | uint32_t perCoreRankNum = rankSize_ / numBlocks_; |
| 465 | uint32_t remainRankNum = rankSize_ % numBlocks_; | 443 | uint32_t remainRankNum = rankSize_ % numBlocks_; |
| 466 | - uint32_t curCoreRankNum = block_idx < remainRankNum ? perCoreRankNum + 1 : perCoreRankNum; | 444 | + uint32_t curCoreRankNum = blockIdx_ < remainRankNum ? perCoreRankNum + 1 : perCoreRankNum; |
| 467 | - uint32_t startRank = block_idx < remainRankNum | 445 | + uint32_t startRank = blockIdx_ < remainRankNum |
| 468 | - ? (perCoreRankNum + 1) * block_idx | 446 | + ? (perCoreRankNum + 1) * blockIdx_ |
| 469 | - : perCoreRankNum * block_idx + remainRankNum; | 447 | + : perCoreRankNum * blockIdx_ + remainRankNum; |
| 470 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank_ * FLAG_SIZE; | 448 | + uint64_t flag_offset = BASE_FLAG_OFFSET - gmOutOffset + rank_ * FLAG_SIZE; |
| 471 | for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | 449 | for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { |
| 472 | Record(rank, flag_offset / FLAG_SIZE, 1); | 450 | Record(rank, flag_offset / FLAG_SIZE, 1); |
| 473 | } | 451 | } |
| 474 | PipeBarrier<PIPE_ALL>(); | 452 | PipeBarrier<PIPE_ALL>(); |
| 475 | for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | 453 | for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { |
| 476 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank * FLAG_SIZE; | 454 | + uint64_t flag_offset = BASE_FLAG_OFFSET - gmOutOffset + rank * FLAG_SIZE; |
| 477 | WaitFlag(rank_, flag_offset / FLAG_SIZE, 1); | 455 | WaitFlag(rank_, flag_offset / FLAG_SIZE, 1); |
| 478 | Record(rank_, flag_offset / FLAG_SIZE, 0); | 456 | Record(rank_, flag_offset / FLAG_SIZE, 0); |
| 479 | } | 457 | } |
| 480 | } | 458 | } |
| 481 | 459 | ||
| 482 | -__aicore__ inline void AivCommBase::SubBarrierAllForAlltoAllV(uint32_t (&sendRecvRank)[MAX_RANK_SIZE], uint64_t loop) | ||
| 483 | -{ | ||
| 484 | - SyncAll<true>(); | ||
| 485 | - // 每个核分配多个rank | ||
| 486 | - uint32_t perCoreRankNum = rankSize_ / numBlocks_; | ||
| 487 | - uint32_t remainRankNum = rankSize_ % numBlocks_; | ||
| 488 | - uint32_t curCoreRankNum = block_idx < remainRankNum ? perCoreRankNum + 1 : perCoreRankNum; | ||
| 489 | - uint32_t startRank = block_idx < remainRankNum | ||
| 490 | - ? (perCoreRankNum + 1) * block_idx | ||
| 491 | - : perCoreRankNum * block_idx + remainRankNum; | ||
| 492 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank_ * FLAG_SIZE; | ||
| 493 | - for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 494 | - // loop为0的时候,给对端初始化置为0 | ||
| 495 | - if (loop == 0 && sendRecvRank[rank] == 0) { | ||
| 496 | - Record(rank, flag_offset / FLAG_SIZE, 0); | ||
| 497 | - } | ||
| 498 | - if (sendRecvRank[rank] == 1) { | ||
| 499 | - if (loop > 0) { | ||
| 500 | - WaitFlag(rank, flag_offset / FLAG_SIZE, 0); // 防止后续record 0 之前重入 | ||
| 501 | - } | ||
| 502 | - Record(rank, flag_offset / FLAG_SIZE, 1); | ||
| 503 | - } | ||
| 504 | - } | ||
| 505 | - PipeBarrier<PIPE_ALL>(); | ||
| 506 | - for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 507 | - if (sendRecvRank[rank] == 1) { | ||
| 508 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank * FLAG_SIZE; | ||
| 509 | - WaitFlag(rank_, flag_offset / FLAG_SIZE, 1); | ||
| 510 | - Record(rank_, flag_offset / FLAG_SIZE, 0); | ||
| 511 | - } | ||
| 512 | - } | ||
| 513 | - SyncAll<true>(); | ||
| 514 | -} | ||
| 515 | - | ||
| 516 | -__aicore__ inline void AivCommBase::PreBarrierAllForAlltoAllV(uint32_t tag, uint64_t loopTimes) | ||
| 517 | -{ | ||
| 518 | - SyncAll<true>(); | ||
| 519 | - // 每个核分配多个rank | ||
| 520 | - uint32_t perCoreRankNum = rankSize_ / numBlocks_; | ||
| 521 | - uint32_t remainRankNum = rankSize_ % numBlocks_; | ||
| 522 | - uint32_t curCoreRankNum = block_idx < remainRankNum ? perCoreRankNum + 1 : perCoreRankNum; | ||
| 523 | - uint32_t startRank = block_idx < remainRankNum | ||
| 524 | - ? (perCoreRankNum + 1) * block_idx | ||
| 525 | - : perCoreRankNum * block_idx + remainRankNum; | ||
| 526 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank_ * FLAG_SIZE; | ||
| 527 | - for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 528 | - if (loopTimes > 0) { | ||
| 529 | - // loopTimes>0的时候,SubBarrierAllForAlltoAllV会给全部rank置0,这里肯定可以wait到 | ||
| 530 | - WaitFlag(rank, flag_offset / FLAG_SIZE, 0); // 防止重入 | ||
| 531 | - } | ||
| 532 | - Record(rank, flag_offset / FLAG_SIZE, tag); | ||
| 533 | - } | ||
| 534 | - PipeBarrier<PIPE_ALL>(); | ||
| 535 | -} | ||
| 536 | - | ||
| 537 | -__aicore__ inline void AivCommBase::PostBarrierAllForAlltoAllV(uint32_t tag) | ||
| 538 | -{ | ||
| 539 | - SyncAll<true>(); | ||
| 540 | - | ||
| 541 | - // 每个核分配多个rank | ||
| 542 | - uint32_t perCoreRankNum = rankSize_ / numBlocks_; | ||
| 543 | - uint32_t remainRankNum = rankSize_ % numBlocks_; | ||
| 544 | - uint32_t curCoreRankNum = block_idx < remainRankNum ? perCoreRankNum + 1 : perCoreRankNum; | ||
| 545 | - uint32_t startRank = block_idx < remainRankNum | ||
| 546 | - ? (perCoreRankNum + 1) * block_idx | ||
| 547 | - : perCoreRankNum * block_idx + remainRankNum; | ||
| 548 | - | ||
| 549 | - for (uint32_t rank = startRank; rank < startRank + curCoreRankNum; rank++) { | ||
| 550 | - uint64_t flag_offset = BASE_FLAG_OFFSET + rank * FLAG_SIZE; | ||
| 551 | - WaitFlag(rank_, flag_offset / FLAG_SIZE, tag); | ||
| 552 | - Record(rank_, flag_offset / FLAG_SIZE, 0); | ||
| 553 | - } | ||
| 554 | -} | ||
| 555 | - | ||
| 556 | // 为sendRecv单独设计 | 460 | // 为sendRecv单独设计 |
| 557 | __aicore__ inline void AivCommBase::SendRecvBarrierAll(uint32_t myRank, uint32_t remoteRank) | 461 | __aicore__ inline void AivCommBase::SendRecvBarrierAll(uint32_t myRank, uint32_t remoteRank) |
| 558 | { | 462 | { |
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | constexpr uint64_t BUFFER_OUT_ADDR_OFFSET = 16 * 1024; | 19 | constexpr uint64_t BUFFER_OUT_ADDR_OFFSET = 16 * 1024; |
| 20 | -constexpr uint64_t FLAG_ADDR_OFFSET = 40 * 1024; | 20 | +constexpr uint64_t FLAG1_OFFSET = 1 * 1024 * 1024; |
| 21 | 21 | ||
| 22 | void aiv_env_init(uint32_t rankId, | 22 | void aiv_env_init(uint32_t rankId, |
| 23 | size_t blockNum, | 23 | size_t blockNum, |
| @@ -85,7 +85,7 @@ void aiv_env_init(uint32_t rankId, | |||
| 85 | static_cast<const uint8_t *>(buffIn) + BUFFER_OUT_ADDR_OFFSET); | 85 | static_cast<const uint8_t *>(buffIn) + BUFFER_OUT_ADDR_OFFSET); |
| 86 | for (uint32_t i = 0; i < rankSize; ++i) { | 86 | for (uint32_t i = 0; i < rankSize; ++i) { |
| 87 | const uint64_t cclBuffer = cclBufferTable[i]; | 87 | const uint64_t cclBuffer = cclBufferTable[i]; |
| 88 | - const uint64_t flagBuffer = flagBufferTable[i] + FLAG_ADDR_OFFSET; | 88 | + const uint64_t flagBuffer = flagBufferTable[i] + FLAG1_OFFSET; |
| 89 | const std::string cclMemDesc = AivSim::Mem{cclBuffer, cclBufferSize}.Describe(); | 89 | const std::string cclMemDesc = AivSim::Mem{cclBuffer, cclBufferSize}.Describe(); |
| 90 | const std::string flagMemDesc = AivSim::Mem{flagBuffer, flagBufferSize}.Describe(); | 90 | const std::string flagMemDesc = AivSim::Mem{flagBuffer, flagBufferSize}.Describe(); |
| 91 | HCCL_VM_DEBUG( | 91 | HCCL_VM_DEBUG( |
| @@ -25,7 +25,7 @@ uint64_t MsprofStr2Id(const char *hashInfo, size_t length) | |||
| 25 | { | 25 | { |
| 26 | (void) hashInfo; | 26 | (void) hashInfo; |
| 27 | (void) length; | 27 | (void) length; |
| 28 | - HCCL_VM_INFO("[APROF] [{}] stub", __func__); | 28 | + HCCL_VM_INFO("[APROF] stub"); |
| 29 | return 1; | 29 | return 1; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| @@ -34,13 +34,13 @@ int32_t MsprofRegTypeInfo(uint16_t level, uint32_t typeId, const char *typeName) | |||
| 34 | (void) level; | 34 | (void) level; |
| 35 | (void) typeId; | 35 | (void) typeId; |
| 36 | (void) typeName; | 36 | (void) typeName; |
| 37 | - HCCL_VM_INFO("[APROF] [{}] stub", __func__); | 37 | + HCCL_VM_INFO("[APROF] stub"); |
| 38 | return 0; | 38 | return 0; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | uint64_t MsprofSysCycleTime() | 41 | uint64_t MsprofSysCycleTime() |
| 42 | { | 42 | { |
| 43 | - HCCL_VM_INFO("[APROF] [{}] stub", __func__); | 43 | + HCCL_VM_INFO("[APROF] stub"); |
| 44 | return 1; | 44 | return 1; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| @@ -48,7 +48,7 @@ int32_t MsprofRegisterCallback(uint32_t moduleId, ProfCommandHandle handle) | |||
| 48 | { | 48 | { |
| 49 | (void) moduleId; | 49 | (void) moduleId; |
| 50 | (void) handle; | 50 | (void) handle; |
| 51 | - HCCL_VM_INFO("[APROF] [{}] stub", __func__); | 51 | + HCCL_VM_INFO("[APROF] stub"); |
| 52 | return 0; | 52 | return 0; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| @@ -56,7 +56,7 @@ int32_t MsprofReportApi(uint32_t agingFlag, const MsprofApi *api) | |||
| 56 | { | 56 | { |
| 57 | (void) agingFlag; | 57 | (void) agingFlag; |
| 58 | (void) api; | 58 | (void) api; |
| 59 | - HCCL_VM_INFO("[APROF] [{}] stub", __func__); | 59 | + HCCL_VM_INFO("[APROF] stub"); |
| 60 | return 0; | 60 | return 0; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| @@ -65,7 +65,7 @@ int32_t MsprofReportAdditionalInfo(uint32_t agingFlag, const VOID_PTR data, uint | |||
| 65 | (void) agingFlag; | 65 | (void) agingFlag; |
| 66 | (void) data; | 66 | (void) data; |
| 67 | (void) length; | 67 | (void) length; |
| 68 | - HCCL_VM_INFO("[APROF] [{}] stub", __func__); | 68 | + HCCL_VM_INFO("[APROF] stub"); |
| 69 | return 0; | 69 | return 0; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| @@ -74,7 +74,7 @@ int32_t MsprofReportCompactInfo(uint32_t agingFlag, const VOID_PTR data, uint32_ | |||
| 74 | (void) agingFlag; | 74 | (void) agingFlag; |
| 75 | (void) data; | 75 | (void) data; |
| 76 | (void) length; | 76 | (void) length; |
| 77 | - HCCL_VM_INFO("[APROF] [{}] stub", __func__); | 77 | + HCCL_VM_INFO("[APROF] stub"); |
| 78 | return 0; | 78 | return 0; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| @@ -121,6 +121,7 @@ drvError_t drvGetPlatformInfo(uint32_t *info) | |||
| 121 | 121 | ||
| 122 | drvError_t drvGetDevNum(uint32_t *num_dev) | 122 | drvError_t drvGetDevNum(uint32_t *num_dev) |
| 123 | { | 123 | { |
| 124 | + (void) num_dev; | ||
| 124 | sim::Runner runner; | 125 | sim::Runner runner; |
| 125 | if (!sim::GetCurrRunnerTls(0, runner)) { | 126 | if (!sim::GetCurrRunnerTls(0, runner)) { |
| 126 | return DRV_ERROR_NO_DEVICE; | 127 | return DRV_ERROR_NO_DEVICE; |
| @@ -31,7 +31,10 @@ | |||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | + | ||
| 34 | 35 | ||
| 36 | + | ||
| 37 | + | ||
| 35 | 38 | ||
| 36 | 39 | ||
| 37 | 40 | ||
| @@ -628,16 +631,16 @@ constexpr int32_t AIV_STUB_TOPO_LEN = 128; | |||
| 628 | constexpr uint64_t AIV_STUB_GM_IN_TABLE_OFFSET = 0; | 631 | constexpr uint64_t AIV_STUB_GM_IN_TABLE_OFFSET = 0; |
| 629 | constexpr uint64_t AIV_STUB_GM_OUT_TABLE_OFFSET = 16 * 1024; | 632 | constexpr uint64_t AIV_STUB_GM_OUT_TABLE_OFFSET = 16 * 1024; |
| 630 | constexpr uint64_t AIV_STUB_TOPO_OFFSET = 32 * 1024; | 633 | constexpr uint64_t AIV_STUB_TOPO_OFFSET = 32 * 1024; |
| 631 | -constexpr uint64_t AIV_STUB_FLAG_OFFSET = 40 * 1024; | 634 | +constexpr uint64_t AIV_STUB_FLAG1_OFFSET = 1 * 1024 * 1024; |
| 632 | -constexpr uint64_t AIV_STUB_TAG_CLEAR_OFFSET = 16 * 1024 * 1024; | 635 | +constexpr uint64_t AIV_STUB_FLAG2_OFFSET = 5 * 1024 * 1024; |
| 633 | -constexpr uint64_t AIV_STUB_FLAG_EMPTY_OFFSET = 17 * 1024 * 1024; | 636 | +constexpr uint64_t AIV_STUB_TAG_CLEAR_OFFSET = 512 * 1024; |
| 634 | -constexpr uint64_t AIV_STUB_COMM_INFO_SIZE = 33 * 1024 * 1024; | 637 | +constexpr uint64_t AIV_STUB_BASE_FLAG_OFFSET = 9 * 1024 * 1024; |
| 638 | +constexpr uint64_t AIV_STUB_FLAG_EMPTY_OFFSET = 10 * 1024 * 1024; | ||
| 639 | +constexpr uint64_t AIV_STUB_GM_OUT_PING_OFFSET = 18 * 1024 * 1024; | ||
| 640 | +constexpr uint64_t AIV_STUB_GM_OUT_PONG_OFFSET = 34 * 1024 * 1024; | ||
| 641 | +constexpr uint64_t AIV_STUB_COMM_INFO_SIZE = 65 * 1024 * 1024; | ||
| 635 | constexpr uint64_t AIV_STUB_UB_ALIGN_SIZE = 32; | 642 | constexpr uint64_t AIV_STUB_UB_ALIGN_SIZE = 32; |
| 636 | constexpr uint64_t AIV_STUB_FLAG_SLOT_SIZE = 128; | 643 | constexpr uint64_t AIV_STUB_FLAG_SLOT_SIZE = 128; |
| 637 | -constexpr uint64_t AIV_STUB_BASE_FLAG_OFFSET = | ||
| 638 | - (AIV_STUB_TAG_CLEAR_OFFSET - AIV_STUB_FLAG_OFFSET) - | ||
| 639 | - AIV_STUB_MAX_RANK_SIZE * AIV_STUB_FLAG_SLOT_SIZE; | ||
| 640 | -constexpr uint32_t AIV_STUB_DEVICE_MAX_NUM_BLOCKS = 48; | ||
| 641 | constexpr uint32_t AIV_STUB_FLAG_SLOT_PRINT_NUM = 16; | 644 | constexpr uint32_t AIV_STUB_FLAG_SLOT_PRINT_NUM = 16; |
| 642 | constexpr uint32_t AIV_STUB_TAG_PRINT_NUM = 16; | 645 | constexpr uint32_t AIV_STUB_TAG_PRINT_NUM = 16; |
| 643 | 646 | ||
| @@ -718,6 +721,7 @@ struct AivKernelArgs { | |||
| 718 | uint64_t repeatNum = 0; | 721 | uint64_t repeatNum = 0; |
| 719 | uint64_t inputRepeatStride = 0; | 722 | uint64_t inputRepeatStride = 0; |
| 720 | uint64_t outputRepeatStride = 0; | 723 | uint64_t outputRepeatStride = 0; |
| 724 | + uint32_t numBlocks = 0; | ||
| 721 | bool isOpBase = false; | 725 | bool isOpBase = false; |
| 722 | const void *headCountMem = nullptr; | 726 | const void *headCountMem = nullptr; |
| 723 | const void *tailCountMem = nullptr; | 727 | const void *tailCountMem = nullptr; |
| @@ -746,6 +750,7 @@ struct AivExtraKernelArgs { | |||
| 746 | uint64_t repeatNum = 0; | 750 | uint64_t repeatNum = 0; |
| 747 | uint64_t inputRepeatStride = 0; | 751 | uint64_t inputRepeatStride = 0; |
| 748 | uint64_t outputRepeatStride = 0; | 752 | uint64_t outputRepeatStride = 0; |
| 753 | + uint32_t numBlocks = 0; | ||
| 749 | bool isOpBase = false; | 754 | bool isOpBase = false; |
| 750 | const void *headCountMem = nullptr; | 755 | const void *headCountMem = nullptr; |
| 751 | const void *tailCountMem = nullptr; | 756 | const void *tailCountMem = nullptr; |
| @@ -775,6 +780,7 @@ struct AivHostLaunchArgs { | |||
| 775 | uint64_t repeatNum = 0; | 780 | uint64_t repeatNum = 0; |
| 776 | uint64_t inputRepeatStride = 0; | 781 | uint64_t inputRepeatStride = 0; |
| 777 | uint64_t outputRepeatStride = 0; | 782 | uint64_t outputRepeatStride = 0; |
| 783 | + uint32_t numBlocks = 0; | ||
| 778 | bool isOpBase = false; | 784 | bool isOpBase = false; |
| 779 | const void *headCountMem = nullptr; | 785 | const void *headCountMem = nullptr; |
| 780 | const void *tailCountMem = nullptr; | 786 | const void *tailCountMem = nullptr; |
| @@ -810,6 +816,7 @@ using AivOpKernelFunc = void (*)( | |||
| 810 | uint64_t repeatNum, | 816 | uint64_t repeatNum, |
| 811 | uint64_t inputRepeatStride, | 817 | uint64_t inputRepeatStride, |
| 812 | uint64_t outputRepeatStride, | 818 | uint64_t outputRepeatStride, |
| 819 | + uint32_t numBlocks, | ||
| 813 | bool isOpBase, | 820 | bool isOpBase, |
| 814 | uint8_t *headCountMem, | 821 | uint8_t *headCountMem, |
| 815 | uint8_t *tailCountMem, | 822 | uint8_t *tailCountMem, |
| @@ -836,6 +843,7 @@ using AivExtraOpKernelFunc = void (*)( | |||
| 836 | uint64_t repeatNum, | 843 | uint64_t repeatNum, |
| 837 | uint64_t inputRepeatStride, | 844 | uint64_t inputRepeatStride, |
| 838 | uint64_t outputRepeatStride, | 845 | uint64_t outputRepeatStride, |
| 846 | + uint32_t numBlocks, | ||
| 839 | bool isOpBase, | 847 | bool isOpBase, |
| 840 | uint8_t *headCountMem, | 848 | uint8_t *headCountMem, |
| 841 | uint8_t *tailCountMem, | 849 | uint8_t *tailCountMem, |
| @@ -924,7 +932,6 @@ static ResolvedHostPtrHandle ResolveHostPtr(const void *devPtr) | |||
| 924 | handle.phyMem = phyMem; | 932 | handle.phyMem = phyMem; |
| 925 | handle.needRelease = true; | 933 | handle.needRelease = true; |
| 926 | } | 934 | } |
| 927 | - | ||
| 928 | handle.hostPtr = hostBasePtr + offset; | 935 | handle.hostPtr = hostBasePtr + offset; |
| 929 | return handle; | 936 | return handle; |
| 930 | } | 937 | } |
| @@ -935,7 +942,12 @@ static void ReleaseHostPtr(ResolvedHostPtrHandle &handle) | |||
| 935 | return; | 942 | return; |
| 936 | } | 943 | } |
| 937 | 944 | ||
| 938 | - sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(handle.phyMem.name, handle.phyMem.device_id); | 945 | + // needRelease 仅在走 AcquirePhyMem 时置位;按 size 判定是否走了复用区(与申请同一判据) |
| 946 | + if (sim::CommPoolPolicy::ShouldRedirect(handle.phyMem.size, sim::IsCheckOnlyMode())) { | ||
| 947 | + sim::MemoryManager::GetInstance().ReleaseMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 948 | + } else { | ||
| 949 | + sim::DeviceMemoryManager::GetInstance().ReleasePhyMem(handle.phyMem.name, handle.phyMem.device_id); | ||
| 950 | + } | ||
| 939 | handle.hostPtr = nullptr; | 951 | handle.hostPtr = nullptr; |
| 940 | handle.phyMem = {}; | 952 | handle.phyMem = {}; |
| 941 | handle.needRelease = false; | 953 | handle.needRelease = false; |
| @@ -1020,19 +1032,31 @@ static void DumpBuffersInParsedDeviceView(const void *buffersInDev, uint32_t ran | |||
| 1020 | const auto *gmInTable = reinterpret_cast<const uint64_t *>(buffersInHost + AIV_STUB_GM_IN_TABLE_OFFSET); | 1032 | const auto *gmInTable = reinterpret_cast<const uint64_t *>(buffersInHost + AIV_STUB_GM_IN_TABLE_OFFSET); |
| 1021 | const auto *gmOutTable = reinterpret_cast<const uint64_t *>(buffersInHost + AIV_STUB_GM_OUT_TABLE_OFFSET); | 1033 | const auto *gmOutTable = reinterpret_cast<const uint64_t *>(buffersInHost + AIV_STUB_GM_OUT_TABLE_OFFSET); |
| 1022 | const auto *topoTable = reinterpret_cast<const uint64_t *>(buffersInHost + AIV_STUB_TOPO_OFFSET); | 1034 | const auto *topoTable = reinterpret_cast<const uint64_t *>(buffersInHost + AIV_STUB_TOPO_OFFSET); |
| 1023 | - const auto *flagBase = buffersInHost + AIV_STUB_FLAG_OFFSET; | 1035 | + const auto *flag1Base = buffersInHost + AIV_STUB_FLAG1_OFFSET; |
| 1024 | const auto *tagTable = reinterpret_cast<const int32_t *>(buffersInHost + AIV_STUB_TAG_CLEAR_OFFSET); | 1036 | const auto *tagTable = reinterpret_cast<const int32_t *>(buffersInHost + AIV_STUB_TAG_CLEAR_OFFSET); |
| 1025 | const auto *emptyClearTable = reinterpret_cast<const int32_t *>(buffersInHost + AIV_STUB_FLAG_EMPTY_OFFSET); | 1037 | const auto *emptyClearTable = reinterpret_cast<const int32_t *>(buffersInHost + AIV_STUB_FLAG_EMPTY_OFFSET); |
| 1038 | + const uint64_t nonPingpongBaseFlagOffset = AIV_STUB_BASE_FLAG_OFFSET - AIV_STUB_FLAG1_OFFSET; | ||
| 1026 | 1039 | ||
| 1027 | oss << " [buffersIn-parse] device-side parsed results from buffersIn (not a raw buffersIn pointer dump):\n"; | 1040 | oss << " [buffersIn-parse] device-side parsed results from buffersIn (not a raw buffersIn pointer dump):\n"; |
| 1028 | oss << " AIV comm layout: commInfoSize=0x" << std::hex | 1041 | oss << " AIV comm layout: commInfoSize=0x" << std::hex |
| 1029 | << static_cast<unsigned long long>(AIV_STUB_COMM_INFO_SIZE) | 1042 | << static_cast<unsigned long long>(AIV_STUB_COMM_INFO_SIZE) |
| 1030 | << ", GM_OUT_TABLE=0x" << static_cast<unsigned long long>(AIV_STUB_GM_OUT_TABLE_OFFSET) | 1043 | << ", GM_OUT_TABLE=0x" << static_cast<unsigned long long>(AIV_STUB_GM_OUT_TABLE_OFFSET) |
| 1031 | << ", TOPO=0x" << static_cast<unsigned long long>(AIV_STUB_TOPO_OFFSET) | 1044 | << ", TOPO=0x" << static_cast<unsigned long long>(AIV_STUB_TOPO_OFFSET) |
| 1032 | - << ", FLAG=0x" << static_cast<unsigned long long>(AIV_STUB_FLAG_OFFSET) | ||
| 1033 | << ", TAG/CLEAR=0x" << static_cast<unsigned long long>(AIV_STUB_TAG_CLEAR_OFFSET) | 1045 | << ", TAG/CLEAR=0x" << static_cast<unsigned long long>(AIV_STUB_TAG_CLEAR_OFFSET) |
| 1046 | + << ", FLAG1=0x" << static_cast<unsigned long long>(AIV_STUB_FLAG1_OFFSET) | ||
| 1047 | + << ", FLAG2=0x" << static_cast<unsigned long long>(AIV_STUB_FLAG2_OFFSET) | ||
| 1048 | + << ", BASE_FLAG=0x" << static_cast<unsigned long long>(AIV_STUB_BASE_FLAG_OFFSET) | ||
| 1034 | << ", EMPTY_CLEAR=0x" << static_cast<unsigned long long>(AIV_STUB_FLAG_EMPTY_OFFSET) | 1049 | << ", EMPTY_CLEAR=0x" << static_cast<unsigned long long>(AIV_STUB_FLAG_EMPTY_OFFSET) |
| 1050 | + << ", PING=0x" << static_cast<unsigned long long>(AIV_STUB_GM_OUT_PING_OFFSET) | ||
| 1051 | + << ", PONG=0x" << static_cast<unsigned long long>(AIV_STUB_GM_OUT_PONG_OFFSET) | ||
| 1035 | << std::dec << '\n'; | 1052 | << std::dec << '\n'; |
| 1053 | + oss << " Compatibility note: not support pingpong yet; AllGather pingpong data" | ||
| 1054 | + << " slots are dumped for layout visibility only.\n"; | ||
| 1055 | + oss << " Legacy host DFX flag offset remains 0x" << std::hex | ||
| 1056 | + << static_cast<unsigned long long>(40 * 1024) | ||
| 1057 | + << ", but device-side non-pingpong GM_OUT uses FLAG1_OFFSET(0x" | ||
| 1058 | + << static_cast<unsigned long long>(AIV_STUB_FLAG1_OFFSET) << ").\n" | ||
| 1059 | + << std::dec; | ||
| 1036 | oss << " GM_IN parsed entries count=" << parsedRankSize | 1060 | oss << " GM_IN parsed entries count=" << parsedRankSize |
| 1037 | << " from +0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_GM_IN_TABLE_OFFSET) << std::dec | 1061 | << " from +0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_GM_IN_TABLE_OFFSET) << std::dec |
| 1038 | << '\n'; | 1062 | << '\n'; |
| @@ -1046,11 +1070,11 @@ static void DumpBuffersInParsedDeviceView(const void *buffersInDev, uint32_t ran | |||
| 1046 | 1070 | ||
| 1047 | oss << " GM_OUT parsed entries count=" << parsedRankSize | 1071 | oss << " GM_OUT parsed entries count=" << parsedRankSize |
| 1048 | << " from (+0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_GM_OUT_TABLE_OFFSET) | 1072 | << " from (+0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_GM_OUT_TABLE_OFFSET) |
| 1049 | - << " table) + FLAG_OFFSET(0x" << static_cast<unsigned long long>(AIV_STUB_FLAG_OFFSET) << ')' | 1073 | + << " table) + FLAG1_OFFSET(0x" << static_cast<unsigned long long>(AIV_STUB_FLAG1_OFFSET) << ')' |
| 1050 | << std::dec << '\n'; | 1074 | << std::dec << '\n'; |
| 1051 | for (uint32_t i = 0; i < parsedRankSize; ++i) { | 1075 | for (uint32_t i = 0; i < parsedRankSize; ++i) { |
| 1052 | const uint64_t commInfoDev = gmOutTable[i]; | 1076 | const uint64_t commInfoDev = gmOutTable[i]; |
| 1053 | - const uint64_t flagDev = (commInfoDev == 0) ? 0 : (commInfoDev + AIV_STUB_FLAG_OFFSET); | 1077 | + const uint64_t flagDev = (commInfoDev == 0) ? 0 : (commInfoDev + AIV_STUB_FLAG1_OFFSET); |
| 1054 | oss << " GM_OUT[" << i << "] dev=0x" << std::hex << static_cast<unsigned long long>(flagDev) | 1078 | oss << " GM_OUT[" << i << "] dev=0x" << std::hex << static_cast<unsigned long long>(flagDev) |
| 1055 | << " (src commInfoDev=0x" << std::hex << static_cast<unsigned long long>(commInfoDev) | 1079 | << " (src commInfoDev=0x" << std::hex << static_cast<unsigned long long>(commInfoDev) |
| 1056 | << std::dec << ")\n"; | 1080 | << std::dec << ")\n"; |
| @@ -1067,29 +1091,29 @@ static void DumpBuffersInParsedDeviceView(const void *buffersInDev, uint32_t ran | |||
| 1067 | 1091 | ||
| 1068 | const uint32_t barrierSlotPrintNum = | 1092 | const uint32_t barrierSlotPrintNum = |
| 1069 | (rankSize < AIV_STUB_MAX_RANK_SIZE) ? rankSize : AIV_STUB_MAX_RANK_SIZE; | 1093 | (rankSize < AIV_STUB_MAX_RANK_SIZE) ? rankSize : AIV_STUB_MAX_RANK_SIZE; |
| 1070 | - const uint32_t deviceNumBlocks = | ||
| 1071 | - (numBlocks < AIV_STUB_DEVICE_MAX_NUM_BLOCKS) ? numBlocks : AIV_STUB_DEVICE_MAX_NUM_BLOCKS; | ||
| 1072 | - | ||
| 1073 | oss << " [buffersIn-parse] follow-up work areas derived from the same base:\n"; | 1094 | oss << " [buffersIn-parse] follow-up work areas derived from the same base:\n"; |
| 1074 | - oss << " FLAG work area @ +0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_FLAG_OFFSET) | 1095 | + oss << " FLAG1 non-pingpong GM_OUT @ +0x" << std::hex |
| 1075 | - << ", bytes=[0x0, 0x" | 1096 | + << static_cast<unsigned long long>(AIV_STUB_FLAG1_OFFSET) |
| 1076 | - << static_cast<unsigned long long>(AIV_STUB_TAG_CLEAR_OFFSET - AIV_STUB_FLAG_OFFSET) << ')' | ||
| 1077 | << ", flagSlotSize=" << std::dec << AIV_STUB_FLAG_SLOT_SIZE | 1097 | << ", flagSlotSize=" << std::dec << AIV_STUB_FLAG_SLOT_SIZE |
| 1078 | - << ", baseFlagOffset=0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_BASE_FLAG_OFFSET) | 1098 | + << ", baseFlagOffset relative to GM_OUT=0x" << std::hex |
| 1099 | + << static_cast<unsigned long long>(nonPingpongBaseFlagOffset) | ||
| 1100 | + << ", absoluteBaseFlag=0x" << static_cast<unsigned long long>(AIV_STUB_BASE_FLAG_OFFSET) | ||
| 1079 | << std::dec << '\n'; | 1101 | << std::dec << '\n'; |
| 1080 | - DumpFlagSlots(oss, flagBase, 0, AIV_STUB_FLAG_SLOT_PRINT_NUM, "operator slots[0..15]"); | 1102 | + oss << " FLAG2 pingpong alt @ +0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_FLAG2_OFFSET) |
| 1081 | - DumpFlagSlots(oss, flagBase, AIV_STUB_BASE_FLAG_OFFSET, barrierSlotPrintNum, "BASE_FLAG_OFFSET barrier slots"); | 1103 | + << ", PING data @ +0x" << static_cast<unsigned long long>(AIV_STUB_GM_OUT_PING_OFFSET) |
| 1104 | + << ", PONG data @ +0x" << static_cast<unsigned long long>(AIV_STUB_GM_OUT_PONG_OFFSET) | ||
| 1105 | + << std::dec << '\n'; | ||
| 1106 | + oss << " FLAG1 bytes=[0x0, 0x" | ||
| 1107 | + << std::hex << static_cast<unsigned long long>(AIV_STUB_FLAG_EMPTY_OFFSET - AIV_STUB_FLAG1_OFFSET) << ')' | ||
| 1108 | + << ", flagSlotSize=" << std::dec << AIV_STUB_FLAG_SLOT_SIZE | ||
| 1109 | + << std::dec << '\n'; | ||
| 1110 | + DumpFlagSlots(oss, flag1Base, 0, AIV_STUB_FLAG_SLOT_PRINT_NUM, "FLAG1 operator slots[0..15]"); | ||
| 1111 | + DumpFlagSlots(oss, flag1Base, nonPingpongBaseFlagOffset, barrierSlotPrintNum, | ||
| 1112 | + "BASE_FLAG_OFFSET - FLAG1_OFFSET barrier slots"); | ||
| 1082 | 1113 | ||
| 1083 | oss << " TAG/CLEAR ints[0.." << (AIV_STUB_TAG_PRINT_NUM - 1) | 1114 | oss << " TAG/CLEAR ints[0.." << (AIV_STUB_TAG_PRINT_NUM - 1) |
| 1084 | << "] @ +0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_TAG_CLEAR_OFFSET) << std::dec << '\n'; | 1115 | << "] @ +0x" << std::hex << static_cast<unsigned long long>(AIV_STUB_TAG_CLEAR_OFFSET) << std::dec << '\n'; |
| 1085 | - if (deviceNumBlocks == 0) { | 1116 | + oss << " non-pingpong model currently keeps tag_ fixed at 1; real HCCL reads/writes this slot.\n"; |
| 1086 | - oss << " numBlocks is 0, skip GetTag block mapping summary.\n"; | ||
| 1087 | - } else { | ||
| 1088 | - oss << " GetTag uses deviceMaxBlocks=" << AIV_STUB_DEVICE_MAX_NUM_BLOCKS | ||
| 1089 | - << ", numBlocks=" << deviceNumBlocks | ||
| 1090 | - << ", baseSetBlockNum=" << (AIV_STUB_DEVICE_MAX_NUM_BLOCKS / deviceNumBlocks) | ||
| 1091 | - << ", remainder=" << (AIV_STUB_DEVICE_MAX_NUM_BLOCKS % deviceNumBlocks) << '\n'; | ||
| 1092 | - } | ||
| 1093 | for (uint32_t i = 0; i < AIV_STUB_TAG_PRINT_NUM; ++i) { | 1117 | for (uint32_t i = 0; i < AIV_STUB_TAG_PRINT_NUM; ++i) { |
| 1094 | oss << " TAG_CLEAR[" << i << "] = " << tagTable[i] << '\n'; | 1118 | oss << " TAG_CLEAR[" << i << "] = " << tagTable[i] << '\n'; |
| 1095 | } | 1119 | } |
| @@ -1201,6 +1225,7 @@ static void CopyCommonKernelArgsToHostArgs(const AivKernelArgs &src, AivHostLaun | |||
| 1201 | dst.repeatNum = src.repeatNum; | 1225 | dst.repeatNum = src.repeatNum; |
| 1202 | dst.inputRepeatStride = src.inputRepeatStride; | 1226 | dst.inputRepeatStride = src.inputRepeatStride; |
| 1203 | dst.outputRepeatStride = src.outputRepeatStride; | 1227 | dst.outputRepeatStride = src.outputRepeatStride; |
| 1228 | + dst.numBlocks = src.numBlocks; | ||
| 1204 | dst.isOpBase = src.isOpBase; | 1229 | dst.isOpBase = src.isOpBase; |
| 1205 | dst.headCountMem = src.headCountMem; | 1230 | dst.headCountMem = src.headCountMem; |
| 1206 | dst.tailCountMem = src.tailCountMem; | 1231 | dst.tailCountMem = src.tailCountMem; |
| @@ -1230,6 +1255,7 @@ static void CopyCommonKernelArgsToHostArgs(const AivExtraKernelArgs &src, AivHos | |||
| 1230 | dst.repeatNum = src.repeatNum; | 1255 | dst.repeatNum = src.repeatNum; |
| 1231 | dst.inputRepeatStride = src.inputRepeatStride; | 1256 | dst.inputRepeatStride = src.inputRepeatStride; |
| 1232 | dst.outputRepeatStride = src.outputRepeatStride; | 1257 | dst.outputRepeatStride = src.outputRepeatStride; |
| 1258 | + dst.numBlocks = src.numBlocks; | ||
| 1233 | dst.isOpBase = src.isOpBase; | 1259 | dst.isOpBase = src.isOpBase; |
| 1234 | dst.headCountMem = src.headCountMem; | 1260 | dst.headCountMem = src.headCountMem; |
| 1235 | dst.tailCountMem = src.tailCountMem; | 1261 | dst.tailCountMem = src.tailCountMem; |
| @@ -1312,6 +1338,7 @@ static void DumpHostLaunchArgs(const AivHostLaunchArgs *hostArgs, size_t argsSiz | |||
| 1312 | oss << " hostArgs.repeatNum = " << static_cast<unsigned long long>(hostArgs->repeatNum) << '\n'; | 1338 | oss << " hostArgs.repeatNum = " << static_cast<unsigned long long>(hostArgs->repeatNum) << '\n'; |
| 1313 | oss << " hostArgs.inputRepeatStride = " << static_cast<unsigned long long>(hostArgs->inputRepeatStride) << '\n'; | 1339 | oss << " hostArgs.inputRepeatStride = " << static_cast<unsigned long long>(hostArgs->inputRepeatStride) << '\n'; |
| 1314 | oss << " hostArgs.outputRepeatStride = " << static_cast<unsigned long long>(hostArgs->outputRepeatStride) << '\n'; | 1340 | oss << " hostArgs.outputRepeatStride = " << static_cast<unsigned long long>(hostArgs->outputRepeatStride) << '\n'; |
| 1341 | + oss << " hostArgs.numBlocks = " << hostArgs->numBlocks << '\n'; | ||
| 1315 | oss << " hostArgs.isOpBase = " << static_cast<int>(hostArgs->isOpBase) << '\n'; | 1342 | oss << " hostArgs.isOpBase = " << static_cast<int>(hostArgs->isOpBase) << '\n'; |
| 1316 | oss << " hostArgs.headCountMem = " << hostArgs->headCountMem << '\n'; | 1343 | oss << " hostArgs.headCountMem = " << hostArgs->headCountMem << '\n'; |
| 1317 | oss << " hostArgs.tailCountMem = " << hostArgs->tailCountMem << '\n'; | 1344 | oss << " hostArgs.tailCountMem = " << hostArgs->tailCountMem << '\n'; |
| @@ -1494,7 +1521,7 @@ static std::string GetAivLibraryPath(const std::string &soName, const std::strin | |||
| 1494 | 1521 | ||
| 1495 | std::error_code ec; | 1522 | std::error_code ec; |
| 1496 | const fs::path installDir = fs::path(installDirEnv); | 1523 | const fs::path installDir = fs::path(installDirEnv); |
| 1497 | - const fs::path soPath = installDir / soName; | 1524 | + const fs::path soPath = installDir / "lib" / "x86_64" / soName; |
| 1498 | if (!fs::exists(soPath, ec)) { | 1525 | if (!fs::exists(soPath, ec)) { |
| 1499 | if (ec) { | 1526 | if (ec) { |
| 1500 | HCCL_VM_ERROR("[virtual-aiv] failed to stat aiv library path, kernel={}, HCCL_VM_INSTALL_DIR={}, so={}, err={}", | 1527 | HCCL_VM_ERROR("[virtual-aiv] failed to stat aiv library path, kernel={}, HCCL_VM_INSTALL_DIR={}, so={}, err={}", |
| @@ -1769,7 +1796,7 @@ static void ResolveVirtualAivBufferSizes(const std::string &kernelName, | |||
| 1769 | } | 1796 | } |
| 1770 | 1797 | ||
| 1771 | cclBufferSize = 0; | 1798 | cclBufferSize = 0; |
| 1772 | - flagBufferSize = AIV_STUB_COMM_INFO_SIZE - AIV_STUB_FLAG_OFFSET; | 1799 | + flagBufferSize = AIV_STUB_COMM_INFO_SIZE - AIV_STUB_FLAG1_OFFSET; |
| 1773 | 1800 | ||
| 1774 | if (resolvedArgs.args.buffersIn == nullptr) { | 1801 | if (resolvedArgs.args.buffersIn == nullptr) { |
| 1775 | return; | 1802 | return; |
| @@ -1888,6 +1915,8 @@ static void DumpVirtualKernelFuncArgs( | |||
| 1888 | oss << " kernelFunc.outputRepeatStride = " | 1915 | oss << " kernelFunc.outputRepeatStride = " |
| 1889 | << static_cast<unsigned long long>(resolvedArgs.args.outputRepeatStride) | 1916 | << static_cast<unsigned long long>(resolvedArgs.args.outputRepeatStride) |
| 1890 | << " <- aclrtLaunchKernelWithHostArgs(hostArgs->outputRepeatStride)\n"; | 1917 | << " <- aclrtLaunchKernelWithHostArgs(hostArgs->outputRepeatStride)\n"; |
| 1918 | + oss << " kernelFunc.numBlocks = " << resolvedArgs.args.numBlocks | ||
| 1919 | + << " <- aclrtLaunchKernelWithHostArgs(hostArgs->numBlocks)\n"; | ||
| 1891 | oss << " kernelFunc.isOpBase = " << (resolvedArgs.args.isOpBase ? "true" : "false") | 1920 | oss << " kernelFunc.isOpBase = " << (resolvedArgs.args.isOpBase ? "true" : "false") |
| 1892 | << " <- aclrtLaunchKernelWithHostArgs(hostArgs->isOpBase)\n"; | 1921 | << " <- aclrtLaunchKernelWithHostArgs(hostArgs->isOpBase)\n"; |
| 1893 | oss << " kernelFunc.headCountMem = " << resolvedArgs.args.headCountMem | 1922 | oss << " kernelFunc.headCountMem = " << resolvedArgs.args.headCountMem |
| @@ -2150,6 +2179,7 @@ static aclError VirtualExecuteAivKernel( | |||
| 2150 | resolvedArgs.args.repeatNum, | 2179 | resolvedArgs.args.repeatNum, |
| 2151 | resolvedArgs.args.inputRepeatStride, | 2180 | resolvedArgs.args.inputRepeatStride, |
| 2152 | resolvedArgs.args.outputRepeatStride, | 2181 | resolvedArgs.args.outputRepeatStride, |
| 2182 | + resolvedArgs.args.numBlocks, | ||
| 2153 | resolvedArgs.args.isOpBase, | 2183 | resolvedArgs.args.isOpBase, |
| 2154 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.headCountMem)), | 2184 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.headCountMem)), |
| 2155 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.tailCountMem)), | 2185 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.tailCountMem)), |
| @@ -2179,6 +2209,7 @@ static aclError VirtualExecuteAivKernel( | |||
| 2179 | resolvedArgs.args.repeatNum, | 2209 | resolvedArgs.args.repeatNum, |
| 2180 | resolvedArgs.args.inputRepeatStride, | 2210 | resolvedArgs.args.inputRepeatStride, |
| 2181 | resolvedArgs.args.outputRepeatStride, | 2211 | resolvedArgs.args.outputRepeatStride, |
| 2212 | + resolvedArgs.args.numBlocks, | ||
| 2182 | resolvedArgs.args.isOpBase, | 2213 | resolvedArgs.args.isOpBase, |
| 2183 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.headCountMem)), | 2214 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.headCountMem)), |
| 2184 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.tailCountMem)), | 2215 | const_cast<uint8_t *>(static_cast<const uint8_t *>(resolvedArgs.args.tailCountMem)), |
| @@ -24,6 +24,8 @@ | |||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | + | ||
| 28 | + | ||
| 27 | 29 | ||
| 28 | 30 | ||
| 29 | 31 | ||
| @@ -119,7 +121,9 @@ void DumpCcuSqeToFile(uint32_t startId, uint32_t instrCnt, uint32_t argSize, uin | |||
| 119 | namespace fs = std::filesystem; | 121 | namespace fs = std::filesystem; |
| 120 | 122 | ||
| 121 | bool write_or_overwrite_in_cwd(const std::string& filename, const std::string &data) { | 123 | bool write_or_overwrite_in_cwd(const std::string& filename, const std::string &data) { |
| 122 | - fs::path target = fs::current_path() / filename; | 124 | + fs::path target = fs::path(filename).is_absolute() |
| 125 | + ? fs::path(filename) | ||
| 126 | + : fs::current_path() / filename; | ||
| 123 | 127 | ||
| 124 | std::error_code ec; | 128 | std::error_code ec; |
| 125 | bool exists = fs::exists(target, ec); | 129 | bool exists = fs::exists(target, ec); |
| @@ -199,6 +203,7 @@ int LoadMicrocodeInstructionStub(uint32_t devId, uint8_t dieId, const channel_in | |||
| 199 | return -1; | 203 | return -1; |
| 200 | } | 204 | } |
| 201 | 205 | ||
| 206 | + fs::create_directories(fs::path(InstallPath::ResolveToInstallRoot("data"))); | ||
| 202 | std::ostringstream fileName; | 207 | std::ostringstream fileName; |
| 203 | fileName << "mc_instr_info_rank_" << rankId<<"_die_"<<static_cast<uint32_t>(dieId)<<".txt"; | 208 | fileName << "mc_instr_info_rank_" << rankId<<"_die_"<<static_cast<uint32_t>(dieId)<<".txt"; |
| 204 | std::ostringstream mcData; | 209 | std::ostringstream mcData; |
| @@ -212,7 +217,7 @@ int LoadMicrocodeInstructionStub(uint32_t devId, uint8_t dieId, const channel_in | |||
| 212 | return HCCL_E_NOT_SUPPORT; | 217 | return HCCL_E_NOT_SUPPORT; |
| 213 | } | 218 | } |
| 214 | 219 | ||
| 215 | - auto status = write_or_overwrite_in_cwd(fileName.str(), mcData.str()); | 220 | + auto status = write_or_overwrite_in_cwd(InstallPath::ResolveToInstallRoot("data/" + fileName.str()), mcData.str()); |
| 216 | 221 | ||
| 217 | sim::CcuInstrTab instr{}; | 222 | sim::CcuInstrTab instr{}; |
| 218 | instr.id = 0; | 223 | instr.id = 0; |
| @@ -523,6 +528,7 @@ int rtCCULaunch(rtCcuTaskInfo_t *taskInfo, rtStream_t const stream) | |||
| 523 | 528 | ||
| 524 | memcpy(&taskMetaData.taskData.ccu, taskInfo, sizeof(rtCcuTaskInfo_t)); | 529 | memcpy(&taskMetaData.taskData.ccu, taskInfo, sizeof(rtCcuTaskInfo_t)); |
| 525 | 530 | ||
| 531 | + fs::create_directories(fs::path(InstallPath::ResolveToInstallRoot("data"))); | ||
| 526 | std::ostringstream fileName; | 532 | std::ostringstream fileName; |
| 527 | fileName << "sqe_info_rank_" << curRank << "_die_" << static_cast<uint32_t>(taskInfo->dieId) << "_mission_" | 533 | fileName << "sqe_info_rank_" << curRank << "_die_" << static_cast<uint32_t>(taskInfo->dieId) << "_mission_" |
| 528 | << static_cast<uint32_t>(taskInfo->missionId) << "_startId_" << taskInfo->instStartId << ".txt"; | 534 | << static_cast<uint32_t>(taskInfo->missionId) << "_startId_" << taskInfo->instStartId << ".txt"; |
| @@ -531,7 +537,7 @@ int rtCCULaunch(rtCcuTaskInfo_t *taskInfo, rtStream_t const stream) | |||
| 531 | for (uint32_t idx = 0; idx < taskInfo->argSize; idx++) { | 537 | for (uint32_t idx = 0; idx < taskInfo->argSize; idx++) { |
| 532 | sqeData << "[SQE Arg][" << idx << "]: " << taskInfo->args[idx] << "\n"; | 538 | sqeData << "[SQE Arg][" << idx << "]: " << taskInfo->args[idx] << "\n"; |
| 533 | } | 539 | } |
| 534 | - auto status = write_or_overwrite_in_cwd(fileName.str(), sqeData.str()); | 540 | + auto status = write_or_overwrite_in_cwd(InstallPath::ResolveToInstallRoot("data/" + fileName.str()), sqeData.str()); |
| 535 | 541 | ||
| 536 | uint32_t index{0}; | 542 | uint32_t index{0}; |
| 537 | auto ret = InsertTaskToCollection(&taskMetaData, &index); | 543 | auto ret = InsertTaskToCollection(&taskMetaData, &index); |
| @@ -252,7 +252,7 @@ int RaSocketBatchConnect(struct SocketConnectInfoT conn[], unsigned int num) | |||
| 252 | HCCL_VM_INFO("[RASOCKET] dev:{} sock:{} connect dev:{} ip addr:{} tag:{}", localSock->device_id, localFd, remoteDevId, ipAddr, conn[i].tag); | 252 | HCCL_VM_INFO("[RASOCKET] dev:{} sock:{} connect dev:{} ip addr:{} tag:{}", localSock->device_id, localFd, remoteDevId, ipAddr, conn[i].tag); |
| 253 | uint32_t count = 0; | 253 | uint32_t count = 0; |
| 254 | while (true) { | 254 | while (true) { |
| 255 | - if (count++ >= 120) { | 255 | + if (count++ >= 600) { // 超时60s |
| 256 | HCCL_VM_ERROR("[RASOCKET] can not get break dev:{} sock:{} connect dev:{} ip addr:{} tag:{}", localSock->device_id, localFd, remoteDevId, ipAddr, conn[i].tag); | 256 | HCCL_VM_ERROR("[RASOCKET] can not get break dev:{} sock:{} connect dev:{} ip addr:{} tag:{}", localSock->device_id, localFd, remoteDevId, ipAddr, conn[i].tag); |
| 257 | break; | 257 | break; |
| 258 | } | 258 | } |
| @@ -261,7 +261,7 @@ int RaSocketBatchConnect(struct SocketConnectInfoT conn[], unsigned int num) | |||
| 261 | return socket.device_id == remoteDevId && socket.endpoint_id == remoteEndPointId; | 261 | return socket.device_id == remoteDevId && socket.endpoint_id == remoteEndPointId; |
| 262 | }); | 262 | }); |
| 263 | if (!remoteSockRes.second) { | 263 | if (!remoteSockRes.second) { |
| 264 | - if (count % 10 == 0) { | 264 | + if (count % 100 == 0) { |
| 265 | HCCL_VM_WARN("[RASOCKET] can not find remote dev:{}, endpoint:{}", remoteDevId, remoteEndPointId); | 265 | HCCL_VM_WARN("[RASOCKET] can not find remote dev:{}, endpoint:{}", remoteDevId, remoteEndPointId); |
| 266 | } | 266 | } |
| 267 | 267 | ||
| @@ -344,12 +344,16 @@ int RaGetSockets(unsigned int role, struct SocketInfoT conn[], unsigned int num, | |||
| 344 | 344 | ||
| 345 | uint32_t count = 0; | 345 | uint32_t count = 0; |
| 346 | bool found = false; | 346 | bool found = false; |
| 347 | - while (count++ < 60) { | 347 | + while (count++ < 180) { |
| 348 | auto remoteSockRes = RunnerDB::GetOneByPred<sim::RaSocket>( | 348 | auto remoteSockRes = RunnerDB::GetOneByPred<sim::RaSocket>( |
| 349 | [remoteDevId, remoteEndpointId](const sim::RaSocket &socket) { | 349 | [remoteDevId, remoteEndpointId](const sim::RaSocket &socket) { |
| 350 | return socket.device_id == remoteDevId && socket.endpoint_id == remoteEndpointId; | 350 | return socket.device_id == remoteDevId && socket.endpoint_id == remoteEndpointId; |
| 351 | }); | 351 | }); |
| 352 | if (!remoteSockRes.second) { | 352 | if (!remoteSockRes.second) { |
| 353 | + if (count % 60 == 0) { | ||
| 354 | + HCCL_VM_WARN("[RASOCKET] waiting for remote socket dev:{}, endpoint:{}, attempt:{}/180", | ||
| 355 | + remoteDevId, remoteEndpointId, count); | ||
| 356 | + } | ||
| 353 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); | 357 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
| 354 | continue; | 358 | continue; |
| 355 | } | 359 | } |
| @@ -364,6 +368,10 @@ int RaGetSockets(unsigned int role, struct SocketInfoT conn[], unsigned int num, | |||
| 364 | }); | 368 | }); |
| 365 | 369 | ||
| 366 | if (!pairRes.second) { | 370 | if (!pairRes.second) { |
| 371 | + if (count % 60 == 0) { | ||
| 372 | + HCCL_VM_WARN("[RASOCKET] waiting for socket pair local:{:d} peer:{:d} tag_hash:{:d}, attempt:{}/180", | ||
| 373 | + loadFd, peerFd, tagHash, count); | ||
| 374 | + } | ||
| 367 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); | 375 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
| 368 | continue; | 376 | continue; |
| 369 | } | 377 | } |
| @@ -35,14 +35,10 @@ int32_t CheckLogLevel(int32_t moduleId, int32_t logLevel) | |||
| 35 | void DlogPrintStub(int level, const char *msgBuffer) | 35 | void DlogPrintStub(int level, const char *msgBuffer) |
| 36 | { | 36 | { |
| 37 | std::call_once(log_initialized_flag, []() { | 37 | std::call_once(log_initialized_flag, []() { |
| 38 | - LogConfig config; | 38 | + if (g_logger != nullptr) { |
| 39 | - config.fileBaseName = "hccl_proxy"; | 39 | + return; |
| 40 | - // auto* proxyConfig = SHMManager::GetProxyConfig(); | 40 | + } |
| 41 | - // if (proxyConfig != nullptr) { | 41 | + LogConfig config = LoadLogConfig("proxy"); |
| 42 | - // config.consoleLevel = proxyConfig->consoleLogLevel; | ||
| 43 | - // config.fileLevel = proxyConfig->fileLogLevel; | ||
| 44 | - // } | ||
| 45 | - config.filePath = "logs/proxy"; | ||
| 46 | InitLogger(config); | 42 | InitLogger(config); |
| 47 | }); | 43 | }); |
| 48 | 44 | ||
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | add_subdirectory(modeldb) | 9 | add_subdirectory(modeldb) |
| 10 | 10 | ||
| 11 | -add_library(runnerdb SHARED) | 11 | +add_library(runnerdb STATIC) |
| 12 | 12 | ||
| 13 | target_sources(runnerdb PRIVATE | 13 | target_sources(runnerdb PRIVATE |
| 14 | ${CMAKE_CURRENT_SOURCE_DIR}/tracedb/db_sim_runner_db.cc | 14 | ${CMAKE_CURRENT_SOURCE_DIR}/tracedb/db_sim_runner_db.cc |
| @@ -25,10 +25,12 @@ target_include_directories(runnerdb PRIVATE | |||
| 25 | ${ASCEND_CANN_PACKAGE_PATH}/include/hccl | 25 | ${ASCEND_CANN_PACKAGE_PATH}/include/hccl |
| 26 | ) | 26 | ) |
| 27 | target_include_directories(runnerdb PRIVATE | 27 | target_include_directories(runnerdb PRIVATE |
| 28 | - ${PROJECT_SOURCE_DIR}/include | 28 | + ${PROJECT_SOURCE_DIR}/include |
| 29 | - ${PROJECT_SOURCE_DIR}/include/runnerdb | 29 | + ${PROJECT_SOURCE_DIR}/include/runnerdb |
| 30 | ) | 30 | ) |
| 31 | 31 | ||
| 32 | +target_link_libraries(runnerdb PUBLIC log modeldb) | ||
| 33 | + | ||
| 32 | target_include_directories(runnerdb PRIVATE | 34 | target_include_directories(runnerdb PRIVATE |
| 33 | # hccl_proxy依赖的Checker L2其他模块的头文件 | 35 | # hccl_proxy依赖的Checker L2其他模块的头文件 |
| 34 | ${HCOMM_VM_ROOT_PATH}/include | 36 | ${HCOMM_VM_ROOT_PATH}/include |
| @@ -43,6 +45,7 @@ target_include_directories(runnerdb PRIVATE | |||
| 43 | ) | 45 | ) |
| 44 | 46 | ||
| 45 | target_compile_options(runnerdb PRIVATE | 47 | target_compile_options(runnerdb PRIVATE |
| 48 | + -fPIC | ||
| 46 | -Werror | 49 | -Werror |
| 47 | -fno-common | 50 | -fno-common |
| 48 | -fno-strict-aliasing | 51 | -fno-strict-aliasing |
| @@ -54,36 +57,5 @@ target_compile_options(runnerdb PRIVATE | |||
| 54 | 57 | ||
| 55 | find_package(SQLite3 REQUIRED) | 58 | find_package(SQLite3 REQUIRED) |
| 56 | 59 | ||
| 57 | -target_link_libraries(runnerdb PRIVATE | 60 | +target_link_libraries(runnerdb PUBLIC SQLite::SQLite3) |
| 58 | - log | ||
| 59 | - modeldb | ||
| 60 | - SQLite::SQLite3 | ||
| 61 | - sqlite3 | ||
| 62 | -) | ||
| 63 | 61 | ||
| 64 | -install(TARGETS runnerdb | ||
| 65 | - DESTINATION "." | ||
| 66 | - # 文件的权限 (755) | ||
| 67 | - PERMISSIONS | ||
| 68 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 69 | - GROUP_READ GROUP_EXECUTE | ||
| 70 | - WORLD_READ WORLD_EXECUTE | ||
| 71 | -) | ||
| 72 | - | ||
| 73 | -install(TARGETS runnerdb | ||
| 74 | - DESTINATION "plugin/validate/runner" | ||
| 75 | - # 文件的权限 (755) | ||
| 76 | - PERMISSIONS | ||
| 77 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 78 | - GROUP_READ GROUP_EXECUTE | ||
| 79 | - WORLD_READ WORLD_EXECUTE | ||
| 80 | -) | ||
| 81 | - | ||
| 82 | -install(TARGETS runnerdb | ||
| 83 | - DESTINATION "plugin/validate/checker" | ||
| 84 | - # 文件的权限 (755) | ||
| 85 | - PERMISSIONS | ||
| 86 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 87 | - GROUP_READ GROUP_EXECUTE | ||
| 88 | - WORLD_READ WORLD_EXECUTE | ||
| 89 | -) | ||
| @@ -15,12 +15,14 @@ target_sources(modeldb PRIVATE | |||
| 15 | ) | 15 | ) |
| 16 | 16 | ||
| 17 | target_include_directories(modeldb PRIVATE | 17 | target_include_directories(modeldb PRIVATE |
| 18 | - ${PROJECT_SOURCE_DIR}/include | 18 | + ${PROJECT_SOURCE_DIR}/include |
| 19 | - ${PROJECT_SOURCE_DIR}/include/runnerdb | 19 | + ${PROJECT_SOURCE_DIR}/include/runnerdb |
| 20 | - ${PROJECT_SOURCE_DIR}/include | ||
| 21 | ) | 20 | ) |
| 22 | 21 | ||
| 22 | +target_link_libraries(modeldb PRIVATE log) | ||
| 23 | + | ||
| 23 | target_compile_options(modeldb PRIVATE | 24 | target_compile_options(modeldb PRIVATE |
| 25 | + -fPIC | ||
| 24 | -Werror | 26 | -Werror |
| 25 | -fno-common | 27 | -fno-common |
| 26 | -fno-strict-aliasing | 28 | -fno-strict-aliasing |
| @@ -32,15 +34,5 @@ target_compile_options(modeldb PRIVATE | |||
| 32 | 34 | ||
| 33 | find_package(SQLite3 REQUIRED) | 35 | find_package(SQLite3 REQUIRED) |
| 34 | 36 | ||
| 35 | -target_link_libraries(modeldb PRIVATE | 37 | +target_link_libraries(modeldb PUBLIC SQLite::SQLite3) |
| 36 | - log | ||
| 37 | - SQLite::SQLite3 | ||
| 38 | -) | ||
| 39 | 38 | ||
| 40 | -install(TARGETS modeldb | ||
| 41 | - DESTINATION "." | ||
| 42 | - PERMISSIONS | ||
| 43 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 44 | - GROUP_READ GROUP_EXECUTE | ||
| 45 | - WORLD_READ WORLD_EXECUTE | ||
| 46 | -) | ||
| @@ -11,12 +11,15 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | + | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 21 | + | ||
| 22 | + | ||
| 20 | 23 | ||
| 21 | namespace HcclSim { | 24 | namespace HcclSim { |
| 22 | namespace DB { | 25 | namespace DB { |
| @@ -29,7 +32,7 @@ OpDbOps::OpDbOps() | |||
| 29 | { | 32 | { |
| 30 | sim::DBConfig config; | 33 | sim::DBConfig config; |
| 31 | config.type = sim::DbType::SQLITE3; | 34 | config.type = sim::DbType::SQLITE3; |
| 32 | - config.dbPath = "./hccl_vm_data.db"; | 35 | + config.dbPath = InstallPath::ResolveToInstallRoot("data/hccl_vm_data.db"); |
| 33 | 36 | ||
| 34 | auto db = HcclSim::DB::HcclDBFactory::Instance().CreateDB(config.type); | 37 | auto db = HcclSim::DB::HcclDBFactory::Instance().CreateDB(config.type); |
| 35 | if (!db || db->Connect(config) != HcclSim::HCCL_SIM_SUCCESS) { | 38 | if (!db || db->Connect(config) != HcclSim::HCCL_SIM_SUCCESS) { |
| @@ -9,6 +9,7 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | + | ||
| 12 | 13 | ||
| 13 | 14 | ||
| 14 | 15 | ||
| @@ -350,12 +351,47 @@ uint32_t GetCubeCoreCount(uint64_t deviceId) | |||
| 350 | return vectorCoreCount; | 351 | return vectorCoreCount; |
| 351 | } | 352 | } |
| 352 | 353 | ||
| 353 | -bool GetRankIdByMPI(uint32_t &rankId) | 354 | +std::set<uint64_t> GetUsedServerNum() |
| 355 | +{ | ||
| 356 | + try { | ||
| 357 | + auto allRanks = RunnerDB::GetByPred<sim::Rank>([](const sim::Rank& d) { | ||
| 358 | + return d.state == 1; | ||
| 359 | + }); | ||
| 360 | + std::set<uint64_t> usedServerIds; | ||
| 361 | + for (auto &rank : allRanks) { | ||
| 362 | + auto deviceKey = rank.device_id; | ||
| 363 | + auto ret = RunnerDB::GetOneByPred<sim::Device>([deviceKey](const sim::Device &d) { | ||
| 364 | + return d.id == deviceKey; | ||
| 365 | + }); | ||
| 366 | + if (!ret.second) { | ||
| 367 | + continue; | ||
| 368 | + } | ||
| 369 | + auto serverId = ret.first.server_id; | ||
| 370 | + usedServerIds.insert(serverId); | ||
| 371 | + } | ||
| 372 | + return usedServerIds; | ||
| 373 | + } catch (const std::exception &e) { | ||
| 374 | + HCCL_VM_ERROR("[GetUsedServerNum] exception: {}", e.what()); | ||
| 375 | + return {}; | ||
| 376 | + } | ||
| 377 | +} | ||
| 378 | + | ||
| 379 | +bool GetRankIdByMPI(uint32_t &rankId, uint64_t &serverId) | ||
| 354 | { | 380 | { |
| 355 | const char *ompiRankStr = std::getenv("OMPI_COMM_WORLD_RANK"); | 381 | const char *ompiRankStr = std::getenv("OMPI_COMM_WORLD_RANK"); |
| 356 | const char *mpichRankStr = std::getenv("PMI_RANK"); | 382 | const char *mpichRankStr = std::getenv("PMI_RANK"); |
| 357 | if (ompiRankStr == nullptr && mpichRankStr == nullptr) { | 383 | if (ompiRankStr == nullptr && mpichRankStr == nullptr) { |
| 358 | - HCCL_VM_ERROR("[HVM] env OMPI_COMM_WORLD_RANK or PMI_RANK are not found."); | 384 | + // 单server用例,默认serverId为1 |
| 385 | + auto usedServerIds = GetUsedServerNum(); | ||
| 386 | + if (usedServerIds.size() == 1) { | ||
| 387 | + if (*usedServerIds.begin() != 1) { | ||
| 388 | + HCCL_VM_ERROR("[HVM] env OMPI_COMM_WORLD_RANK or PMI_RANK are not found, serverId is not 1."); | ||
| 389 | + return false; | ||
| 390 | + } | ||
| 391 | + serverId = 1; | ||
| 392 | + return true; | ||
| 393 | + } | ||
| 394 | + HCCL_VM_ERROR("[HVM] env OMPI_COMM_WORLD_RANK or PMI_RANK are not found, usedServerIds size is not 1."); | ||
| 359 | return false; | 395 | return false; |
| 360 | } else if (ompiRankStr != nullptr) { | 396 | } else if (ompiRankStr != nullptr) { |
| 361 | rankId = static_cast<uint32_t>(atoi(ompiRankStr)); | 397 | rankId = static_cast<uint32_t>(atoi(ompiRankStr)); |
| @@ -74,7 +74,7 @@ bool GetCurrRunnerTls(uint64_t serverKey, Runner &runner) | |||
| 74 | { | 74 | { |
| 75 | if (g_runner.id == 0 && serverKey == 0) | 75 | if (g_runner.id == 0 && serverKey == 0) |
| 76 | { | 76 | { |
| 77 | - HCCL_VM_ERROR("[{}] can not get runner by server key: {:d}", __func__, serverKey); | 77 | + HCCL_VM_ERROR("can not get runner by server key: {:d}", serverKey); |
| 78 | return false; | 78 | return false; |
| 79 | } | 79 | } |
| 80 | if (g_runner.id == 0) { | 80 | if (g_runner.id == 0) { |
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | file(GLOB_RECURSE HCCL_SOURCES "*.cc") | 9 | file(GLOB_RECURSE HCCL_SOURCES "*.cc") |
| 10 | 10 | ||
| 11 | -# 添加共享库 | 11 | +# 添加静态库 |
| 12 | -add_library(store SHARED ${HCCL_SOURCES}) | 12 | +add_library(store STATIC ${HCCL_SOURCES}) |
| 13 | target_compile_options(store PRIVATE | 13 | target_compile_options(store PRIVATE |
| 14 | -fPIC | 14 | -fPIC |
| 15 | -g | 15 | -g |
| @@ -46,27 +46,4 @@ target_include_directories(store PRIVATE | |||
| 46 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime/runtime/rts | 46 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime/runtime/rts |
| 47 | ) | 47 | ) |
| 48 | 48 | ||
| 49 | -target_link_libraries(store PRIVATE | 49 | +target_link_libraries(store PUBLIC log loader) |
| 50 | - log | ||
| 51 | - loader | ||
| 52 | - runnerdb | ||
| 53 | - rt | ||
| 54 | -) | ||
| 55 | - | ||
| 56 | -install(TARGETS store | ||
| 57 | - DESTINATION "." | ||
| 58 | - # 文件的权限 (755) | ||
| 59 | - PERMISSIONS | ||
| 60 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 61 | - GROUP_READ GROUP_EXECUTE | ||
| 62 | - WORLD_READ WORLD_EXECUTE | ||
| 63 | -) | ||
| 64 | - | ||
| 65 | -install(TARGETS store | ||
| 66 | - DESTINATION "plugin/validate/runner" | ||
| 67 | - # 文件的权限 (755) | ||
| 68 | - PERMISSIONS | ||
| 69 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 70 | - GROUP_READ GROUP_EXECUTE | ||
| 71 | - WORLD_READ WORLD_EXECUTE | ||
| 72 | -) | ||
| @@ -20,6 +20,8 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | + | ||
| 24 | + | ||
| 23 | 25 | ||
| 24 | 26 | ||
| 25 | 27 | ||
| @@ -197,9 +199,41 @@ HcclVmResult CreateChannelInfo(HcclVmSynData &hvmSynData) | |||
| 197 | chData.dstDieId = static_cast<uint8_t>(ch.dstDieId); | 199 | chData.dstDieId = static_cast<uint8_t>(ch.dstDieId); |
| 198 | chData.srcRank = ch.srcRankId; | 200 | chData.srcRank = ch.srcRankId; |
| 199 | chData.dstRank = ch.dstRankId; | 201 | chData.dstRank = ch.dstRankId; |
| 202 | + | ||
| 200 | std::memcpy(chData.leid, ch.leid, sizeof(chData.leid)); | 203 | std::memcpy(chData.leid, ch.leid, sizeof(chData.leid)); |
| 201 | std::memcpy(chData.reid, ch.reid, sizeof(chData.reid)); | 204 | std::memcpy(chData.reid, ch.reid, sizeof(chData.reid)); |
| 202 | - chData.protocol = ch.protocol; | 205 | + |
| 206 | + uint8_t* leidPtr = chData.leid; | ||
| 207 | + auto lEpRet = RunnerDB::GetOneByPred<sim::EndPoint>([leidPtr](const sim::EndPoint &ep) { | ||
| 208 | + return memcmp(ep.eid, leidPtr, sizeof(ep.eid)) == 0; | ||
| 209 | + }); | ||
| 210 | + if (!lEpRet.second) { | ||
| 211 | + std::cout<<"cannot find EndPoint by ip addr:"<<leidPtr<< std::endl; | ||
| 212 | + return HcclVmResult::HCCL_SIM_E_NOT_FOUND; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + uint8_t* reidPtr = chData.reid; | ||
| 216 | + auto rEpRet = RunnerDB::GetOneByPred<sim::EndPoint>([reidPtr](const sim::EndPoint &ep) { | ||
| 217 | + return memcmp(ep.eid, reidPtr, sizeof(ep.eid)) == 0; | ||
| 218 | + }); | ||
| 219 | + if (!rEpRet.second) { | ||
| 220 | + std::cout<<"cannot find EndPoint by ip addr:"<<reidPtr<< std::endl; | ||
| 221 | + return HcclVmResult::HCCL_SIM_E_NOT_FOUND; | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + auto localEpId = lEpRet.first.id; | ||
| 225 | + auto remoteEpId = rEpRet.first.id; | ||
| 226 | + | ||
| 227 | + auto pairOpt = RunnerDB::GetOneByPred<sim::EndPointPair>([localEpId, remoteEpId](const sim::EndPointPair &pair) { | ||
| 228 | + return ((pair.local_enpoint_id == localEpId) && (pair.remote_enpoint_id == remoteEpId)); | ||
| 229 | + }); | ||
| 230 | + | ||
| 231 | + if (!pairOpt.second) { | ||
| 232 | + std::cout<<"cannot find EndPointPair by local:"<<localEpId<<" remote:"<<remoteEpId<< std::endl; | ||
| 233 | + return HcclVmResult::HCCL_SIM_E_NOT_FOUND; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + chData.protocol = pairOpt.first.tp_type; | ||
| 203 | chData.jettyNum = ch.jettyNum; | 237 | chData.jettyNum = ch.jettyNum; |
| 204 | // ChannelData.jettyId[32] 仅容纳前 32 个,与 CcuChannelTab.jettyId[64] 差异 | 238 | // ChannelData.jettyId[32] 仅容纳前 32 个,与 CcuChannelTab.jettyId[64] 差异 |
| 205 | uint32_t copyNum = std::min(static_cast<uint32_t>(chData.jettyNum), | 239 | uint32_t copyNum = std::min(static_cast<uint32_t>(chData.jettyNum), |
| @@ -208,7 +242,7 @@ HcclVmResult CreateChannelInfo(HcclVmSynData &hvmSynData) | |||
| 208 | 242 | ||
| 209 | std::cout << "[CreateChannelInfo] channelId=" << chData.channelId | 243 | std::cout << "[CreateChannelInfo] channelId=" << chData.channelId |
| 210 | << ", srcRank=" << chData.srcRank << ", dstRank=" << chData.dstRank | 244 | << ", srcRank=" << chData.srcRank << ", dstRank=" << chData.dstRank |
| 211 | - << ", jettyNum=" << chData.jettyNum << std::endl; | 245 | + << ", jettyNum=" << chData.jettyNum << "protocol:"<< chData.protocol << std::endl; |
| 212 | 246 | ||
| 213 | hvmSynData.channel_info.data.push_back(chData); | 247 | hvmSynData.channel_info.data.push_back(chData); |
| 214 | } | 248 | } |
| @@ -259,7 +293,10 @@ HcclVmResult CreateJettyInfo(HcclVmSynData &hvmSynData) | |||
| 259 | } | 293 | } |
| 260 | 294 | ||
| 261 | uint64_t raCtxHandle = raCtx.first.id; | 295 | uint64_t raCtxHandle = raCtx.first.id; |
| 262 | - auto raJettys = RunnerDB::GetByPred<sim::RaJetty>([raCtxHandle](const sim::RaJetty& jetty) { return jetty.ctx_handle == raCtxHandle; }); | 296 | + auto raJettys = RunnerDB::GetByPred<sim::RaJetty>([raCtxHandle](const sim::RaJetty& jetty) { return jetty.ctx_handle == raCtxHandle && jetty.mode == 3; }); |
| 297 | + if (raJettys.empty()) { | ||
| 298 | + continue; | ||
| 299 | + } | ||
| 263 | channelData.jettyNum = raJettys.size(); | 300 | channelData.jettyNum = raJettys.size(); |
| 264 | for (int i = 0; i < channelData.jettyNum; i++) { | 301 | for (int i = 0; i < channelData.jettyNum; i++) { |
| 265 | channelData.jettyId[i] = raJettys[i].jetty_id; | 302 | channelData.jettyId[i] = raJettys[i].jetty_id; |
| @@ -383,9 +420,8 @@ HcclVmResult DumpHcclVmSynthesisData(const std::string &dataId) | |||
| 383 | char fileName[256]; | 420 | char fileName[256]; |
| 384 | snprintf(fileName, sizeof(fileName), HCCLVM_SYN_DATA_FILE.c_str(), dataId.c_str()); | 421 | snprintf(fileName, sizeof(fileName), HCCLVM_SYN_DATA_FILE.c_str(), dataId.c_str()); |
| 385 | 422 | ||
| 386 | - // 假设 FindRootPath() 已经实现并返回插件根目录 | 423 | + fs::create_directories(fs::path(InstallPath::ResolveToInstallRoot("data"))); |
| 387 | - std::string rootPath = GetBinLocation(); | 424 | + std::string fullPath = InstallPath::ResolveToInstallRoot("data" + std::string(fileName)); |
| 388 | - std::string fullPath = rootPath + DATA_FILE_PATH + fileName; | ||
| 389 | 425 | ||
| 390 | // 构造hccl vm synthesis数据 | 426 | // 构造hccl vm synthesis数据 |
| 391 | HcclVmSynData hvmSynData; | 427 | HcclVmSynData hvmSynData; |
| @@ -471,13 +507,11 @@ HcclVmResult DumpHcclVmInstrData(const std::string &dataId) | |||
| 471 | char fileName[256]; | 507 | char fileName[256]; |
| 472 | snprintf(fileName, sizeof(fileName), HCCLVM_INSTR_DATA_FILE.c_str(), dataId.c_str()); | 508 | snprintf(fileName, sizeof(fileName), HCCLVM_INSTR_DATA_FILE.c_str(), dataId.c_str()); |
| 473 | 509 | ||
| 474 | - // 假设 FindRootPath() 已经实现并返回插件根目录 | 510 | + fs::create_directories(fs::path(InstallPath::ResolveToInstallRoot("data"))); |
| 475 | - std::string rootPath = GetBinLocation(); | 511 | + std::string fullPath = InstallPath::ResolveToInstallRoot("data" + std::string(fileName)); |
| 476 | - std::string fullPath = rootPath + DATA_FILE_PATH + fileName; | ||
| 477 | - | ||
| 478 | FILE *fp = fopen(fullPath.c_str(), "wb"); | 512 | FILE *fp = fopen(fullPath.c_str(), "wb"); |
| 479 | if (!fp) { | 513 | if (!fp) { |
| 480 | - std::cout << "[ERROR][DumpHcclVmInstrData] Open file failed: "<<rootPath << std::endl; | 514 | + std::cout << "[ERROR][DumpHcclVmInstrData] Open file failed: "<<fullPath << std::endl; |
| 481 | return HcclVmResult::HCCL_SIM_E_INTERNAL; | 515 | return HcclVmResult::HCCL_SIM_E_INTERNAL; |
| 482 | } | 516 | } |
| 483 | 517 | ||
| @@ -563,13 +597,12 @@ HcclVmResult DumpHcclVmTask(const std::string &dataId) | |||
| 563 | char fileName[256]; | 597 | char fileName[256]; |
| 564 | snprintf(fileName, sizeof(fileName), HCCLVM_TASK_DATA_FILE.c_str(), dataId.c_str()); | 598 | snprintf(fileName, sizeof(fileName), HCCLVM_TASK_DATA_FILE.c_str(), dataId.c_str()); |
| 565 | 599 | ||
| 566 | - // 假设 FindRootPath() 已经实现并返回插件根目录 | 600 | + fs::create_directories(fs::path(InstallPath::ResolveToInstallRoot("data"))); |
| 567 | - std::string rootPath = GetBinLocation(); | 601 | + std::string fullPath = InstallPath::ResolveToInstallRoot("data" + std::string(fileName)); |
| 568 | - std::string fullPath = rootPath + DATA_FILE_PATH + fileName; | ||
| 569 | 602 | ||
| 570 | FILE *fp = fopen(fullPath.c_str(), "wb"); | 603 | FILE *fp = fopen(fullPath.c_str(), "wb"); |
| 571 | if (!fp) { | 604 | if (!fp) { |
| 572 | - std::cout << "[ERROR][DumpHcclVmTask] Open file failed: "<<rootPath << std::endl; | 605 | + std::cout << "[ERROR][DumpHcclVmTask] Open file failed: "<<fullPath << std::endl; |
| 573 | return HcclVmResult::HCCL_SIM_E_INTERNAL; | 606 | return HcclVmResult::HCCL_SIM_E_INTERNAL; |
| 574 | } | 607 | } |
| 575 | 608 | ||
| @@ -19,7 +19,9 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | + | ||
| 22 | 23 | ||
| 24 | + | ||
| 23 | 25 | ||
| 24 | namespace sim | 26 | namespace sim |
| 25 | { | 27 | { |
| @@ -71,31 +73,62 @@ namespace sim | |||
| 71 | HCCL_VM_INFO("dev:{:d} free vir mem:{:p}", devPhyId, virAddr); | 73 | HCCL_VM_INFO("dev:{:d} free vir mem:{:p}", devPhyId, virAddr); |
| 72 | } | 74 | } |
| 73 | 75 | ||
| 74 | - // 分配物理内存 | 76 | + // 分配物理内存:大块(仅校验模式开)引流到复用区,否则按名独立分配 |
| 75 | void* DeviceMemoryManager::AllocPhyMem(const char* name, uint64_t deviceId, size_t size) | 77 | void* DeviceMemoryManager::AllocPhyMem(const char* name, uint64_t deviceId, size_t size) |
| 76 | { | 78 | { |
| 77 | - HCCL_VM_INFO("dev:{:d} alloc phy mem:{}", deviceId, name); | 79 | + if (name == nullptr) { |
| 80 | + return nullptr; | ||
| 81 | + } | ||
| 82 | + HCCL_VM_INFO("dev:{:d} alloc phy mem:{}, size:{}", deviceId, name, size); | ||
| 83 | + bool checkOnlyMode = IsCheckOnlyMode(); | ||
| 84 | + // 超过复用区上界直接报错,不回退真实分配(避免巨块吃满 /dev/shm)。 | ||
| 85 | + if (CommPoolPolicy::ExceedsCeiling(size, checkOnlyMode)) { | ||
| 86 | + HCCL_VM_ERROR("dev:{:d} alloc phy mem:{} size:{} exceeds pool ceiling:{}, reject", | ||
| 87 | + deviceId, name, size, CommPoolPolicy::kPoolSize); | ||
| 88 | + return nullptr; | ||
| 89 | + } | ||
| 90 | + if (CommPoolPolicy::ShouldRedirect(size, checkOnlyMode)) { | ||
| 91 | + return MemoryManager::GetInstance().AcquireMemByName(CommPoolPolicy::kPoolName); | ||
| 92 | + } | ||
| 78 | return MemoryManager::GetInstance().AllocMemByName(name, size); | 93 | return MemoryManager::GetInstance().AllocMemByName(name, size); |
| 79 | } | 94 | } |
| 80 | 95 | ||
| 81 | - // 释放物理内存 | 96 | + // 释放物理内存(非复用区):是否在复用区由调用方按 size 判断后分流,这里只做真正的释放。 |
| 82 | void DeviceMemoryManager::FreePhyMem(const char* name, uint64_t deviceId) | 97 | void DeviceMemoryManager::FreePhyMem(const char* name, uint64_t deviceId) |
| 83 | { | 98 | { |
| 99 | + if (name == nullptr) { | ||
| 100 | + return; | ||
| 101 | + } | ||
| 84 | HCCL_VM_INFO("dev:{:d} free phy mem:{}", deviceId, name); | 102 | HCCL_VM_INFO("dev:{:d} free phy mem:{}", deviceId, name); |
| 85 | MemoryManager::GetInstance().FreeMemByName(name); | 103 | MemoryManager::GetInstance().FreeMemByName(name); |
| 86 | } | 104 | } |
| 87 | - | 105 | + |
| 88 | - // 获取物理内存 | 106 | + // 获取物理内存:大块(仅校验模式开)引流到复用区,否则按名独立分配 |
| 89 | void* DeviceMemoryManager::AcquirePhyMem(const char* name, uint64_t deviceId, size_t size) | 107 | void* DeviceMemoryManager::AcquirePhyMem(const char* name, uint64_t deviceId, size_t size) |
| 90 | { | 108 | { |
| 91 | - (void) size; | 109 | + if (name == nullptr) { |
| 92 | - HCCL_VM_INFO("dev:{:d} acquire phy mem:{}", deviceId, name); | 110 | + return nullptr; |
| 93 | - return MemoryManager::GetInstance().AcquireMemByName(name); | 111 | + } |
| 112 | + HCCL_VM_INFO("dev:{:d} acquire phy mem:{}, size:{}", deviceId, name, size); | ||
| 113 | + bool checkOnlyMode = IsCheckOnlyMode(); | ||
| 114 | + // 超过复用区上界直接报错,不回退真实分配。 | ||
| 115 | + if (CommPoolPolicy::ExceedsCeiling(size, checkOnlyMode)) { | ||
| 116 | + HCCL_VM_ERROR("dev:{:d} acquire phy mem:{} size:{} exceeds pool ceiling:{}, reject", | ||
| 117 | + deviceId, name, size, CommPoolPolicy::kPoolSize); | ||
| 118 | + return nullptr; | ||
| 119 | + } | ||
| 120 | + if (CommPoolPolicy::ShouldRedirect(size, checkOnlyMode)) { | ||
| 121 | + return MemoryManager::GetInstance().AcquireMemByName(CommPoolPolicy::kPoolName); | ||
| 122 | + } | ||
| 123 | + return MemoryManager::GetInstance().AcquireMemByName(name); | ||
| 94 | } | 124 | } |
| 95 | 125 | ||
| 96 | - // 释放物理内存 | 126 | + // 释放物理内存(非复用区):是否在复用区由调用方按 size 判断后分流,这里只做真正的释放。 |
| 97 | int DeviceMemoryManager::ReleasePhyMem(const char* name, uint64_t deviceId) | 127 | int DeviceMemoryManager::ReleasePhyMem(const char* name, uint64_t deviceId) |
| 98 | { | 128 | { |
| 129 | + if (name == nullptr) { | ||
| 130 | + return 0; | ||
| 131 | + } | ||
| 99 | HCCL_VM_INFO("dev:{:d} release phy mem:{}", deviceId, name); | 132 | HCCL_VM_INFO("dev:{:d} release phy mem:{}", deviceId, name); |
| 100 | MemoryManager::GetInstance().ReleaseMemByName(name); | 133 | MemoryManager::GetInstance().ReleaseMemByName(name); |
| 101 | return 0; | 134 | return 0; |
| @@ -0,0 +1,30 @@ | |||
| 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 | +namespace sim { | ||
| 17 | +bool ProbeCheckOnlyMode() | ||
| 18 | +{ | ||
| 19 | + auto cfg = RunnerDB::GetOneByPred<RunModeConfig>( | ||
| 20 | + [](const RunModeConfig&) { return true; }); | ||
| 21 | + return cfg.second && cfg.first.mode != 0; | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +bool IsCheckOnlyMode() | ||
| 25 | +{ | ||
| 26 | + // 函数局部静态变量初始化线程安全,进程内只读一次并缓存。 | ||
| 27 | + static bool cached = ProbeCheckOnlyMode(); | ||
| 28 | + return cached; | ||
| 29 | +} | ||
| 30 | +} // namespace sim | ||
| @@ -6,7 +6,7 @@ | |||
| 6 | # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 6 | # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| 7 | # See LICENSE in the root of the software repository for the full text of the License. | 7 | # See LICENSE in the root of the software repository for the full text of the License. |
| 8 | 8 | ||
| 9 | -add_library(topo SHARED "") | 9 | +add_library(topo STATIC "") |
| 10 | 10 | ||
| 11 | target_sources(topo PRIVATE | 11 | target_sources(topo PRIVATE |
| 12 | topo_cluster_ir.cc | 12 | topo_cluster_ir.cc |
| @@ -16,7 +16,6 @@ target_sources(topo PRIVATE | |||
| 16 | ) | 16 | ) |
| 17 | 17 | ||
| 18 | target_include_directories(topo PRIVATE | 18 | target_include_directories(topo PRIVATE |
| 19 | - ${THRID_PARTY_DIR} | ||
| 20 | ${THRID_PARTY_DIR}/nlohmann_json | 19 | ${THRID_PARTY_DIR}/nlohmann_json |
| 21 | ${HCOMM_VM_ROOT_PATH}/include | 20 | ${HCOMM_VM_ROOT_PATH}/include |
| 22 | ${HCOMM_VM_ROOT_PATH}/include | 21 | ${HCOMM_VM_ROOT_PATH}/include |
| @@ -30,6 +29,7 @@ target_include_directories(topo PRIVATE | |||
| 30 | ) | 29 | ) |
| 31 | 30 | ||
| 32 | target_compile_options(topo PRIVATE | 31 | target_compile_options(topo PRIVATE |
| 32 | + -fPIC | ||
| 33 | -Werror | 33 | -Werror |
| 34 | -fno-common | 34 | -fno-common |
| 35 | -fno-strict-aliasing | 35 | -fno-strict-aliasing |
| @@ -39,16 +39,4 @@ target_compile_options(topo PRIVATE | |||
| 39 | -D_GLIBCXX_USE_CXX11_ABI=0 | 39 | -D_GLIBCXX_USE_CXX11_ABI=0 |
| 40 | ) | 40 | ) |
| 41 | 41 | ||
| 42 | -target_link_libraries(topo PRIVATE | 42 | +target_link_libraries(topo PRIVATE log) |
| 43 | - runnerdb | ||
| 44 | - log | ||
| 45 | -) | ||
| 46 | - | ||
| 47 | -install(TARGETS topo | ||
| 48 | - DESTINATION "." | ||
| 49 | - # 文件的权限 (755) | ||
| 50 | - PERMISSIONS | ||
| 51 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 52 | - GROUP_READ GROUP_EXECUTE | ||
| 53 | - WORLD_READ WORLD_EXECUTE | ||
| 54 | -) | ||
| @@ -18,10 +18,16 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace fs = std::filesystem; | ||
| 21 | 25 | ||
| 22 | 26 | ||
| 23 | 27 | ||
| 24 | 28 | ||
| 29 | + | ||
| 30 | + | ||
| 25 | 31 | ||
| 26 | 32 | ||
| 27 | 33 | ||
| @@ -107,7 +113,8 @@ HcclVmResult AscendClusterTopoParser::InitClusterTopo(const std::string &cluster | |||
| 107 | HCCL_VM_DEBUG("Total device count: {}", network_.GetTotalDeviceCount()); | 113 | HCCL_VM_DEBUG("Total device count: {}", network_.GetTotalDeviceCount()); |
| 108 | HCCL_VM_DEBUG("Total link count: {}", network_.GetTotalLinkCount()); | 114 | HCCL_VM_DEBUG("Total link count: {}", network_.GetTotalLinkCount()); |
| 109 | 115 | ||
| 110 | - ClusterTopoDumper::DumpToFile(network_, outputFile_); | 116 | + fs::create_directories(fs::path(InstallPath::ResolveToInstallRoot("data"))); |
| 117 | + ClusterTopoDumper::DumpToFile(network_, InstallPath::ResolveToInstallRoot("data/" + outputFile_)); | ||
| 111 | 118 | ||
| 112 | // 3. 初始化IR数据,保存至DB层 | 119 | // 3. 初始化IR数据,保存至DB层 |
| 113 | if (InitClusterStaticTopoData() != HcclVmResult::HCCL_SIM_SUCCESS) { | 120 | if (InitClusterStaticTopoData() != HcclVmResult::HCCL_SIM_SUCCESS) { |
| @@ -307,10 +314,8 @@ HcclVmResult AscendClusterTopoParser::BuildLevelList(const Server &server, int s | |||
| 307 | rankAddrList.push_back(addrEntry); | 314 | rankAddrList.push_back(addrEntry); |
| 308 | } | 315 | } |
| 309 | 316 | ||
| 310 | - if (!rankAddrList.empty()) { | 317 | + levelEntry["rank_addr_list"] = rankAddrList; |
| 311 | - levelEntry["rank_addr_list"] = rankAddrList; | 318 | + levelList.push_back(levelEntry); |
| 312 | - levelList.push_back(levelEntry); | ||
| 313 | - } | ||
| 314 | } | 319 | } |
| 315 | 320 | ||
| 316 | // Process PEER2NET from rootinfo portGroups | 321 | // Process PEER2NET from rootinfo portGroups |
| @@ -411,7 +416,16 @@ HcclVmResult AscendClusterTopoParser::CreateRankTableFile(const TopoMeta &topoMe | |||
| 411 | } | 416 | } |
| 412 | } | 417 | } |
| 413 | 418 | ||
| 414 | - std::string outputPath = "ranktable.json"; | 419 | + std::error_code ec; |
| 420 | + fs::path exePath = fs::read_symlink("/proc/self/exe", ec); | ||
| 421 | + fs::path binDir = ec ? fs::current_path() : exePath.parent_path(); | ||
| 422 | + if (binDir.filename() == "bin") { | ||
| 423 | + binDir = binDir.parent_path(); | ||
| 424 | + } | ||
| 425 | + fs::path dataDir = binDir / "data"; | ||
| 426 | + std::error_code ec2; | ||
| 427 | + fs::create_directories(dataDir, ec2); | ||
| 428 | + std::string outputPath = (dataDir / "ranktable.json").string(); | ||
| 415 | std::ofstream ofs(outputPath); | 429 | std::ofstream ofs(outputPath); |
| 416 | if (!ofs.is_open()) { | 430 | if (!ofs.is_open()) { |
| 417 | HCCL_VM_ERROR("[{}] failed to open ranktable.json for writing", __func__); | 431 | HCCL_VM_ERROR("[{}] failed to open ranktable.json for writing", __func__); |
| @@ -6,21 +6,27 @@ | |||
| 6 | # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 6 | # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| 7 | # See LICENSE in the root of the software repository for the full text of the License. | 7 | # See LICENSE in the root of the software repository for the full text of the License. |
| 8 | 8 | ||
| 9 | -# --- log library (from sim_log.cc) --- | 9 | +# --- log library (sim_log.cc + sim_yaml_config.cc + sim_common.cpp) --- |
| 10 | -add_library(log SHARED sim_log.cc) | 10 | +add_library(log STATIC sim_log.cc sim_yaml_config.cc sim_common_api.cc) |
| 11 | 11 | ||
| 12 | target_include_directories(log PUBLIC | 12 | target_include_directories(log PUBLIC |
| 13 | ${CMAKE_SOURCE_DIR}/include | 13 | ${CMAKE_SOURCE_DIR}/include |
| 14 | ${CMAKE_SOURCE_DIR}/third_party | 14 | ${CMAKE_SOURCE_DIR}/third_party |
| 15 | + ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | ||
| 16 | + ${CMAKE_SOURCE_DIR}/third_party/yaml-cpp/include | ||
| 15 | ) | 17 | ) |
| 16 | 18 | ||
| 17 | target_include_directories(log PRIVATE | 19 | target_include_directories(log PRIVATE |
| 18 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc | 20 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc |
| 19 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime | 21 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime |
| 20 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/profiling | 22 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/profiling |
| 23 | + ${YAMLCPP_INCLUDE_DIR} | ||
| 21 | ) | 24 | ) |
| 22 | 25 | ||
| 26 | +target_compile_definitions(log PRIVATE HAVE_YAML_CPP) | ||
| 27 | + | ||
| 23 | target_compile_options(log PRIVATE | 28 | target_compile_options(log PRIVATE |
| 29 | + -fPIC | ||
| 24 | -std=c++14 | 30 | -std=c++14 |
| 25 | -Werror | 31 | -Werror |
| 26 | -fno-common | 32 | -fno-common |
| @@ -31,32 +37,14 @@ target_compile_options(log PRIVATE | |||
| 31 | -D_GLIBCXX_USE_CXX11_ABI=0 | 37 | -D_GLIBCXX_USE_CXX11_ABI=0 |
| 32 | ) | 38 | ) |
| 33 | 39 | ||
| 34 | -install(TARGETS log | 40 | +target_link_libraries(log PRIVATE yaml-cpp::yaml-cpp) |
| 35 | - DESTINATION "." | ||
| 36 | - PERMISSIONS | ||
| 37 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 38 | - GROUP_READ GROUP_EXECUTE | ||
| 39 | - WORLD_READ WORLD_EXECUTE | ||
| 40 | -) | ||
| 41 | 41 | ||
| 42 | -install(TARGETS log | 42 | +if(TARGET third_party_yaml_cpp) |
| 43 | - DESTINATION "plugin/validate/runner" | 43 | + add_dependencies(log third_party_yaml_cpp) |
| 44 | - PERMISSIONS | 44 | +endif() |
| 45 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 46 | - GROUP_READ GROUP_EXECUTE | ||
| 47 | - WORLD_READ WORLD_EXECUTE | ||
| 48 | -) | ||
| 49 | - | ||
| 50 | -install(TARGETS log | ||
| 51 | - DESTINATION "plugin/validate/checker" | ||
| 52 | - PERMISSIONS | ||
| 53 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 54 | - GROUP_READ GROUP_EXECUTE | ||
| 55 | - WORLD_READ WORLD_EXECUTE | ||
| 56 | -) | ||
| 57 | 45 | ||
| 58 | # --- loader library (from sim_loader.cc, migrated from src/loader) --- | 46 | # --- loader library (from sim_loader.cc, migrated from src/loader) --- |
| 59 | -add_library(loader SHARED sim_loader.cc) | 47 | +add_library(loader STATIC sim_loader.cc) |
| 60 | 48 | ||
| 61 | target_compile_options(loader PRIVATE | 49 | target_compile_options(loader PRIVATE |
| 62 | -fPIC | 50 | -fPIC |
| @@ -95,27 +83,3 @@ target_link_libraries(loader PRIVATE | |||
| 95 | runnerdb | 83 | runnerdb |
| 96 | rt | 84 | rt |
| 97 | ) | 85 | ) |
| 98 | - | ||
| 99 | -install(TARGETS loader | ||
| 100 | - DESTINATION "." | ||
| 101 | - PERMISSIONS | ||
| 102 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 103 | - GROUP_READ GROUP_EXECUTE | ||
| 104 | - WORLD_READ WORLD_EXECUTE | ||
| 105 | -) | ||
| 106 | - | ||
| 107 | -install(TARGETS loader | ||
| 108 | - DESTINATION "plugin/validate/checker" | ||
| 109 | - PERMISSIONS | ||
| 110 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 111 | - GROUP_READ GROUP_EXECUTE | ||
| 112 | - WORLD_READ WORLD_EXECUTE | ||
| 113 | -) | ||
| 114 | - | ||
| 115 | -install(TARGETS loader | ||
| 116 | - DESTINATION "plugin/validate/runner" | ||
| 117 | - PERMISSIONS | ||
| 118 | - OWNER_READ OWNER_WRITE OWNER_EXECUTE | ||
| 119 | - GROUP_READ GROUP_EXECUTE | ||
| 120 | - WORLD_READ WORLD_EXECUTE | ||
| 121 | -) | ||
| @@ -0,0 +1,76 @@ | |||
| 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 | +static std::string GetExePath() | ||
| 20 | +{ | ||
| 21 | + char buf[PATH_MAX] = {0}; | ||
| 22 | + ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); | ||
| 23 | + if (len <= 0) return ""; | ||
| 24 | + buf[len] = '\0'; | ||
| 25 | + return std::string(buf); | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +static std::string GetExeDir() | ||
| 29 | +{ | ||
| 30 | + std::string full = GetExePath(); | ||
| 31 | + if (full.empty()) { | ||
| 32 | + return "."; | ||
| 33 | + } | ||
| 34 | + size_t pos = full.find_last_of('/'); | ||
| 35 | + return (pos == std::string::npos) ? "." : full.substr(0, pos); | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +static std::string ComputeInstallRoot() | ||
| 39 | +{ | ||
| 40 | + const char* env = std::getenv("HCCL_VM_INSTALL_ROOT"); | ||
| 41 | + if (env && *env) { | ||
| 42 | + return std::string(env); | ||
| 43 | + } | ||
| 44 | + std::string exe = GetExePath(); | ||
| 45 | + if (exe.empty()) { | ||
| 46 | + return "."; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + std::string cur = exe; | ||
| 50 | + for (int i = 0; i < 8; ++i) { | ||
| 51 | + size_t pos = cur.find_last_of('/'); | ||
| 52 | + if (pos == std::string::npos || pos == 0) { | ||
| 53 | + break; | ||
| 54 | + } | ||
| 55 | + cur = cur.substr(0, pos); | ||
| 56 | + if (std::ifstream(cur + "/config/log_config.yaml").good()) { | ||
| 57 | + return cur; | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + return GetExeDir(); | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +const std::string& InstallPath::GetHcclVmInstallAbsPath() | ||
| 64 | +{ | ||
| 65 | + static const std::string root = ComputeInstallRoot(); | ||
| 66 | + return root; | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +std::string InstallPath::ResolveToInstallRoot(const std::string& relPath) | ||
| 70 | +{ | ||
| 71 | + if (relPath.empty() || relPath[0] == '/' || | ||
| 72 | + (relPath.size() >= 2 && relPath[0] == '.' && relPath[1] == '/')) { | ||
| 73 | + return relPath; | ||
| 74 | + } | ||
| 75 | + return GetHcclVmInstallAbsPath() + "/" + relPath; | ||
| 76 | +} | ||
| @@ -15,6 +15,8 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 19 | + | ||
| 18 | 20 | ||
| 19 | 21 | ||
| 20 | namespace loader { | 22 | namespace loader { |
| @@ -35,8 +37,9 @@ HcclResult Loader::LoadOpTaskFile(const std::string dbPath) | |||
| 35 | targetPath = dbPath; | 37 | targetPath = dbPath; |
| 36 | HCCL_VM_INFO("[Loader] Loading from specific backup path: {}", targetPath); | 38 | HCCL_VM_INFO("[Loader] Loading from specific backup path: {}", targetPath); |
| 37 | } else { | 39 | } else { |
| 38 | - targetPath = "./../../../hccl_vm_data.db"; | 40 | + targetPath = InstallPath::ResolveToInstallRoot("data/hccl_vm_data.db"); |
| 39 | - HCCL_VM_INFO("[Loader] Loading using default configuration path: {}", targetPath); | 41 | + std::string absPath = std::filesystem::absolute(targetPath).string(); |
| 42 | + HCCL_VM_INFO("[Loader] Loading using default configuration path: {}", absPath); | ||
| 40 | } | 43 | } |
| 41 | 44 | ||
| 42 | config.dbPath = targetPath; | 45 | config.dbPath = targetPath; |
| @@ -11,8 +11,15 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | + | ||
| 14 | 15 | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 15 | 20 | ||
| 21 | + | ||
| 22 | + | ||
| 16 | 23 | ||
| 17 | 24 | ||
| 18 | 25 | ||
| @@ -47,13 +54,11 @@ std::shared_ptr<spdlog::sinks::rotating_file_sink_mt> InitFileSink(const LogConf | |||
| 47 | << config.fileSuffix; | 54 | << config.fileSuffix; |
| 48 | const std::string newPath = oss.str(); | 55 | const std::string newPath = oss.str(); |
| 49 | if (spdlog::details::os::rename(filePath, newPath) != 0) { | 56 | if (spdlog::details::os::rename(filePath, newPath) != 0) { |
| 50 | - std::cout << "[ERROR] Fail to rename rotating log file: " << newPath << std::endl; | 57 | + std::cout << "[ERROR] Fail to rename rotating log file: " << filePath << " -> " << newPath << " current pid " << getpid() << " errno: " << errno << std::endl; |
| 51 | return; | 58 | return; |
| 52 | } | 59 | } |
| 53 | - | ||
| 54 | }; | 60 | }; |
| 55 | 61 | ||
| 56 | - // log file name | ||
| 57 | std::ostringstream logFileName; | 62 | std::ostringstream logFileName; |
| 58 | logFileName << config.filePath << "/" << config.fileBaseName << "_" << std::to_string(getpid()) << config.fileSuffix; | 63 | logFileName << config.filePath << "/" << config.fileBaseName << "_" << std::to_string(getpid()) << config.fileSuffix; |
| 59 | 64 | ||
| @@ -64,6 +69,81 @@ std::shared_ptr<spdlog::sinks::rotating_file_sink_mt> InitFileSink(const LogConf | |||
| 64 | return sink; | 69 | return sink; |
| 65 | } | 70 | } |
| 66 | 71 | ||
| 72 | +static std::string GetLogYamlConfigPath() | ||
| 73 | +{ | ||
| 74 | + const char* env = std::getenv("HCCL_VM_LOG_CONFIG_PATH"); | ||
| 75 | + if (env && *env) { | ||
| 76 | + return env; | ||
| 77 | + } | ||
| 78 | + return InstallPath::ResolveToInstallRoot("config/log_config.yaml"); | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +LogConfig LoadLogConfig(const std::string& process_name) | ||
| 82 | +{ | ||
| 83 | + LogConfig cfg; | ||
| 84 | + | ||
| 85 | + static const std::map<std::string, std::string> yaml_node_map = { | ||
| 86 | + {"device_aarch64", "proxy"} | ||
| 87 | + }; | ||
| 88 | + std::string node_name = process_name; | ||
| 89 | + auto it = yaml_node_map.find(process_name); | ||
| 90 | + if (it != yaml_node_map.end()) { | ||
| 91 | + node_name = it->second; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + std::map<std::string, std::string> fields; | ||
| 95 | + if (LoadYamlStringMap(GetLogYamlConfigPath(), node_name, fields)) { | ||
| 96 | + auto it_console = fields.find("console_level"); | ||
| 97 | + auto it_file = fields.find("file_level"); | ||
| 98 | + auto it_max_size = fields.find("max_file_size"); | ||
| 99 | + auto it_max_num = fields.find("max_files"); | ||
| 100 | + auto it_path = fields.find("file_path"); | ||
| 101 | + auto it_suffix = fields.find("file_suffix"); | ||
| 102 | + auto it_compress = fields.find("enable_compress"); | ||
| 103 | + | ||
| 104 | + if (it_console != fields.end()) { | ||
| 105 | + cfg.consoleLevel = std::stoi(it_console->second); | ||
| 106 | + } | ||
| 107 | + if (it_file != fields.end()) { | ||
| 108 | + cfg.fileLevel = std::stoi(it_file->second); | ||
| 109 | + } | ||
| 110 | + if (it_max_size != fields.end()) { | ||
| 111 | + cfg.maxFileSize = static_cast<size_t>(std::stoull(it_max_size->second)); | ||
| 112 | + } | ||
| 113 | + if (it_max_num != fields.end()) { | ||
| 114 | + cfg.maxFiles = static_cast<size_t>(std::stoull(it_max_num->second)); | ||
| 115 | + } | ||
| 116 | + if (it_path != fields.end()) { | ||
| 117 | + cfg.filePath = InstallPath::ResolveToInstallRoot(it_path->second); | ||
| 118 | + } | ||
| 119 | + if (it_suffix != fields.end()) { | ||
| 120 | + cfg.fileSuffix = it_suffix->second; | ||
| 121 | + } | ||
| 122 | + if (it_compress != fields.end()) { | ||
| 123 | + cfg.enableCompress = (it_compress->second == "true" || it_compress->second == "1"); | ||
| 124 | + } | ||
| 125 | + } else { | ||
| 126 | + if (process_name == "proxy") { | ||
| 127 | + cfg.filePath = InstallPath::ResolveToInstallRoot("logs/proxy"); | ||
| 128 | + } else if (process_name == "device_aarch64") { | ||
| 129 | + cfg.filePath = InstallPath::ResolveToInstallRoot("logs/proxy"); | ||
| 130 | + } else if (process_name == "runner") { | ||
| 131 | + cfg.filePath = InstallPath::ResolveToInstallRoot("logs/runner"); | ||
| 132 | + } else if (process_name == "checker") { | ||
| 133 | + cfg.filePath = InstallPath::ResolveToInstallRoot("logs/checker"); | ||
| 134 | + } else if (process_name == "hccl_vm") { | ||
| 135 | + cfg.filePath = InstallPath::ResolveToInstallRoot("logs"); | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + if (process_name == "device_aarch64") { | ||
| 140 | + cfg.fileBaseName = "proxy_" + std::to_string(getppid()); | ||
| 141 | + } else { | ||
| 142 | + cfg.fileBaseName = process_name; | ||
| 143 | + } | ||
| 144 | + return cfg; | ||
| 145 | +} | ||
| 146 | + | ||
| 67 | void InitLogger(const LogConfig& config) | 147 | void InitLogger(const LogConfig& config) |
| 68 | { | 148 | { |
| 69 | try { | 149 | try { |
| @@ -0,0 +1,50 @@ | |||
| 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 | +bool LoadYamlStringMap(const std::string& yamlPath, | ||
| 23 | + const std::string& nodeName, | ||
| 24 | + std::map<std::string, std::string>& out) | ||
| 25 | +{ | ||
| 26 | + | ||
| 27 | + try { | ||
| 28 | + if (!std::ifstream(yamlPath).good()) { | ||
| 29 | + return false; | ||
| 30 | + } | ||
| 31 | + YAML::Node root = YAML::LoadFile(yamlPath); | ||
| 32 | + if (!root[nodeName]) { | ||
| 33 | + return false; | ||
| 34 | + } | ||
| 35 | + const YAML::Node& node = root[nodeName]; | ||
| 36 | + for (auto it = node.begin(); it != node.end(); ++it) { | ||
| 37 | + out[it->first.as<std::string>()] = it->second.as<std::string>(); | ||
| 38 | + } | ||
| 39 | + return true; | ||
| 40 | + } catch (const std::exception& e) { | ||
| 41 | + HCCL_VM_ERROR("[SimYamlConfig] Failed to parse YAML file {}: {}", yamlPath, e.what()); | ||
| 42 | + return false; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + (void)yamlPath; | ||
| 46 | + (void)nodeName; | ||
| 47 | + (void)out; | ||
| 48 | + return false; | ||
| 49 | + | ||
| 50 | +} | ||
| @@ -69,6 +69,7 @@ target_link_libraries(test_cmd_base_utils PRIVATE | |||
| 69 | cmd | 69 | cmd |
| 70 | store | 70 | store |
| 71 | runnerdb | 71 | runnerdb |
| 72 | + topo | ||
| 72 | log | 73 | log |
| 73 | yaml-cpp | 74 | yaml-cpp |
| 74 | z | 75 | z |
| @@ -116,6 +117,7 @@ target_link_libraries(test_cmd_table_utils PRIVATE | |||
| 116 | cmd | 117 | cmd |
| 117 | store | 118 | store |
| 118 | runnerdb | 119 | runnerdb |
| 120 | + topo | ||
| 119 | log | 121 | log |
| 120 | yaml-cpp | 122 | yaml-cpp |
| 121 | z | 123 | z |
| @@ -155,6 +157,7 @@ target_link_libraries(test_cmd_cluster_model_utils PRIVATE | |||
| 155 | cmd | 157 | cmd |
| 156 | store | 158 | store |
| 157 | runnerdb | 159 | runnerdb |
| 160 | + topo | ||
| 158 | log | 161 | log |
| 159 | yaml-cpp | 162 | yaml-cpp |
| 160 | z | 163 | z |
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | + | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | 17 | ||
| @@ -23,6 +24,7 @@ | |||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | 26 | ||
| 27 | + | ||
| 26 | 28 | ||
| 27 | using namespace HcclSim; | 29 | using namespace HcclSim; |
| 28 | 30 | ||
| @@ -1461,32 +1463,48 @@ class InitHvmEnvTest : public testing::Test { | |||
| 1461 | protected: | 1463 | protected: |
| 1462 | void SetUp() override { | 1464 | void SetUp() override { |
| 1463 | sim::MemoryManager::GetInstance().FreeMemByName("HcclAicpuData"); | 1465 | sim::MemoryManager::GetInstance().FreeMemByName("HcclAicpuData"); |
| 1466 | + shm_unlink("HcclAicpuData"); | ||
| 1467 | + // 逐用例清掉 HcclCommPool 残留。 | ||
| 1468 | + sim::MemoryManager::GetInstance().FreeMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 1469 | + shm_unlink(sim::CommPoolPolicy::kPoolName); | ||
| 1464 | unsetenv("HCCL_OP_EXPANSION_MODE"); | 1470 | unsetenv("HCCL_OP_EXPANSION_MODE"); |
| 1465 | unsetenv("HCCL_VM_INSTALL_DIR"); | 1471 | unsetenv("HCCL_VM_INSTALL_DIR"); |
| 1466 | } | 1472 | } |
| 1467 | void TearDown() override { | 1473 | void TearDown() override { |
| 1468 | sim::MemoryManager::GetInstance().FreeMemByName("HcclAicpuData"); | 1474 | sim::MemoryManager::GetInstance().FreeMemByName("HcclAicpuData"); |
| 1475 | + sim::MemoryManager::GetInstance().FreeMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 1469 | unsetenv("HCCL_OP_EXPANSION_MODE"); | 1476 | unsetenv("HCCL_OP_EXPANSION_MODE"); |
| 1470 | unsetenv("HCCL_VM_INSTALL_DIR"); | 1477 | unsetenv("HCCL_VM_INSTALL_DIR"); |
| 1471 | } | 1478 | } |
| 1472 | }; | 1479 | }; |
| 1473 | 1480 | ||
| 1474 | TEST_F(InitHvmEnvTest, InitializesSharedMemoryWithoutAivValidation) { | 1481 | TEST_F(InitHvmEnvTest, InitializesSharedMemoryWithoutAivValidation) { |
| 1475 | - HcclVmResult ret = InitHvmEnv("/nonexistent/path/for/ut", 2); | 1482 | + HcclVmResult ret = InitHvmEnv("/nonexistent/path/for/ut", 2, false); |
| 1476 | EXPECT_EQ(ret, HCCL_SIM_HOST_SUCCESS_CMD); | 1483 | EXPECT_EQ(ret, HCCL_SIM_HOST_SUCCESS_CMD); |
| 1477 | 1484 | ||
| 1478 | void *shm = sim::MemoryManager::GetInstance().AcquireMemByName("HcclAicpuData"); | 1485 | void *shm = sim::MemoryManager::GetInstance().AcquireMemByName("HcclAicpuData"); |
| 1479 | ASSERT_NE(shm, nullptr); | 1486 | ASSERT_NE(shm, nullptr); |
| 1480 | sim::MemoryManager::GetInstance().ReleaseMemByName("HcclAicpuData"); | 1487 | sim::MemoryManager::GetInstance().ReleaseMemByName("HcclAicpuData"); |
| 1488 | + | ||
| 1489 | + // clean 模式不建复用区 HcclCommPool。 | ||
| 1490 | + EXPECT_EQ(sim::MemoryManager::GetInstance().AcquireMemByName(sim::CommPoolPolicy::kPoolName), nullptr); | ||
| 1481 | } | 1491 | } |
| 1482 | 1492 | ||
| 1483 | TEST_F(InitHvmEnvTest, FailsInAivModeWithoutInstallDir) { | 1493 | TEST_F(InitHvmEnvTest, FailsInAivModeWithoutInstallDir) { |
| 1484 | setenv("HCCL_OP_EXPANSION_MODE", "AIV", 1); | 1494 | setenv("HCCL_OP_EXPANSION_MODE", "AIV", 1); |
| 1485 | 1495 | ||
| 1486 | - HcclVmResult ret = InitHvmEnv("/nonexistent/path/for/ut", 2); | 1496 | + HcclVmResult ret = InitHvmEnv("/nonexistent/path/for/ut", 2, false); |
| 1487 | EXPECT_EQ(ret, HCCL_SIM_HOST_ERROR_CMD); | 1497 | EXPECT_EQ(ret, HCCL_SIM_HOST_ERROR_CMD); |
| 1488 | } | 1498 | } |
| 1489 | 1499 | ||
| 1500 | +TEST_F(InitHvmEnvTest, FailsWhenCommPoolNameAlreadyExists) { | ||
| 1501 | + // 仅校验模式下池名被预先占用时,InitHvmEnv 建池失败、返回错误,且不创建 HcclAicpuData。 | ||
| 1502 | + ASSERT_NE(sim::MemoryManager::GetInstance().AllocMemByName( | ||
| 1503 | + sim::CommPoolPolicy::kPoolName, 4096), nullptr); | ||
| 1504 | + EXPECT_EQ(InitHvmEnv("/nonexistent/path/for/ut", 2, true), HCCL_SIM_HOST_ERROR_CMD); | ||
| 1505 | + EXPECT_EQ(sim::MemoryManager::GetInstance().AcquireMemByName("HcclAicpuData"), nullptr); | ||
| 1506 | +} | ||
| 1507 | + | ||
| 1490 | // ==================== IsAivExpansionModeEnabled Tests ==================== | 1508 | // ==================== IsAivExpansionModeEnabled Tests ==================== |
| 1491 | 1509 | ||
| 1492 | class IsAivExpansionModeEnabledTest : public testing::Test { | 1510 | class IsAivExpansionModeEnabledTest : public testing::Test { |
| @@ -20,7 +20,7 @@ set(SUBCMD_OBJS | |||
| 20 | set(SUBCMD_LIBS | 20 | set(SUBCMD_LIBS |
| 21 | gtest_main gtest | 21 | gtest_main gtest |
| 22 | ${SUBCMD_OBJS} | 22 | ${SUBCMD_OBJS} |
| 23 | - common cmd store runnerdb log yaml-cpp sqlite3 dl rt | 23 | + common cmd store runnerdb topo log yaml-cpp sqlite3 dl rt |
| 24 | z | 24 | z |
| 25 | ) | 25 | ) |
| 26 | 26 | ||
| @@ -21,7 +21,7 @@ set(COMMON_INCLUDE_DIRS | |||
| 21 | ${CMAKE_SOURCE_DIR}/src/plugin/checker/header/external | 21 | ${CMAKE_SOURCE_DIR}/src/plugin/checker/header/external |
| 22 | ${CMAKE_SOURCE_DIR}/third_party/CLI11 | 22 | ${CMAKE_SOURCE_DIR}/third_party/CLI11 |
| 23 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 23 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 24 | - ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 24 | + ${CMAKE_SOURCE_DIR}/third_party |
| 25 | $ENV{HCCL_CODE_HOME}/src/ops/op_common/inc | 25 | $ENV{HCCL_CODE_HOME}/src/ops/op_common/inc |
| 26 | $ENV{HCCL_CODE_HOME}/src/common | 26 | $ENV{HCCL_CODE_HOME}/src/common |
| 27 | $ENV{HCCL_CODE_HOME}/src/common/hcomm_dlsym | 27 | $ENV{HCCL_CODE_HOME}/src/common/hcomm_dlsym |
| @@ -17,7 +17,7 @@ target_include_directories(test_device_vir PRIVATE | |||
| 17 | ${CMAKE_SOURCE_DIR}/include/runnerdb | 17 | ${CMAKE_SOURCE_DIR}/include/runnerdb |
| 18 | ${CMAKE_SOURCE_DIR}/third_party/CLI11 | 18 | ${CMAKE_SOURCE_DIR}/third_party/CLI11 |
| 19 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 19 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 20 | - ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 20 | + ${CMAKE_SOURCE_DIR}/third_party |
| 21 | ) | 21 | ) |
| 22 | 22 | ||
| 23 | target_link_libraries(test_device_vir PRIVATE | 23 | target_link_libraries(test_device_vir PRIVATE |
| @@ -30,7 +30,7 @@ include_directories( | |||
| 30 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/asc/hccl/internal/hcomm/pkg_inc/hcomm/ccu | 30 | ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/asc/hccl/internal/hcomm/pkg_inc/hcomm/ccu |
| 31 | ${HOME} | 31 | ${HOME} |
| 32 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 32 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 33 | - ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 33 | + ${CMAKE_SOURCE_DIR}/third_party |
| 34 | ) | 34 | ) |
| 35 | 35 | ||
| 36 | link_directories( | 36 | link_directories( |
| @@ -28,7 +28,7 @@ include_directories( | |||
| 28 | ${CMAKE_SOURCE_DIR}/include/runnerdb | 28 | ${CMAKE_SOURCE_DIR}/include/runnerdb |
| 29 | ${CMAKE_SOURCE_DIR}/third_party/CLI11 | 29 | ${CMAKE_SOURCE_DIR}/third_party/CLI11 |
| 30 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 30 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 31 | - ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 31 | + ${CMAKE_SOURCE_DIR}/third_party |
| 32 | ${CMAKE_SOURCE_DIR}/third_party | 32 | ${CMAKE_SOURCE_DIR}/third_party |
| 33 | ${CMAKE_SOURCE_DIR}/third_party/spdlog | 33 | ${CMAKE_SOURCE_DIR}/third_party/spdlog |
| 34 | ${CMAKE_SOURCE_DIR}/third_party/spdlog/include | 34 | ${CMAKE_SOURCE_DIR}/third_party/spdlog/include |
| @@ -108,6 +108,9 @@ target_include_directories(test_checker BEFORE PRIVATE | |||
| 108 | ${CHECKER_HDR}/internal | 108 | ${CHECKER_HDR}/internal |
| 109 | ${CHECKER_HDR}/external | 109 | ${CHECKER_HDR}/external |
| 110 | ${CHECKER_HDR}/external/nlohmann | 110 | ${CHECKER_HDR}/external/nlohmann |
| 111 | + ${THRID_PARTY_DIR}/nlohmann_json | ||
| 112 | + ${THRID_PARTY_DIR} | ||
| 113 | + ${THRID_PARTY_DIR}/yaml-cpp/include | ||
| 111 | ${CMAKE_SOURCE_DIR}/src/plugin/runner/ccu_executor | 114 | ${CMAKE_SOURCE_DIR}/src/plugin/runner/ccu_executor |
| 112 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include | 115 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include |
| 113 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc | 116 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc |
| @@ -178,6 +181,9 @@ target_include_directories(test_storage_manager_checker BEFORE PRIVATE | |||
| 178 | ${CHECKER_HDR}/internal | 181 | ${CHECKER_HDR}/internal |
| 179 | ${CHECKER_HDR}/external | 182 | ${CHECKER_HDR}/external |
| 180 | ${CHECKER_HDR}/external/nlohmann | 183 | ${CHECKER_HDR}/external/nlohmann |
| 184 | + ${THRID_PARTY_DIR}/nlohmann_json | ||
| 185 | + ${THRID_PARTY_DIR} | ||
| 186 | + ${THRID_PARTY_DIR}/yaml-cpp/include | ||
| 181 | ${CMAKE_SOURCE_DIR}/src/plugin/runner/ccu_executor | 187 | ${CMAKE_SOURCE_DIR}/src/plugin/runner/ccu_executor |
| 182 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include | 188 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include |
| 183 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc | 189 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc |
| @@ -230,6 +236,9 @@ target_include_directories(test_task_utils BEFORE PRIVATE | |||
| 230 | ${CHECKER_HDR}/internal | 236 | ${CHECKER_HDR}/internal |
| 231 | ${CHECKER_HDR}/external | 237 | ${CHECKER_HDR}/external |
| 232 | ${CHECKER_HDR}/external/nlohmann | 238 | ${CHECKER_HDR}/external/nlohmann |
| 239 | + ${THRID_PARTY_DIR}/nlohmann_json | ||
| 240 | + ${THRID_PARTY_DIR} | ||
| 241 | + ${THRID_PARTY_DIR}/yaml-cpp/include | ||
| 233 | ${CMAKE_SOURCE_DIR}/src/plugin/runner/ccu_executor | 242 | ${CMAKE_SOURCE_DIR}/src/plugin/runner/ccu_executor |
| 234 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc | 243 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc |
| 235 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl | 244 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/pkg_inc/hccl |
| @@ -39,13 +39,20 @@ using Json = nlohmann::json; | |||
| 39 | namespace V3 = HcclSim::TaskGraphGeneratorV3; | 39 | namespace V3 = HcclSim::TaskGraphGeneratorV3; |
| 40 | 40 | ||
| 41 | constexpr uint32_t TASK_MEM_COPY = 0; | 41 | constexpr uint32_t TASK_MEM_COPY = 0; |
| 42 | +constexpr uint32_t TASK_REDUCE = 1; | ||
| 43 | +constexpr uint32_t TASK_SET_FLAG = 2; | ||
| 44 | +constexpr uint32_t TASK_WAIT_FLAG = 3; | ||
| 42 | constexpr uint32_t TASK_PIPE_BARRIER = 4; | 45 | constexpr uint32_t TASK_PIPE_BARRIER = 4; |
| 43 | constexpr uint32_t TASK_SYNC_ALL = 5; | 46 | constexpr uint32_t TASK_SYNC_ALL = 5; |
| 44 | constexpr uint32_t TASK_SEND_FLAG = 6; | 47 | constexpr uint32_t TASK_SEND_FLAG = 6; |
| 45 | constexpr uint32_t TASK_RECV_FLAG = 7; | 48 | constexpr uint32_t TASK_RECV_FLAG = 7; |
| 49 | +constexpr uint32_t BUFFER_OUTPUT = 1; | ||
| 46 | constexpr uint32_t BUFFER_INPUT = 0; | 50 | constexpr uint32_t BUFFER_INPUT = 0; |
| 47 | constexpr uint32_t BUFFER_CCL = 2; | 51 | constexpr uint32_t BUFFER_CCL = 2; |
| 48 | constexpr uint32_t BUFFER_UB = 3; | 52 | constexpr uint32_t BUFFER_UB = 3; |
| 53 | +constexpr uint32_t BUFFER_FLAG = 4; | ||
| 54 | +constexpr uint32_t PIPE_MTE2 = 1; | ||
| 55 | +constexpr uint32_t PIPE_MTE3 = 2; | ||
| 49 | constexpr uint32_t PIPE_ALL = 3; | 56 | constexpr uint32_t PIPE_ALL = 3; |
| 50 | constexpr uint64_t DEFAULT_BUFFER_SIZE = 1ULL << 20; | 57 | constexpr uint64_t DEFAULT_BUFFER_SIZE = 1ULL << 20; |
| 51 | 58 | ||
| @@ -160,6 +167,29 @@ Json MemCopy(uint32_t taskId, uint32_t rank, uint32_t block, uint32_t pipe, uint | |||
| 160 | {"dst", Slice(dstType, dstOffset, size)}}); | 167 | {"dst", Slice(dstType, dstOffset, size)}}); |
| 161 | } | 168 | } |
| 162 | 169 | ||
| 170 | +Json Reduce(uint32_t taskId, uint32_t rank, uint32_t block, uint32_t pipe, uint32_t srcRank, uint32_t dstRank, | ||
| 171 | + uint32_t srcType, uint64_t srcOffset, uint32_t dstType, uint64_t dstOffset, uint64_t size = 64, | ||
| 172 | + uint32_t dataType = 0, uint32_t reduceOp = 0) | ||
| 173 | +{ | ||
| 174 | + return RuntimeTask(TASK_REDUCE, "Reduce", taskId, rank, block, pipe, | ||
| 175 | + Json{{"srcRank", srcRank}, {"dstRank", dstRank}, {"src", Slice(srcType, srcOffset, size)}, | ||
| 176 | + {"dst", Slice(dstType, dstOffset, size)}, {"dataType", dataType}, {"reduceOp", reduceOp}}); | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +Json SetFlag(uint32_t taskId, uint32_t rank, uint32_t block, uint32_t pipe, uint32_t srcPipe, uint32_t dstPipe, | ||
| 180 | + int32_t eventId) | ||
| 181 | +{ | ||
| 182 | + return RuntimeTask(TASK_SET_FLAG, "SetFlag", taskId, rank, block, pipe, | ||
| 183 | + Json{{"srcPipe", srcPipe}, {"dstPipe", dstPipe}, {"eventId", eventId}}); | ||
| 184 | +} | ||
| 185 | + | ||
| 186 | +Json WaitFlag(uint32_t taskId, uint32_t rank, uint32_t block, uint32_t pipe, uint32_t srcPipe, uint32_t dstPipe, | ||
| 187 | + int32_t eventId) | ||
| 188 | +{ | ||
| 189 | + return RuntimeTask(TASK_WAIT_FLAG, "WaitFlag", taskId, rank, block, pipe, | ||
| 190 | + Json{{"srcPipe", srcPipe}, {"dstPipe", dstPipe}, {"eventId", eventId}}); | ||
| 191 | +} | ||
| 192 | + | ||
| 163 | Json NormalTask(uint32_t taskId, uint32_t rank, uint32_t block, uint32_t pipe) | 193 | Json NormalTask(uint32_t taskId, uint32_t rank, uint32_t block, uint32_t pipe) |
| 164 | { | 194 | { |
| 165 | const uint64_t base = 0x20000ULL + static_cast<uint64_t>(rank) * 0x4000ULL + | 195 | const uint64_t base = 0x20000ULL + static_cast<uint64_t>(rank) * 0x4000ULL + |
| @@ -374,6 +404,58 @@ Json SendRecvSnapshot(uint32_t rank, uint32_t rankSize, uint64_t launch) | |||
| 374 | {NormalTask(12, rank, 0, 2)})}); | 404 | {NormalTask(12, rank, 0, 2)})}); |
| 375 | } | 405 | } |
| 376 | 406 | ||
| 407 | +Json CpGm2GMSnapshot(uint32_t rank, uint32_t rankSize, uint64_t launch, uint32_t iterationCount, bool reduceOut, | ||
| 408 | + bool flagMem = false, bool externalGap = false) | ||
| 409 | +{ | ||
| 410 | + std::vector<Json> mte2; | ||
| 411 | + std::vector<Json> mte3; | ||
| 412 | + const uint64_t sliceSize = 64; | ||
| 413 | + const uint32_t extSrcType = flagMem ? BUFFER_FLAG : BUFFER_INPUT; | ||
| 414 | + const uint32_t extDstType = flagMem ? BUFFER_FLAG : BUFFER_OUTPUT; | ||
| 415 | + for (uint32_t index = 0; index < iterationCount; ++index) { | ||
| 416 | + const uint32_t base = 100 + index * 6; | ||
| 417 | + const uint64_t offset = static_cast<uint64_t>(index) * (sliceSize + (externalGap ? sliceSize : 0)); | ||
| 418 | + mte2.push_back(MemCopy(base + 0, rank, 0, PIPE_MTE2, rank, rank, extSrcType, offset, BUFFER_UB, 0, | ||
| 419 | + sliceSize)); | ||
| 420 | + mte2.push_back(SetFlag(base + 1, rank, 0, PIPE_MTE2, PIPE_MTE2, PIPE_MTE3, 0)); | ||
| 421 | + mte2.push_back(WaitFlag(base + 5, rank, 0, PIPE_MTE2, PIPE_MTE3, PIPE_MTE2, 1)); | ||
| 422 | + | ||
| 423 | + mte3.push_back(WaitFlag(base + 2, rank, 0, PIPE_MTE3, PIPE_MTE2, PIPE_MTE3, 0)); | ||
| 424 | + if (reduceOut) { | ||
| 425 | + mte3.push_back(Reduce(base + 3, rank, 0, PIPE_MTE3, rank, rank, BUFFER_UB, 0, extDstType, offset, | ||
| 426 | + sliceSize)); | ||
| 427 | + } else { | ||
| 428 | + mte3.push_back(MemCopy(base + 3, rank, 0, PIPE_MTE3, rank, rank, BUFFER_UB, 0, extDstType, offset, | ||
| 429 | + sliceSize)); | ||
| 430 | + } | ||
| 431 | + mte3.push_back(SetFlag(base + 4, rank, 0, PIPE_MTE3, PIPE_MTE3, PIPE_MTE2, 1)); | ||
| 432 | + } | ||
| 433 | + return Snapshot(rank, rankSize, launch, {Block(0, {}, std::move(mte2), std::move(mte3))}); | ||
| 434 | +} | ||
| 435 | + | ||
| 436 | +Json CpGm2GMPipeBoundarySnapshot(uint32_t rank, uint32_t rankSize, uint64_t launch) | ||
| 437 | +{ | ||
| 438 | + std::vector<Json> mte2{NormalTask(90, rank, 0, PIPE_MTE2)}; | ||
| 439 | + std::vector<Json> mte3{NormalTask(91, rank, 0, PIPE_MTE3)}; | ||
| 440 | + const uint64_t sliceSize = 64; | ||
| 441 | + for (uint32_t index = 0; index < 2; ++index) { | ||
| 442 | + const uint32_t base = 100 + index * 6; | ||
| 443 | + const uint64_t offset = static_cast<uint64_t>(index) * sliceSize; | ||
| 444 | + mte2.push_back(MemCopy(base + 0, rank, 0, PIPE_MTE2, rank, rank, BUFFER_INPUT, offset, BUFFER_UB, 0, | ||
| 445 | + sliceSize)); | ||
| 446 | + mte2.push_back(SetFlag(base + 1, rank, 0, PIPE_MTE2, PIPE_MTE2, PIPE_MTE3, 0)); | ||
| 447 | + mte2.push_back(WaitFlag(base + 5, rank, 0, PIPE_MTE2, PIPE_MTE3, PIPE_MTE2, 1)); | ||
| 448 | + | ||
| 449 | + mte3.push_back(WaitFlag(base + 2, rank, 0, PIPE_MTE3, PIPE_MTE2, PIPE_MTE3, 0)); | ||
| 450 | + mte3.push_back(MemCopy(base + 3, rank, 0, PIPE_MTE3, rank, rank, BUFFER_UB, 0, BUFFER_OUTPUT, offset, | ||
| 451 | + sliceSize)); | ||
| 452 | + mte3.push_back(SetFlag(base + 4, rank, 0, PIPE_MTE3, PIPE_MTE3, PIPE_MTE2, 1)); | ||
| 453 | + } | ||
| 454 | + mte2.push_back(NormalTask(1000, rank, 0, PIPE_MTE2)); | ||
| 455 | + mte3.push_back(NormalTask(1001, rank, 0, PIPE_MTE3)); | ||
| 456 | + return Snapshot(rank, rankSize, launch, {Block(0, {}, std::move(mte2), std::move(mte3))}); | ||
| 457 | +} | ||
| 458 | + | ||
| 377 | struct CaseConfig { | 459 | struct CaseConfig { |
| 378 | std::string name; | 460 | std::string name; |
| 379 | uint32_t rankSize{2}; | 461 | uint32_t rankSize{2}; |
| @@ -497,6 +579,49 @@ size_t CountDirectEdges(const V3::TaskGraphGeneratorV3 &graph, V3::TaskType pare | |||
| 497 | return count; | 579 | return count; |
| 498 | } | 580 | } |
| 499 | 581 | ||
| 582 | +std::vector<const V3::TaskNode *> CollectNodesByType(const V3::TaskGraphGeneratorV3 &graph, V3::TaskType type) | ||
| 583 | +{ | ||
| 584 | + std::vector<const V3::TaskNode *> result; | ||
| 585 | + for (const auto &node : graph.GetNodes()) { | ||
| 586 | + if (node != nullptr && node->GetType() == type) { | ||
| 587 | + result.push_back(node.get()); | ||
| 588 | + } | ||
| 589 | + } | ||
| 590 | + return result; | ||
| 591 | +} | ||
| 592 | + | ||
| 593 | +const V3::TaskNode *FindNodeByTaskId(const V3::TaskGraphGeneratorV3 &graph, uint32_t rank, uint32_t pipe, | ||
| 594 | + uint32_t taskId) | ||
| 595 | +{ | ||
| 596 | + for (const auto &node : graph.GetNodes()) { | ||
| 597 | + if (node == nullptr) { | ||
| 598 | + continue; | ||
| 599 | + } | ||
| 600 | + const V3::TaskPosition &position = node->GetPosition(); | ||
| 601 | + if (position.rankId == rank && position.launchIdx == 0 && position.blockId == 0 && position.pipe == pipe && | ||
| 602 | + position.taskId == taskId) { | ||
| 603 | + return node.get(); | ||
| 604 | + } | ||
| 605 | + } | ||
| 606 | + return nullptr; | ||
| 607 | +} | ||
| 608 | + | ||
| 609 | +size_t CountLinkedNodesByTypeAndPipe(const std::vector<V3::TaskNode *> &nodes, V3::TaskType type, uint32_t pipe, | ||
| 610 | + uint32_t minTaskId) | ||
| 611 | +{ | ||
| 612 | + size_t count = 0; | ||
| 613 | + for (const V3::TaskNode *node : nodes) { | ||
| 614 | + if (node == nullptr) { | ||
| 615 | + continue; | ||
| 616 | + } | ||
| 617 | + const V3::TaskPosition &position = node->GetPosition(); | ||
| 618 | + if (node->GetType() == type && position.pipe == pipe && position.taskId > minTaskId) { | ||
| 619 | + ++count; | ||
| 620 | + } | ||
| 621 | + } | ||
| 622 | + return count; | ||
| 623 | +} | ||
| 624 | + | ||
| 500 | class AivStTest : public testing::Test { | 625 | class AivStTest : public testing::Test { |
| 501 | protected: | 626 | protected: |
| 502 | void SetUp() override | 627 | void SetUp() override |
| @@ -739,3 +864,82 @@ TEST_F(AivStTest, AIV_ST_4P_009_CclCrossRankParallelWriteNoConflict) | |||
| 739 | ASSERT_EQ(result.genRet, HCCL_SUCCESS); | 864 | ASSERT_EQ(result.genRet, HCCL_SUCCESS); |
| 740 | EXPECT_EQ(result.memRet, HCCL_SUCCESS); | 865 | EXPECT_EQ(result.memRet, HCCL_SUCCESS); |
| 741 | } | 866 | } |
| 867 | + | ||
| 868 | +TEST_F(AivStTest, AIV_ST_2P_014_CpGm2GMMemCopyLoopMergePositive) | ||
| 869 | +{ | ||
| 870 | + RunResult result = RunAivCase({"AIV_ST_2P_014", 2, {0}, | ||
| 871 | + [](uint32_t rank, uint64_t launch) { return CpGm2GMSnapshot(rank, 2, launch, 3, false); }}, true); | ||
| 872 | + ASSERT_EQ(result.genRet, HCCL_SUCCESS); | ||
| 873 | + EXPECT_EQ(result.memRet, HCCL_SUCCESS); | ||
| 874 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmLoopMergeCount, 2U); | ||
| 875 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmMergedIterationCount, 6U); | ||
| 876 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmMergedOriginalNodeCount, 36U); | ||
| 877 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmGeneratedNodeCount, 12U); | ||
| 878 | + EXPECT_LT(result.graph->GetAivExpandStats().dagNodeCountAfterCpGmMerge, | ||
| 879 | + result.graph->GetAivExpandStats().dagNodeCountBeforeCpGmMerge); | ||
| 880 | + EXPECT_EQ(CollectNodesByType(*result.graph, V3::TaskType::BATCH_TRANS_MEM).size(), 4U); | ||
| 881 | +} | ||
| 882 | + | ||
| 883 | +TEST_F(AivStTest, AIV_ST_2P_015_CpGm2GMReduceLoopMergePositive) | ||
| 884 | +{ | ||
| 885 | + RunResult result = RunAivCase({"AIV_ST_2P_015", 2, {0}, | ||
| 886 | + [](uint32_t rank, uint64_t launch) { return CpGm2GMSnapshot(rank, 2, launch, 2, true); }}, true); | ||
| 887 | + ASSERT_EQ(result.genRet, HCCL_SUCCESS); | ||
| 888 | + EXPECT_EQ(result.memRet, HCCL_SUCCESS); | ||
| 889 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmLoopMergeCount, 2U); | ||
| 890 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmMergedIterationCount, 4U); | ||
| 891 | + EXPECT_EQ(CollectNodesByType(*result.graph, V3::TaskType::BATCH_TRANS_MEM).size(), 2U); | ||
| 892 | + EXPECT_EQ(CollectNodesByType(*result.graph, V3::TaskType::BATCH_REDUCE).size(), 2U); | ||
| 893 | +} | ||
| 894 | + | ||
| 895 | +TEST_F(AivStTest, AIV_ST_2P_016_CpGm2GMSingleIterationNoMerge) | ||
| 896 | +{ | ||
| 897 | + RunResult result = RunAivCase({"AIV_ST_2P_016", 2, {0}, | ||
| 898 | + [](uint32_t rank, uint64_t launch) { return CpGm2GMSnapshot(rank, 2, launch, 1, false); }}); | ||
| 899 | + ASSERT_EQ(result.genRet, HCCL_SUCCESS); | ||
| 900 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmLoopMergeCount, 0U); | ||
| 901 | + EXPECT_EQ(CollectNodesByType(*result.graph, V3::TaskType::BATCH_TRANS_MEM).size(), 0U); | ||
| 902 | +} | ||
| 903 | + | ||
| 904 | +TEST_F(AivStTest, AIV_ST_2P_017_CpGm2GMFlagMemLoopMergePositive) | ||
| 905 | +{ | ||
| 906 | + RunResult result = RunAivCase({"AIV_ST_2P_017", 2, {0}, | ||
| 907 | + [](uint32_t rank, uint64_t launch) { return CpGm2GMSnapshot(rank, 2, launch, 3, false, true); }}); | ||
| 908 | + ASSERT_EQ(result.genRet, HCCL_SUCCESS); | ||
| 909 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmLoopMergeCount, 2U); | ||
| 910 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmMergedIterationCount, 6U); | ||
| 911 | + EXPECT_EQ(CollectNodesByType(*result.graph, V3::TaskType::BATCH_TRANS_MEM).size(), 4U); | ||
| 912 | +} | ||
| 913 | + | ||
| 914 | +TEST_F(AivStTest, AIV_ST_2P_018_CpGm2GMExternalGapNoMerge) | ||
| 915 | +{ | ||
| 916 | + RunResult result = RunAivCase({"AIV_ST_2P_018", 2, {0}, | ||
| 917 | + [](uint32_t rank, uint64_t launch) { return CpGm2GMSnapshot(rank, 2, launch, 2, false, false, true); }}); | ||
| 918 | + ASSERT_EQ(result.genRet, HCCL_SUCCESS); | ||
| 919 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmLoopMergeCount, 0U); | ||
| 920 | + EXPECT_EQ(CollectNodesByType(*result.graph, V3::TaskType::BATCH_TRANS_MEM).size(), 0U); | ||
| 921 | +} | ||
| 922 | + | ||
| 923 | +TEST_F(AivStTest, AIV_ST_2P_019_CpGm2GMMte3BoundaryKeepPipe) | ||
| 924 | +{ | ||
| 925 | + RunResult result = RunAivCase({"AIV_ST_2P_019", 2, {0}, | ||
| 926 | + [](uint32_t rank, uint64_t launch) { return CpGm2GMPipeBoundarySnapshot(rank, 2, launch); }}); | ||
| 927 | + ASSERT_EQ(result.genRet, HCCL_SUCCESS); | ||
| 928 | + EXPECT_EQ(result.graph->GetAivExpandStats().cpGmLoopMergeCount, 2U); | ||
| 929 | + | ||
| 930 | + constexpr uint32_t minSyntheticTaskId = 1001; | ||
| 931 | + for (uint32_t rank = 0; rank < 2; ++rank) { | ||
| 932 | + const V3::TaskNode *mte3Before = FindNodeByTaskId(*result.graph, rank, PIPE_MTE3, 91); | ||
| 933 | + const V3::TaskNode *mte3After = FindNodeByTaskId(*result.graph, rank, PIPE_MTE3, 1001); | ||
| 934 | + ASSERT_NE(mte3Before, nullptr); | ||
| 935 | + ASSERT_NE(mte3After, nullptr); | ||
| 936 | + EXPECT_EQ(CountLinkedNodesByTypeAndPipe(mte3Before->GetChildren(), V3::TaskType::AIV_WAIT_FLAG, PIPE_MTE3, | ||
| 937 | + minSyntheticTaskId), 1U); | ||
| 938 | + EXPECT_EQ(CountLinkedNodesByTypeAndPipe(mte3Before->GetChildren(), V3::TaskType::BATCH_TRANS_MEM, PIPE_MTE2, | ||
| 939 | + minSyntheticTaskId), 0U); | ||
| 940 | + EXPECT_EQ(CountLinkedNodesByTypeAndPipe(mte3After->GetParents(), V3::TaskType::AIV_SET_FLAG, PIPE_MTE3, | ||
| 941 | + minSyntheticTaskId), 1U); | ||
| 942 | + EXPECT_EQ(CountLinkedNodesByTypeAndPipe(mte3After->GetParents(), V3::TaskType::AIV_WAIT_FLAG, PIPE_MTE2, | ||
| 943 | + minSyntheticTaskId), 0U); | ||
| 944 | + } | ||
| 945 | +} | ||
| @@ -131,6 +131,10 @@ target_sources(test_aiv_task_json PRIVATE | |||
| 131 | set_target_properties(test_aiv_task_json PROPERTIES | 131 | set_target_properties(test_aiv_task_json PROPERTIES |
| 132 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" | 132 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" |
| 133 | ) | 133 | ) |
| 134 | +target_include_directories(test_aiv_task_json PRIVATE | ||
| 135 | + ${THRID_PARTY_DIR}/nlohmann_json | ||
| 136 | + ${THRID_PARTY_DIR} | ||
| 137 | +) | ||
| 134 | target_link_libraries(test_aiv_task_json log pthread) | 138 | target_link_libraries(test_aiv_task_json log pthread) |
| 135 | 139 | ||
| 136 | add_executable(test_aiv_task_snapshot_loader aiv_task_snapshot_loader_test.cc ../main.cc) | 140 | add_executable(test_aiv_task_snapshot_loader aiv_task_snapshot_loader_test.cc ../main.cc) |
| @@ -143,6 +147,11 @@ target_sources(test_aiv_task_snapshot_loader PRIVATE | |||
| 143 | set_target_properties(test_aiv_task_snapshot_loader PROPERTIES | 147 | set_target_properties(test_aiv_task_snapshot_loader PROPERTIES |
| 144 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" | 148 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" |
| 145 | ) | 149 | ) |
| 150 | +target_include_directories(test_aiv_task_snapshot_loader PRIVATE | ||
| 151 | + ${THRID_PARTY_DIR}/nlohmann_json | ||
| 152 | + ${THRID_PARTY_DIR} | ||
| 153 | + ${CMAKE_SOURCE_DIR}/src/plugin/runner/aiv_executor | ||
| 154 | +) | ||
| 146 | target_link_libraries(test_aiv_task_snapshot_loader log pthread) | 155 | target_link_libraries(test_aiv_task_snapshot_loader log pthread) |
| 147 | 156 | ||
| 148 | add_executable(test_aiv_resource_manager aiv_resource_manager_test.cc ../main.cc) | 157 | add_executable(test_aiv_resource_manager aiv_resource_manager_test.cc ../main.cc) |
| @@ -53,6 +53,7 @@ include_directories( | |||
| 53 | ${CMAKE_SOURCE_DIR}/include/store | 53 | ${CMAKE_SOURCE_DIR}/include/store |
| 54 | ${CMAKE_SOURCE_DIR}/include/runnerdb | 54 | ${CMAKE_SOURCE_DIR}/include/runnerdb |
| 55 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 55 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 56 | + ${CMAKE_SOURCE_DIR}/third_party/yaml-cpp/include | ||
| 56 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 57 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json |
| 57 | ) | 58 | ) |
| 58 | 59 | ||
| @@ -147,6 +147,18 @@ set_target_properties(test_aclrt_stub PROPERTIES | |||
| 147 | ) | 147 | ) |
| 148 | target_link_libraries(test_aclrt_stub gtest_main) | 148 | target_link_libraries(test_aclrt_stub gtest_main) |
| 149 | 149 | ||
| 150 | +# test_aclrt_memory_stub —— 主机侧大块引流/上界/FreeHost 行为单测 | ||
| 151 | +# InsertTaskToCollection 由 link_libraries 的 store 库提供,无需额外编 device_arm 源。 | ||
| 152 | +add_executable(test_aclrt_memory_stub aclrt_memory_stub_test.cc) | ||
| 153 | +target_sources(test_aclrt_memory_stub PRIVATE | ||
| 154 | + ${CMAKE_SOURCE_DIR}/src/proxy/aclrt_memory_stub.cc | ||
| 155 | + ${CMAKE_SOURCE_DIR}/src/proxy/hccl_proxy_common.cc | ||
| 156 | +) | ||
| 157 | +set_target_properties(test_aclrt_memory_stub PROPERTIES | ||
| 158 | + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" | ||
| 159 | +) | ||
| 160 | +target_link_libraries(test_aclrt_memory_stub gtest_main) | ||
| 161 | + | ||
| 150 | add_executable(test_hccl_comm_stub hccl_comm_stub_test.cc) | 162 | add_executable(test_hccl_comm_stub hccl_comm_stub_test.cc) |
| 151 | target_sources(test_hccl_comm_stub PRIVATE | 163 | target_sources(test_hccl_comm_stub PRIVATE |
| 152 | ${CMAKE_SOURCE_DIR}/src/proxy/hccl_comm_stub.cc | 164 | ${CMAKE_SOURCE_DIR}/src/proxy/hccl_comm_stub.cc |
| @@ -0,0 +1,147 @@ | |||
| 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 | +// 主机侧单测:覆盖大块引流、上界报错、aclrtFreeHost 身份判定。 | ||
| 12 | +// MallocHost 走真实 MemoryManager 和 HcclCommPool 共享内存,不用 mock。 | ||
| 13 | +// memcpy/memset 的设备侧短路判定由 CommPoolPolicy::ShouldRedirect 的纯函数用例覆盖边界。 | ||
| 14 | +// 本文件聚焦不依赖 RunnerDB/Runner 上下文的主机侧入口。 | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +extern "C" { | ||
| 31 | + aclError aclrtMallocHost(void **hostPtr, size_t size); | ||
| 32 | + aclError aclrtFreeHost(void *hostPtr); | ||
| 33 | + aclError aclrtMallocHostWithCfg(void **ptr, uint64_t size, aclrtMallocConfig *cfg); | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +// aclrt_memory_stub.cc 编进本二进制,其 __attribute__((constructor)) PrimeCheckOnlyMode 在 | ||
| 37 | +// 加载期(先于 main)缓存仅校验模式。须在该构造器之前把 mode=1 写进 DB,否则缓存成 false。 | ||
| 38 | +// 带优先级的构造器先于无优先级的 PrimeCheckOnlyMode 运行,借此抢先写入。 | ||
| 39 | +__attribute__((constructor(101))) static void SeedCheckOnlyMode() | ||
| 40 | +{ | ||
| 41 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 42 | + sim::RunModeConfig cfg{}; | ||
| 43 | + cfg.mode = 1; | ||
| 44 | + RunnerDB::Add<sim::RunModeConfig>(cfg); | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +// 复用区在整个套件期间保持存活,套件开头建池一次,结束再回收。 | ||
| 48 | +class AclrtMemStubTest : public testing::Test { | ||
| 49 | +protected: | ||
| 50 | + static void SetUpTestSuite() { | ||
| 51 | + // 清掉上次异常退出残留的 /dev/shm/HcclCommPool(ShmCreate 用 O_EXCL,残留会建池失败)。 | ||
| 52 | + shm_unlink(sim::CommPoolPolicy::kPoolName); | ||
| 53 | + ASSERT_NE(sim::MemoryManager::GetInstance().AllocMemByName( | ||
| 54 | + sim::CommPoolPolicy::kPoolName, sim::CommPoolPolicy::kPoolSize), nullptr); | ||
| 55 | + } | ||
| 56 | + static void TearDownTestSuite() { | ||
| 57 | + // 关闭并 unlink,保证 /dev/shm 不泄漏,独立重跑不撞 O_EXCL。 | ||
| 58 | + sim::MemoryManager::GetInstance().FreeMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 59 | + // 清掉本套件写进共享 DB 的仅校验模式行,避免给其它测试二进制留下 check-only(mode=1)。 | ||
| 60 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 61 | + } | ||
| 62 | +}; | ||
| 63 | + | ||
| 64 | +// 主机大块两次申请归同一池首址,且与设备侧大块同址,主机与设备共用 HcclCommPool。 | ||
| 65 | +TEST_F(AclrtMemStubTest, MallocHost_BigBlock_TwiceSameAddr_SharesDevicePool) { | ||
| 66 | + EXPECT_TRUE(sim::IsCheckOnlyMode()); // 加载期构造器已写入仅校验模式,首次缓存须为 true。 | ||
| 67 | + const size_t big = sim::CommPoolPolicy::kBigBlockThreshold; // 200MB | ||
| 68 | + void* h1 = nullptr; | ||
| 69 | + void* h2 = nullptr; | ||
| 70 | + ASSERT_EQ(aclrtMallocHost(&h1, big), ACL_SUCCESS); | ||
| 71 | + ASSERT_EQ(aclrtMallocHost(&h2, big), ACL_SUCCESS); | ||
| 72 | + ASSERT_NE(h1, nullptr); | ||
| 73 | + EXPECT_EQ(h1, h2); // 两次大块同址 | ||
| 74 | + | ||
| 75 | + // 设备侧大块也归同一池基址 | ||
| 76 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 77 | + void* d = mgr.AllocPhyMem("host_share_probe", 0, big); | ||
| 78 | + EXPECT_EQ(h1, d); // 主机与设备共用同一池 | ||
| 79 | + mgr.FreePhyMem("host_share_probe", 0); | ||
| 80 | + | ||
| 81 | + EXPECT_EQ(aclrtFreeHost(h1), ACL_SUCCESS); | ||
| 82 | + EXPECT_EQ(aclrtFreeHost(h2), ACL_SUCCESS); | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +// 主机小块走真实 malloc,独立于池,内容正确。 | ||
| 86 | +TEST_F(AclrtMemStubTest, MallocHost_SmallBlock_RealAlloc_NotPool) { | ||
| 87 | + void* big = nullptr; | ||
| 88 | + ASSERT_EQ(aclrtMallocHost(&big, sim::CommPoolPolicy::kBigBlockThreshold), ACL_SUCCESS); | ||
| 89 | + | ||
| 90 | + void* s1 = nullptr; | ||
| 91 | + void* s2 = nullptr; | ||
| 92 | + ASSERT_EQ(aclrtMallocHost(&s1, 4096), ACL_SUCCESS); | ||
| 93 | + ASSERT_EQ(aclrtMallocHost(&s2, 4096), ACL_SUCCESS); | ||
| 94 | + ASSERT_NE(s1, nullptr); | ||
| 95 | + ASSERT_NE(s2, nullptr); | ||
| 96 | + EXPECT_NE(s1, s2); // 两个小块各自独立分配 | ||
| 97 | + EXPECT_NE(s1, big); // 小块不进池 | ||
| 98 | + | ||
| 99 | + // 小块内容正确,互不覆盖 | ||
| 100 | + memset(s1, 0xAA, 4096); | ||
| 101 | + memset(s2, 0xBB, 4096); | ||
| 102 | + EXPECT_EQ(static_cast<unsigned char*>(s1)[0], 0xAAu); | ||
| 103 | + EXPECT_EQ(static_cast<unsigned char*>(s2)[0], 0xBBu); | ||
| 104 | + | ||
| 105 | + EXPECT_EQ(aclrtFreeHost(s1), ACL_SUCCESS); | ||
| 106 | + EXPECT_EQ(aclrtFreeHost(s2), ACL_SUCCESS); | ||
| 107 | + EXPECT_EQ(aclrtFreeHost(big), ACL_SUCCESS); | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +// 主机大块 >4GB 报错,不引流也不真实分配。 | ||
| 111 | +TEST_F(AclrtMemStubTest, MallocHost_ExceedCeiling_Reject) { | ||
| 112 | + void* p = reinterpret_cast<void*>(0xDEADBEEF); // 哨兵:失败时不应被改写 | ||
| 113 | + aclError ret = aclrtMallocHost(&p, sim::CommPoolPolicy::kPoolSize + 1); | ||
| 114 | + EXPECT_NE(ret, ACL_SUCCESS); | ||
| 115 | + EXPECT_EQ(p, reinterpret_cast<void*>(0xDEADBEEF)); // 报错路径未写出指针 | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +// aclrtFreeHost 身份判定:池内地址 noop,池外真实地址正常 free。 | ||
| 119 | +TEST_F(AclrtMemStubTest, FreeHost_PoolAddrNoop_RealAddrFree) { | ||
| 120 | + const size_t big = sim::CommPoolPolicy::kBigBlockThreshold; | ||
| 121 | + void* poolPtr = nullptr; | ||
| 122 | + ASSERT_EQ(aclrtMallocHost(&poolPtr, big), ACL_SUCCESS); | ||
| 123 | + ASSERT_NE(poolPtr, nullptr); | ||
| 124 | + | ||
| 125 | + // 池内地址 free 为 noop:返回成功且池仍可写读 | ||
| 126 | + EXPECT_EQ(aclrtFreeHost(poolPtr), ACL_SUCCESS); | ||
| 127 | + const char* sentinel = "pool-alive-after-noop-free"; | ||
| 128 | + memcpy(poolPtr, sentinel, strlen(sentinel) + 1); | ||
| 129 | + EXPECT_STREQ(static_cast<char*>(poolPtr), sentinel); | ||
| 130 | + | ||
| 131 | + // 池外真实地址:正常 free,不抛异常 | ||
| 132 | + void* real = nullptr; | ||
| 133 | + ASSERT_EQ(aclrtMallocHost(&real, 4096), ACL_SUCCESS); | ||
| 134 | + EXPECT_EQ(aclrtFreeHost(real), ACL_SUCCESS); | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +// MallocHostWithCfg 委托 MallocHost:大块同样引流到池。 | ||
| 138 | +TEST_F(AclrtMemStubTest, MallocHostWithCfg_BigBlock_DelegatesToPool) { | ||
| 139 | + void* viaPlain = nullptr; | ||
| 140 | + void* viaCfg = nullptr; | ||
| 141 | + const size_t big = sim::CommPoolPolicy::kBigBlockThreshold; | ||
| 142 | + ASSERT_EQ(aclrtMallocHost(&viaPlain, big), ACL_SUCCESS); | ||
| 143 | + ASSERT_EQ(aclrtMallocHostWithCfg(&viaCfg, big, nullptr), ACL_SUCCESS); | ||
| 144 | + EXPECT_EQ(viaPlain, viaCfg); // 两条入口归同一池 | ||
| 145 | + aclrtFreeHost(viaPlain); | ||
| 146 | + aclrtFreeHost(viaCfg); | ||
| 147 | +} | ||
| @@ -1,8 +1,8 @@ | |||
| 1 | -# CheckerL2 UT 测试执行脚本 | 1 | +# HCCL_VM UT 测试执行脚本 |
| 2 | 2 | ||
| 3 | ## 概述 | 3 | ## 概述 |
| 4 | 4 | ||
| 5 | -`run_ut.sh` 是 CheckerL2 项目的单元测试执行脚本,用于自动化编译和执行测试用例。 | 5 | +`run_ut.sh` 是 HCCL_VM 项目中的单元测试执行脚本,用于自动化编译和执行测试用例。 |
| 6 | 6 | ||
| 7 | ## 三步流程 | 7 | ## 三步流程 |
| 8 | 8 | ||
| @@ -18,7 +18,7 @@ | |||
| 18 | ## 用法 | 18 | ## 用法 |
| 19 | 19 | ||
| 20 | ```bash | 20 | ```bash |
| 21 | -cd /home/q30033976/checker_0506/CheckerL2/test | 21 | +cd {HCCL_VM路径}/test |
| 22 | 22 | ||
| 23 | # 基本用法 | 23 | # 基本用法 |
| 24 | ./run_ut.sh # 全量编译+执行所有测试 | 24 | ./run_ut.sh # 全量编译+执行所有测试 |
| @@ -139,7 +139,7 @@ cd /home/q30033976/checker_0506/CheckerL2/test | |||
| 139 | 每次执行都会在 `ut_logs/<时间戳>/` 下生成日志文件: | 139 | 每次执行都会在 `ut_logs/<时间戳>/` 下生成日志文件: |
| 140 | 140 | ||
| 141 | ```text | 141 | ```text |
| 142 | -/home/q30033976/checker_0506/CheckerL2/ut_logs/20260425_142048/ | 142 | +{HCCL_VM路径}/ut_logs/20260425_142048/ |
| 143 | ├── build.log # 编译详细日志 (cmake + make 输出) | 143 | ├── build.log # 编译详细日志 (cmake + make 输出) |
| 144 | ├── run.log # 执行详细日志 (每个测试的完整输出) | 144 | ├── run.log # 执行详细日志 (每个测试的完整输出) |
| 145 | └── summary.log # 汇总日志 (每个测试的执行结果) | 145 | └── summary.log # 汇总日志 (每个测试的执行结果) |
| @@ -256,7 +256,7 @@ source /home/myuser/workspace/Ascend/cann/set_env.sh | |||
| 256 | A: 目前脚本设计为编译+执行一体化,如需只编译,请直接使用 cmake 和 make 命令: | 256 | A: 目前脚本设计为编译+执行一体化,如需只编译,请直接使用 cmake 和 make 命令: |
| 257 | 257 | ||
| 258 | ```bash | 258 | ```bash |
| 259 | -cd /home/q30033976/checker_0506/CheckerL2/build | 259 | +cd {HCCL_VM路径}/build |
| 260 | cmake .. && make -j8 test_checker | 260 | cmake .. && make -j8 test_checker |
| 261 | ``` | 261 | ``` |
| 262 | 262 | ||
| @@ -18,7 +18,7 @@ include_directories( | |||
| 18 | ${CMAKE_SOURCE_DIR}/include | 18 | ${CMAKE_SOURCE_DIR}/include |
| 19 | ${CMAKE_SOURCE_DIR}/include/store | 19 | ${CMAKE_SOURCE_DIR}/include/store |
| 20 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 20 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 21 | - ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 21 | + ${CMAKE_SOURCE_DIR}/third_party |
| 22 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include | 22 | ${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux/include |
| 23 | ) | 23 | ) |
| 24 | 24 | ||
| @@ -511,3 +511,36 @@ TEST_F(SimSqliteDbTableTest, AddCcuResource_InsertsRecord) | |||
| 511 | ASSERT_TRUE(found.has_value()); | 511 | ASSERT_TRUE(found.has_value()); |
| 512 | EXPECT_EQ(found->ccu_id, 1); | 512 | EXPECT_EQ(found->ccu_id, 1); |
| 513 | } | 513 | } |
| 514 | + | ||
| 515 | +TEST_F(SimSqliteDbTest, RunModeConfig_WriteThenRead_RoundTrip) { | ||
| 516 | + // RunModeConfig 表惰性注册,ClearAll 不一定覆盖到它,写入前先显式清空,避免跨用例残留。 | ||
| 517 | + SimRunnerSqliteDB::Instance().DeleteAll<sim::RunModeConfig>(); | ||
| 518 | + sim::RunModeConfig cfg{}; | ||
| 519 | + cfg.mode = 1; | ||
| 520 | + SimRunnerSqliteDB::Instance().Add<sim::RunModeConfig>(cfg); | ||
| 521 | + | ||
| 522 | + auto got = SimRunnerSqliteDB::Instance().Query<sim::RunModeConfig>( | ||
| 523 | + [](const sim::RunModeConfig&) { return true; }); | ||
| 524 | + EXPECT_TRUE(got.second); | ||
| 525 | + EXPECT_EQ(got.first.mode, 1); | ||
| 526 | +} | ||
| 527 | + | ||
| 528 | +TEST_F(SimSqliteDbTest, RunModeConfig_DeleteAllThenWrite_LatestSingleRowWins) { | ||
| 529 | + // RunModeConfig 表惰性注册,ClearAll 不一定覆盖到它,进表前先显式清空,避免跨用例残留。 | ||
| 530 | + SimRunnerSqliteDB::Instance().DeleteAll<sim::RunModeConfig>(); | ||
| 531 | + // 先写仅校验模式行,DeleteAll 清空后再写 clean 行:单行覆盖语义,读到的是清空后的最新值。 | ||
| 532 | + sim::RunModeConfig checkOnly{}; | ||
| 533 | + checkOnly.mode = 1; | ||
| 534 | + SimRunnerSqliteDB::Instance().Add<sim::RunModeConfig>(checkOnly); | ||
| 535 | + | ||
| 536 | + SimRunnerSqliteDB::Instance().DeleteAll<sim::RunModeConfig>(); | ||
| 537 | + | ||
| 538 | + sim::RunModeConfig clean{}; | ||
| 539 | + clean.mode = 0; | ||
| 540 | + SimRunnerSqliteDB::Instance().Add<sim::RunModeConfig>(clean); | ||
| 541 | + | ||
| 542 | + auto all = SimRunnerSqliteDB::Instance().QueryList<sim::RunModeConfig>( | ||
| 543 | + [](const sim::RunModeConfig&) { return true; }); | ||
| 544 | + ASSERT_EQ(all.size(), 1); | ||
| 545 | + EXPECT_EQ(all[0].mode, 0); | ||
| 546 | +} | ||
| @@ -32,7 +32,7 @@ include_directories( | |||
| 32 | ${CMAKE_SOURCE_DIR}/include | 32 | ${CMAKE_SOURCE_DIR}/include |
| 33 | ${CMAKE_SOURCE_DIR}/include/runnerdb | 33 | ${CMAKE_SOURCE_DIR}/include/runnerdb |
| 34 | ${CMAKE_SOURCE_DIR}/include | 34 | ${CMAKE_SOURCE_DIR}/include |
| 35 | - ${CMAKE_SOURCE_DIR}/third_party | 35 | + ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json |
| 36 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 36 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 37 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 37 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json |
| 38 | ${CMAKE_SOURCE_DIR}/src | 38 | ${CMAKE_SOURCE_DIR}/src |
| @@ -142,7 +142,7 @@ include_directories( | |||
| 142 | ${CMAKE_SOURCE_DIR}/include | 142 | ${CMAKE_SOURCE_DIR}/include |
| 143 | ${CMAKE_SOURCE_DIR}/include/runnerdb | 143 | ${CMAKE_SOURCE_DIR}/include/runnerdb |
| 144 | ${CMAKE_SOURCE_DIR}/include | 144 | ${CMAKE_SOURCE_DIR}/include |
| 145 | - ${CMAKE_SOURCE_DIR}/third_party | 145 | + ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json |
| 146 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include | 146 | ${CMAKE_BINARY_DIR}/_deps/yaml-cpp-src/include |
| 147 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | 147 | ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json |
| 148 | ) | 148 | ) |
| @@ -169,3 +169,15 @@ target_link_libraries(test_sim_shm_ops_static PRIVATE pthread rt log) | |||
| 169 | set_target_properties(test_sim_shm_ops_static PROPERTIES | 169 | set_target_properties(test_sim_shm_ops_static PROPERTIES |
| 170 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" | 170 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" |
| 171 | ) | 171 | ) |
| 172 | + | ||
| 173 | +add_executable(test_sim_run_mode sim_run_mode_test.cc) | ||
| 174 | +target_link_libraries(test_sim_run_mode PRIVATE pthread rt store runnerdb SQLite::SQLite3 log) | ||
| 175 | +set_target_properties(test_sim_run_mode PROPERTIES | ||
| 176 | + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" | ||
| 177 | +) | ||
| 178 | + | ||
| 179 | +add_executable(test_sim_check_only_off sim_check_only_off_test.cc) | ||
| 180 | +target_link_libraries(test_sim_check_only_off PRIVATE pthread rt store runnerdb SQLite::SQLite3 log) | ||
| 181 | +set_target_properties(test_sim_check_only_off PROPERTIES | ||
| 182 | + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" | ||
| 183 | +) | ||
| @@ -0,0 +1,47 @@ | |||
| 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 | +// clean 模式设备侧集成:IsCheckOnlyMode() 每进程只 latch 一次,本二进制全程不 seed check-only(mode=1), | ||
| 12 | +// 借此验证 clean 模式下大块走真实独立分配(与仅校验模式同址复用对照)。 | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +class CheckOnlyOffTest : public testing::Test { | ||
| 26 | +protected: | ||
| 27 | + void SetUp() override { | ||
| 28 | + // 清进程内/磁盘上残留的 HcclCommPool。 | ||
| 29 | + sim::MemoryManager::GetInstance().FreeMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 30 | + shm_unlink(sim::CommPoolPolicy::kPoolName); | ||
| 31 | + // 清空 RunModeConfig,保证 ProbeCheckOnlyMode 为 false。本文件不写任何 check-only(mode=1) 行。 | ||
| 32 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 33 | + } | ||
| 34 | +}; | ||
| 35 | + | ||
| 36 | +TEST_F(CheckOnlyOffTest, NormalMode_BigBlocks_RealIndependentAlloc) { | ||
| 37 | + EXPECT_FALSE(sim::IsCheckOnlyMode()); // 全程未 seed,首次 latch 须为 false。 | ||
| 38 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 39 | + const size_t big = 256ULL * 1024 * 1024; | ||
| 40 | + void* a = mgr.AllocPhyMem("clean_big_a", 0, big); | ||
| 41 | + void* b = mgr.AllocPhyMem("clean_big_b", 0, big); | ||
| 42 | + ASSERT_NE(a, nullptr); | ||
| 43 | + ASSERT_NE(b, nullptr); | ||
| 44 | + EXPECT_NE(a, b); // clean 模式各自真实独立分配(仅校验模式下两者同为池首址)。 | ||
| 45 | + mgr.FreePhyMem("clean_big_a", 0); | ||
| 46 | + mgr.FreePhyMem("clean_big_b", 0); | ||
| 47 | +} | ||
| @@ -10,11 +10,87 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 13 | 21 | ||
| 14 | 22 | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +// 阈值和上界取自 CommPoolPolicy,下面纯判定用例用这两个短别名。 | ||
| 28 | +static constexpr size_t kThr = sim::CommPoolPolicy::kBigBlockThreshold; // 200MB | ||
| 29 | +static constexpr size_t kPool = sim::CommPoolPolicy::kPoolSize; // 4GB | ||
| 30 | + | ||
| 31 | +// 仅校验模式关:任何 size 都不引流。 | ||
| 32 | +TEST(VmemDecisionTest, CheckOnlyOff_AtThreshold_NoPool) { | ||
| 33 | + EXPECT_FALSE(sim::CommPoolPolicy::ShouldRedirect(kThr, false, kThr, kPool)); | ||
| 34 | +} | ||
| 35 | +TEST(VmemDecisionTest, CheckOnlyOff_AtPoolCeiling_NoPool) { | ||
| 36 | + EXPECT_FALSE(sim::CommPoolPolicy::ShouldRedirect(kPool, false, kThr, kPool)); | ||
| 37 | +} | ||
| 38 | +// 仅校验模式开:边界判定。 | ||
| 39 | +TEST(VmemDecisionTest, ZeroSize_NoPool) { | ||
| 40 | + EXPECT_FALSE(sim::CommPoolPolicy::ShouldRedirect(0, true, kThr, kPool)); | ||
| 41 | +} | ||
| 42 | +TEST(VmemDecisionTest, BelowThreshold_NoPool) { | ||
| 43 | + EXPECT_FALSE(sim::CommPoolPolicy::ShouldRedirect(kThr - 1, true, kThr, kPool)); | ||
| 44 | +} | ||
| 45 | +TEST(VmemDecisionTest, AtThreshold_Pool) { | ||
| 46 | + EXPECT_TRUE(sim::CommPoolPolicy::ShouldRedirect(kThr, true, kThr, kPool)); | ||
| 47 | +} | ||
| 48 | +TEST(VmemDecisionTest, AboveThreshold_Pool) { | ||
| 49 | + EXPECT_TRUE(sim::CommPoolPolicy::ShouldRedirect(kThr + 1, true, kThr, kPool)); | ||
| 50 | +} | ||
| 51 | +TEST(VmemDecisionTest, JustBelowPoolCeiling_Pool) { | ||
| 52 | + EXPECT_TRUE(sim::CommPoolPolicy::ShouldRedirect(kPool - 1, true, kThr, kPool)); | ||
| 53 | +} | ||
| 54 | +TEST(VmemDecisionTest, AtPoolCeiling_Pool) { | ||
| 55 | + EXPECT_TRUE(sim::CommPoolPolicy::ShouldRedirect(kPool, true, kThr, kPool)); | ||
| 56 | +} | ||
| 57 | +TEST(VmemDecisionTest, AbovePoolCeiling_NoPool) { | ||
| 58 | + EXPECT_FALSE(sim::CommPoolPolicy::ShouldRedirect(kPool + 1, true, kThr, kPool)); | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +// 上界纯判定:仅校验模式开 >4GB 拦截报错,==4GB 和小块不拦,仅校验模式关不拦。 | ||
| 62 | +TEST(VmemCeilingTest, WithinCeiling_NotExceed) { | ||
| 63 | + EXPECT_FALSE(sim::CommPoolPolicy::ExceedsCeiling(kPool, true, kPool)); | ||
| 64 | + EXPECT_FALSE(sim::CommPoolPolicy::ExceedsCeiling(kThr, true, kPool)); | ||
| 65 | +} | ||
| 66 | +TEST(VmemCeilingTest, AbovePoolCeiling_Exceed) { | ||
| 67 | + EXPECT_TRUE(sim::CommPoolPolicy::ExceedsCeiling(kPool + 1, true, kPool)); | ||
| 68 | +} | ||
| 69 | +TEST(VmemCeilingTest, CheckOnlyOff_NeverExceed) { | ||
| 70 | + EXPECT_FALSE(sim::CommPoolPolicy::ExceedsCeiling(kPool + 1, false, kPool)); | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +// 建/拆复用区 HcclCommPool。 | ||
| 74 | +static void* CreateCommPool() { | ||
| 75 | + return sim::MemoryManager::GetInstance().AllocMemByName( | ||
| 76 | + sim::CommPoolPolicy::kPoolName, sim::CommPoolPolicy::kPoolSize); | ||
| 77 | +} | ||
| 78 | +static void DestroyCommPool() { | ||
| 79 | + sim::MemoryManager::GetInstance().FreeMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 80 | +} | ||
| 15 | 81 | ||
| 16 | class DeviceMemoryManagerTest : public testing::Test { | 82 | class DeviceMemoryManagerTest : public testing::Test { |
| 17 | protected: | 83 | protected: |
| 84 | + void SetUp() override { | ||
| 85 | + // 清进程内和磁盘上残留的 HcclCommPool,保证乱序和重跑自洽。 | ||
| 86 | + sim::MemoryManager::GetInstance().FreeMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 87 | + shm_unlink(sim::CommPoolPolicy::kPoolName); | ||
| 88 | + // 写入仅校验模式,让 IsCheckOnlyMode() 缓存为 true,大块引流集成用例才会命中复用区。 | ||
| 89 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 90 | + sim::RunModeConfig cfg{}; | ||
| 91 | + cfg.mode = 1; | ||
| 92 | + RunnerDB::Add<sim::RunModeConfig>(cfg); | ||
| 93 | + } | ||
| 18 | void TearDown() override { | 94 | void TearDown() override { |
| 19 | sim::MemoryManager::GetInstance().FreeMemByName("dev_test_phy"); | 95 | sim::MemoryManager::GetInstance().FreeMemByName("dev_test_phy"); |
| 20 | } | 96 | } |
| @@ -124,3 +200,186 @@ TEST_F(DeviceMemoryManagerTest, GetHostPtrByDevPtr_NotExist_ReturnsNull) { | |||
| 124 | void* result = sim::DeviceMemoryManager::GetInstance().GetHostPtrByDevPtr(devPtr); | 200 | void* result = sim::DeviceMemoryManager::GetInstance().GetHostPtrByDevPtr(devPtr); |
| 125 | EXPECT_EQ(result, nullptr); | 201 | EXPECT_EQ(result, nullptr); |
| 126 | } | 202 | } |
| 203 | + | ||
| 204 | +// SetUp 已写入仅校验模式,集成路径走仅校验模式开分支。仅校验模式关时不引流由 VmemDecisionTest 覆盖。 | ||
| 205 | +// 池基址用大块 AllocPhyMem 的返回值获取,命中复用即返回池首址,不依赖内部 getter。 | ||
| 206 | + | ||
| 207 | +TEST_F(DeviceMemoryManagerTest, AllocPhyMem_BigBlocks_ShareSamePool) { | ||
| 208 | + EXPECT_TRUE(sim::IsCheckOnlyMode()); // fixture 已写入仅校验模式,首次缓存须为 true。 | ||
| 209 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 210 | + ASSERT_NE(CreateCommPool(), nullptr); | ||
| 211 | + const size_t big = sim::CommPoolPolicy::kBigBlockThreshold; // 200MB | ||
| 212 | + void* a = mgr.AllocPhyMem("big_a", 0, big); | ||
| 213 | + void* b = mgr.AllocPhyMem("big_b", 0, big); | ||
| 214 | + void* small = mgr.AllocPhyMem("small_c", 0, 1024); | ||
| 215 | + EXPECT_NE(a, nullptr); | ||
| 216 | + EXPECT_EQ(a, b); // 两个大块归同一复用区 | ||
| 217 | + EXPECT_NE(a, small); // 小块走独立真实分配 | ||
| 218 | + mgr.FreePhyMem("big_a", 0); | ||
| 219 | + mgr.FreePhyMem("big_b", 0); | ||
| 220 | + mgr.FreePhyMem("small_c", 0); | ||
| 221 | + DestroyCommPool(); | ||
| 222 | +} | ||
| 223 | + | ||
| 224 | +TEST_F(DeviceMemoryManagerTest, AllocPhyMem_ExceedCeiling_Reject) { | ||
| 225 | + // 仅校验模式下单块 >4GB 报错,不回退真实分配。 | ||
| 226 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 227 | + const size_t tooBig = sim::CommPoolPolicy::kPoolSize + 1; // >4GB | ||
| 228 | + EXPECT_EQ(mgr.AllocPhyMem("too_big_alloc", 0, tooBig), nullptr); | ||
| 229 | + EXPECT_EQ(mgr.AcquirePhyMem("too_big_acq", 0, tooBig), nullptr); | ||
| 230 | + // 报错路径不留记账,后续 free/release 当未记录处理,不抛异常。 | ||
| 231 | + EXPECT_NO_THROW(mgr.FreePhyMem("too_big_alloc", 0)); | ||
| 232 | + EXPECT_EQ(mgr.ReleasePhyMem("too_big_acq", 0), 0); | ||
| 233 | +} | ||
| 234 | + | ||
| 235 | +TEST_F(DeviceMemoryManagerTest, FreePhyMem_BigBlock_PoolReleaseMovedToCaller) { | ||
| 236 | + // 大块引流到复用区,FreePhyMem 走非池释放,对从未单独注册的大块名是空操作。 | ||
| 237 | + // 复用区的释放由 aclrt 调用方完成,不在 FreePhyMem 处理。 | ||
| 238 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 239 | + void* base = CreateCommPool(); | ||
| 240 | + ASSERT_NE(base, nullptr); | ||
| 241 | + void* a = mgr.AllocPhyMem("big_free", 0, sim::CommPoolPolicy::kBigBlockThreshold); | ||
| 242 | + EXPECT_EQ(a, base); // 大块拿到的就是复用区基址 | ||
| 243 | + EXPECT_NO_THROW(mgr.FreePhyMem("big_free", 0)); // 非池释放,不触碰复用区 | ||
| 244 | + // 释放由调用方完成,这里手动配平 AllocPhyMem 内部的那次 acquire | ||
| 245 | + sim::MemoryManager::GetInstance().ReleaseMemByName(sim::CommPoolPolicy::kPoolName); | ||
| 246 | + DestroyCommPool(); | ||
| 247 | +} | ||
| 248 | + | ||
| 249 | +TEST_F(DeviceMemoryManagerTest, AllocPhyMem_SmallBlock_ContentCorrect) { | ||
| 250 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 251 | + ASSERT_NE(CreateCommPool(), nullptr); | ||
| 252 | + char* p = static_cast<char*>(mgr.AllocPhyMem("small_int", 0, 4096)); | ||
| 253 | + ASSERT_NE(p, nullptr); | ||
| 254 | + const char* msg = "checker-vmem-small-correct"; | ||
| 255 | + memcpy(p, msg, strlen(msg) + 1); | ||
| 256 | + EXPECT_STREQ(p, msg); // 小块内容正确 | ||
| 257 | + mgr.FreePhyMem("small_int", 0); // 小块走原逻辑,内部已 FreeMemByName 释放 | ||
| 258 | + DestroyCommPool(); | ||
| 259 | +} | ||
| 260 | + | ||
| 261 | +TEST_F(DeviceMemoryManagerTest, AllocPhyMem_RepeatedBig_NoGrowth) { | ||
| 262 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 263 | + ASSERT_NE(CreateCommPool(), nullptr); | ||
| 264 | + void* first = mgr.AllocPhyMem("loop_0", 0, sim::CommPoolPolicy::kBigBlockThreshold); | ||
| 265 | + mgr.FreePhyMem("loop_0", 0); | ||
| 266 | + for (int i = 1; i < 100; ++i) { | ||
| 267 | + char n[32]; | ||
| 268 | + snprintf(n, sizeof(n), "loop_%d", i); | ||
| 269 | + void* p = mgr.AllocPhyMem(n, 0, sim::CommPoolPolicy::kBigBlockThreshold); | ||
| 270 | + EXPECT_EQ(p, first); // 反复申请恒归同一池、占用不增长 | ||
| 271 | + mgr.FreePhyMem(n, 0); | ||
| 272 | + } | ||
| 273 | + DestroyCommPool(); | ||
| 274 | +} | ||
| 275 | + | ||
| 276 | +TEST_F(DeviceMemoryManagerTest, AllocPhyMem_ConcurrentBig_ThreadSafe) { | ||
| 277 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 278 | + ASSERT_NE(CreateCommPool(), nullptr); | ||
| 279 | + void* base = mgr.AllocPhyMem("cc_base", 0, sim::CommPoolPolicy::kBigBlockThreshold); | ||
| 280 | + mgr.FreePhyMem("cc_base", 0); | ||
| 281 | + std::atomic<int> mismatch{0}; | ||
| 282 | + std::vector<std::thread> ts; | ||
| 283 | + for (int t = 0; t < 8; ++t) { | ||
| 284 | + ts.emplace_back([&, t] { | ||
| 285 | + for (int i = 0; i < 50; ++i) { | ||
| 286 | + char n[40]; | ||
| 287 | + snprintf(n, sizeof(n), "cc_%d_%d", t, i); | ||
| 288 | + void* p = mgr.AllocPhyMem(n, 0, sim::CommPoolPolicy::kBigBlockThreshold); | ||
| 289 | + if (p != base) { | ||
| 290 | + mismatch++; | ||
| 291 | + } | ||
| 292 | + mgr.FreePhyMem(n, 0); | ||
| 293 | + } | ||
| 294 | + }); | ||
| 295 | + } | ||
| 296 | + for (auto& x : ts) { | ||
| 297 | + x.join(); | ||
| 298 | + } | ||
| 299 | + EXPECT_EQ(mismatch.load(), 0); // 并发下均归同一池、无竞态 | ||
| 300 | + DestroyCommPool(); | ||
| 301 | +} | ||
| 302 | + | ||
| 303 | +TEST_F(DeviceMemoryManagerTest, PoolCeiling_FullSpanAddressable_ContentCorrect) { | ||
| 304 | + // 复用区 4GB。验证首址和紧贴 4GB 上界的末字节都能写读、内容正确,整段 4GB 在规格内可寻址。 | ||
| 305 | + // mmap 惰性提交,只触碰的页才落 /dev/shm,只占几页,不会真占 4GB。 | ||
| 306 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 307 | + ASSERT_NE(CreateCommPool(), nullptr); | ||
| 308 | + char* base = static_cast<char*>( | ||
| 309 | + mgr.AllocPhyMem("ceiling_probe", 0, sim::CommPoolPolicy::kBigBlockThreshold)); | ||
| 310 | + ASSERT_NE(base, nullptr); | ||
| 311 | + const size_t pool = sim::CommPoolPolicy::kPoolSize; // 规格 4GB | ||
| 312 | + | ||
| 313 | + // 首址写读 | ||
| 314 | + const char* sHead = "vmem-pool-head"; | ||
| 315 | + memcpy(base, sHead, strlen(sHead) + 1); | ||
| 316 | + EXPECT_STREQ(base, sHead); | ||
| 317 | + | ||
| 318 | + // 紧贴 4GB 上界的最后 64 字节写读,验证整段 4GB 在规格内可寻址 | ||
| 319 | + const char* sTail = "vmem-4G-ceiling"; | ||
| 320 | + char* last = base + pool - 64; | ||
| 321 | + memcpy(last, sTail, strlen(sTail) + 1); | ||
| 322 | + EXPECT_STREQ(last, sTail); | ||
| 323 | + | ||
| 324 | + mgr.FreePhyMem("ceiling_probe", 0); | ||
| 325 | + DestroyCommPool(); | ||
| 326 | +} | ||
| 327 | + | ||
| 328 | +TEST_F(DeviceMemoryManagerTest, AllocPhyMem_BigBlockOverwrite_NoContentGuarantee) { | ||
| 329 | + // 两个不同名大块(两个 rank)都引流到同一池区,后写者覆盖先写者,内容不保证正确。 | ||
| 330 | + // 覆盖是共享后备存储的性质,与进程边界无关,每个 rank 都 Acquire 同一 HcclCommPool。 | ||
| 331 | + // 与小块各自独立分配对照。 | ||
| 332 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 333 | + ASSERT_NE(CreateCommPool(), nullptr); | ||
| 334 | + const size_t big = sim::CommPoolPolicy::kBigBlockThreshold; // 200MB | ||
| 335 | + const size_t probe = 4096; // 只触碰首页,避免真占 200MB | ||
| 336 | + | ||
| 337 | + char* a = static_cast<char*>(mgr.AllocPhyMem("rankA_big", 0, big)); | ||
| 338 | + char* b = static_cast<char*>(mgr.AllocPhyMem("rankB_big", 0, big)); | ||
| 339 | + ASSERT_NE(a, nullptr); | ||
| 340 | + ASSERT_EQ(a, b); // 两个大块别名同一池区 | ||
| 341 | + | ||
| 342 | + memset(a, 0xAA, probe); // rankA 先写 | ||
| 343 | + ASSERT_EQ(static_cast<unsigned char>(a[0]), 0xAAu); | ||
| 344 | + memset(b, 0xBB, probe); // rankB 后写 | ||
| 345 | + // 经 A 读回变成 0xBB,rankA 的数据被 rankB 覆盖 | ||
| 346 | + EXPECT_EQ(static_cast<unsigned char>(a[0]), 0xBBu); | ||
| 347 | + EXPECT_EQ(static_cast<unsigned char>(a[probe - 1]), 0xBBu); | ||
| 348 | + mgr.FreePhyMem("rankA_big", 0); | ||
| 349 | + mgr.FreePhyMem("rankB_big", 0); | ||
| 350 | + | ||
| 351 | + // 对照:两个小块各自独立分配,互不覆盖 | ||
| 352 | + char* sa = static_cast<char*>(mgr.AllocPhyMem("rankA_small", 0, 4096)); | ||
| 353 | + char* sb = static_cast<char*>(mgr.AllocPhyMem("rankB_small", 0, 4096)); | ||
| 354 | + ASSERT_NE(sa, nullptr); | ||
| 355 | + ASSERT_NE(sb, nullptr); | ||
| 356 | + EXPECT_NE(sa, sb); // 小块异址 | ||
| 357 | + memset(sa, 0xAA, 64); | ||
| 358 | + memset(sb, 0xBB, 64); | ||
| 359 | + EXPECT_EQ(static_cast<unsigned char>(sa[0]), 0xAAu); // 小块不被覆盖 | ||
| 360 | + EXPECT_EQ(static_cast<unsigned char>(sb[0]), 0xBBu); | ||
| 361 | + mgr.FreePhyMem("rankA_small", 0); | ||
| 362 | + mgr.FreePhyMem("rankB_small", 0); | ||
| 363 | + DestroyCommPool(); | ||
| 364 | +} | ||
| 365 | + | ||
| 366 | +TEST_F(DeviceMemoryManagerTest, AcquirePhyMem_BigBlockExternalPool_HitsPool) { | ||
| 367 | + // 池由主进程建好,本进程未建池,大块 Acquire 按 size 引流命中同一池。 | ||
| 368 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 369 | + void* poolByMain = CreateCommPool(); | ||
| 370 | + ASSERT_NE(poolByMain, nullptr); | ||
| 371 | + char* big = static_cast<char*>( | ||
| 372 | + mgr.AcquirePhyMem("proxy_big", 0, sim::CommPoolPolicy::kBigBlockThreshold)); | ||
| 373 | + ASSERT_NE(big, nullptr); | ||
| 374 | + EXPECT_EQ(static_cast<void*>(big), poolByMain); // 未建池也命中同一池首址 | ||
| 375 | + mgr.ReleasePhyMem("proxy_big", 0); | ||
| 376 | + DestroyCommPool(); // 强制关闭并 unlink | ||
| 377 | +} | ||
| 378 | + | ||
| 379 | +TEST_F(DeviceMemoryManagerTest, FreeReleasePhyMem_UnrecordedAndNull_Tolerated) { | ||
| 380 | + auto& mgr = sim::DeviceMemoryManager::GetInstance(); | ||
| 381 | + EXPECT_NO_THROW(mgr.FreePhyMem("never_alloced", 0)); | ||
| 382 | + EXPECT_EQ(mgr.ReleasePhyMem("never_acquired", 0), 0); | ||
| 383 | + EXPECT_EQ(mgr.AllocPhyMem(nullptr, 0, sim::CommPoolPolicy::kBigBlockThreshold), nullptr); | ||
| 384 | + EXPECT_EQ(mgr.AcquirePhyMem(nullptr, 0, sim::CommPoolPolicy::kBigBlockThreshold), nullptr); | ||
| 385 | +} | ||
| @@ -0,0 +1,36 @@ | |||
| 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 | +// 表为空时 ProbeCheckOnlyMode 返回 false。 | ||
| 17 | +TEST(RunModeTest, ProbeCheckOnlyMode_EmptyTable_False) { | ||
| 18 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 19 | + EXPECT_FALSE(sim::ProbeCheckOnlyMode()); | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +// 写入 mode=1 后 ProbeCheckOnlyMode 返回 true。 | ||
| 23 | +TEST(RunModeTest, ProbeCheckOnlyMode_CheckOnlyRow_True) { | ||
| 24 | + RunnerDB::DeleteAll<sim::RunModeConfig>(); | ||
| 25 | + sim::RunModeConfig cfg{}; | ||
| 26 | + cfg.mode = 1; | ||
| 27 | + RunnerDB::Add<sim::RunModeConfig>(cfg); | ||
| 28 | + EXPECT_TRUE(sim::ProbeCheckOnlyMode()); | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +// IsCheckOnlyMode 进程内 latch:第二次调用与第一次一致。 | ||
| 32 | +TEST(RunModeTest, IsCheckOnlyMode_Latches) { | ||
| 33 | + bool first = sim::IsCheckOnlyMode(); | ||
| 34 | + bool second = sim::IsCheckOnlyMode(); | ||
| 35 | + EXPECT_EQ(first, second); | ||
| 36 | +} | ||
| @@ -13,10 +13,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) | |||
| 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -D_GLIBCXX_USE_CXX11_ABI=0") | 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -D_GLIBCXX_USE_CXX11_ABI=0") |
| 14 | 14 | ||
| 15 | include_directories( | 15 | include_directories( |
| 16 | - ${CMAKE_SOURCE_DIR}/include | ||
| 17 | ${CMAKE_SOURCE_DIR}/include | 16 | ${CMAKE_SOURCE_DIR}/include |
| 18 | ${CMAKE_SOURCE_DIR}/src/utils | 17 | ${CMAKE_SOURCE_DIR}/src/utils |
| 19 | ${CMAKE_SOURCE_DIR}/third_party | 18 | ${CMAKE_SOURCE_DIR}/third_party |
| 19 | + ${CMAKE_SOURCE_DIR}/third_party/nlohmann_json | ||
| 20 | + ${CMAKE_SOURCE_DIR}/third_party/yaml-cpp/include | ||
| 20 | ) | 21 | ) |
| 21 | 22 | ||
| 22 | link_libraries( | 23 | link_libraries( |
| @@ -27,8 +28,10 @@ link_libraries( | |||
| 27 | add_executable(test_sim_log | 28 | add_executable(test_sim_log |
| 28 | sim_log_test.cc | 29 | sim_log_test.cc |
| 29 | ${CMAKE_SOURCE_DIR}/src/utils/sim_log.cc | 30 | ${CMAKE_SOURCE_DIR}/src/utils/sim_log.cc |
| 31 | + ${CMAKE_SOURCE_DIR}/src/utils/sim_yaml_config.cc | ||
| 32 | + ${CMAKE_SOURCE_DIR}/src/utils/sim_common_api.cc | ||
| 30 | ) | 33 | ) |
| 31 | -target_link_libraries(test_sim_log pthread) | 34 | +target_link_libraries(test_sim_log pthread yaml-cpp::yaml-cpp) |
| 32 | set_target_properties(test_sim_log PROPERTIES | 35 | set_target_properties(test_sim_log PROPERTIES |
| 33 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" | 36 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output/bin" |
| 34 | ) | 37 | ) |