| @@ -13,9 +13,9 @@ if(NOT ENABLE_EXPERIMENTAL) | |||
| 13 | endif() | 13 | endif() |
| 14 | 14 | ||
| 15 | add_subdirectory(op_common) | 15 | add_subdirectory(op_common) |
| 16 | +add_subdirectory(all_reduce) | ||
| 16 | add_subdirectory(reduce_scatter) | 17 | add_subdirectory(reduce_scatter) |
| 17 | add_subdirectory(reduce_scatter_v) | 18 | add_subdirectory(reduce_scatter_v) |
| 18 | -add_subdirectory(all_reduce/example) | ||
| 19 | 19 | ||
| 20 | set(EXPERIMENTAL_INCLUDE_LIST | 20 | set(EXPERIMENTAL_INCLUDE_LIST |
| 21 | ${CMAKE_CURRENT_SOURCE_DIR}/../ | 21 | ${CMAKE_CURRENT_SOURCE_DIR}/../ |
| @@ -23,18 +23,20 @@ set(EXPERIMENTAL_INCLUDE_LIST | |||
| 23 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/ | 23 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/ |
| 24 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/template | 24 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/template |
| 25 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/topo | 25 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/topo |
| 26 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/ | ||
| 27 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/biar/ | ||
| 28 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/biar/template/ | ||
| 29 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/ | ||
| 30 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/template/ | ||
| 31 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/template/ccu/ | ||
| 32 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/template/ccu/kernel/ | ||
| 33 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/executor/ | ||
| 26 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/ | 34 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/ |
| 27 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/ | 35 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/ |
| 28 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/template/ | 36 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/template/ |
| 29 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter_v/ | 37 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter_v/ |
| 30 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter_v/birs/ | 38 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter_v/birs/ |
| 31 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter_v/birs/template/ | 39 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter_v/birs/template/ |
| 32 | - ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/ | ||
| 33 | - ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/ | ||
| 34 | - ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/template/ | ||
| 35 | - ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/template/ccu/ | ||
| 36 | - ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/template/ccu/kernel/ | ||
| 37 | - ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/example/executor/ | ||
| 38 | ) | 40 | ) |
| 39 | 41 | ||
| 40 | if(TARGET scatter_aicpu_kernel) | 42 | if(TARGET scatter_aicpu_kernel) |
| @@ -43,6 +45,10 @@ if(TARGET scatter_aicpu_kernel) | |||
| 43 | target_sources(scatter_aicpu_kernel PRIVATE | 45 | target_sources(scatter_aicpu_kernel PRIVATE |
| 44 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/template/alg_template_base_experimental.cc | 46 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/template/alg_template_base_experimental.cc |
| 45 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/topo/topo_experimental.cc | 47 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common/topo/topo_experimental.cc |
| 48 | + ${CMAKE_CURRENT_SOURCE_DIR}/op_common/coll_executor_base_experimental.cc | ||
| 49 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/biar/all_reduce_biar_executor.cc | ||
| 50 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/biar/all_reduce_executor_base.cc | ||
| 51 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce/biar/template/all_reduce_biar.cc | ||
| 46 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/reduce_scatter_birs_executor.cc | 52 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/reduce_scatter_birs_executor.cc |
| 47 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/reduce_scatter_executor_base.cc | 53 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/reduce_scatter_executor_base.cc |
| 48 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/template/reduce_scatter_birs.cc | 54 | ${CMAKE_CURRENT_SOURCE_DIR}/reduce_scatter/birs/template/reduce_scatter_birs.cc |
| @@ -0,0 +1,26 @@ | |||
| 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 | +if(NOT ENABLE_EXPERIMENTAL) | ||
| 12 | + return() | ||
| 13 | +endif() | ||
| 14 | + | ||
| 15 | +add_subdirectory(biar) | ||
W | |||
| 16 | +add_subdirectory(example) | ||
| 17 | + | ||
| 18 | +set(src_list | ||
| 19 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce_op_experimental.cc | ||
| 20 | +) | ||
| 21 | + | ||
| 22 | +if(TARGET hccl) | ||
| 23 | + target_sources(hccl PRIVATE | ||
| 24 | + ${src_list} | ||
| 25 | + ) | ||
| 26 | +endif() | ||
| @@ -0,0 +1,157 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include "all_reduce_op_experimental.h" | ||
| 12 | +#include "reduce_scatter_op_experimental.h" | ||
| 13 | +#include "topo_host.h" | ||
| 14 | +#include <algorithm> | ||
| 15 | +#include <future> | ||
| 16 | +#include <map> | ||
| 17 | +#include <string> | ||
| 18 | +#include "op_common_experimental.h" | ||
| 19 | +#include "param_check.h" | ||
| 20 | +#include "all_reduce.h" | ||
| 21 | +#include "load_kernel.h" | ||
| 22 | +#include "hcomm_dlsym.h" | ||
| 23 | +#include "hcomm_host_profiling_dl.h" | ||
| 24 | + | ||
| 25 | +using namespace std; | ||
| 26 | + | ||
| 27 | +extern "C" HcclResult HcclAllReduceInner( | ||
| 28 | + void* sendBuf, void* recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, | ||
| 29 | + aclrtStream stream); | ||
| 30 | + | ||
| 31 | +namespace ops_hccl_experimental { | ||
| 32 | +using ops_hccl::AllReduceEntryLog; | ||
| 33 | +using ops_hccl::DATATYPE_SIZE_TABLE; | ||
| 34 | +using ops_hccl::HcclNetLayer; | ||
| 35 | +using ops_hccl::LoadAICPUKernel; | ||
| 36 | +using ops_hccl::LogHcclExit; | ||
| 37 | +using ops_hccl::OpMode; | ||
| 38 | + | ||
| 39 | +static bool MatchBIAR(HcclComm comm) | ||
| 40 | +{ | ||
| 41 | + if (!MatchBIRS()) { | ||
[LOW] HCCL_BIRS_ENABLE 语义扩展至 AllReduce 未同步文档 问题分析:
MatchBIAR 复用 MatchBIRS(即 HCCL_BIRS_ENABLE 环境变量),使该环境变量的行为契约从 RFC 0001 文档所写的「ReduceScatter calls are routed to the BIRS implementation」静默扩展为同时路由 AllReduce;本 PR 描述的 Documentation Update 一节为空,docs/zh 与 docs/en 的 RFC 0001 环境变量表均未更新。实验特性阶段,用户按文档排障时会误以为该变量只影响 ReduceScatter。 建议修复:在 RFC 0001 环境变量表(中英文两份)补充 AllReduce BIAR 的路由说明与适用条件(910_93、偶数 rank、每 server 不少于 4 rank),或在 PR 描述 Documentation Update 中列出后续文档更新计划。 ![]() ![]() | |||
| 42 | + return false; | ||
| 43 | + } | ||
| 44 | + u32 rankSize = INVALID_VALUE_RANKSIZE; | ||
| 45 | + if (HcclGetRankSize(comm, &rankSize) != HCCL_SUCCESS) { | ||
| 46 | + return false; | ||
| 47 | + } | ||
| 48 | + HcclDevType deviceType = HcclDevType::DEV_TYPE_COUNT; | ||
| 49 | + if (HcclGetDeviceType(deviceType) != HCCL_SUCCESS) { | ||
| 50 | + return false; | ||
| 51 | + } | ||
| 52 | + uint32_t* instSizeList = nullptr; | ||
| 53 | + uint32_t serverNum = 0; | ||
| 54 | + if (HcclRankGraphGetInstSizeListByLayer( | ||
| 55 | + comm, static_cast<uint32_t>(HcclNetLayer::HCCL_NetLayer_L0), &instSizeList, &serverNum) | ||
| 56 | + != HCCL_SUCCESS) { | ||
| 57 | + return false; | ||
| 58 | + } | ||
| 59 | + // 不适用条件统一回退老路径, 须与 DecideAllReduceBiarAlg 的拒绝条件保持一致(selector 仅作兜底), | ||
| 60 | + // 避免奇数规模静默回退而小规模偶数硬报错的分裂处置 | ||
| 61 | + if (rankSize == 1 || deviceType != HcclDevType::DEV_TYPE_910_93 || rankSize % 2 != 0 || serverNum == 0 | ||
| 62 | + || rankSize / serverNum < 4) { | ||
| 63 | + HCCL_INFO( | ||
| 64 | + "AllReduceBIAR not applicable: deviceType[%d] rankSize[%u] serverNum[%u], fallback to the default " | ||
| 65 | + "AllReduce", | ||
| 66 | + deviceType, rankSize, serverNum); | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + return true; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +HcclResult AllReduceExperimental( | ||
| 73 | + void* sendBuf, void* recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, | ||
| 74 | + aclrtStream stream) | ||
| 75 | +{ | ||
| 76 | + if (!MatchBIAR(comm)) { | ||
| 77 | + return HcclAllReduceInner(sendBuf, recvBuf, count, dataType, op, comm, stream); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + CHK_PRT_RET(count == 0, HCCL_WARNING("input count is 0, return all reduce success"), HCCL_SUCCESS); | ||
| 81 | + | ||
| 82 | + HcclUs startut = TIME_NOW(); // 走老流程的判断时间不统计在内 | ||
| 83 | + OpParam param; | ||
| 84 | + CHK_RET(AllReduceInitAndCheck(comm, sendBuf, recvBuf, count, dataType, op, stream, param)); | ||
| 85 | + | ||
| 86 | + u32 rankSize = INVALID_VALUE_RANKSIZE; | ||
| 87 | + CHK_RET(HcclGetRankSize(comm, &rankSize)); | ||
[MEDIUM] 第 78-89 行与 AllReduceInitAndCheck 的校验序列完全重复 问题分析:
第 76 行已调用 AllReduceInitAndCheck(src/ops/all_reduce/all_reduce.cc 第 111-138 行),其内部已完成 InitEnvConfig、CheckAllReduceInputPara、HcclGetRankSize、HcclGetRankId、HcclGetCommName、tag 填充与 HcclCheckTag、HcomCheckUserRank、CheckCount、CheckDataType、CheckReduceOp;本函数 78-89 行又把其中 8 项原样重做一遍。每次走 BIAR 路径的 AllReduce 都多执行一轮 dlsym 跨界查询与校验(集合通信热路径),且两处逻辑需双份同步维护——未来 tag/校验规则变化容易漏改其中一处。对照 ReduceScatterExperimental 只做一遍内联校验,无此重复。 建议修复:删除 78-89 行的重复块,仅保留 rankSize 的单次获取(供第 94 行 AllReduceOutPlaceCustom 使用),AllReduceEntryLog 直接复用 InitAndCheck 已填好的 param.tag 与 param.commName。 ![]() ![]() Davydov_Danil 21 天前 评论: 21 天前 评论: | |||
| 88 | + | ||
| 89 | + /* 接口交互信息日志 */ | ||
| 90 | + CHK_RET(AllReduceEntryLog(sendBuf, recvBuf, count, dataType, op, stream, param.tag, "HcclAllReduce")); | ||
| 91 | + | ||
| 92 | + CHK_RET(AllReduceOutPlaceCustom(param, sendBuf, recvBuf, count, dataType, op, comm, stream, rankSize)); | ||
| 93 | + | ||
| 94 | + CHK_RET(LogHcclExit("HcclAllReduce", param.tag, startut)); | ||
| 95 | + | ||
| 96 | + return HCCL_SUCCESS; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +static HcclResult PrepareAllReduceParam( | ||
| 100 | + OpParam& param, void* sendBuf, void* recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, | ||
| 101 | + aclrtStream stream, OpMode opMode) | ||
| 102 | +{ | ||
| 103 | + u32 perDataSize = DATATYPE_SIZE_TABLE[dataType]; | ||
| 104 | + u64 outputSize = count * perDataSize; | ||
| 105 | + u64 inputSize = outputSize; | ||
| 106 | + | ||
| 107 | + param.stream = stream; | ||
| 108 | + param.reduceType = op; | ||
| 109 | + param.opMode = opMode; | ||
| 110 | + | ||
| 111 | + if (param.commName[0] == '\0') { | ||
| 112 | + CHK_RET(HcclGetCommName(comm, param.commName)); | ||
| 113 | + } | ||
| 114 | + HcclDevType deviceType = HcclDevType::DEV_TYPE_COUNT; | ||
| 115 | + CHK_RET(HcclGetDeviceType(deviceType)); | ||
| 116 | + | ||
| 117 | + param.inputSize = inputSize; | ||
| 118 | + param.inputPtr = sendBuf; | ||
| 119 | + param.outputSize = outputSize; | ||
| 120 | + param.outputPtr = recvBuf; | ||
| 121 | + param.DataDes.dataType = dataType; | ||
| 122 | + param.DataDes.count = count; | ||
| 123 | + param.enableDetour = false; | ||
| 124 | + param.opType = HcclCMDType::HCCL_CMD_ALLREDUCE; | ||
| 125 | + param.deviceType = deviceType; | ||
| 126 | + | ||
| 127 | + return HCCL_SUCCESS; | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +HcclResult AllReduceOutPlaceCustom( | ||
| 131 | + OpParam& param, void* sendBuf, void* recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, | ||
| 132 | + aclrtStream stream, u32 userRankSize) | ||
| 133 | +{ | ||
| 134 | + HCCL_INFO("Start to execute AllReduceOutPlaceCustom"); | ||
| 135 | + CHK_RET(PrepareAllReduceParam(param, sendBuf, recvBuf, count, dataType, op, comm, stream, OpMode::OPBASE)); | ||
| 136 | + | ||
| 137 | + if (IsAiCpuMode(param.deviceType, userRankSize)) { | ||
| 138 | + HCCL_DEBUG("is aicpu mode"); | ||
| 139 | + CHK_RET(LoadAICPUKernel()); | ||
| 140 | + param.engine = CommEngine::COMM_ENGINE_AICPU_TS; | ||
| 141 | + } else { | ||
| 142 | + HCCL_DEBUG("is host mode"); | ||
| 143 | + param.engine = CommEngine::COMM_ENGINE_CPU_TS; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + uint64_t beginTime = 0; | ||
| 147 | + if (HcommIsProfilingSupported()) { | ||
| 148 | + beginTime = HcommGetProfilingSysCycleTime(); | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + CHK_RET(ProcessA3(comm, param, beginTime)); | ||
| 152 | + | ||
| 153 | + HCCL_INFO("Execute AllReduceOutPlaceCustom success."); | ||
| 154 | + return HCCL_SUCCESS; | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +} // namespace ops_hccl_experimental | ||
| @@ -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 | +#ifndef OPS_HCCL_SRC_OPS_ALL_REDUCE_OP_CUSTOM | ||
| 12 | +#define OPS_HCCL_SRC_OPS_ALL_REDUCE_OP_CUSTOM | ||
| 13 | + | ||
| 14 | +#include <string> | ||
| 15 | +#include <memory> | ||
| 16 | +#include "hccl.h" | ||
| 17 | + | ||
| 18 | +#include "alg_param.h" | ||
| 19 | +#include "executor_v2_base.h" | ||
| 20 | +#include "alg_type.h" | ||
| 21 | +#include "execute_selector.h" | ||
| 22 | + | ||
| 23 | +#ifdef __cplusplus | ||
| 24 | +extern "C" { | ||
| 25 | +#endif | ||
| 26 | + | ||
| 27 | +#ifdef __cplusplus | ||
| 28 | +} | ||
| 29 | +#endif | ||
| 30 | + | ||
| 31 | +namespace ops_hccl_experimental { | ||
| 32 | +using ops_hccl::OpParam; | ||
| 33 | + | ||
| 34 | +HcclResult AllReduceExperimental( | ||
| 35 | + void* sendBuf, void* recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, | ||
| 36 | + aclrtStream stream); | ||
| 37 | +HcclResult AllReduceOutPlaceCustom( | ||
| 38 | + OpParam& param, void* sendBuf, void* recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, | ||
| 39 | + aclrtStream stream, u32 userRankSize); | ||
| 40 | +} // namespace ops_hccl_experimental | ||
| 41 | + | ||
| 42 | +#endif | ||
| @@ -0,0 +1,27 @@ | |||
| 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 | +if(NOT ENABLE_EXPERIMENTAL) | ||
| 12 | + return() | ||
| 13 | +endif() | ||
| 14 | + | ||
| 15 | +add_subdirectory(template) | ||
| 16 | + | ||
| 17 | +set(src_list | ||
| 18 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce_executor_base.cc | ||
| 19 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce_biar_executor.cc | ||
| 20 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce_biar_selector.cc | ||
| 21 | +) | ||
| 22 | + | ||
| 23 | +if(TARGET hccl) | ||
| 24 | + target_sources(hccl PRIVATE | ||
| 25 | + ${src_list} | ||
| 26 | + ) | ||
| 27 | +endif() | ||
| @@ -0,0 +1,110 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include <numeric> | ||
| 12 | +#include "all_reduce_biar_executor.h" | ||
| 13 | +#include "all_reduce_biar.h" | ||
| 14 | +#include "topo_experimental.h" | ||
| 15 | + | ||
| 16 | +namespace ops_hccl_experimental { | ||
| 17 | + | ||
| 18 | +AllReduceBIARExecutor::AllReduceBIARExecutor() : AllReduceExecutorBase() | ||
| 19 | +{ | ||
| 20 | + desc_.level1SupportedAlgos | ||
| 21 | + = {AlgTypeLevel1::ALG_LEVEL1_NHR, AlgTypeLevel1::ALG_LEVEL1_NB, AlgTypeLevel1::ALG_LEVEL1_RING}; | ||
| 22 | + desc_.level2SupportedAlgos | ||
| 23 | + = {AlgTypeLevel2::ALG_LEVEL2_NHR, AlgTypeLevel2::ALG_LEVEL2_NB, AlgTypeLevel2::ALG_LEVEL2_RING}; | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +HcclResult AllReduceBIARExecutor::CalcResRequest( | ||
| 27 | + HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, | ||
| 28 | + AlgResourceRequest& resourceRequest, AlgType& algType) | ||
| 29 | +{ | ||
| 30 | + if (topoInfo->serverNum == 1) { | ||
| 31 | + CHK_RET(CalcGeneralTopoInfoForA3(comm, topoInfo, algHierarchyInfo)); | ||
| 32 | + } else { | ||
| 33 | + CHK_RET(CalcGeneralTopoInfoInterServer(comm, topoInfo, algHierarchyInfo)); | ||
| 34 | + } | ||
| 35 | + CHK_RET(RefreshAlgType(algType)); | ||
| 36 | + algType.algoLevel0 = AlgTypeLevel0::ALG_LEVEL0_NP_MESH; | ||
| 37 | + | ||
| 38 | + resourceRequest.slaveThreadNum = BIAR_THREAD_NUM; | ||
| 39 | + for (u32 index = 0; index < BIAR_THREAD_NUM; index++) { | ||
| 40 | + resourceRequest.notifyNumPerThread.push_back(1); | ||
| 41 | + } | ||
| 42 | + resourceRequest.notifyNumOnMainThread = BIAR_THREAD_NUM; | ||
| 43 | + | ||
| 44 | + // level0 channel | ||
| 45 | + std::vector<HcclChannelDesc> level0Channels; | ||
| 46 | + CHK_RET(CalcLevel0ChannelRequest(param, topoInfo, algHierarchyInfo, algType, level0Channels)); | ||
| 47 | + resourceRequest.channels.push_back(level0Channels); | ||
| 48 | + | ||
| 49 | + HCCL_INFO( | ||
| 50 | + "[AllReduceBIARExecutor][CalcResRequest]slaveThreadNum[%u] notifyNumPerThread[%zu]" | ||
| 51 | + " notifyNumOnMainThread[%u] level0Channels[%zu]", | ||
| 52 | + resourceRequest.slaveThreadNum, resourceRequest.notifyNumPerThread.size(), | ||
| 53 | + resourceRequest.notifyNumOnMainThread, level0Channels.size()); | ||
| 54 | + return HCCL_SUCCESS; | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +HcclResult AllReduceBIARExecutor::KernelRun(const OpParam& param, ExecMem& execMem) | ||
| 58 | +{ | ||
| 59 | + HCCL_CONFIG_INFO(HCCL_ALG, "[AllReduceBIARExecutor][KernelRun] starts."); | ||
| 60 | + | ||
| 61 | + CHK_RET(KernelRunLevel0(param, execMem)); | ||
| 62 | + | ||
| 63 | + HCCL_INFO("AllReduce BIAR run success"); | ||
| 64 | + return HCCL_SUCCESS; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +HcclResult AllReduceBIARExecutor::SelectAndPrepareBirsTemplate( | ||
| 68 | + u32 localRank, u32 localRankSize, std::unique_ptr<AlgTemplateBase>& templatePtr) | ||
| 69 | +{ | ||
| 70 | + TemplateType RStplType = TEMPLATE_ALL_REDUCE_BIAR; | ||
| 71 | + templatePtr = AlgTemplateRegistry::Instance().GetAlgTemplate(RStplType); | ||
| 72 | + CHK_SMART_PTR_NULL(templatePtr); | ||
| 73 | + CHK_RET(templatePtr->Prepare(localRank, localRankSize)); | ||
| 74 | + HCCL_CONFIG_INFO(HCCL_ALG, "[%s] Run TEMPLATE_ALL_REDUCE_BIAR in COMM_LEVEL0", __func__); | ||
| 75 | + | ||
| 76 | + return HCCL_SUCCESS; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +HcclResult AllReduceBIARExecutor::KernelRunLevel0(const OpParam& param, ExecMem& execMem) | ||
| 80 | +{ | ||
| 81 | + SubCommInfo level0CommInfo; | ||
| 82 | + CHK_RET(GetSubCommInfo(COMM_LEVEL0, level0CommInfo)); | ||
| 83 | + u32 level0LocalRank = level0CommInfo.localRank; | ||
| 84 | + u32 level0LocalRankSize = level0CommInfo.localRankSize; | ||
| 85 | + u32 sliceNum = level0LocalRankSize; | ||
| 86 | + std::vector<Slice> dataSegsSlice; | ||
| 87 | + CHK_RET(PrepareDataSlice(execMem.count, unitSize_, sliceNum, dataSegsSlice)); | ||
| 88 | + | ||
| 89 | + std::unique_ptr<AlgTemplateBase> tempAlg = nullptr; | ||
| 90 | + CHK_RET(SelectAndPrepareBirsTemplate(level0LocalRank, level0LocalRankSize, tempAlg)); | ||
| 91 | + | ||
| 92 | + HcclMem UsrInputMem{HCCL_MEM_TYPE_DEVICE, execMem.inputPtr, execMem.count * unitSize_}; | ||
| 93 | + HcclMem UsrOutputMem{HCCL_MEM_TYPE_DEVICE, execMem.outputPtr, execMem.count * unitSize_}; | ||
| 94 | + | ||
| 95 | + if (auto Exp = dynamic_cast<AlgTemplateBaseExperimental*>(tempAlg.get())) { | ||
[MEDIUM] dynamic_cast 结果未校验,转换失败时静默跳过全部逻辑返回 SUCCESS 问题分析:
建议修复: 在 if 块后添加 nullptr 校验:
![]() ![]() | |||
| 96 | + CHK_RET(Exp->Prepare( | ||
| 97 | + UsrInputMem, UsrOutputMem, execMem.inputMem, execMem.count, param.DataDes.dataType, thread_, slaveThreads_, | ||
| 98 | + param.reduceType, 0, dataSegsSlice, 0, false)); | ||
| 99 | + | ||
| 100 | + CHK_RET(Exp->RunAsync(level0LocalRank, level0LocalRankSize, channels_[COMM_LEVEL0])); | ||
| 101 | + } else { | ||
| 102 | + HCCL_ERROR("[AllReduceBIARExecutor] template is not AlgTemplateBaseExperimental"); | ||
| 103 | + return HCCL_E_INTERNAL; | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + return HCCL_SUCCESS; | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +REGISTER_EXEC("AllReduceBIARExecutor", AllReduceBIAR, AllReduceBIARExecutor); | ||
| 110 | +} // namespace ops_hccl_experimental | ||
| @@ -0,0 +1,59 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#ifndef ALL_REDUCE_BIAR_EXECUTOR_H | ||
| 12 | +#define ALL_REDUCE_BIAR_EXECUTOR_H | ||
| 13 | +#include "all_reduce_executor_base.h" | ||
| 14 | +#include "alg_template_base_experimental.h" | ||
| 15 | +#include "coll_alg_exec_registry.h" | ||
| 16 | + | ||
| 17 | +namespace ops_hccl_experimental { | ||
| 18 | +using ops_hccl::AddAlgToAllAlgos; | ||
| 19 | +using ops_hccl::AlgHierarchyInfo; | ||
| 20 | +using ops_hccl::AlgResourceCtx; | ||
| 21 | +using ops_hccl::AlgResourceRequest; | ||
| 22 | +using ops_hccl::AlgTemplateBase; | ||
| 23 | +using ops_hccl::AlgTemplateRegistry; | ||
| 24 | +using ops_hccl::AlgType; | ||
| 25 | +using ops_hccl::AlgTypeLevel0; | ||
| 26 | +using ops_hccl::AlgTypeLevel1; | ||
| 27 | +using ops_hccl::AlgTypeLevel2; | ||
| 28 | +using ops_hccl::ChannelInfo; | ||
| 29 | +using ops_hccl::CollAlgExecRegistry; | ||
| 30 | +using ops_hccl::COMM_LEVEL0; | ||
| 31 | +using ops_hccl::DefaultExecCreator; | ||
| 32 | +using ops_hccl::ExecMem; | ||
| 33 | +using ops_hccl::ExecutorBase; | ||
| 34 | +using ops_hccl::HCCL_ALG; | ||
| 35 | +using ops_hccl::OpParam; | ||
| 36 | +using ops_hccl::Slice; | ||
| 37 | +using ops_hccl::SubCommInfo; | ||
| 38 | +using ops_hccl::TemplateType; | ||
| 39 | +using ops_hccl::TopoInfo; | ||
| 40 | + | ||
| 41 | +class AllReduceBIARExecutor : public AllReduceExecutorBase { | ||
| 42 | +public: | ||
| 43 | + explicit AllReduceBIARExecutor(); | ||
| 44 | + ~AllReduceBIARExecutor() override = default; | ||
| 45 | + | ||
| 46 | + HcclResult CalcResRequest( | ||
| 47 | + HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, | ||
| 48 | + AlgResourceRequest& resourceRequest, AlgType& algType) override; | ||
| 49 | + | ||
| 50 | +private: | ||
| 51 | + HcclResult | ||
| 52 | + SelectAndPrepareBirsTemplate(u32 localRank, u32 localRankSize, std::unique_ptr<AlgTemplateBase>& templatePtr); | ||
| 53 | + HcclResult KernelRunLevel0(const OpParam& param, ExecMem& execMem); | ||
| 54 | + HcclResult KernelRun(const OpParam& param, ExecMem& execMem) override; | ||
| 55 | +}; | ||
| 56 | + | ||
| 57 | +} // namespace ops_hccl_experimental | ||
| 58 | + | ||
| 59 | +#endif | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include "all_reduce_biar_selector.h" | ||
| 12 | + | ||
| 13 | +namespace ops_hccl_experimental { | ||
| 14 | +using ops_hccl::TopoInfo; | ||
| 15 | + | ||
| 16 | +BiarSelectResult DecideAllReduceBiarAlg(const TopoInfo& topoInfo, std::string& algName) | ||
| 17 | +{ | ||
| 18 | + if (topoInfo.userRankSize == 1) { | ||
| 19 | + return BiarSelectResult::bRejectRankSizeOne; | ||
| 20 | + } | ||
| 21 | + if (topoInfo.deviceType != HcclDevType::DEV_TYPE_910_93 || (topoInfo.userRankSize % 2 != 0)) { | ||
| 22 | + return BiarSelectResult::bNotSelected; | ||
| 23 | + } | ||
| 24 | + if (topoInfo.serverNum == 0) { | ||
| 25 | + return BiarSelectResult::bRejectServerNumZero; | ||
| 26 | + } | ||
| 27 | + if (topoInfo.userRankSize / topoInfo.serverNum < 4) { | ||
W 🔴 [严重] [代码正确性] experimental/ops/all_reduce/biar/all_reduce_biar_selector.cc:27 selector 仅校验 userRankSize/serverNum < 4,未拒绝 serverNum > 1;而 AllReduceBIAR 模板只有单机 level0 实现(RunReduceScatter + RunAllGather,无 inter-server 归约/广播阶段),且 AllReduceBIARExecutor::SelectAndPrepareBirsTemplate 的 isSingleServer 参数声明后未使用,恒选 TEMPLATE_ALL_REDUCE_BIAR。 后果:serverNum≥2 且每 server≥4 rank 时,AllReduce 退化为各 server 独立的 intra-server allreduce,跨 server 分量既不归约也不广播,结果错误。ST 用例 st_all_reduce_1416_test(1×4×16)恰会命中此路径,但该 ST 未纳入默认构建故未暴露。 建议:selector 增加 serverNum != 1 时返回 bNotSelected(回退老流程),或实现 AllReduceBIARInter 变体并让 isSingleServer 真实分流模板。 ![]() ![]() | |||
| 28 | + return BiarSelectResult::bRejectRanksPerServerLT4; | ||
| 29 | + } | ||
| 30 | + algName = "AllReduceBIARExecutor"; | ||
| 31 | + return BiarSelectResult::bSelected; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +HcclResult BiarSelectResultToCode(BiarSelectResult result) | ||
| 35 | +{ | ||
| 36 | + switch (result) { | ||
| 37 | + case BiarSelectResult::bSelected: | ||
| 38 | + case BiarSelectResult::bNotSelected: | ||
| 39 | + return HCCL_SUCCESS; | ||
| 40 | + case BiarSelectResult::bRejectRankSizeOne: | ||
| 41 | + return HCCL_E_INTERNAL; | ||
[MEDIUM] 单 rank AllReduce 仍返回 HCCL_E_INTERNAL,核心问题未修复 复检核验:作者回复称已 fixed, add selector and unit tests。实读 current head
建议修复:单 rank 不应返回错误码,应在 ![]() ![]() | |||
| 42 | + case BiarSelectResult::bRejectServerNumZero: | ||
| 43 | + case BiarSelectResult::bRejectRanksPerServerLT4: | ||
| 44 | + return HCCL_E_PARA; | ||
| 45 | + } | ||
| 46 | + return HCCL_E_INTERNAL; | ||
| 47 | +} | ||
| 48 | +} // namespace ops_hccl_experimental | ||
| @@ -0,0 +1,31 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#ifndef OPS_HCCL_EXPERIMENTAL_ALL_REDUCE_BIAR_SELECTOR | ||
| 12 | +#define OPS_HCCL_EXPERIMENTAL_ALL_REDUCE_BIAR_SELECTOR | ||
| 13 | + | ||
| 14 | +#include <string> | ||
| 15 | +#include "alg_param.h" | ||
| 16 | + | ||
| 17 | +namespace ops_hccl_experimental { | ||
| 18 | +enum class BiarSelectResult { | ||
| 19 | + bNotSelected, | ||
| 20 | + bSelected, | ||
| 21 | + bRejectRankSizeOne, | ||
| 22 | + bRejectServerNumZero, | ||
| 23 | + bRejectRanksPerServerLT4, | ||
| 24 | +}; | ||
| 25 | + | ||
| 26 | +BiarSelectResult DecideAllReduceBiarAlg(const ops_hccl::TopoInfo& topoInfo, std::string& algName); | ||
| 27 | + | ||
| 28 | +HcclResult BiarSelectResultToCode(BiarSelectResult result); | ||
| 29 | +} // namespace ops_hccl_experimental | ||
| 30 | + | ||
| 31 | +#endif | ||
| @@ -0,0 +1,49 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include "all_reduce_executor_base.h" | ||
| 12 | + | ||
| 13 | +namespace ops_hccl_experimental { | ||
| 14 | + | ||
| 15 | +AllReduceExecutorBase::AllReduceExecutorBase() : CollExecutorBaseExperimental() {} | ||
| 16 | + | ||
| 17 | +HcclResult AllReduceExecutorBase::CalcResRequest( | ||
| 18 | + HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, | ||
| 19 | + AlgResourceRequest& resourceRequest, AlgType& algType) | ||
| 20 | +{ | ||
| 21 | + // 子类必须 override 完成资源申请;默认返回不支持错误,避免静默跳过。 | ||
| 22 | + return HCCL_E_NOT_SUPPORT; | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +HcclResult | ||
| 26 | +AllReduceExecutorBase::PrepareDataSlice(u64 dataCount, u32 unitSize, u32 sliceNum, std::vector<Slice>& dataSlice) | ||
| 27 | +{ | ||
| 28 | + CHK_PRT_RET((sliceNum == 0), HCCL_ERROR("[AllReduceExecutorBase][PrepareDataSlice]sliceNum is zero."), HCCL_E_PARA); | ||
| 29 | + | ||
| 30 | + dataSlice.resize(sliceNum); | ||
| 31 | + // V-style slicing: distribute remainder elements to the first 'remainder' ranks | ||
| 32 | + u64 baseCount = dataCount / sliceNum; | ||
| 33 | + u64 remainder = dataCount % sliceNum; | ||
| 34 | + u64 offsetCount = 0; | ||
| 35 | + for (u32 i = 0; i < sliceNum; i++) { | ||
| 36 | + u64 curCount = baseCount + (i < remainder ? 1 : 0); | ||
| 37 | + dataSlice[i].size = curCount * unitSize; | ||
| 38 | + dataSlice[i].offset = offsetCount * unitSize; | ||
| 39 | + offsetCount += curCount; | ||
| 40 | + HCCL_DEBUG( | ||
| 41 | + "[AllReduceExecutorBase][PrepareDataSlice] slice[%u]: offset[%llu] size[%llu] count[%llu]", i, | ||
| 42 | + dataSlice[i].offset, dataSlice[i].size, curCount); | ||
| 43 | + } | ||
| 44 | + return HCCL_SUCCESS; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +u64 AllReduceExecutorBase::CalcScratchDemand(u64 curRecvSize) const { return curRecvSize; } | ||
| 48 | + | ||
| 49 | +} // namespace ops_hccl_experimental | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#ifndef ALL_REDUCE_EXECUTOR_H | ||
| 12 | +#define ALL_REDUCE_EXECUTOR_H | ||
| 13 | + | ||
| 14 | +#include "alg_param.h" | ||
| 15 | +#include "executor_base.h" | ||
| 16 | +#include "config_log.h" | ||
| 17 | +#include "alg_template_base_experimental.h" | ||
| 18 | +#include "coll_executor_base_experimental.h" | ||
| 19 | + | ||
| 20 | +namespace ops_hccl_experimental { | ||
| 21 | +using ops_hccl::AlgHierarchyInfo; | ||
| 22 | +using ops_hccl::AlgResourceRequest; | ||
| 23 | +using ops_hccl::AlgType; | ||
| 24 | +using ops_hccl::OpParam; | ||
| 25 | +using ops_hccl::Slice; | ||
| 26 | +using ops_hccl::TopoInfo; | ||
| 27 | + | ||
| 28 | +class AllReduceExecutorBase : public CollExecutorBaseExperimental { | ||
| 29 | +public: | ||
| 30 | + explicit AllReduceExecutorBase(); | ||
| 31 | + ~AllReduceExecutorBase() override = default; | ||
| 32 | + | ||
| 33 | + /* *************** 资源计算 *************** */ | ||
| 34 | + HcclResult CalcResRequest( | ||
| 35 | + HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, | ||
| 36 | + AlgResourceRequest& resourceRequest, AlgType& algType) override; | ||
| 37 | + | ||
| 38 | +protected: | ||
| 39 | + /* *************** 通用工具 *************** */ | ||
| 40 | + virtual HcclResult PrepareDataSlice(u64 dataCount, u32 unitSize, u32 sliceNum, std::vector<Slice>& dataSlice); | ||
| 41 | + | ||
| 42 | + // AllReduce(BIAR) 为 RS+AG 分解: 切片总和为单 rank 数据量, scratch 需求按单 rank 量校验 | ||
| 43 | + u64 CalcScratchDemand(u64 curRecvSize) const override; | ||
| 44 | +}; | ||
| 45 | + | ||
| 46 | +} // namespace ops_hccl_experimental | ||
| 47 | + | ||
| 48 | +#endif | ||
| @@ -0,0 +1,23 @@ | |||
| 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 | +if(NOT ENABLE_EXPERIMENTAL) | ||
| 12 | + return() | ||
| 13 | +endif() | ||
| 14 | + | ||
| 15 | +set(src_list | ||
| 16 | + ${CMAKE_CURRENT_SOURCE_DIR}/all_reduce_biar.cc | ||
| 17 | +) | ||
| 18 | + | ||
| 19 | +if(TARGET hccl) | ||
| 20 | + target_sources(hccl PRIVATE | ||
| 21 | + ${src_list} | ||
| 22 | + ) | ||
| 23 | +endif() | ||
| @@ -0,0 +1,393 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include "alg_template_register.h" | ||
| 12 | +#include "all_reduce_biar.h" | ||
| 13 | + | ||
| 14 | +namespace ops_hccl_experimental { | ||
| 15 | + | ||
| 16 | +AllReduceBIAR::AllReduceBIAR() : AlgTemplateBaseExperimental() {} | ||
| 17 | + | ||
| 18 | +AllReduceBIAR::~AllReduceBIAR() {} | ||
| 19 | + | ||
| 20 | +HcclResult AllReduceBIAR::Prepare(u32 interRank, u32 interRankSize) | ||
| 21 | +{ | ||
| 22 | + interRank_ = interRank; | ||
| 23 | + interRankSize_ = interRankSize; | ||
| 24 | + return HCCL_SUCCESS; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +HcclResult AllReduceBIAR::Prepare( | ||
| 28 | + HcclMem& inputMem, HcclMem& outputMem, HcclMem& scratchMem, const u64 count, const HcclDataType dataType, | ||
| 29 | + ThreadHandle thread, const std::vector<ThreadHandle>& slaveThreads, const HcclReduceOp reductionOp, const u32 root, | ||
| 30 | + const std::vector<Slice>& slices, const u64 baseOffset, const bool disableDMAReduce) | ||
| 31 | +{ | ||
| 32 | + mainThread_ = thread; | ||
| 33 | + subThreads_ = slaveThreads; | ||
| 34 | + AlgTemplateBase::Prepare( | ||
| 35 | + inputMem, outputMem, scratchMem, count, dataType, thread, reductionOp, root, slices, baseOffset, | ||
| 36 | + disableDMAReduce); | ||
| 37 | + return HCCL_SUCCESS; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +void AllReduceBIAR::GetNotifyIdxMainToSub(std::vector<u32>& notifyIdxMainToSub) | ||
| 41 | +{ | ||
| 42 | + notifyIdxMainToSub.clear(); | ||
| 43 | + u32 slaveThreadNum = BIAR_THREAD_NUM; | ||
| 44 | + for (u32 slaveThreadIdx = 0; slaveThreadIdx < slaveThreadNum; slaveThreadIdx++) { | ||
| 45 | + notifyIdxMainToSub.push_back(0); | ||
| 46 | + } | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +void AllReduceBIAR::GetNotifyIdxSubToMain(std::vector<u32>& notifyIdxSubToMain) | ||
| 50 | +{ | ||
| 51 | + notifyIdxSubToMain.clear(); | ||
| 52 | + u32 notifyNum = BIAR_THREAD_NUM; | ||
| 53 | + for (u32 notifyIdx = 0; notifyIdx < notifyNum; notifyIdx++) { | ||
| 54 | + notifyIdxSubToMain.push_back(notifyIdx); | ||
| 55 | + } | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +HcclResult AllReduceBIAR::Preprocess(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels) | ||
| 59 | +{ | ||
| 60 | + if (rankSize == 1) { | ||
| 61 | + if (inputMem_.addr != outputMem_.addr) { | ||
| 62 | + CHK_RET(static_cast<HcclResult>( | ||
| 63 | + HcommLocalCopyOnThread(thread_, outputMem_.addr, inputMem_.addr, inputMem_.size))); | ||
| 64 | + } | ||
| 65 | + return HCCL_SUCCESS; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + if (channels.size() < rankSize) { | ||
| 69 | + HCCL_ERROR( | ||
| 70 | + "[AllReduceBIAR][RunAsync]rank[%u] linksize[%llu] is less than rankSize[%u]", rank, channels.size(), | ||
| 71 | + rankSize); | ||
| 72 | + return HCCL_E_INTERNAL; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + unitSize_ = DataUnitSize(dataType_); | ||
| 76 | + if (unitSize_ == 0) { | ||
| 77 | + HCCL_ERROR("[AllReduceBIAR][RunAsync]rank[%u] unit data size is zero", rank); | ||
| 78 | + return HCCL_E_INTERNAL; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + return HCCL_SUCCESS; | ||
| 82 | +} | ||
| 83 | + | ||
| 84 | +HcclResult AllReduceBIAR::LocalReduceCCLToCCL(u64 srcOffset, u64 dstOffset, u64 size, ThreadHandle thread) | ||
| 85 | +{ | ||
| 86 | + void* srcSlice = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + srcOffset); | ||
| 87 | + void* dstSlice = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + dstOffset); | ||
| 88 | + CHK_RET(static_cast<HcclResult>(HcommLocalReduceOnThread( | ||
| 89 | + thread, dstSlice, srcSlice, size / unitSize_, static_cast<HcommDataType>(dataType_), | ||
| 90 | + static_cast<HcommReduceOp>(reductionOp_)))); | ||
| 91 | + return HCCL_SUCCESS; | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +HcclResult | ||
| 95 | +AllReduceBIAR::HCCSProcessRsLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX, u64 localStrideSize) | ||
| 96 | +{ | ||
| 97 | + if (round != 0 && round <= hccs_ranks.size()) { | ||
| 98 | + CHK_RET(static_cast<HcclResult>( | ||
| 99 | + HcommChannelNotifyRecordOnThread(subThreads_[0], hccs_links[round - 1].handle, NOTIFY_IDX_ACK))); | ||
| 100 | + CHK_RET(static_cast<HcclResult>(HcommChannelNotifyWaitOnThread( | ||
| 101 | + subThreads_[0], hccs_links_reversed[round - 1].handle, NOTIFY_IDX_ACK, CUSTOM_TIMEOUT))); | ||
| 102 | + u64 localOffsetByte = hccs_ranks[round - 1] / rankSizeX * localStrideSize; | ||
| 103 | + u64 remoteOffsetByte = ((rankSize / rankSizeX) + rank / rankSizeX) * localStrideSize; | ||
| 104 | + void* src = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + localOffsetByte); | ||
| 105 | + void* dst = static_cast<void*>(static_cast<u8*>(hccs_links[round - 1].remoteOutput.addr) + remoteOffsetByte); | ||
| 106 | + | ||
| 107 | + if (slices_[hccs_ranks[round - 1]].size > 0) { | ||
| 108 | + CHK_RET(static_cast<HcclResult>(HcommWriteOnThread( | ||
| 109 | + subThreads_[0], hccs_links[round - 1].handle, dst, src, slices_[hccs_ranks[round - 1]].size))); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + CHK_RET(static_cast<HcclResult>( | ||
| 113 | + HcommChannelNotifyRecordOnThread(subThreads_[0], hccs_links[round - 1].handle, NOTIFY_IDX_DATA_SIGNAL))); | ||
| 114 | + CHK_RET(static_cast<HcclResult>(HcommChannelNotifyWaitOnThread( | ||
| 115 | + subThreads_[0], hccs_links_reversed[round - 1].handle, NOTIFY_IDX_DATA_SIGNAL, CUSTOM_TIMEOUT))); | ||
| 116 | + } | ||
| 117 | + return HCCL_SUCCESS; | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +HcclResult | ||
| 121 | +AllReduceBIAR::SIOProcessRsLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX, u64 localStrideSize) | ||
| 122 | +{ | ||
| 123 | + CHK_RET(static_cast<HcclResult>(HcommChannelNotifyRecordOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_ACK))); | ||
| 124 | + CHK_RET(static_cast<HcclResult>( | ||
| 125 | + HcommChannelNotifyWaitOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_ACK, CUSTOM_TIMEOUT))); | ||
| 126 | + | ||
| 127 | + u64 localOffsetByte | ||
| 128 | + = (round < hccs_ranks.size()) ? slices_[hccs_neighbour_rank[round]].offset : slices_[sio_rank_].offset; | ||
| 129 | + u64 remoteOffsetByte = (round < hccs_ranks.size()) ? hccs_ranks[round] / rankSizeX * localStrideSize : | ||
| 130 | + rank / rankSizeX * localStrideSize; | ||
| 131 | + u64 curSliceSize = (round < hccs_ranks.size()) ? slices_[hccs_neighbour_rank[round]].size : slices_[sio_rank_].size; | ||
| 132 | + void* src = static_cast<void*>(static_cast<u8*>(inputMem_.addr) + localOffsetByte); | ||
| 133 | + void* dst = static_cast<void*>(static_cast<u8*>(sio_link.remoteOutput.addr) + remoteOffsetByte); | ||
| 134 | + | ||
| 135 | + if (curSliceSize > 0) { | ||
| 136 | + CHK_RET(static_cast<HcclResult>(HcommWriteReduceOnThread( | ||
| 137 | + mainThread_, sio_link.handle, dst, src, curSliceSize / unitSize_, static_cast<HcommDataType>(dataType_), | ||
| 138 | + static_cast<HcommReduceOp>(reductionOp_)))); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + CHK_RET(static_cast<HcclResult>( | ||
| 142 | + HcommChannelNotifyRecordOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_DATA_SIGNAL))); | ||
| 143 | + CHK_RET(static_cast<HcclResult>( | ||
| 144 | + HcommChannelNotifyWaitOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_DATA_SIGNAL, CUSTOM_TIMEOUT))); | ||
| 145 | + | ||
| 146 | + return HCCL_SUCCESS; | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +HcclResult | ||
| 150 | +AllReduceBIAR::LocalCopyRsLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX, u64 localStrideSize) | ||
| 151 | +{ | ||
| 152 | + if (round < hccs_ranks.size()) { | ||
| 153 | + u32 rank_idx = (round + 1 < hccs_ranks.size()) ? hccs_ranks[round + 1] : rank; | ||
| 154 | + void* srcSlice = static_cast<void*>(static_cast<u8*>(inputMem_.addr) + slices_[rank_idx].offset); | ||
| 155 | + void* dstSlice | ||
| 156 | + = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + rank_idx / rankSizeX * localStrideSize); | ||
| 157 | + if (slices_[rank_idx].size > 0) { | ||
| 158 | + CHK_RET(static_cast<HcclResult>( | ||
| 159 | + HcommLocalCopyOnThread(subThreads_[1], dstSlice, srcSlice, slices_[rank_idx].size))); | ||
| 160 | + } | ||
| 161 | + } | ||
| 162 | + return HCCL_SUCCESS; | ||
| 163 | +} | ||
| 164 | + | ||
| 165 | +HcclResult AllReduceBIAR::TreeReduceRs(const u32 rank, const u32 rankSize, u32 rankSizeX, u64 localStrideSize) | ||
| 166 | +{ | ||
| 167 | + std::vector<u64> vec; | ||
| 168 | + for (u32 i = 0; i < (rankSize / rankSizeX); i++) { | ||
| 169 | + if (i == (rank / rankSizeX)) { | ||
| 170 | + vec.push_back((rank / rankSizeX) * localStrideSize); | ||
| 171 | + } else { | ||
| 172 | + vec.push_back(((rankSize / rankSizeX) + i) * localStrideSize); | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | + // Tree local reduce | ||
| 176 | + auto ind = rankSize / rankSizeX; | ||
| 177 | + for (u32 stride = 1; stride < ind; stride *= 2) { | ||
| 178 | + for (u32 i = stride; i < ind; i += stride * 2) { | ||
| 179 | + if (slices_[rank].size > 0) { | ||
| 180 | + CHK_RET(LocalReduceCCLToCCL(vec[i], vec[i - stride], slices_[rank].size, mainThread_)); | ||
| 181 | + } | ||
| 182 | + } | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + u64 allGatherOffset = rank / rankSizeX * localStrideSize; | ||
| 186 | + | ||
| 187 | + if (vec[0] != allGatherOffset) { | ||
| 188 | + void* srcSlice = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + vec[0]); | ||
| 189 | + void* dstSlice = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + allGatherOffset); | ||
| 190 | + if (slices_[rank].size > 0) { | ||
| 191 | + CHK_RET( | ||
| 192 | + static_cast<HcclResult>(HcommLocalCopyOnThread(mainThread_, dstSlice, srcSlice, slices_[rank].size))); | ||
| 193 | + } | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + return HCCL_SUCCESS; | ||
| 197 | +} | ||
| 198 | + | ||
| 199 | +HcclResult AllReduceBIAR::RunReduceScatter( | ||
| 200 | + const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels, u64 localStrideSize) | ||
| 201 | +{ | ||
| 202 | + for (u32 round = 0; round < hccs_ranks.size() + 1; round++) { | ||
| 203 | + // MainRecordSub + SubWaitMain | ||
| 204 | + CHK_RET(PreSyncInterThreads(mainThread_, subThreads_, notifyIdxMainToSub_)); | ||
| 205 | + | ||
| 206 | + CHK_RET(HCCSProcessRsLoop(round, rank, rankSize, rankSizeX_, localStrideSize)); | ||
| 207 | + CHK_RET(SIOProcessRsLoop(round, rank, rankSize, rankSizeX_, localStrideSize)); | ||
| 208 | + CHK_RET(LocalCopyRsLoop(round, rank, rankSize, rankSizeX_, localStrideSize)); | ||
| 209 | + | ||
| 210 | + // SubRecordMain + MainWaitSub | ||
| 211 | + CHK_RET(PostSyncInterThreads(mainThread_, subThreads_, notifyIdxSubToMain_)); | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + CHK_RET(PreSyncInterThreads(mainThread_, subThreads_, notifyIdxMainToSub_)); | ||
| 215 | + | ||
| 216 | + CHK_RET(TreeReduceRs(rank, rankSize, rankSizeX_, localStrideSize)); | ||
| 217 | + | ||
| 218 | + CHK_RET(PostSyncInterThreads(mainThread_, subThreads_, notifyIdxSubToMain_)); | ||
| 219 | + | ||
| 220 | + return HCCL_SUCCESS; | ||
| 221 | +} | ||
| 222 | + | ||
| 223 | +HcclResult | ||
| 224 | +AllReduceBIAR::HCCSProcessAgLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX, u64 localStrideSize) | ||
| 225 | +{ | ||
| 226 | + u64 allGatherOffset = rank / rankSizeX * localStrideSize; | ||
| 227 | + if (round < hccs_ranks.size()) { | ||
| 228 | + CHK_RET(static_cast<HcclResult>( | ||
| 229 | + HcommChannelNotifyRecordOnThread(subThreads_[0], hccs_links[round].handle, NOTIFY_IDX_ACK))); | ||
| 230 | + CHK_RET(static_cast<HcclResult>(HcommChannelNotifyWaitOnThread( | ||
| 231 | + subThreads_[0], hccs_links_reversed[round].handle, NOTIFY_IDX_ACK, CUSTOM_TIMEOUT))); | ||
| 232 | + u64 remoteOffsetByte = (rank / rankSizeX) * localStrideSize; | ||
| 233 | + void* src = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + allGatherOffset); | ||
| 234 | + void* dst = static_cast<void*>(static_cast<u8*>(hccs_links[round].remoteOutput.addr) + remoteOffsetByte); | ||
| 235 | + | ||
| 236 | + if (slices_[rank].size > 0) { | ||
| 237 | + CHK_RET(static_cast<HcclResult>( | ||
| 238 | + HcommWriteOnThread(subThreads_[0], hccs_links[round].handle, dst, src, slices_[rank].size))); | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + CHK_RET(static_cast<HcclResult>( | ||
| 242 | + HcommChannelNotifyRecordOnThread(subThreads_[0], hccs_links[round].handle, NOTIFY_IDX_DATA_SIGNAL))); | ||
| 243 | + CHK_RET(static_cast<HcclResult>(HcommChannelNotifyWaitOnThread( | ||
| 244 | + subThreads_[0], hccs_links_reversed[round].handle, NOTIFY_IDX_DATA_SIGNAL, CUSTOM_TIMEOUT))); | ||
| 245 | + } | ||
| 246 | + return HCCL_SUCCESS; | ||
| 247 | +} | ||
| 248 | + | ||
| 249 | +HcclResult | ||
| 250 | +AllReduceBIAR::SIOProcessAgLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX, u64 localStrideSize) | ||
| 251 | +{ | ||
| 252 | + CHK_RET(static_cast<HcclResult>(HcommChannelNotifyRecordOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_ACK))); | ||
| 253 | + CHK_RET(static_cast<HcclResult>( | ||
| 254 | + HcommChannelNotifyWaitOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_ACK, CUSTOM_TIMEOUT))); | ||
| 255 | + | ||
| 256 | + u32 agRank = (round != 0 && round <= hccs_ranks.size()) ? (hccs_ranks_reversed[round - 1] ^ 1) : sio_rank_; | ||
| 257 | + u64 localOffsetByte = slices_[agRank].offset; | ||
| 258 | + u64 remoteOffsetByte = (round != 0 && round <= hccs_ranks.size()) ? | ||
| 259 | + (hccs_ranks_reversed[round - 1] / rankSizeX) * localStrideSize : | ||
| 260 | + (sio_rank_ / rankSizeX) * localStrideSize; | ||
| 261 | + void* src = static_cast<void*>(static_cast<u8*>(sio_link.remoteOutput.addr) + remoteOffsetByte); | ||
| 262 | + void* dst = static_cast<void*>(static_cast<u8*>(outputMem_.addr) + localOffsetByte); | ||
| 263 | + | ||
| 264 | + if (slices_[agRank].size > 0) { | ||
| 265 | + CHK_RET( | ||
| 266 | + static_cast<HcclResult>(HcommReadOnThread(mainThread_, sio_link.handle, dst, src, slices_[agRank].size))); | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + CHK_RET(static_cast<HcclResult>( | ||
| 270 | + HcommChannelNotifyRecordOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_DATA_SIGNAL))); | ||
| 271 | + CHK_RET(static_cast<HcclResult>( | ||
| 272 | + HcommChannelNotifyWaitOnThread(mainThread_, sio_link.handle, NOTIFY_IDX_DATA_SIGNAL, CUSTOM_TIMEOUT))); | ||
| 273 | + | ||
| 274 | + return HCCL_SUCCESS; | ||
| 275 | +} | ||
| 276 | + | ||
| 277 | +HcclResult | ||
| 278 | +AllReduceBIAR::LocalCopyAgLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX, u64 localStrideSize) | ||
| 279 | +{ | ||
| 280 | + if (round != 0 && round <= hccs_ranks.size()) { | ||
| 281 | + void* srcSlice = static_cast<void*>( | ||
| 282 | + static_cast<u8*>(scratchMem_.addr) + (hccs_ranks_reversed[round - 1] / rankSizeX) * localStrideSize); | ||
| 283 | + void* dstSlice | ||
| 284 | + = static_cast<void*>(static_cast<u8*>(outputMem_.addr) + slices_[hccs_ranks_reversed[round - 1]].offset); | ||
| 285 | + if (slices_[hccs_ranks_reversed[round - 1]].size > 0) { | ||
| 286 | + CHK_RET(static_cast<HcclResult>(HcommLocalCopyOnThread( | ||
| 287 | + subThreads_[1], dstSlice, srcSlice, slices_[hccs_ranks_reversed[round - 1]].size))); | ||
| 288 | + } | ||
| 289 | + } | ||
| 290 | + return HCCL_SUCCESS; | ||
| 291 | +} | ||
| 292 | + | ||
| 293 | +HcclResult | ||
| 294 | +AllReduceBIAR::RunAllGather(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels, u64 localStrideSize) | ||
| 295 | +{ | ||
| 296 | + for (u32 round = 0; round < hccs_ranks.size() + 1; round++) { | ||
| 297 | + // MainRecordSub + SubWaitMain | ||
| 298 | + CHK_RET(PreSyncInterThreads(mainThread_, subThreads_, notifyIdxMainToSub_)); | ||
| 299 | + CHK_RET(HCCSProcessAgLoop(round, rank, rankSize, rankSizeX_, localStrideSize)); | ||
| 300 | + CHK_RET(SIOProcessAgLoop(round, rank, rankSize, rankSizeX_, localStrideSize)); | ||
| 301 | + CHK_RET(LocalCopyAgLoop(round, rank, rankSize, rankSizeX_, localStrideSize)); | ||
| 302 | + | ||
| 303 | + // SubRecordMain + MainWaitSub | ||
| 304 | + CHK_RET(PostSyncInterThreads(mainThread_, subThreads_, notifyIdxSubToMain_)); | ||
| 305 | + } | ||
| 306 | + CHK_RET(PreSyncInterThreads(mainThread_, subThreads_, notifyIdxMainToSub_)); | ||
| 307 | + u64 allGatherOffset = rank / rankSizeX_ * localStrideSize; | ||
| 308 | + void* srcSlice = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + allGatherOffset); | ||
| 309 | + void* dstSlice = static_cast<void*>(static_cast<u8*>(outputMem_.addr) + slices_[rank].offset); | ||
| 310 | + if (slices_[rank].size > 0) { | ||
| 311 | + CHK_RET(static_cast<HcclResult>(HcommLocalCopyOnThread(mainThread_, dstSlice, srcSlice, slices_[rank].size))); | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + CHK_RET(PostSyncInterThreads(mainThread_, subThreads_, notifyIdxSubToMain_)); | ||
| 315 | + return HCCL_SUCCESS; | ||
| 316 | +} | ||
| 317 | + | ||
| 318 | +HcclResult AllReduceBIAR::CheckScratchCapacity(u32 rankSize, u64 localStrideSize) | ||
| 319 | +{ | ||
| 320 | + u64 scratchDemand = static_cast<u64>(rankSize) * localStrideSize; | ||
| 321 | + CHK_PRT_RET( | ||
| 322 | + scratchDemand > scratchMem_.size, | ||
| 323 | + HCCL_ERROR( | ||
| 324 | + "[AllReduceBIAR][CheckScratchCapacity]scratch demand[%llu] exceeds scratchMem size[%llu]", scratchDemand, | ||
| 325 | + scratchMem_.size), | ||
| 326 | + HCCL_E_PARA); | ||
| 327 | + return HCCL_SUCCESS; | ||
| 328 | +} | ||
| 329 | + | ||
| 330 | +HcclResult AllReduceBIAR::RunAsync(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels) | ||
| 331 | +{ | ||
| 332 | + HCCL_INFO( | ||
| 333 | + "AllReduceBIAR run: rank[%u] rankSize[%u] inputMem[%p] to outputMem[%p] count[%llu]", rank, rankSize, | ||
| 334 | + inputMem_.addr, outputMem_.addr, count_); | ||
| 335 | + | ||
| 336 | + CHK_RET(Preprocess(rank, rankSize, channels)); | ||
| 337 | + | ||
| 338 | + rankSizeX_ = 2; | ||
| 339 | + if (rankSize % rankSizeX_ != 0) { | ||
| 340 | + HCCL_ERROR( | ||
| 341 | + "[AllReduceBIAR][RunAsync]rankSize[%u] is not evenly divisible by rankSizeX_[%u]", rankSize, rankSizeX_); | ||
| 342 | + return HCCL_E_INTERNAL; | ||
| 343 | + } | ||
| 344 | + rankSizeY_ = rankSize / rankSizeX_; | ||
| 345 | + | ||
| 346 | + sio_rank_ = rank ^ 1; | ||
| 347 | + sio_link = channels[sio_rank_]; | ||
| 348 | + | ||
| 349 | + for (u32 i = 1; i < rankSize / rankSizeX_; ++i) { | ||
| 350 | + u32 current_hccs_rank = (rank + rankSizeX_ * i) % (rankSizeX_ * rankSizeY_); | ||
| 351 | + hccs_ranks.push_back(current_hccs_rank); | ||
| 352 | + hccs_neighbour_rank.push_back(current_hccs_rank ^ 1); | ||
| 353 | + hccs_links.push_back(channels[hccs_ranks[i - 1]]); | ||
| 354 | + } | ||
| 355 | + hccs_ranks_reversed.assign(hccs_ranks.rbegin(), hccs_ranks.rend()); | ||
| 356 | + hccs_links_reversed.assign(hccs_links.rbegin(), hccs_links.rend()); | ||
| 357 | + | ||
| 358 | + // slices_ prepared by Prepare() with V-style distribution (ReduceScatterV) | ||
| 359 | + u64 sliceSize = 0; | ||
| 360 | + for (u32 i = 0; i < rankSize; i++) { | ||
| 361 | + if (slices_[i].size > sliceSize) { | ||
| 362 | + sliceSize = slices_[i].size; | ||
| 363 | + } | ||
| 364 | + HCCL_DEBUG(" slice[%u]: offset: [%llu] size[%llu]", i, slices_[i].offset, slices_[i].size); | ||
| 365 | + } | ||
| 366 | + u64 localStrideSize = RoundUpWithDivisor(sliceSize, HCCL_MIN_SLICE_ALIGN_910B); | ||
[HIGH] RunAsync 计算 scratch 布局后无容量校验,大消息场景 CCL buffer 越界写 问题分析:
模板在 RunAsync/TreeReduceRs/HCCSProcessAgLoop 中按 (rankSize/rankSizeX + i) * localStrideSize 计算偏移写入 scratchMem_(即 CCL buffer 前半区 cclInputMem),最大写入范围约为 rankSize * localStrideSize 量级。但整个 BIAR 路径没有任何 scratch 容量校验:本仓 ReduceScatterV 路径已有 CheckScratchCapacity 先例(reduce_scatter_v_birs.cc 第 60-69 行,scratchDemand = rankSize * localStrideSize 与 scratchMem_.size 比较,不足即报 HCCL_E_PARA),BIAR 完全没有对应检查。cclInputMem 实际容量为 HcclGetHcclBuffer 返回的固定 cclBufferSize/2(scatter.cc AllocAlgResource 第 802 行),大消息(数据总量接近或超过 cclBufferSize/2)时树归约与 HCCS 写远端的偏移将越过 buffer 末端,造成设备侧越界写、数据静默损坏。 建议修复: 参照 ReduceScatterVBIRS::CheckScratchCapacity 在 RunAsync 计算 localStrideSize 后增加校验:
注意配套修正 scratchMem_.size 的声明来源(见对 coll_executor_base_experimental.cc RunLoop 的意见),否则该校验会被虚高的声明大小放行。 ![]() ![]() Davydov_Danil 21 天前 评论: 21 天前 评论: | |||
| 367 | + | ||
| 368 | + CHK_RET(CheckScratchCapacity(rankSize, localStrideSize)); | ||
| 369 | + | ||
| 370 | + GetNotifyIdxMainToSub(notifyIdxMainToSub_); | ||
| 371 | + CHK_RET(PreSyncInterThreads(mainThread_, subThreads_, notifyIdxMainToSub_)); | ||
| 372 | + | ||
| 373 | + if (!hccs_ranks.empty() && slices_[hccs_ranks[0]].size > 0) { | ||
| 374 | + void* srcSlice = static_cast<void*>(static_cast<u8*>(inputMem_.addr) + slices_[hccs_ranks[0]].offset); | ||
| 375 | + void* dstSlice | ||
| 376 | + = static_cast<void*>(static_cast<u8*>(scratchMem_.addr) + hccs_ranks[0] / rankSizeX_ * localStrideSize); | ||
| 377 | + CHK_RET(static_cast<HcclResult>( | ||
| 378 | + HcommLocalCopyOnThread(mainThread_, dstSlice, srcSlice, slices_[hccs_ranks[0]].size))); | ||
| 379 | + } | ||
| 380 | + | ||
| 381 | + GetNotifyIdxSubToMain(notifyIdxSubToMain_); | ||
| 382 | + CHK_RET(PostSyncInterThreads(mainThread_, subThreads_, notifyIdxSubToMain_)); | ||
| 383 | + | ||
| 384 | + // MainRecordSub + SubWaitMain | ||
| 385 | + CHK_RET(RunReduceScatter(rank, rankSize, channels, localStrideSize)); | ||
| 386 | + CHK_RET(RunAllGather(rank, rankSize, channels, localStrideSize)); | ||
| 387 | + | ||
| 388 | + HCCL_INFO("AllReduceBIAR finished: rank[%u]", rank); | ||
| 389 | + return HCCL_SUCCESS; | ||
| 390 | +} | ||
| 391 | + | ||
| 392 | +REGISTER_TEMPLATE(TEMPLATE_ALL_REDUCE_BIAR, AllReduceBIAR); | ||
| 393 | +} // namespace ops_hccl_experimental | ||
| @@ -0,0 +1,97 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#ifndef ALL_REDUCE_BIAR_H | ||
| 12 | +#define ALL_REDUCE_BIAR_H | ||
| 13 | + | ||
| 14 | +#include "alg_template_base.h" | ||
| 15 | +#include "alg_data_trans_wrapper.h" | ||
| 16 | +#include "alg_template_base_experimental.h" | ||
| 17 | + | ||
| 18 | +namespace ops_hccl_experimental { | ||
| 19 | +using ops_hccl::AlgTemplateBase; | ||
| 20 | +using ops_hccl::AlgTemplateRegistry; | ||
| 21 | +using ops_hccl::ChannelInfo; | ||
| 22 | +using ops_hccl::CUSTOM_TIMEOUT; | ||
| 23 | +using ops_hccl::DefaultTemplateCreator; | ||
| 24 | +using ops_hccl::HCCL_MIN_SLICE_ALIGN_910B; | ||
| 25 | +using ops_hccl::NOTIFY_IDX_ACK; | ||
| 26 | +using ops_hccl::NOTIFY_IDX_DATA_SIGNAL; | ||
| 27 | +using ops_hccl::PostSyncInterThreads; | ||
| 28 | +using ops_hccl::PreSyncInterThreads; | ||
| 29 | +using ops_hccl::RoundUpWithDivisor; | ||
| 30 | +using ops_hccl::Slice; | ||
| 31 | +using ops_hccl::TemplateType; | ||
| 32 | + | ||
| 33 | +// BIAR 从线程数单一事实源: executor 侧据此申请 slaveThreadNum/notify 资源, 模板侧据此生成 notifyIdx | ||
| 34 | +// 并索引 subThreads_, 两侧必须一致 | ||
| 35 | +constexpr u32 BIAR_THREAD_NUM = 2; | ||
| 36 | + | ||
| 37 | +class AllReduceBIAR : public AlgTemplateBaseExperimental { | ||
| 38 | +public: | ||
| 39 | + explicit AllReduceBIAR(); | ||
[LOW] 无参构造函数标注 explicit 无意义 问题分析:
建议修复: 移除 explicit,或直接 AllReduceBIAR() = default; ![]() ![]() | |||
| 40 | + | ||
| 41 | + ~AllReduceBIAR() override; | ||
| 42 | + | ||
| 43 | + // should be called soon after template AllReduceBIAR instance created | ||
| 44 | + HcclResult Prepare(u32 interRank, u32 interRankSize) override; | ||
| 45 | + | ||
| 46 | + HcclResult Prepare( | ||
| 47 | + HcclMem& inputMem, HcclMem& outputMem, HcclMem& scratchMem, const u64 count, const HcclDataType dataType, | ||
| 48 | + ThreadHandle thread, const std::vector<ThreadHandle>& slaveThreads, const HcclReduceOp reductionOp, | ||
| 49 | + const u32 root, const std::vector<Slice>& slices, const u64 baseOffset, const bool disableDMAReduce) override; | ||
| 50 | + | ||
| 51 | + HcclResult RunAsync(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels) override; | ||
| 52 | + | ||
| 53 | +protected: | ||
| 54 | + void GetNotifyIdxMainToSub(std::vector<u32>& notifyIdxMainToSub); | ||
| 55 | + void GetNotifyIdxSubToMain(std::vector<u32>& notifyIdxSubToMain); | ||
| 56 | + | ||
| 57 | + virtual HcclResult Preprocess(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels); | ||
| 58 | + HcclResult CheckScratchCapacity(u32 rankSize, u64 localStrideSize); | ||
| 59 | + HcclResult | ||
| 60 | + RunReduceScatter(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels, u64 localStrideSize); | ||
| 61 | + HcclResult | ||
| 62 | + RunAllGather(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels, u64 localStrideSize); | ||
| 63 | + | ||
| 64 | + HcclResult HCCSProcessRsLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX_, u64 localStrideSize); | ||
| 65 | + HcclResult SIOProcessRsLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX_, u64 localStrideSize); | ||
| 66 | + HcclResult LocalCopyRsLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX_, u64 localStrideSize); | ||
| 67 | + HcclResult TreeReduceRs(const u32 rank, const u32 rankSize, u32 rankSizeX_, u64 localStrideSize); | ||
| 68 | + HcclResult LocalReduceCCLToCCL(u64 srcOffset, u64 dstOffset, u64 size, ThreadHandle thread); | ||
| 69 | + | ||
| 70 | + HcclResult HCCSProcessAgLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX_, u64 localStrideSize); | ||
| 71 | + HcclResult SIOProcessAgLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX_, u64 localStrideSize); | ||
| 72 | + HcclResult LocalCopyAgLoop(u32 round, const u32 rank, const u32 rankSize, u32 rankSizeX_, u64 localStrideSize); | ||
| 73 | + | ||
| 74 | + u32 interRank_; | ||
| 75 | + u32 interRankSize_; | ||
| 76 | + u32 sio_rank_; | ||
| 77 | + std::vector<u32> hccs_ranks; | ||
| 78 | + std::vector<u32> hccs_ranks_reversed; | ||
| 79 | + std::vector<u32> hccs_neighbour_rank; | ||
| 80 | + | ||
| 81 | + std::vector<ChannelInfo> hccs_links; | ||
| 82 | + std::vector<ChannelInfo> hccs_links_reversed; | ||
| 83 | + ChannelInfo sio_link; | ||
| 84 | + | ||
| 85 | + u32 unitSize_; | ||
| 86 | + ThreadHandle mainThread_; | ||
| 87 | + std::vector<ThreadHandle> subThreads_; | ||
| 88 | + std::vector<u32> notifyIdxMainToSub_; | ||
| 89 | + std::vector<u32> notifyIdxSubToMain_; | ||
| 90 | + u32 rankSizeX_; | ||
| 91 | + u32 rankSizeY_; | ||
| 92 | + | ||
| 93 | +private: | ||
| 94 | +}; | ||
| 95 | +} // namespace ops_hccl_experimental | ||
| 96 | + | ||
| 97 | +#endif /* ALL_REDUCE_BIAR_H */ | ||
| @@ -13,6 +13,7 @@ add_subdirectory(recursive_executor) | |||
| 13 | 13 | ||
| 14 | set(src_list | 14 | set(src_list |
| 15 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common_experimental.cc | 15 | ${CMAKE_CURRENT_SOURCE_DIR}/op_common_experimental.cc |
| 16 | + ${CMAKE_CURRENT_SOURCE_DIR}/coll_executor_base_experimental.cc | ||
| 16 | ) | 17 | ) |
| 17 | 18 | ||
| 18 | if(TARGET hccl) | 19 | if(TARGET hccl) |
| @@ -0,0 +1,184 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include "coll_executor_base_experimental.h" | ||
| 12 | + | ||
| 13 | +namespace ops_hccl_experimental { | ||
| 14 | +using ops_hccl::AlgHierarchyInfo; | ||
| 15 | +using ops_hccl::ExecMem; | ||
| 16 | +using ops_hccl::HCCL_INTERNODE_MAX_DATA_RATE; | ||
| 17 | +using ops_hccl::RDMA_SEND_MAX_SIZE; | ||
| 18 | +using ops_hccl::SDMA_SEND_MAX_SIZE; | ||
| 19 | + | ||
| 20 | +CollExecutorBaseExperimental::CollExecutorBaseExperimental() : ExecutorBase() {} | ||
| 21 | + | ||
| 22 | +u32 CollExecutorBaseExperimental::CalcUnitSize(const OpParam& param) const | ||
| 23 | +{ | ||
| 24 | + return HCCL_SIZE_TABLE[param.DataDes.dataType]; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +u64 CollExecutorBaseExperimental::CalcScratchDemand(u64 curRecvSize) const | ||
| 28 | +{ | ||
| 29 | + return topoInfo_->userRankSize * curRecvSize; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +// 执行入口 | ||
| 33 | +HcclResult CollExecutorBaseExperimental::Orchestrate(const OpParam& param, AlgResourceCtx* resCtx) | ||
| 34 | +{ | ||
| 35 | + HcclUs startut = TIME_NOW(); | ||
| 36 | + topoInfo_ = &(resCtx->topoInfo); | ||
| 37 | + algResource_ = resCtx; | ||
| 38 | + tag_ = std::string(param.tag); | ||
| 39 | + algType_ = resCtx->algType; | ||
| 40 | + unitSize_ = CalcUnitSize(param); | ||
| 41 | + | ||
| 42 | + CHK_PTR_NULL(param.inputPtr); | ||
| 43 | + CHK_PTR_NULL(param.outputPtr); | ||
| 44 | + | ||
| 45 | + // 做参数的还原 | ||
| 46 | + ThreadHandle* threadHandlePtr | ||
| 47 | + = reinterpret_cast<ThreadHandle*>(reinterpret_cast<char*>(algResource_) + sizeof(AlgResourceCtx)); | ||
| 48 | + ChannelInfo* channelInfoPtr = reinterpret_cast<ChannelInfo*>( | ||
| 49 | + reinterpret_cast<char*>(threadHandlePtr) + sizeof(ThreadHandle) * (algResource_->slaveThreadNum + 1)); | ||
| 50 | + | ||
| 51 | + HCCL_DEBUG("[CollExecutorBaseExperimental][Orchestrate] slaveThreadNum[%u]", algResource_->slaveThreadNum); | ||
| 52 | + for (u32 i = 0; i < algResource_->slaveThreadNum + 1; i++) { | ||
| 53 | + HCCL_DEBUG("[CollExecutorBaseExperimental][Orchestrate] threadHandle[%u]=[%llu]", i, threadHandlePtr[i]); | ||
| 54 | + if (i == 0) { | ||
| 55 | + thread_ = threadHandlePtr[i]; | ||
| 56 | + } else { | ||
| 57 | + slaveThreads_.push_back(threadHandlePtr[i]); | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + AlgHierarchyInfo& algHierarchyInfo = resCtx->algHierarchyInfo; | ||
| 61 | + channels_.resize(algHierarchyInfo.levels); | ||
| 62 | + for (u32 level = 0; level < algHierarchyInfo.levels; level++) { | ||
| 63 | + u32 curLevelRankSize = algHierarchyInfo.infos[level].localRankSize; | ||
| 64 | + channels_[level].resize(curLevelRankSize); | ||
| 65 | + for (u32 rank = 0; rank < curLevelRankSize; rank++) { | ||
| 66 | + channels_[level][rank] = channelInfoPtr[rank]; | ||
| 67 | + } | ||
| 68 | + channelInfoPtr += curLevelRankSize; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + HcclResult ret = RunLoop(param); | ||
| 72 | + CHK_PRT_RET( | ||
| 73 | + ret != HCCL_SUCCESS, | ||
| 74 | + HCCL_ERROR( | ||
| 75 | + "[CollExecutorBaseExperimental][Orchestrate]errNo[0x%016llx]collective executor kernel run failed", | ||
| 76 | + HCCL_ERROR_CODE(ret)), | ||
| 77 | + ret); | ||
| 78 | + HCCL_INFO( | ||
| 79 | + "[CollExecutorBaseExperimental][Orchestrate]tag[%s] collective executor orchestrate success, take time " | ||
| 80 | + "[%lld]us.", | ||
| 81 | + param.tag, DURATION_US(TIME_NOW() - startut)); | ||
| 82 | + return HCCL_SUCCESS; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +bool CollExecutorBaseExperimental::IsHugeData(u64 curSize) const | ||
| 86 | +{ | ||
| 87 | + bool hugeData = curSize * topoInfo_->userRankSize / HCCL_INTERNODE_MAX_DATA_RATE > RDMA_SEND_MAX_SIZE | ||
| 88 | + || curSize > SDMA_SEND_MAX_SIZE; | ||
| 89 | + return hugeData; | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +HcclResult CollExecutorBaseExperimental::RunLoop(const OpParam& param) | ||
| 93 | +{ | ||
| 94 | + u64 totalRecvCount = param.DataDes.count; | ||
| 95 | + | ||
| 96 | + u8* curUserInputPtr = static_cast<u8*>(param.inputPtr); | ||
| 97 | + u8* curUserOutputPtr = static_cast<u8*>(param.outputPtr); | ||
| 98 | + auto cclInputMem = algResource_->cclInputMem; | ||
| 99 | + auto cclOutputMem = algResource_->cclOutputMem; | ||
| 100 | + CHK_PRT_RET( | ||
| 101 | + (cclInputMem.size == 0), HCCL_ERROR("[CollExecutorBaseExperimental][RunLoop]cclBuffer size is zero"), | ||
| 102 | + HCCL_E_PARA); | ||
| 103 | + | ||
| 104 | + u64 curRecvCount = totalRecvCount; | ||
| 105 | + u64 curRecvSize = curRecvCount * unitSize_; | ||
| 106 | + u64 curSendSize = topoInfo_->userRankSize * curRecvSize; | ||
| 107 | + | ||
| 108 | + // 资源申请(HcommAcquireComm/HcommBatchModeStart)前先做容量校验, 校验失败直接返回不持有任何资源。 | ||
| 109 | + // scratch 需求随算子语义不同: ReduceScatter 为全量(userRankSize*单rank量), AllReduce(RS+AG 分解, | ||
| 110 | + // 切片总和为单 rank 数据量)为单 rank 量, 由 CalcScratchDemand 统一提供 | ||
| 111 | + u64 scratchDemand = CalcScratchDemand(curRecvSize); | ||
| 112 | + CHK_PRT_RET( | ||
| 113 | + scratchDemand > cclInputMem.size, | ||
| 114 | + HCCL_ERROR( | ||
| 115 | + "[CollExecutorBaseExperimental][RunLoop]scratch demand[%llu] exceeds cclInputMem size[%llu]", scratchDemand, | ||
| 116 | + cclInputMem.size), | ||
| 117 | + HCCL_E_PARA); | ||
| 118 | + | ||
| 119 | + if (param.engine == CommEngine::COMM_ENGINE_CPU_TS || param.engine == CommEngine::COMM_ENGINE_CPU) { | ||
| 120 | + int32_t ret = HcommAcquireComm(param.commName); | ||
| 121 | + CHK_PRT_RET( | ||
| 122 | + ret != HCCL_SUCCESS, HCCL_ERROR("[%s] [%s] HcommAcquireComm failed ", __func__, param.commName), | ||
| 123 | + static_cast<HcclResult>(ret)); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | +#ifndef AICPU_COMPILE | ||
| 127 | + if (!IsHugeData(curRecvSize)) { | ||
| 128 | + HcclResult startRet = static_cast<HcclResult>(HcommBatchModeStart(param.algTag)); | ||
| 129 | + if (startRet != HCCL_SUCCESS) { | ||
| 130 | + HCCL_ERROR("[%s] [%s] HcommBatchModeStart failed", __func__, param.algTag); | ||
| 131 | + if (param.engine == CommEngine::COMM_ENGINE_CPU_TS || param.engine == CommEngine::COMM_ENGINE_CPU) { | ||
| 132 | + int32_t relRet = HcommReleaseComm(param.commName); | ||
| 133 | + if (relRet != HCCL_SUCCESS) { | ||
| 134 | + HCCL_ERROR("[%s] [%s] HcommReleaseComm failed ", __func__, param.commName); | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + return startRet; | ||
| 138 | + } | ||
| 139 | + } | ||
| 140 | +#endif | ||
| 141 | + // scratch 实际可用区域为整个 cclInputMem(CCL buffer 前半区), 声明大小必须传真实容量而非 curSendSize: | ||
| 142 | + // 模板容量校验(如 CheckScratchCapacity)以 scratchMem_.size 判断, 声明失真会误报或漏判 | ||
| 143 | + HcclMem curInputMem{cclInputMem.type, cclInputMem.addr, cclInputMem.size}; | ||
| 144 | + HcclMem curOutputMem{cclOutputMem.type, cclOutputMem.addr, curRecvSize}; | ||
| 145 | + | ||
| 146 | + ExecMem execMem; | ||
| 147 | + execMem.count = curRecvCount; | ||
| 148 | + execMem.inputMem = curInputMem; | ||
| 149 | + execMem.outputMem = curOutputMem; | ||
| 150 | + execMem.inputPtr = curUserInputPtr; | ||
| 151 | + execMem.outputPtr = curUserOutputPtr; | ||
| 152 | + | ||
| 153 | + HCCL_DEBUG( | ||
| 154 | + "[CollExecutorBaseExperimental][RunLoop] curUserInputPtr[%p], curUserOutputPtr[%p], " | ||
| 155 | + "curRecvCount[%llu], curRecvSize[%llu], curSendSize[%llu], inputPtr[%p], outputPtr[%p]", | ||
| 156 | + curUserInputPtr, curUserOutputPtr, curRecvCount, curRecvSize, curSendSize, curInputMem.addr, curOutputMem.addr); | ||
| 157 | + | ||
| 158 | + HcclResult runRet = KernelRun(param, execMem); | ||
| 159 | + | ||
| 160 | + HcclResult releaseRet = HCCL_SUCCESS; | ||
| 161 | +#ifndef AICPU_COMPILE | ||
| 162 | + if (!IsHugeData(curRecvSize)) { | ||
| 163 | + releaseRet = static_cast<HcclResult>(HcommBatchModeEnd(param.algTag)); | ||
| 164 | + if (releaseRet != HCCL_SUCCESS) { | ||
| 165 | + HCCL_ERROR("[%s] [%s] HcommBatchModeEnd failed", __func__, param.algTag); | ||
| 166 | + } | ||
| 167 | + } | ||
| 168 | +#endif | ||
| 169 | + if (param.engine == CommEngine::COMM_ENGINE_CPU_TS || param.engine == CommEngine::COMM_ENGINE_CPU) { | ||
| 170 | + int32_t ret = HcommReleaseComm(param.commName); | ||
| 171 | + if (ret != HCCL_SUCCESS) { | ||
| 172 | + HCCL_ERROR("[%s] [%s] HcommReleaseComm failed ", __func__, param.commName); | ||
| 173 | + if (releaseRet == HCCL_SUCCESS) { | ||
| 174 | + releaseRet = static_cast<HcclResult>(ret); | ||
| 175 | + } | ||
| 176 | + } | ||
| 177 | + } | ||
| 178 | + if (runRet != HCCL_SUCCESS) { | ||
| 179 | + return runRet; | ||
| 180 | + } | ||
| 181 | + return releaseRet; | ||
| 182 | +} | ||
| 183 | + | ||
| 184 | +} // namespace ops_hccl_experimental | ||
| @@ -0,0 +1,56 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#ifndef COLL_EXECUTOR_BASE_EXPERIMENTAL_H | ||
| 12 | +#define COLL_EXECUTOR_BASE_EXPERIMENTAL_H | ||
| 13 | + | ||
| 14 | +#include "alg_param.h" | ||
| 15 | +#include "executor_base.h" | ||
| 16 | +#include "config_log.h" | ||
| 17 | + | ||
| 18 | +namespace ops_hccl_experimental { | ||
| 19 | +using ops_hccl::AlgResourceCtx; | ||
| 20 | +using ops_hccl::ChannelInfo; | ||
| 21 | +using ops_hccl::ExecutorBase; | ||
| 22 | +using ops_hccl::OpParam; | ||
| 23 | + | ||
| 24 | +// 集合通信 executor 公共 orchestration 基类: 统一 Orchestrate/RunLoop/IsHugeData 与线程/通道成员, | ||
| 25 | +// 消除各算子 executor 基类的逐行重复; RunLoop 失败路径保证 HcommBatchModeEnd/HcommReleaseComm 释放。 | ||
| 26 | +// 数据切片语义(均匀/V式)由派生类自行实现 PrepareDataSlice。 | ||
| 27 | +class CollExecutorBaseExperimental : public ExecutorBase { | ||
| 28 | +public: | ||
| 29 | + explicit CollExecutorBaseExperimental(); | ||
| 30 | + ~CollExecutorBaseExperimental() override = default; | ||
| 31 | + | ||
| 32 | + HcclResult Orchestrate(const OpParam& param, AlgResourceCtx* resCtx) override; | ||
| 33 | + | ||
| 34 | +protected: | ||
| 35 | + // 用于需要Loop的Executor | ||
| 36 | + virtual HcclResult RunLoop(const OpParam& param); | ||
| 37 | + | ||
| 38 | + bool IsHugeData(u64 curSize) const; | ||
| 39 | + | ||
| 40 | + // 单位数据大小: 默认取 DataDes.dataType; 变长算子(如 ReduceScatterV) override 取 vDataDes.dataType | ||
| 41 | + virtual u32 CalcUnitSize(const OpParam& param) const; | ||
| 42 | + | ||
| 43 | + // RunLoop 的 scratch 容量校验值: 默认按 ReduceScatter 语义取全量(userRankSize*单rank接收量, | ||
| 44 | + // 全量数据驻留 CCL buffer 前半区); AllReduce(RS+AG 分解, 切片总和为单 rank 数据量)等 | ||
| 45 | + // 单 rank 量需求的算子由派生类 override | ||
| 46 | + virtual u64 CalcScratchDemand(u64 curRecvSize) const; | ||
| 47 | + | ||
| 48 | + ThreadHandle thread_ = 0; | ||
| 49 | + std::vector<ThreadHandle> slaveThreads_; | ||
| 50 | + std::vector<std::vector<ChannelInfo>> channels_; | ||
| 51 | + u32 unitSize_; | ||
| 52 | +}; | ||
| 53 | + | ||
| 54 | +} // namespace ops_hccl_experimental | ||
| 55 | + | ||
| 56 | +#endif | ||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "hcomm_host_profiling_dl.h" | 20 | #include "hcomm_host_profiling_dl.h" |
| 21 | #include "reduce_scatter_birs_selector.h" | 21 | #include "reduce_scatter_birs_selector.h" |
| 22 | #include "reduce_scatter_v_birs_selector.h" | 22 | #include "reduce_scatter_v_birs_selector.h" |
| 23 | +#include "all_reduce_biar_selector.h" | ||
| 23 | #include <algorithm> | 24 | #include <algorithm> |
| 24 | #include <future> | 25 | #include <future> |
| 25 | #include <map> | 26 | #include <map> |
| @@ -178,6 +179,38 @@ SelectAlgReduceScatterV(HcclComm comm, OpParam& param, TopoInfo* topoInfo, AlgTy | |||
| 178 | return HCCL_SUCCESS; | 179 | return HCCL_SUCCESS; |
| 179 | } | 180 | } |
| 180 | 181 | ||
| 182 | +HcclResult SelectAlgAllReduce(HcclComm comm, OpParam& param, TopoInfo* topoInfo, AlgType& algType, std::string& algName) | ||
| 183 | +{ | ||
| 184 | + (void)comm; | ||
| 185 | + ValidateAndResetAlgLevel1(algType, "All_Reduce"); | ||
| 186 | + | ||
| 187 | + const BiarSelectResult biarResult = DecideAllReduceBiarAlg(*topoInfo, algName); | ||
| 188 | + const HcclResult biarRet = BiarSelectResultToCode(biarResult); | ||
| 189 | + if (biarRet != HCCL_SUCCESS) { | ||
| 190 | + if (biarResult == BiarSelectResult::bRejectServerNumZero) { | ||
| 191 | + HCCL_ERROR( | ||
| 192 | + "[%s] AllReduceBIAR not supported: serverNum is 0, cannot compute ranks per server " | ||
| 193 | + "(userRankSize[%u])", | ||
| 194 | + __func__, topoInfo->userRankSize); | ||
| 195 | + } else if (biarResult == BiarSelectResult::bRejectRanksPerServerLT4) { | ||
| 196 | + HCCL_ERROR( | ||
| 197 | + "[%s] AllReduceBIAR not supported: userRankSize[%u] / serverNum[%u] < 4", __func__, | ||
| 198 | + topoInfo->userRankSize, topoInfo->serverNum); | ||
| 199 | + } | ||
| 200 | + return biarRet; | ||
| 201 | + } | ||
| 202 | + if (biarResult != BiarSelectResult::bSelected || algName.empty()) { | ||
| 203 | + HCCL_ERROR( | ||
| 204 | + "[%s] AllReduceBIAR not selected: deviceType[%d] and even userRankSize[%u] are required, " | ||
| 205 | + "no fallback executor on the BIRS path", | ||
| 206 | + __func__, topoInfo->deviceType, topoInfo->userRankSize); | ||
| 207 | + return HCCL_E_PARA; | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + CHK_RET(FillAlgTagAndDebugInfo(param, topoInfo, algType, algName, "All_Reduce")); | ||
| 211 | + return HCCL_SUCCESS; | ||
| 212 | +} | ||
🟡 Medium Priority changed line → affected behavior/contract → failure mode → suggested fix
if (topoInfo->userRankSize == 1) { return HCCL_E_INTERNAL; } else if (topoInfo->deviceType == DevType::DEV_TYPE_910_93 && (topoInfo->userRankSize % 2 == 0)) { algName = "AllReduceBIARExecutor"; } // 当 deviceType != 910_93 或 rankSize 为奇数(且 >1)时,algName 保持空字符串 CHK_RET(FillAlgTagAndDebugInfo(param, topoInfo, algType, algName, "All_Reduce")); return HCCL_SUCCESS; 触发条件:当用户设置 失败模式: 建议:在 if-else 链之后增加 ![]() ![]() 不准确? Lankin Ivan 9月1日 评论: 9月1日 评论: | |||
| 213 | + | ||
| 181 | struct ThreadResources { | 214 | struct ThreadResources { |
| 182 | ThreadHandle cpuTsThread = 0; | 215 | ThreadHandle cpuTsThread = 0; |
| 183 | ThreadHandle exportedAicpuTsThread = 0; | 216 | ThreadHandle exportedAicpuTsThread = 0; |
| @@ -341,7 +374,12 @@ HcclResult DoAicpuKernelLaunch(OpParam& param, uint64_t& beginTime) | |||
| 341 | HCCL_E_OPEN_FILE_FAILURE); | 374 | HCCL_E_OPEN_FILE_FAILURE); |
| 342 | 375 | ||
| 343 | if (HcommIsProfilingSupported()) { | 376 | if (HcommIsProfilingSupported()) { |
| 344 | - std::string profName = "ReduceScatterAicpuKernel"; | 377 | + std::string profName = ""; |
| 378 | + if (param.opType == HCCL_CMD_REDUCE_SCATTER) { | ||
| 379 | + profName = "ReduceScatterAicpuKernel"; | ||
| 380 | + } else if (param.opType == HCCL_CMD_ALLREDUCE) { | ||
| 381 | + profName = "AllReduceAicpuKernel"; | ||
| 382 | + } | ||
| 345 | HCCL_DEBUG("[%s] profName = [%s]", __func__, profName); | 383 | HCCL_DEBUG("[%s] profName = [%s]", __func__, profName); |
| 346 | HcommProfilingReportKernel(beginTime, profName.c_str()); | 384 | HcommProfilingReportKernel(beginTime, profName.c_str()); |
| 347 | } | 385 | } |
| @@ -388,6 +426,8 @@ HcclResult ExecOpBirs(HcclComm comm, OpParam& param) | |||
| 388 | CHK_RET(SelectAlgReduceScatter(comm, param, topoInfo, algType, algName)); | 426 | CHK_RET(SelectAlgReduceScatter(comm, param, topoInfo, algType, algName)); |
| 389 | } else if (param.opType == HCCL_CMD_REDUCE_SCATTER_V) { | 427 | } else if (param.opType == HCCL_CMD_REDUCE_SCATTER_V) { |
| 390 | CHK_RET(SelectAlgReduceScatterV(comm, param, topoInfo, algType, algName)); | 428 | CHK_RET(SelectAlgReduceScatterV(comm, param, topoInfo, algType, algName)); |
| 429 | + } else if (param.opType == HCCL_CMD_ALLREDUCE) { | ||
| 430 | + CHK_RET(SelectAlgAllReduce(comm, param, topoInfo, algType, algName)); | ||
| 391 | } | 431 | } |
| 392 | 432 | ||
| 393 | std::unique_ptr<ExecutorBase> executor = CollAlgExecRegistry::Instance().GetAlgExec(algName); | 433 | std::unique_ptr<ExecutorBase> executor = CollAlgExecRegistry::Instance().GetAlgExec(algName); |
| @@ -26,6 +26,7 @@ constexpr TemplateType TEMPLATE_REDUCE_SCATTER_BIRS = static_cast<TemplateType>( | |||
| 26 | constexpr TemplateType TEMPLATE_REDUCE_SCATTER_BIRS_INTER = static_cast<TemplateType>(1002); | 26 | constexpr TemplateType TEMPLATE_REDUCE_SCATTER_BIRS_INTER = static_cast<TemplateType>(1002); |
| 27 | constexpr TemplateType TEMPLATE_REDUCE_SCATTER_V_BIRS = static_cast<TemplateType>(1003); | 27 | constexpr TemplateType TEMPLATE_REDUCE_SCATTER_V_BIRS = static_cast<TemplateType>(1003); |
| 28 | constexpr TemplateType TEMPLATE_REDUCE_SCATTER_V_BIRS_INTER = static_cast<TemplateType>(1004); | 28 | constexpr TemplateType TEMPLATE_REDUCE_SCATTER_V_BIRS_INTER = static_cast<TemplateType>(1004); |
| 29 | +constexpr TemplateType TEMPLATE_ALL_REDUCE_BIAR = static_cast<TemplateType>(1005); | ||
| 29 | 30 | ||
| 30 | class AlgTemplateBaseExperimental : public ops_hccl::AlgTemplateBase { | 31 | class AlgTemplateBaseExperimental : public ops_hccl::AlgTemplateBase { |
| 31 | public: | 32 | public: |
| @@ -11,131 +11,8 @@ | |||
| 11 | #include "reduce_scatter_executor_base.h" | 11 | #include "reduce_scatter_executor_base.h" |
| 12 | 12 | ||
| 13 | namespace ops_hccl_experimental { | 13 | namespace ops_hccl_experimental { |
| 14 | -using ops_hccl::ExecMem; | ||
| 15 | -using ops_hccl::HCCL_INTERNODE_MAX_DATA_RATE; | ||
| 16 | -using ops_hccl::RDMA_SEND_MAX_SIZE; | ||
| 17 | -using ops_hccl::SDMA_SEND_MAX_SIZE; | ||
| 18 | 14 | ||
| 19 | -ReduceScatterExecutorBase::ReduceScatterExecutorBase() : ExecutorBase() {} | 15 | +ReduceScatterExecutorBase::ReduceScatterExecutorBase() : CollExecutorBaseExperimental() {} |
| 20 | - | ||
| 21 | -// 执行入口 | ||
| 22 | -HcclResult ReduceScatterExecutorBase::Orchestrate(const OpParam& param, AlgResourceCtx* resCtx) | ||
| 23 | -{ | ||
| 24 | - HcclUs startut = TIME_NOW(); | ||
| 25 | - topoInfo_ = &(resCtx->topoInfo); | ||
| 26 | - algResource_ = resCtx; | ||
| 27 | - tag_ = std::string(param.tag); | ||
| 28 | - algType_ = resCtx->algType; | ||
| 29 | - unitSize_ = HCCL_SIZE_TABLE[param.DataDes.dataType]; | ||
| 30 | - | ||
| 31 | - CHK_PTR_NULL(param.inputPtr); | ||
| 32 | - CHK_PTR_NULL(param.outputPtr); | ||
| 33 | - | ||
| 34 | - // 做参数的还原 | ||
| 35 | - ThreadHandle* threadHandlePtr | ||
| 36 | - = reinterpret_cast<ThreadHandle*>(reinterpret_cast<char*>(algResource_) + sizeof(AlgResourceCtx)); | ||
| 37 | - ChannelInfo* channelInfoPtr = reinterpret_cast<ChannelInfo*>( | ||
| 38 | - reinterpret_cast<char*>(threadHandlePtr) + sizeof(ThreadHandle) * (algResource_->slaveThreadNum + 1)); | ||
| 39 | - | ||
| 40 | - HCCL_DEBUG("[ReduceScatterExecutorBase][Orchestrate] slaveThreadNum[%u]", algResource_->slaveThreadNum); | ||
| 41 | - for (u32 i = 0; i < algResource_->slaveThreadNum + 1; i++) { | ||
| 42 | - HCCL_DEBUG("[ReduceScatterExecutorBase][Orchestrate] threadHandle[%u]=[%llu]", i, threadHandlePtr[i]); | ||
| 43 | - if (i == 0) { | ||
| 44 | - thread_ = threadHandlePtr[i]; | ||
| 45 | - } else { | ||
| 46 | - slaveThreads_.push_back(threadHandlePtr[i]); | ||
| 47 | - } | ||
| 48 | - } | ||
| 49 | - AlgHierarchyInfo& algHierarchyInfo = resCtx->algHierarchyInfo; | ||
| 50 | - channels_.resize(algHierarchyInfo.levels); | ||
| 51 | - for (u32 level = 0; level < algHierarchyInfo.levels; level++) { | ||
| 52 | - u32 curLevelRankSize = algHierarchyInfo.infos[level].localRankSize; | ||
| 53 | - channels_[level].resize(curLevelRankSize); | ||
| 54 | - for (u32 rank = 0; rank < curLevelRankSize; rank++) { | ||
| 55 | - channels_[level][rank] = channelInfoPtr[rank]; | ||
| 56 | - } | ||
| 57 | - channelInfoPtr += curLevelRankSize; | ||
| 58 | - } | ||
| 59 | - | ||
| 60 | - HcclResult ret = RunLoop(param); | ||
| 61 | - CHK_PRT_RET( | ||
| 62 | - ret != HCCL_SUCCESS, | ||
| 63 | - HCCL_ERROR( | ||
| 64 | - "[ReduceScatterExecutorBase][Orchestrate]errNo[0x%016llx] ReduceScatter executor kernel run failed", | ||
| 65 | - HCCL_ERROR_CODE(ret)), | ||
| 66 | - ret); | ||
| 67 | - HCCL_INFO( | ||
| 68 | - "[ReduceScatterExecutorBase][Orchestrate]tag[%s] ReduceScatter executor orchestrate success, take time " | ||
| 69 | - "[%lld]us.", | ||
| 70 | - param.tag, DURATION_US(TIME_NOW() - startut)); | ||
| 71 | - return HCCL_SUCCESS; | ||
| 72 | -} | ||
| 73 | - | ||
| 74 | -bool ReduceScatterExecutorBase::IsHugeData(u64 curSize) const | ||
| 75 | -{ | ||
| 76 | - bool hugeData = curSize * topoInfo_->userRankSize / HCCL_INTERNODE_MAX_DATA_RATE > RDMA_SEND_MAX_SIZE | ||
| 77 | - || curSize > SDMA_SEND_MAX_SIZE; | ||
| 78 | - return hugeData; | ||
| 79 | -} | ||
| 80 | - | ||
| 81 | -HcclResult ReduceScatterExecutorBase::RunLoop(const OpParam& param) | ||
| 82 | -{ | ||
| 83 | - u64 totalRecvCount = param.DataDes.count; | ||
| 84 | - u64 totalRecvSize = totalRecvCount * unitSize_; | ||
| 85 | - | ||
| 86 | - u8* curUserInputPtr = static_cast<u8*>(param.inputPtr); | ||
| 87 | - u8* curUserOutputPtr = static_cast<u8*>(param.outputPtr); | ||
| 88 | - auto cclInputMem = algResource_->cclInputMem; | ||
| 89 | - auto cclOutputMem = algResource_->cclOutputMem; | ||
| 90 | - CHK_PRT_RET( | ||
| 91 | - (cclInputMem.size == 0), HCCL_ERROR("[ReduceScatterExecutorBase][RunLoop]cclBuffer size is zero"), HCCL_E_PARA); | ||
| 92 | - | ||
| 93 | - if (param.engine == CommEngine::COMM_ENGINE_CPU_TS || param.engine == CommEngine::COMM_ENGINE_CPU) { | ||
| 94 | - int32_t ret = HcommAcquireComm(param.commName); | ||
| 95 | - CHK_PRT_RET( | ||
| 96 | - ret != HCCL_SUCCESS, HCCL_ERROR("[%s] [%s] HcommAcquireComm failed ", __func__, param.commName), | ||
| 97 | - static_cast<HcclResult>(ret)); | ||
| 98 | - } | ||
| 99 | - | ||
| 100 | - u64 curRecvCount = totalRecvCount; | ||
| 101 | - u64 curRecvSize = curRecvCount * unitSize_; | ||
| 102 | - u64 curSendSize = topoInfo_->userRankSize * curRecvSize; | ||
| 103 | - | ||
| 104 | -#ifndef AICPU_COMPILE | ||
| 105 | - if (!IsHugeData(curRecvSize)) { | ||
| 106 | - CHK_RET(static_cast<HcclResult>(HcommBatchModeStart(param.algTag))); | ||
| 107 | - } | ||
| 108 | -#endif | ||
| 109 | - HcclMem curInputMem{cclInputMem.type, cclInputMem.addr, curSendSize}; | ||
| 110 | - HcclMem curOutputMem{cclOutputMem.type, cclOutputMem.addr, curRecvSize}; | ||
| 111 | - | ||
| 112 | - ExecMem execMem; | ||
| 113 | - execMem.count = curRecvCount; | ||
| 114 | - execMem.inputMem = curInputMem; | ||
| 115 | - execMem.outputMem = curOutputMem; | ||
| 116 | - execMem.inputPtr = curUserInputPtr; | ||
| 117 | - execMem.outputPtr = curUserOutputPtr; | ||
| 118 | - | ||
| 119 | - HCCL_DEBUG( | ||
| 120 | - "[ReduceScatterExecutorBase][RunLoop] curUserInputPtr[%p], curUserOutputPtr[%p], " | ||
| 121 | - "curRecvCount[%llu], curRecvSize[%llu], curSendSize[%llu], inputPtr[%p], outputPtr[%p]", | ||
| 122 | - curUserInputPtr, curUserOutputPtr, curRecvCount, curRecvSize, curSendSize, curInputMem.addr, curOutputMem.addr); | ||
| 123 | - | ||
| 124 | - CHK_RET(KernelRun(param, execMem)); | ||
| 125 | - | ||
| 126 | -#ifndef AICPU_COMPILE | ||
| 127 | - if (!IsHugeData(curRecvSize)) { | ||
| 128 | - CHK_RET(static_cast<HcclResult>(HcommBatchModeEnd(param.algTag))); | ||
| 129 | - } | ||
| 130 | -#endif | ||
| 131 | - if (param.engine == CommEngine::COMM_ENGINE_CPU_TS || param.engine == CommEngine::COMM_ENGINE_CPU) { | ||
| 132 | - int32_t ret = HcommReleaseComm(param.commName); | ||
| 133 | - CHK_PRT_RET( | ||
| 134 | - ret != HCCL_SUCCESS, HCCL_ERROR("[%s] [%s] HcommReleaseComm failed ", __func__, param.commName), | ||
| 135 | - static_cast<HcclResult>(ret)); | ||
| 136 | - } | ||
| 137 | - return HCCL_SUCCESS; | ||
| 138 | -} | ||
| 139 | 16 | ||
| 140 | HcclResult ReduceScatterExecutorBase::CalcResRequest( | 17 | HcclResult ReduceScatterExecutorBase::CalcResRequest( |
| 141 | HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, | 18 | HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, |
| @@ -15,44 +15,29 @@ | |||
| 15 | #include "executor_base.h" | 15 | #include "executor_base.h" |
| 16 | #include "config_log.h" | 16 | #include "config_log.h" |
| 17 | #include "alg_template_base_experimental.h" | 17 | #include "alg_template_base_experimental.h" |
| 18 | +#include "coll_executor_base_experimental.h" | ||
| 18 | 19 | ||
| 19 | namespace ops_hccl_experimental { | 20 | namespace ops_hccl_experimental { |
| 20 | using ops_hccl::AlgHierarchyInfo; | 21 | using ops_hccl::AlgHierarchyInfo; |
| 21 | -using ops_hccl::AlgResourceCtx; | ||
| 22 | using ops_hccl::AlgResourceRequest; | 22 | using ops_hccl::AlgResourceRequest; |
| 23 | using ops_hccl::AlgType; | 23 | using ops_hccl::AlgType; |
| 24 | -using ops_hccl::ChannelInfo; | ||
| 25 | -using ops_hccl::ExecutorBase; | ||
| 26 | using ops_hccl::OpParam; | 24 | using ops_hccl::OpParam; |
| 27 | using ops_hccl::Slice; | 25 | using ops_hccl::Slice; |
| 28 | using ops_hccl::TopoInfo; | 26 | using ops_hccl::TopoInfo; |
| 29 | 27 | ||
| 30 | -class ReduceScatterExecutorBase : public ExecutorBase { | 28 | +class ReduceScatterExecutorBase : public CollExecutorBaseExperimental { |
| 31 | public: | 29 | public: |
| 32 | explicit ReduceScatterExecutorBase(); | 30 | explicit ReduceScatterExecutorBase(); |
| 33 | ~ReduceScatterExecutorBase() override = default; | 31 | ~ReduceScatterExecutorBase() override = default; |
| 34 | 32 | ||
| 35 | - HcclResult Orchestrate(const OpParam& param, AlgResourceCtx* resCtx) override; | ||
| 36 | - | ||
| 37 | /* *************** 资源计算 *************** */ | 33 | /* *************** 资源计算 *************** */ |
| 38 | HcclResult CalcResRequest( | 34 | HcclResult CalcResRequest( |
| 39 | HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, | 35 | HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, |
| 40 | AlgResourceRequest& resourceRequest, AlgType& algType) override; | 36 | AlgResourceRequest& resourceRequest, AlgType& algType) override; |
| 41 | 37 | ||
| 42 | protected: | 38 | protected: |
| 43 | - // 用于需要Loop的Executor | ||
| 44 | - virtual HcclResult RunLoop(const OpParam& param); | ||
| 45 | - | ||
| 46 | /* *************** 通用工具 *************** */ | 39 | /* *************** 通用工具 *************** */ |
| 47 | virtual HcclResult PrepareDataSlice(u64 dataCount, u32 unitSize, u32 sliceNum, std::vector<Slice>& dataSlice); | 40 | virtual HcclResult PrepareDataSlice(u64 dataCount, u32 unitSize, u32 sliceNum, std::vector<Slice>& dataSlice); |
| 48 | - bool IsHugeData(u64 curSize) const; | ||
| 49 | - | ||
| 50 | - ThreadHandle thread_ = 0; | ||
| 51 | - std::vector<ThreadHandle> slaveThreads_; | ||
| 52 | - std::vector<std::vector<ChannelInfo>> channels_; | ||
| 53 | - OpParam param_; | ||
| 54 | - u32 unitSize_; | ||
| 55 | - u32 root_ = INVALID_VALUE_RANKID; | ||
| 56 | }; | 41 | }; |
| 57 | 42 | ||
| 58 | } // namespace ops_hccl_experimental | 43 | } // namespace ops_hccl_experimental |
| @@ -12,71 +12,12 @@ | |||
| 12 | 12 | ||
| 13 | namespace ops_hccl_experimental { | 13 | namespace ops_hccl_experimental { |
| 14 | using ops_hccl::ExecMem; | 14 | using ops_hccl::ExecMem; |
| 15 | -using ops_hccl::HCCL_INTERNODE_MAX_DATA_RATE; | ||
| 16 | -using ops_hccl::RDMA_SEND_MAX_SIZE; | ||
| 17 | -using ops_hccl::SDMA_SEND_MAX_SIZE; | ||
| 18 | 15 | ||
| 19 | -ReduceScatterVExecutorBase::ReduceScatterVExecutorBase() : ExecutorBase() {} | 16 | +ReduceScatterVExecutorBase::ReduceScatterVExecutorBase() : CollExecutorBaseExperimental() {} |
| 20 | 17 | ||
| 21 | -// 执行入口 | 18 | +u32 ReduceScatterVExecutorBase::CalcUnitSize(const OpParam& param) const |
| 22 | -HcclResult ReduceScatterVExecutorBase::Orchestrate(const OpParam& param, AlgResourceCtx* resCtx) | ||
| 23 | { | 19 | { |
| 24 | - HcclUs startut = TIME_NOW(); | 20 | + return HCCL_SIZE_TABLE[param.vDataDes.dataType]; |
| 25 | - topoInfo_ = &(resCtx->topoInfo); | ||
| 26 | - algResource_ = resCtx; | ||
| 27 | - tag_ = std::string(param.tag); | ||
| 28 | - algType_ = resCtx->algType; | ||
| 29 | - unitSize_ = HCCL_SIZE_TABLE[param.vDataDes.dataType]; | ||
| 30 | - | ||
| 31 | - CHK_PTR_NULL(param.inputPtr); | ||
| 32 | - CHK_PTR_NULL(param.outputPtr); | ||
| 33 | - | ||
| 34 | - // 做参数的还原 | ||
| 35 | - ThreadHandle* threadHandlePtr | ||
| 36 | - = reinterpret_cast<ThreadHandle*>(reinterpret_cast<char*>(algResource_) + sizeof(AlgResourceCtx)); | ||
| 37 | - ChannelInfo* channelInfoPtr = reinterpret_cast<ChannelInfo*>( | ||
| 38 | - reinterpret_cast<char*>(threadHandlePtr) + sizeof(ThreadHandle) * (algResource_->slaveThreadNum + 1)); | ||
| 39 | - | ||
| 40 | - HCCL_DEBUG("[ReduceScatterVExecutorBase][Orchestrate] slaveThreadNum[%u]", algResource_->slaveThreadNum); | ||
| 41 | - for (u32 i = 0; i < algResource_->slaveThreadNum + 1; i++) { | ||
| 42 | - HCCL_DEBUG("[ReduceScatterVExecutorBase][Orchestrate] threadHandle[%u]=[%llu]", i, threadHandlePtr[i]); | ||
| 43 | - if (i == 0) { | ||
| 44 | - thread_ = threadHandlePtr[i]; | ||
| 45 | - } else { | ||
| 46 | - slaveThreads_.push_back(threadHandlePtr[i]); | ||
| 47 | - } | ||
| 48 | - } | ||
| 49 | - AlgHierarchyInfo& algHierarchyInfo = resCtx->algHierarchyInfo; | ||
| 50 | - channels_.resize(algHierarchyInfo.levels); | ||
| 51 | - for (u32 level = 0; level < algHierarchyInfo.levels; level++) { | ||
| 52 | - u32 curLevelRankSize = algHierarchyInfo.infos[level].localRankSize; | ||
| 53 | - channels_[level].resize(curLevelRankSize); | ||
| 54 | - for (u32 rank = 0; rank < curLevelRankSize; rank++) { | ||
| 55 | - channels_[level][rank] = channelInfoPtr[rank]; | ||
| 56 | - } | ||
| 57 | - channelInfoPtr += curLevelRankSize; | ||
| 58 | - } | ||
| 59 | - | ||
| 60 | - HcclResult ret = RunLoop(param); | ||
| 61 | - CHK_PRT_RET( | ||
| 62 | - ret != HCCL_SUCCESS, | ||
| 63 | - HCCL_ERROR( | ||
| 64 | - "[ReduceScatterVExecutorBase][Orchestrate]errNo[0x%016llx]" | ||
| 65 | - " ReduceScatterV executor kernel run failed", | ||
| 66 | - HCCL_ERROR_CODE(ret)), | ||
| 67 | - ret); | ||
| 68 | - HCCL_INFO( | ||
| 69 | - "[ReduceScatterVExecutorBase][Orchestrate]tag[%s]" | ||
| 70 | - " ReduceScatterV executor orchestrate success, take time [%lld]us.", | ||
| 71 | - param.tag, DURATION_US(TIME_NOW() - startut)); | ||
| 72 | - return HCCL_SUCCESS; | ||
| 73 | -} | ||
| 74 | - | ||
| 75 | -bool ReduceScatterVExecutorBase::IsHugeData(u64 curSize) const | ||
| 76 | -{ | ||
| 77 | - bool hugeData = curSize * topoInfo_->userRankSize / HCCL_INTERNODE_MAX_DATA_RATE > RDMA_SEND_MAX_SIZE | ||
| 78 | - || curSize > SDMA_SEND_MAX_SIZE; | ||
| 79 | - return hugeData; | ||
| 80 | } | 21 | } |
| 81 | 22 | ||
| 82 | HcclResult ReduceScatterVExecutorBase::AcquireCommIfNeeded(const OpParam& param) | 23 | HcclResult ReduceScatterVExecutorBase::AcquireCommIfNeeded(const OpParam& param) |
| @@ -15,14 +15,12 @@ | |||
| 15 | #include "executor_base.h" | 15 | #include "executor_base.h" |
| 16 | #include "config_log.h" | 16 | #include "config_log.h" |
| 17 | #include "alg_template_base_experimental.h" | 17 | #include "alg_template_base_experimental.h" |
| 18 | +#include "coll_executor_base_experimental.h" | ||
| 18 | 19 | ||
| 19 | namespace ops_hccl_experimental { | 20 | namespace ops_hccl_experimental { |
| 20 | using ops_hccl::AlgHierarchyInfo; | 21 | using ops_hccl::AlgHierarchyInfo; |
| 21 | -using ops_hccl::AlgResourceCtx; | ||
| 22 | using ops_hccl::AlgResourceRequest; | 22 | using ops_hccl::AlgResourceRequest; |
| 23 | using ops_hccl::AlgType; | 23 | using ops_hccl::AlgType; |
| 24 | -using ops_hccl::ChannelInfo; | ||
| 25 | -using ops_hccl::ExecutorBase; | ||
| 26 | using ops_hccl::OpParam; | 24 | using ops_hccl::OpParam; |
| 27 | using ops_hccl::Slice; | 25 | using ops_hccl::Slice; |
| 28 | using ops_hccl::TopoInfo; | 26 | using ops_hccl::TopoInfo; |
| @@ -31,13 +29,11 @@ using ops_hccl::TopoInfo; | |||
| 31 | // 两侧统一引用本常量, 禁止再各自定义 | 29 | // 两侧统一引用本常量, 禁止再各自定义 |
| 32 | constexpr u32 BIRS_THREAD_NUM = 2; | 30 | constexpr u32 BIRS_THREAD_NUM = 2; |
| 33 | 31 | ||
| 34 | -class ReduceScatterVExecutorBase : public ExecutorBase { | 32 | +class ReduceScatterVExecutorBase : public CollExecutorBaseExperimental { |
| 35 | public: | 33 | public: |
| 36 | explicit ReduceScatterVExecutorBase(); | 34 | explicit ReduceScatterVExecutorBase(); |
| 37 | ~ReduceScatterVExecutorBase() override = default; | 35 | ~ReduceScatterVExecutorBase() override = default; |
| 38 | 36 | ||
| 39 | - HcclResult Orchestrate(const OpParam& param, AlgResourceCtx* resCtx) override; | ||
| 40 | - | ||
| 41 | /* *************** 资源计算 *************** */ | 37 | /* *************** 资源计算 *************** */ |
| 42 | HcclResult CalcResRequest( | 38 | HcclResult CalcResRequest( |
| 43 | HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, | 39 | HcclComm comm, const OpParam& param, TopoInfo* topoInfo, AlgHierarchyInfo& algHierarchyInfo, |
| @@ -45,20 +41,15 @@ public: | |||
| 45 | 41 | ||
| 46 | protected: | 42 | protected: |
| 47 | // 用于需要Loop的Executor | 43 | // 用于需要Loop的Executor |
| 48 | - virtual HcclResult RunLoop(const OpParam& param); | 44 | + HcclResult RunLoop(const OpParam& param) override; |
| 49 | 45 | ||
| 50 | /* *************** 通用工具 *************** */ | 46 | /* *************** 通用工具 *************** */ |
| 51 | // 根据变长counts/displs准备每个rank的数据切片(变长) | 47 | // 根据变长counts/displs准备每个rank的数据切片(变长) |
| 52 | HcclResult PrepareDataSliceV( | 48 | HcclResult PrepareDataSliceV( |
| 53 | const u64* sendCounts, const u64* sendDispls, u32 unitSize, u32 sliceNum, std::vector<Slice>& dataSlice); | 49 | const u64* sendCounts, const u64* sendDispls, u32 unitSize, u32 sliceNum, std::vector<Slice>& dataSlice); |
| 54 | - bool IsHugeData(u64 curSize) const; | ||
| 55 | HcclResult AcquireCommIfNeeded(const OpParam& param); | 50 | HcclResult AcquireCommIfNeeded(const OpParam& param); |
| 56 | HcclResult ReleaseCommIfNeeded(const OpParam& param); | 51 | HcclResult ReleaseCommIfNeeded(const OpParam& param); |
| 57 | - | 52 | + u32 CalcUnitSize(const OpParam& param) const override; |
| 58 | - ThreadHandle thread_ = 0; | ||
| 59 | - std::vector<ThreadHandle> slaveThreads_; | ||
| 60 | - std::vector<std::vector<ChannelInfo>> channels_; | ||
| 61 | - u32 unitSize_; | ||
| 62 | }; | 53 | }; |
| 63 | 54 | ||
| 64 | } // namespace ops_hccl_experimental | 55 | } // namespace ops_hccl_experimental |
| @@ -32,7 +32,11 @@ HcclResult HcclAllReduce( | |||
| 32 | bool isOutPlace = false; | 32 | bool isOutPlace = false; |
| 33 | CHK_RET(IsOutPlaceDevice(isOutPlace)); | 33 | CHK_RET(IsOutPlaceDevice(isOutPlace)); |
| 34 | if (!isOutPlace) { | 34 | if (!isOutPlace) { |
| 35 | +#ifdef ENABLE_EXPERIMENTAL | ||
| 36 | + return ops_hccl_experimental::AllReduceExperimental(sendBuf, recvBuf, count, dataType, op, comm, stream); | ||
| 37 | +#else | ||
| 35 | return HcclAllReduceInner(sendBuf, recvBuf, count, dataType, op, comm, stream); | 38 | return HcclAllReduceInner(sendBuf, recvBuf, count, dataType, op, comm, stream); |
| 39 | +#endif | ||
| 36 | } | 40 | } |
| 37 | CHK_PRT_RET(count == 0, HCCL_WARNING("input count is 0, return all reduce success"), HCCL_SUCCESS); | 41 | CHK_PRT_RET(count == 0, HCCL_WARNING("input count is 0, return all reduce success"), HCCL_SUCCESS); |
| 38 | 42 | ||
| @@ -18,6 +18,9 @@ | |||
| 18 | #include "executor_v2_base.h" | 18 | #include "executor_v2_base.h" |
| 19 | #include "alg_type.h" | 19 | #include "alg_type.h" |
| 20 | #include "execute_selector.h" | 20 | #include "execute_selector.h" |
| 21 | +#ifdef ENABLE_EXPERIMENTAL | ||
| 22 | +#include "all_reduce_op_experimental.h" | ||
| 23 | +#endif | ||
| 21 | 24 | ||
| 22 | #ifdef __cplusplus | 25 | #ifdef __cplusplus |
| 23 | extern "C" { | 26 | extern "C" { |
| @@ -38,6 +38,7 @@ function(add_st_test OP_NAME OP_SRC) | |||
| 38 | ${HCCL_DEV_BASE}/src/ops/op_common | 38 | ${HCCL_DEV_BASE}/src/ops/op_common |
| 39 | ${HCCL_DEV_BASE}/src/ops/op_common/inc | 39 | ${HCCL_DEV_BASE}/src/ops/op_common/inc |
| 40 | ${HCCL_DEV_BASE}/src/common/hcomm_dlsym | 40 | ${HCCL_DEV_BASE}/src/common/hcomm_dlsym |
| 41 | + ${HCCL_DEV_BASE}/src/common/hcomm_dlsym/ccu | ||
| 41 | 42 | ||
| 42 | ${UTILS_DIR}/sim_world | 43 | ${UTILS_DIR}/sim_world |
| 43 | ${UTILS_DIR}/common/utils | 44 | ${UTILS_DIR}/common/utils |
| @@ -134,6 +135,8 @@ if("all" IN_LIST ST_TASKS OR "reduce_scatter" IN_LIST ST_TASKS) | |||
| 134 | endif() | 135 | endif() |
| 135 | # a3(BIRS/BIRS-V) 用例依赖 experimental 构建的 libhccl(HCCL_BIRS_ENABLE 选路); | 136 | # a3(BIRS/BIRS-V) 用例依赖 experimental 构建的 libhccl(HCCL_BIRS_ENABLE 选路); |
| 136 | # 非 experimental 构建下 HcclReduceScatter(V)Inner 在 ST 打桩为 E_NOT_SUPPORT, 故仅在 ON 时注册 | 137 | # 非 experimental 构建下 HcclReduceScatter(V)Inner 在 ST 打桩为 E_NOT_SUPPORT, 故仅在 ON 时注册 |
| 138 | +# a3(AllReduceBIAR) 用例依赖 experimental 构建的 libhccl(HCCL_BIRS_ENABLE 选路); | ||
| 139 | +# 非 experimental 构建下老流程在 DEV_TYPE_910_93 仿真拓扑无可用算法(taskQueues 为空), 故仅在 ON 时注册 | ||
| 137 | if(ENABLE_EXPERIMENTAL) | 140 | if(ENABLE_EXPERIMENTAL) |
| 138 | if("all" IN_LIST ST_TASKS OR "reduce_scatter_v_a3" IN_LIST ST_TASKS) | 141 | if("all" IN_LIST ST_TASKS OR "reduce_scatter_v_a3" IN_LIST ST_TASKS) |
| 139 | add_st_test(reduce_scatter_v_a3 reduce_scatter_v_testcase_a3.cc) | 142 | add_st_test(reduce_scatter_v_a3 reduce_scatter_v_testcase_a3.cc) |
| @@ -141,6 +144,9 @@ if(ENABLE_EXPERIMENTAL) | |||
| 141 | if("all" IN_LIST ST_TASKS OR "reduce_scatter_a3" IN_LIST ST_TASKS) | 144 | if("all" IN_LIST ST_TASKS OR "reduce_scatter_a3" IN_LIST ST_TASKS) |
| 142 | add_st_test(reduce_scatter_a3 reduce_scatter_testcase_a3.cc) | 145 | add_st_test(reduce_scatter_a3 reduce_scatter_testcase_a3.cc) |
| 143 | endif() | 146 | endif() |
| 147 | + if("all" IN_LIST ST_TASKS OR "all_reduce_a3" IN_LIST ST_TASKS) | ||
| 148 | + add_st_test(all_reduce_a3 all_reduce_testcase_a3.cc) | ||
| 149 | + endif() | ||
| 144 | endif() | 150 | endif() |
| 145 | if("all" IN_LIST ST_TASKS OR "reduce_scatter_3level" IN_LIST ST_TASKS) | 151 | if("all" IN_LIST ST_TASKS OR "reduce_scatter_3level" IN_LIST ST_TASKS) |
| 146 | add_st_test(reduce_scatter_3level reduce_scatter_3level_testcase.cc) | 152 | add_st_test(reduce_scatter_3level reduce_scatter_3level_testcase.cc) |
| @@ -0,0 +1,257 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include "alg_param.h" | ||
| 12 | +#include "gtest/gtest.h" | ||
| 13 | +#include "sim_world.h" | ||
| 14 | +#include "hccl.h" | ||
| 15 | +#include "hccl/hccl_types.h" | ||
| 16 | +#include "acl/acl_rt.h" | ||
| 17 | +#include "hccl_verifier.h" | ||
| 18 | +#include "check_utils.h" | ||
| 19 | +#include <thread> | ||
| 20 | +#include "alg_env_config.h" | ||
| 21 | + | ||
| 22 | +using namespace HcclSim; | ||
| 23 | +using namespace ops_hccl; | ||
| 24 | + | ||
| 25 | +class ST_ALL_REDUCE_TEST_A3 : public ::testing::Test { | ||
| 26 | +protected: | ||
| 27 | + void SetUp() override { ResetAlgEnvConfigInitState(); } | ||
| 28 | + void TearDown() override | ||
| 29 | + { | ||
| 30 | + unsetenv("HCCL_OP_EXPANSION_MODE"); | ||
| 31 | + unsetenv("HCCL_INDEPENDENT_OP"); | ||
| 32 | + unsetenv("HCCL_ENABLE_OPEN_AICPU"); | ||
| 33 | + unsetenv("HCCL_BIRS_ENABLE"); | ||
| 34 | + } | ||
| 35 | + static void SetUpTestCase() {} | ||
| 36 | + static void TearDownTestCase() {} | ||
| 37 | + | ||
| 38 | + void RunAllReduceBiarA3( | ||
| 39 | + const TopoMeta& topoMeta, const u64& count, const HcclDataType& dataType, const HcclReduceOp& reduceOp) | ||
| 40 | + { | ||
| 41 | + SimWorld::Global()->Init(topoMeta, HcclDevType::DEV_TYPE_910_93); | ||
| 42 | + | ||
| 43 | + setenv("HCCL_OP_EXPANSION_MODE", "AI_CPU", 1); | ||
| 44 | + setenv("HCCL_INDEPENDENT_OP", "1", 1); | ||
| 45 | + setenv("HCCL_BIRS_ENABLE", "TRUE", 1); | ||
| 46 | + | ||
| 47 | + // 算子执行参数设置 | ||
| 48 | + auto rankSize = 0; | ||
| 49 | + for (u32 i = 0; i < topoMeta[0].size(); i++) | ||
| 50 | + rankSize += topoMeta[0][i].size(); // 参与集合通信的卡数(同topoMeta卡数一致) | ||
| 51 | + auto dataUnitSize = DATATYPE_SIZE_TABLE[dataType]; | ||
| 52 | + // 多线程运行ReduceScatter算子 | ||
| 53 | + std::vector<std::thread> threads; | ||
| 54 | + for (auto rankId = 0; rankId < rankSize; ++rankId) { | ||
| 55 | + threads.emplace_back([=]() { | ||
| 56 | + // 1.SetDevice | ||
| 57 | + aclrtSetDevice(rankId); | ||
| 58 | + | ||
| 59 | + // 2.创建流 | ||
| 60 | + aclrtStream stream = nullptr; | ||
| 61 | + aclrtCreateStream(&stream); | ||
| 62 | + | ||
| 63 | + // 3.初始化通信域 | ||
| 64 | + HcclComm comm = nullptr; | ||
| 65 | + CHK_RET(HcclCommInitClusterInfo("./ranktable.json", rankId, &comm)); | ||
| 66 | + | ||
| 67 | + void* sendBuf = nullptr; | ||
| 68 | + void* recvBuf = nullptr; | ||
| 69 | + u64 sendBufSize = count * dataUnitSize; // 数据量转化为字节数 | ||
| 70 | + u64 recvBufSize = count * dataUnitSize; | ||
| 71 | + // 打桩实现,仿真运行需标记内存是INPUT和OUTPUT | ||
| 72 | + if (aclrtMalloc(&sendBuf, sendBufSize, static_cast<aclrtMemMallocPolicy>(BUFFER_INPUT_MARK)) | ||
| 73 | + != ACL_SUCCESS) { | ||
| 74 | + return HcclResult::HCCL_E_MEMORY; | ||
| 75 | + } | ||
| 76 | + if (aclrtMalloc(&recvBuf, recvBufSize, static_cast<aclrtMemMallocPolicy>(BUFFER_OUTPUT_MARK)) | ||
| 77 | + != ACL_SUCCESS) { | ||
| 78 | + return HcclResult::HCCL_E_MEMORY; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + // 4.算子下发 | ||
| 82 | + CHK_RET(HcclAllReduce(sendBuf, recvBuf, count, dataType, reduceOp, comm, stream)); | ||
| 83 | + | ||
| 84 | + // 5.销毁通信域 | ||
| 85 | + CHK_RET(HcclCommDestroy(comm)); | ||
| 86 | + return HCCL_SUCCESS; | ||
| 87 | + }); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + // 等待多线程执行完成 | ||
| 91 | + for (auto& thread : threads) { | ||
| 92 | + thread.join(); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + // 结果成图校验 | ||
| 96 | + auto taskQueues = SimTaskQueue::Global()->GetAllRankTaskQueues(); | ||
| 97 | + HcclResult res = CheckAllReduce(taskQueues, rankSize, dataType, count, reduceOp); | ||
| 98 | + EXPECT_TRUE(res == HCCL_SUCCESS); | ||
| 99 | + | ||
| 100 | + // 资源清理 | ||
| 101 | + SimWorld::Global()->Deinit(); | ||
| 102 | + } | ||
| 103 | +}; | ||
| 104 | + | ||
| 105 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_114_test) | ||
| 106 | +{ | ||
| 107 | + // 仿真模型初始化 | ||
| 108 | + TopoMeta topoMeta{{{0, 1, 2, 3}}}; // 三维数组指定超节点-Server-Device信息 | ||
| 109 | + auto count = 400; // 单卡数据量 | ||
| 110 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; // 数据类型 | ||
| 111 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 112 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_114_rem_test) | ||
| 116 | +{ | ||
| 117 | + // 仿真模型初始化 | ||
| 118 | + TopoMeta topoMeta{{{0, 1, 2, 3}}}; // 三维数组指定超节点-Server-Device信息 | ||
| 119 | + auto count = 402; // 单卡数据量 | ||
| 120 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; // 数据类型 | ||
| 121 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 122 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_116_test) | ||
| 126 | +{ | ||
| 127 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5}}}; | ||
| 128 | + auto count = 600; | ||
| 129 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 130 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 131 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_116_rem_test) | ||
| 135 | +{ | ||
| 136 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5}}}; | ||
| 137 | + auto count = 602; | ||
| 138 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 139 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 140 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_118_test) | ||
| 144 | +{ | ||
| 145 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7}}}; | ||
| 146 | + auto count = 800; | ||
| 147 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 148 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 149 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_118_rem_test) | ||
| 153 | +{ | ||
| 154 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7}}}; | ||
| 155 | + auto count = 803; | ||
| 156 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 157 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 158 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_1110_test) | ||
| 162 | +{ | ||
| 163 | + // 仿真模型初始化 | ||
| 164 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}}; // 三维数组指定超节点-Server-Device信息 | ||
| 165 | + auto count = 1000; // 单卡数据量 | ||
| 166 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; // 数据类型 | ||
| 167 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 168 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 169 | +} | ||
| 170 | + | ||
| 171 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_1112_test) | ||
| 172 | +{ | ||
| 173 | + // 仿真模型初始化 | ||
| 174 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}}; // 三维数组指定超节点-Server-Device信息 | ||
| 175 | + auto count = 1200; // 单卡数据量 | ||
| 176 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; // 数据类型 | ||
| 177 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 178 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 179 | +} | ||
| 180 | + | ||
| 181 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_1114_test) | ||
| 182 | +{ | ||
| 183 | + // 仿真模型初始化 | ||
| 184 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}}; // 三维数组指定超节点-Server-Device信息 | ||
| 185 | + auto count = 1400; // 单卡数据量 | ||
| 186 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; // 数据类型 | ||
| 187 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 188 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 189 | +} | ||
| 190 | + | ||
| 191 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_1116_test) | ||
| 192 | +{ | ||
| 193 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}}; | ||
| 194 | + auto count = 1600; | ||
| 195 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 196 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 197 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 198 | +} | ||
| 199 | + | ||
| 200 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_1116_rem_test) | ||
| 201 | +{ | ||
| 202 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}}; | ||
| 203 | + auto count = 1603; | ||
| 204 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 205 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 206 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 207 | +} | ||
| 208 | + | ||
| 209 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_18_min_test) | ||
| 210 | +{ | ||
| 211 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7}}}; | ||
| 212 | + auto count = 800; | ||
| 213 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 214 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_MIN; | ||
| 215 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 216 | +} | ||
| 217 | + | ||
| 218 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_116_rem_max_test) | ||
| 219 | +{ | ||
| 220 | + TopoMeta topoMeta{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}}; | ||
| 221 | + auto count = 1603; | ||
| 222 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 223 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_MAX; | ||
| 224 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 225 | +} | ||
| 226 | + | ||
| 227 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_1416_test) | ||
| 228 | +{ | ||
| 229 | + // 仿真模型初始化 | ||
| 230 | + TopoMeta topoMeta; | ||
| 231 | + std::vector<u32> args{1, 4, 16}; | ||
| 232 | + for (int i = 0; i < args[0]; i++) { | ||
| 233 | + SuperPodMeta superPodMeta; | ||
| 234 | + for (int j = 0; j < args[1]; j++) { | ||
| 235 | + ServerMeta serverMate; | ||
| 236 | + for (int k = 0; k < args[2]; k++) { | ||
| 237 | + serverMate.push_back((unsigned int)k); | ||
| 238 | + } | ||
| 239 | + superPodMeta.push_back(serverMate); | ||
| 240 | + } | ||
| 241 | + topoMeta.push_back(superPodMeta); | ||
| 242 | + } | ||
| 243 | + auto recvCount = 6400; // 单卡数据量 | ||
| 244 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; // 数据类型 | ||
| 245 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_SUM; | ||
| 246 | + RunAllReduceBiarA3(topoMeta, recvCount, dataType, reduceOp); | ||
| 247 | +} | ||
| 248 | + | ||
| 249 | +TEST_F(ST_ALL_REDUCE_TEST_A3, st_all_reduce_1416_max_test) | ||
| 250 | +{ | ||
| 251 | + TopoMeta topoMeta; | ||
| 252 | + GenTopoMeta(topoMeta, 1, 4, 16); | ||
| 253 | + auto count = 640; | ||
| 254 | + auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32; | ||
| 255 | + auto reduceOp = HcclReduceOp::HCCL_REDUCE_MAX; | ||
| 256 | + RunAllReduceBiarA3(topoMeta, count, dataType, reduceOp); | ||
| 257 | +} | ||
| @@ -8,6 +8,7 @@ | |||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | +#include "alg_param.h" | ||
| 11 | #include "gtest/gtest.h" | 12 | #include "gtest/gtest.h" |
| 12 | #include "sim_world.h" | 13 | #include "sim_world.h" |
| 13 | #include "hccl.h" | 14 | #include "hccl.h" |
| @@ -47,7 +48,7 @@ protected: | |||
| 47 | auto rankSize = 0; | 48 | auto rankSize = 0; |
| 48 | for (u32 i = 0; i < topoMeta[0].size(); i++) | 49 | for (u32 i = 0; i < topoMeta[0].size(); i++) |
| 49 | rankSize += topoMeta[0][i].size(); // 参与集合通信的卡数(同topoMeta卡数一致) | 50 | rankSize += topoMeta[0][i].size(); // 参与集合通信的卡数(同topoMeta卡数一致) |
| 50 | - auto dataUnitSize = sizeof(dataType); | 51 | + auto dataUnitSize = DATATYPE_SIZE_TABLE[dataType]; |
| 51 | // 多线程运行ReduceScatter算子 | 52 | // 多线程运行ReduceScatter算子 |
| 52 | std::vector<std::thread> threads; | 53 | std::vector<std::thread> threads; |
| 53 | for (auto rankId = 0; rankId < rankSize; ++rankId) { | 54 | for (auto rankId = 0; rankId < rankSize; ++rankId) { |
| @@ -14,7 +14,8 @@ add_subdirectory(common/topo_match) | |||
| 14 | add_subdirectory(alltoall_hier) | 14 | add_subdirectory(alltoall_hier) |
| 15 | # recursive_executor 测试仅在 --experimental 构建(ENABLE_EXPERIMENTAL=ON)时编译 | 15 | # recursive_executor 测试仅在 --experimental 构建(ENABLE_EXPERIMENTAL=ON)时编译 |
| 16 | if(ENABLE_EXPERIMENTAL) | 16 | if(ENABLE_EXPERIMENTAL) |
| 17 | - add_subdirectory(recursive_executor) | ||
| 18 | add_subdirectory(reduce_scatter_birs) | 17 | add_subdirectory(reduce_scatter_birs) |
| 18 | + add_subdirectory(recursive_executor) | ||
| 19 | + add_subdirectory(all_reduce_biar) | ||
| 19 | add_subdirectory(reduce_scatter_v_birs) | 20 | add_subdirectory(reduce_scatter_v_birs) |
| 20 | endif() | 21 | endif() |
| @@ -0,0 +1,140 @@ | |||
| 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 | +set(_repo_root ${CMAKE_CURRENT_SOURCE_DIR}/../../..) | ||
| 12 | + | ||
| 13 | +set(_biar_ut_include_dirs | ||
| 14 | + ${_repo_root}/experimental/ops/all_reduce/biar | ||
| 15 | + ${_repo_root}/experimental/ops/all_reduce/biar/template | ||
| 16 | + ${_repo_root}/experimental/ops/op_common | ||
| 17 | + ${_repo_root}/experimental/ops/op_common/template | ||
| 18 | + ${_repo_root}/src/ops/op_common/inc | ||
| 19 | + ${_repo_root}/src/ops/op_common | ||
| 20 | + ${_repo_root}/src/ops/op_common/algorithm/template | ||
| 21 | + ${_repo_root}/src/ops/op_common/algorithm/template/registry | ||
| 22 | + ${_repo_root}/src/ops/op_common/algorithm/template/wrapper | ||
| 23 | + ${_repo_root}/src/ops/op_common/algorithm/executor | ||
| 24 | + ${_repo_root}/src/ops/op_common/algorithm/executor/registry | ||
| 25 | + ${_repo_root}/src/ops/op_common/algorithm/executor/channel | ||
| 26 | + ${_repo_root}/src/ops/op_common/algorithm/topo_match | ||
| 27 | + ${_repo_root}/src/ops/op_common/selector | ||
| 28 | + ${_repo_root}/src/ops/op_common/topo_info | ||
| 29 | + ${_repo_root}/src/common | ||
| 30 | + ${_repo_root}/src/common/hcomm_dlsym | ||
| 31 | + ${_repo_root}/src/common/hcomm_dlsym/ccu | ||
| 32 | +) | ||
| 33 | + | ||
| 34 | +# 前向兼容:探测 CANN 版本号,与主构建/ST 保持一致(宏逻辑与 test/ut/recursive_executor 一致)。 | ||
| 35 | +# 缺少该宏时 dlsym_common.h 中的桩类型块会启用,与 CANN 公共头重复定义导致 conflicting declaration。 | ||
| 36 | +macro(_detect_cann_version _target) | ||
| 37 | + file(GLOB _cann_arch_dirs LIST_DIRECTORIES true "${ASCEND_CANN_PACKAGE_PATH}/*-linux") | ||
| 38 | + if(_cann_arch_dirs) | ||
| 39 | + set(_cann_arch_dir "") | ||
| 40 | + foreach(_dir ${_cann_arch_dirs}) | ||
| 41 | + if(_dir MATCHES "/${CMAKE_SYSTEM_PROCESSOR}-linux$") | ||
| 42 | + set(_cann_arch_dir ${_dir}) | ||
| 43 | + break() | ||
| 44 | + endif() | ||
| 45 | + endforeach() | ||
| 46 | + if(NOT _cann_arch_dir) | ||
| 47 | + list(GET _cann_arch_dirs 0 _cann_arch_dir) | ||
| 48 | + endif() | ||
| 49 | + target_include_directories(${_target} PRIVATE | ||
| 50 | + ${_cann_arch_dir}/include | ||
| 51 | + ${_cann_arch_dir}/include/hccl | ||
| 52 | + ${_cann_arch_dir}/include/hcomm | ||
| 53 | + ${_cann_arch_dir}/include/hcomm/ccu | ||
| 54 | + ${_cann_arch_dir}/pkg_inc | ||
| 55 | + ${_cann_arch_dir}/pkg_inc/hccl | ||
| 56 | + ${_cann_arch_dir}/pkg_inc/base | ||
| 57 | + ${_cann_arch_dir}/pkg_inc/hcomm/ccu | ||
| 58 | + ) | ||
| 59 | + foreach(_arch_dir ${_cann_arch_dirs}) | ||
| 60 | + set(_ut_cann_ver_header "${_arch_dir}/include/version/cann_version.h") | ||
| 61 | + if(EXISTS "${_ut_cann_ver_header}") | ||
| 62 | + file(STRINGS "${_ut_cann_ver_header}" _ut_cann_ver_line | ||
| 63 | + REGEX "^#define[ \t]+CANN_VERSION_NUM[ \t]+") | ||
| 64 | + if(_ut_cann_ver_line) | ||
| 65 | + string(REGEX REPLACE "^#define[ \t]+CANN_VERSION_NUM[ \t]+(.+)$" "\\1" | ||
| 66 | + _UT_CANN_VERSION_EXPR "${_ut_cann_ver_line}") | ||
| 67 | + math(EXPR _UT_CANN_VERSION_NUM "${_UT_CANN_VERSION_EXPR}" OUTPUT_FORMAT DECIMAL) | ||
| 68 | + target_compile_definitions(${_target} | ||
| 69 | + PRIVATE CANN_VERSION_NUM=${_UT_CANN_VERSION_NUM}) | ||
| 70 | + message(STATUS "[UT] Detected CANN_VERSION_NUM = ${_UT_CANN_VERSION_NUM}") | ||
| 71 | + else() | ||
| 72 | + message(FATAL_ERROR "[UT] Failed to parse CANN_VERSION_NUM from ${_ut_cann_ver_header}: " | ||
| 73 | + "no '#define CANN_VERSION_NUM' line found. " | ||
| 74 | + "dlsym_common.h stub blocks would collide with CANN public headers.") | ||
| 75 | + endif() | ||
| 76 | + break() | ||
| 77 | + endif() | ||
| 78 | + endforeach() | ||
| 79 | + endif() | ||
| 80 | +endmacro() | ||
| 81 | + | ||
| 82 | +# ---------- all_reduce_biar_selector_test: 选路判定纯逻辑 ---------- | ||
| 83 | +set(ut_src_list | ||
| 84 | + ${CMAKE_CURRENT_SOURCE_DIR}/biar_selector_test.cc | ||
| 85 | + ${_repo_root}/experimental/ops/all_reduce/biar/all_reduce_biar_selector.cc | ||
| 86 | +) | ||
| 87 | + | ||
| 88 | +add_executable(all_reduce_biar_selector_test ${ut_src_list}) | ||
| 89 | + | ||
| 90 | +target_compile_options(all_reduce_biar_selector_test PRIVATE | ||
| 91 | + -U_FORTIFY_SOURCE | ||
| 92 | +) | ||
| 93 | + | ||
| 94 | +target_include_directories(all_reduce_biar_selector_test PRIVATE ${_biar_ut_include_dirs}) | ||
| 95 | + | ||
| 96 | +_detect_cann_version(all_reduce_biar_selector_test) | ||
| 97 | + | ||
| 98 | +target_link_libraries(all_reduce_biar_selector_test PRIVATE | ||
| 99 | + $<BUILD_INTERFACE:intf_llt_pub> | ||
| 100 | + GTest::gtest_main | ||
| 101 | + -lpthread | ||
| 102 | +) | ||
| 103 | + | ||
| 104 | +run_llt_test(TARGET all_reduce_biar_selector_test TASK_NUM 1) | ||
| 105 | + | ||
| 106 | +# ---------- all_reduce_biar_core_test: 切片换算/TreeReduce/RS·AG 环路核心逻辑 ---------- | ||
| 107 | +# executor_base/template 源文件整体编译; HCOMM 原语与 AlgTemplateBase 运行时依赖由本目录桩提供, 不依赖硬件 | ||
| 108 | +set(core_src_list | ||
| 109 | + ${CMAKE_CURRENT_SOURCE_DIR}/biar_core_test.cc | ||
| 110 | + ${CMAKE_CURRENT_SOURCE_DIR}/log_stub.cc | ||
| 111 | + ${CMAKE_CURRENT_SOURCE_DIR}/hcomm_stub.cc | ||
| 112 | + ${CMAKE_CURRENT_SOURCE_DIR}/base_class_stub.cc | ||
| 113 | + ${_repo_root}/experimental/ops/all_reduce/biar/all_reduce_executor_base.cc | ||
| 114 | + ${_repo_root}/experimental/ops/all_reduce/biar/template/all_reduce_biar.cc | ||
| 115 | + ${_repo_root}/experimental/ops/op_common/coll_executor_base_experimental.cc | ||
| 116 | + ${_repo_root}/experimental/ops/op_common/template/alg_template_base_experimental.cc | ||
| 117 | + ${_repo_root}/src/ops/op_common/algorithm/executor/executor_base.cc | ||
| 118 | + ${_repo_root}/src/ops/op_common/algorithm/template/registry/alg_template_register.cc | ||
| 119 | +) | ||
| 120 | + | ||
| 121 | +add_executable(all_reduce_biar_core_test ${core_src_list}) | ||
| 122 | + | ||
| 123 | +target_compile_options(all_reduce_biar_core_test PRIVATE | ||
| 124 | + -U_FORTIFY_SOURCE | ||
| 125 | +) | ||
| 126 | + | ||
| 127 | +target_include_directories(all_reduce_biar_core_test PRIVATE | ||
| 128 | + ${CMAKE_CURRENT_SOURCE_DIR} | ||
| 129 | + ${_biar_ut_include_dirs} | ||
| 130 | +) | ||
| 131 | + | ||
| 132 | +_detect_cann_version(all_reduce_biar_core_test) | ||
| 133 | + | ||
| 134 | +target_link_libraries(all_reduce_biar_core_test PRIVATE | ||
| 135 | + $<BUILD_INTERFACE:intf_llt_pub> | ||
| 136 | + GTest::gtest_main | ||
| 137 | + -lpthread | ||
| 138 | +) | ||
| 139 | + | ||
| 140 | +run_llt_test(TARGET all_reduce_biar_core_test TASK_NUM 1) | ||
| @@ -0,0 +1,113 @@ | |||
| 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 | +// UT 桩: AlgTemplateBase 的构造/析构/虚函数与线程同步原语。 | ||
| 12 | +// 真实实现(src/ops/op_common/algorithm/template/alg_template_base.cc)依赖 ExecTimeoutManager 与 | ||
| 13 | +// hcomm_primitives_dl 的 dlsym 运行时符号, 不适合 UT 独立编译; 本桩按真实实现的成员初始化语义等价提供, | ||
| 14 | +// 保证被测的 BIAR 模板成员(slices_/scratchMem_ 等)行为与生产一致。 | ||
| 15 | +// PreSync/PostSync 除返回成功外还记录调用序列, 供 RunAsync 编排确定性断言使用。 | ||
| 16 | + | ||
| 17 | +#include "alg_template_base.h" | ||
| 18 | +#include "alg_data_trans_wrapper.h" | ||
| 19 | +#include "hcomm_stub.h" | ||
| 20 | + | ||
| 21 | +namespace ops_hccl { | ||
| 22 | + | ||
| 23 | +AlgTemplateBase::AlgTemplateBase() | ||
| 24 | + : slices_(slicesDummy_), | ||
| 25 | + count_(0), | ||
| 26 | + dataBytes_(0), | ||
| 27 | + dataType_(HCCL_DATA_TYPE_RESERVED), | ||
| 28 | + reductionOp_(HCCL_REDUCE_RESERVED), | ||
| 29 | + root_(INVALID_VALUE_RANKID), | ||
| 30 | + baseOffset_(0), | ||
| 31 | + barrierSwitchOn_(true) | ||
| 32 | +{} | ||
| 33 | + | ||
| 34 | +AlgTemplateBase::~AlgTemplateBase() { slices_.clear(); } | ||
| 35 | + | ||
| 36 | +HcclResult AlgTemplateBase::Prepare(PrepareData& param) | ||
| 37 | +{ | ||
| 38 | + (void)param; | ||
| 39 | + return HCCL_E_PARA; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +HcclResult AlgTemplateBase::Prepare( | ||
| 43 | + HcclMem& inputMem, HcclMem& outputMem, HcclMem& scratchMem, const u64 count, const HcclDataType dataType, | ||
| 44 | + ThreadHandle thread, const HcclReduceOp reductionOp, const u32 root, const std::vector<Slice>& slices, | ||
| 45 | + const u64 baseOffset, const bool disableDMAReduce) | ||
| 46 | +{ | ||
| 47 | + inputMem_ = inputMem; | ||
| 48 | + outputMem_ = outputMem; | ||
| 49 | + scratchMem_ = scratchMem; | ||
| 50 | + thread_ = thread; | ||
| 51 | + count_ = count; | ||
| 52 | + dataType_ = dataType; | ||
| 53 | + dataBytes_ = count * DataUnitSize(dataType); | ||
| 54 | + reductionOp_ = reductionOp; | ||
| 55 | + root_ = root; | ||
| 56 | + disableDMAReduce_ = disableDMAReduce; | ||
| 57 | + baseOffset_ = baseOffset; | ||
| 58 | + if (slices.size() > 0) { | ||
| 59 | + slices_.resize(slices.size()); | ||
| 60 | + slices_ = slices; | ||
| 61 | + } | ||
| 62 | + return HCCL_SUCCESS; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +HcclResult AlgTemplateBase::Prepare(u32 interRank, u32 interRankSize) | ||
| 66 | +{ | ||
| 67 | + (void)interRank; | ||
| 68 | + (void)interRankSize; | ||
| 69 | + return HCCL_E_PARA; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +HcclResult AlgTemplateBase::Prepare( | ||
| 73 | + HcclCollOpInfo* opInfo, const u32 userRank, const std::vector<u32>& ringsOrders, | ||
| 74 | + const std::vector<Slice>& userMemInputSlices) | ||
| 75 | +{ | ||
| 76 | + (void)opInfo; | ||
| 77 | + (void)userRank; | ||
| 78 | + (void)ringsOrders; | ||
| 79 | + (void)userMemInputSlices; | ||
| 80 | + return HCCL_E_PARA; | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +HcclResult AlgTemplateBase::RunAsync(const u32 rank, const u32 rankSize, std::vector<ChannelInfo>& channels) | ||
| 84 | +{ | ||
| 85 | + (void)rank; | ||
| 86 | + (void)rankSize; | ||
| 87 | + (void)channels; | ||
| 88 | + return HCCL_SUCCESS; | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +HcclResult PreSyncInterThreads( | ||
| 92 | + const ThreadHandle& mainThread, const std::vector<ThreadHandle>& subThreads, | ||
| 93 | + const std::vector<u32>& notifyIdxMainToSub) | ||
| 94 | +{ | ||
| 95 | + (void)subThreads; | ||
| 96 | + (void)notifyIdxMainToSub; | ||
| 97 | + int32_t stubRet | ||
| 98 | + = biar_ut::RecordCall({biar_ut::StubApi::kPreSync, mainThread, 0, nullptr, nullptr, 0, -1, -1, 0, ""}); | ||
| 99 | + return stubRet == 0 ? HCCL_SUCCESS : static_cast<HcclResult>(stubRet); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +HcclResult PostSyncInterThreads( | ||
| 103 | + const ThreadHandle& mainThread, const std::vector<ThreadHandle>& subThreads, | ||
| 104 | + const std::vector<u32>& notifyIdxSubToMain) | ||
| 105 | +{ | ||
| 106 | + (void)subThreads; | ||
| 107 | + (void)notifyIdxSubToMain; | ||
| 108 | + int32_t stubRet | ||
| 109 | + = biar_ut::RecordCall({biar_ut::StubApi::kPostSync, mainThread, 0, nullptr, nullptr, 0, -1, -1, 0, ""}); | ||
| 110 | + return stubRet == 0 ? HCCL_SUCCESS : static_cast<HcclResult>(stubRet); | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +} // namespace ops_hccl | ||
| @@ -0,0 +1,678 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include <gtest/gtest.h> | ||
| 12 | +#include <vector> | ||
| 13 | +#include "hcomm_stub.h" | ||
| 14 | +#include "hcomm_primitives.h" | ||
| 15 | +#include "all_reduce_biar.h" | ||
| 16 | +#include "all_reduce_executor_base.h" | ||
| 17 | + | ||
| 18 | +namespace { | ||
| 19 | +using namespace ops_hccl; | ||
| 20 | +using namespace ops_hccl_experimental; | ||
| 21 | +using biar_ut::StubApi; | ||
| 22 | +using biar_ut::StubCall; | ||
| 23 | + | ||
| 24 | +void* const kInputBase = reinterpret_cast<void*>(0x10000000000ULL); | ||
| 25 | +void* const kOutputBase = reinterpret_cast<void*>(0x20000000000ULL); | ||
| 26 | +void* const kScratchBase = reinterpret_cast<void*>(0x30000000000ULL); | ||
| 27 | +void* const kRemoteBase = reinterpret_cast<void*>(0x40000000000ULL); | ||
| 28 | +constexpr u64 kMemSize = 1ULL << 20; | ||
| 29 | +constexpr u64 kRemoteStep = 1ULL << 24; | ||
| 30 | +constexpr u64 kStride = 256; | ||
| 31 | +constexpr u32 kUnit = 4; | ||
| 32 | +constexpr ThreadHandle kMainThread = 100; | ||
| 33 | +constexpr ThreadHandle kSub0 = 101; | ||
| 34 | +constexpr ThreadHandle kSub1 = 102; | ||
| 35 | +constexpr ChannelHandle kHandleBase = 0x1000; | ||
| 36 | + | ||
| 37 | +void* PtrAt(void* base, u64 offset) { return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(base) + offset); } | ||
| 38 | + | ||
| 39 | +u64 OffsetFrom(const void* ptr, const void* base) | ||
| 40 | +{ | ||
| 41 | + return static_cast<u64>(reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(base)); | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +std::vector<Slice> MakeSlices(const std::vector<u64>& sizes) | ||
| 45 | +{ | ||
| 46 | + std::vector<Slice> slices; | ||
| 47 | + u64 offset = 0; | ||
| 48 | + for (u64 size : sizes) { | ||
| 49 | + slices.push_back(Slice{offset, size}); | ||
| 50 | + offset += size; | ||
| 51 | + } | ||
| 52 | + return slices; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +ChannelInfo MakeChannel(u32 remoteRank) | ||
| 56 | +{ | ||
| 57 | + ChannelInfo channel; | ||
| 58 | + channel.isValid = true; | ||
| 59 | + channel.remoteRank = remoteRank; | ||
| 60 | + channel.handle = kHandleBase + remoteRank; | ||
| 61 | + channel.remoteOutput = HcclMem{HCCL_MEM_TYPE_DEVICE, PtrAt(kRemoteBase, remoteRank * kRemoteStep), kMemSize}; | ||
| 62 | + return channel; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +std::vector<ChannelInfo> MakeChannels(u32 rankSize) | ||
| 66 | +{ | ||
| 67 | + std::vector<ChannelInfo> channels; | ||
| 68 | + for (u32 i = 0; i < rankSize; i++) { | ||
| 69 | + channels.push_back(MakeChannel(i)); | ||
| 70 | + } | ||
| 71 | + return channels; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +class BiarExecutorUnderTest : public AllReduceExecutorBase { | ||
| 75 | +public: | ||
| 76 | + using AllReduceExecutorBase::PrepareDataSlice; | ||
| 77 | +}; | ||
| 78 | + | ||
| 79 | +class BiarTemplateUnderTest : public AllReduceBIAR { | ||
| 80 | +public: | ||
| 81 | + using AllReduceBIAR::HCCSProcessAgLoop; | ||
| 82 | + using AllReduceBIAR::HCCSProcessRsLoop; | ||
| 83 | + using AllReduceBIAR::LocalCopyAgLoop; | ||
| 84 | + using AllReduceBIAR::LocalCopyRsLoop; | ||
| 85 | + using AllReduceBIAR::Preprocess; | ||
| 86 | + using AllReduceBIAR::SIOProcessAgLoop; | ||
| 87 | + using AllReduceBIAR::SIOProcessRsLoop; | ||
| 88 | + using AllReduceBIAR::TreeReduceRs; | ||
| 89 | + | ||
| 90 | + void SetupMem(const std::vector<Slice>& slices, u64 count, HcclReduceOp op = HCCL_REDUCE_SUM, u32 unitSize = kUnit) | ||
| 91 | + { | ||
| 92 | + HcclMem inputMem{HCCL_MEM_TYPE_DEVICE, kInputBase, kMemSize}; | ||
| 93 | + HcclMem outputMem{HCCL_MEM_TYPE_DEVICE, kOutputBase, kMemSize}; | ||
| 94 | + HcclMem scratchMem{HCCL_MEM_TYPE_DEVICE, kScratchBase, kMemSize}; | ||
| 95 | + std::vector<ThreadHandle> slaveThreads{kSub0, kSub1}; | ||
| 96 | + AllReduceBIAR::Prepare( | ||
| 97 | + inputMem, outputMem, scratchMem, count, HCCL_DATA_TYPE_INT32, kMainThread, slaveThreads, op, 0, slices, 0, | ||
| 98 | + false); | ||
| 99 | + unitSize_ = unitSize; | ||
| 100 | + } | ||
| @@ -0,0 +1,120 @@ | |||
| 1 | +/** | ||
W ⚠️ [中等] [测试覆盖率] test/ut/all_reduce_biar/biar_selector_test.cc:1 当前 UT 仅覆盖 selector 返回码(120 行),all_reduce_biar.cc 382 行模板核心逻辑(PrepareDataSlice 切片换算/余数分布、TreeReduceRs 拓扑、HCCS/SIO ProcessRsLoop、RunAllGather)零 UT。切片换算与 tree-reduce 均为纯逻辑,可低成本单测(参考 PR #2338 补充 birs_v_core_test.cc 的模式)。 建议:补充 core 逻辑 UT,至少覆盖切片换算与 TreeReduce 的非均匀/边界场景。 ![]() ![]() | |||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include <string> | ||
| 12 | +#include <gtest/gtest.h> | ||
| 13 | +#include "all_reduce_biar_selector.h" | ||
| 14 | + | ||
| 15 | +using ops_hccl::TopoInfo; | ||
| 16 | +using ops_hccl_experimental::BiarSelectResult; | ||
| 17 | +using ops_hccl_experimental::BiarSelectResultToCode; | ||
| 18 | +using ops_hccl_experimental::DecideAllReduceBiarAlg; | ||
| 19 | + | ||
| 20 | +namespace { | ||
| 21 | +TopoInfo MakeTopo(u32 userRankSize, u32 serverNum, HcclDevType deviceType) | ||
| 22 | +{ | ||
| 23 | + TopoInfo topo{}; | ||
| 24 | + topo.userRankSize = userRankSize; | ||
| 25 | + topo.serverNum = serverNum; | ||
| 26 | + topo.deviceType = deviceType; | ||
| 27 | + return topo; | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +const std::string BIAR_ALG_NAME = "AllReduceBIARExecutor"; | ||
| 31 | +} // namespace | ||
| 32 | + | ||
| 33 | +TEST(AllReduceBiarSelector, ServerNumZeroIsRejectedInsteadOfDivByZero) | ||
| 34 | +{ | ||
| 35 | + std::string algName; | ||
| 36 | + TopoInfo topo = MakeTopo(8, 0, HcclDevType::DEV_TYPE_910_93); | ||
| 37 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bRejectServerNumZero); | ||
| 38 | + EXPECT_TRUE(algName.empty()); | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +TEST(AllReduceBiarSelector, DualCardSingleServerIsRejected) | ||
| 42 | +{ | ||
| 43 | + std::string algName; | ||
| 44 | + TopoInfo topo = MakeTopo(2, 1, HcclDevType::DEV_TYPE_910_93); | ||
| 45 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bRejectRanksPerServerLT4); | ||
| 46 | + EXPECT_TRUE(algName.empty()); | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +TEST(AllReduceBiarSelector, ThreeRanksPerServerIsRejected) | ||
| 50 | +{ | ||
| 51 | + std::string algName; | ||
| 52 | + TopoInfo topo = MakeTopo(6, 2, HcclDevType::DEV_TYPE_910_93); | ||
| 53 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bRejectRanksPerServerLT4); | ||
| 54 | + EXPECT_TRUE(algName.empty()); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +TEST(AllReduceBiarSelector, RankSizeOneIsRejected) | ||
| 58 | +{ | ||
| 59 | + std::string algName; | ||
| 60 | + TopoInfo topo = MakeTopo(1, 1, HcclDevType::DEV_TYPE_910_93); | ||
| 61 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bRejectRankSizeOne); | ||
| 62 | + EXPECT_TRUE(algName.empty()); | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +TEST(AllReduceBiarSelector, FourRanksPerServerIsSelected) | ||
| 66 | +{ | ||
| 67 | + std::string algName; | ||
| 68 | + TopoInfo topo = MakeTopo(8, 2, HcclDevType::DEV_TYPE_910_93); | ||
| 69 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bSelected); | ||
| 70 | + EXPECT_EQ(algName, BIAR_ALG_NAME); | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +TEST(AllReduceBiarSelector, ExactlyFourRanksPerServerBoundarySelected) | ||
| 74 | +{ | ||
| 75 | + std::string algName; | ||
| 76 | + TopoInfo topo = MakeTopo(4, 1, HcclDevType::DEV_TYPE_910_93); | ||
| 77 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bSelected); | ||
| 78 | + EXPECT_EQ(algName, BIAR_ALG_NAME); | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +TEST(AllReduceBiarSelector, MoreThanFourRanksSingleServerIsSelected) | ||
| 82 | +{ | ||
| 83 | + std::string algName; | ||
| 84 | + TopoInfo topo = MakeTopo(16, 1, HcclDevType::DEV_TYPE_910_93); | ||
| 85 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bSelected); | ||
| 86 | + EXPECT_EQ(algName, BIAR_ALG_NAME); | ||
| 87 | +} | ||
| 88 | + | ||
| 89 | +TEST(AllReduceBiarSelector, MoreThanFourRanksPerServerIsSelected) | ||
| 90 | +{ | ||
| 91 | + std::string algName; | ||
| 92 | + TopoInfo topo = MakeTopo(16, 4, HcclDevType::DEV_TYPE_910_93); | ||
| 93 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bSelected); | ||
| 94 | + EXPECT_EQ(algName, BIAR_ALG_NAME); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +TEST(AllReduceBiarSelector, NonA3DeviceIsNotSelected) | ||
| 98 | +{ | ||
| 99 | + std::string algName; | ||
| 100 | + TopoInfo topo = MakeTopo(8, 2, HcclDevType::DEV_TYPE_910B); | ||
| 101 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bNotSelected); | ||
| 102 | + EXPECT_TRUE(algName.empty()); | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +TEST(AllReduceBiarSelector, OddRankSizeIsNotSelected) | ||
| 106 | +{ | ||
| 107 | + std::string algName; | ||
| 108 | + TopoInfo topo = MakeTopo(9, 1, HcclDevType::DEV_TYPE_910_93); | ||
| 109 | + EXPECT_EQ(DecideAllReduceBiarAlg(topo, algName), BiarSelectResult::bNotSelected); | ||
| 110 | + EXPECT_TRUE(algName.empty()); | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +TEST(AllReduceBiarSelector, SelectResultToCodeMapsRejectsToErrorCodes) | ||
| 114 | +{ | ||
| 115 | + EXPECT_EQ(BiarSelectResultToCode(BiarSelectResult::bSelected), HCCL_SUCCESS); | ||
| 116 | + EXPECT_EQ(BiarSelectResultToCode(BiarSelectResult::bNotSelected), HCCL_SUCCESS); | ||
| 117 | + EXPECT_EQ(BiarSelectResultToCode(BiarSelectResult::bRejectRankSizeOne), HCCL_E_INTERNAL); | ||
| 118 | + EXPECT_EQ(BiarSelectResultToCode(BiarSelectResult::bRejectServerNumZero), HCCL_E_PARA); | ||
| 119 | + EXPECT_EQ(BiarSelectResultToCode(BiarSelectResult::bRejectRanksPerServerLT4), HCCL_E_PARA); | ||
| 120 | +} | ||


⚠️ [中等] [构建] experimental/ops/all_reduce/CMakeLists.txt:15
本文件只 add_subdirectory(biar),遗漏了 add_subdirectory(example);而 experimental/ops/CMakeLists.txt 已将原 add_subdirectory(all_reduce/example) 改为 add_subdirectory(all_reduce)。结果 all_reduce/example(ins_v2_all_reduce_experimental_sole_executor)被移出构建,但其 include 路径仍残留在 EXPERIMENTAL_INCLUDE_LIST。
建议:确认 example 是否仍需编译;若需要,在此补 add_subdirectory(example);若为有意清理,同步移除 include 路径残留。