已合并
mc2 ccu适配:reducescatter & allgather #4645
jiachengtang创建于 7月27日
mc2 ccu适配:reducescatter & allgather #4645
已合并
jiachengtang创建于 7月27日
173 个文件变更+14337-1989
@@ -8,17 +8,20 @@
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# ----------------------------------------------------------------------------------------------------------
10set(OPS_BASE_DIR ${HCCL_CC_DIR})10set(OPS_BASE_DIR ${HCCL_CC_DIR})
11-option(MC2_CLIENT_ENABLE_CCU "Build CCU algorithm implementations into mc2_client" OFF)11+option(MC2_CLIENT_ENABLE_CCU "Build CCU algorithm implementations into mc2_client" ON)
12 12 
13set(INCLUDE_LIST13set(INCLUDE_LIST
14 ${HCCL_CC_INCLUDE_DIR}14 ${HCCL_CC_INCLUDE_DIR}
15 ${HCCL_CC_INCLUDE_DIR}/hcomm15 ${HCCL_CC_INCLUDE_DIR}/hcomm
16+ ${HCCL_CC_INCLUDE_DIR}/hcomm/types
16 ${HCCL_CC_INCLUDE_DIR}/hcomm/hccl17 ${HCCL_CC_INCLUDE_DIR}/hcomm/hccl
17 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc/hccl18 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc/hccl
19+ ${HCCL_CC_INCLUDE_DIR}/hcomm/ccu
18 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc/hcomm/ccu20 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc/hcomm/ccu
19 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc21 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc
20 ${CMAKE_CURRENT_SOURCE_DIR}/common22 ${CMAKE_CURRENT_SOURCE_DIR}/common
21 ${CMAKE_CURRENT_SOURCE_DIR}/common/hcomm_dlsym23 ${CMAKE_CURRENT_SOURCE_DIR}/common/hcomm_dlsym
24+ ${CMAKE_CURRENT_SOURCE_DIR}/common/hcomm_dlsym/ccu
22 25 
23 ${CMAKE_CURRENT_SOURCE_DIR}/ops26 ${CMAKE_CURRENT_SOURCE_DIR}/ops
24 ${CMAKE_CURRENT_SOURCE_DIR}/ops/op_common27 ${CMAKE_CURRENT_SOURCE_DIR}/ops/op_common
@@ -47,7 +50,6 @@ set(INCLUDE_LIST
47 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/selector50 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/selector
48 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template51 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template
49 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/aicpu52 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/aicpu
50- ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/aiv
51 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/ccu53 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/ccu
52 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/ccu/kernel54 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/ccu/kernel
53 55 
@@ -56,11 +58,49 @@ set(INCLUDE_LIST
56 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/selector58 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/selector
57 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template59 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template
58 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu60 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu
59- ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aiv
60 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/ccu61 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/ccu
61 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/ccu/kernel62 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/ccu/kernel
63+ 
64+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/kfc_server
65+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/kfc_server/executor
66+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/kfc_server/selector
67+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/kfc_server/template
68+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/kfc_server/template/ccu
69+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/kfc_server/template/ccu/kernel
62)70)
63 71 
72+list(APPEND INCLUDE_LIST
73+ ${ASCEND_CANN_PACKAGE_PATH}/include
74+ ${ASCEND_CANN_PACKAGE_PATH}/include/acl
75+ 
76+ # hcomm头文件
77+ ${ASCEND_CANN_PACKAGE_PATH}/include/ccu
78+ ${ASCEND_CANN_PACKAGE_PATH}/include/hccl
79+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm
80+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm/ccu
81+ 
82+ # runtime头文件
83+ ${ASCEND_CANN_PACKAGE_PATH}/include/base/
84+ ${ASCEND_CANN_PACKAGE_PATH}/include/driver/
85+ ${ASCEND_CANN_PACKAGE_PATH}/include/dump/
86+ ${ASCEND_CANN_PACKAGE_PATH}/include/external/
87+ ${ASCEND_CANN_PACKAGE_PATH}/include/platform/
88+ 
89+ # mmpa头文件
90+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/mmpa/
91+ 
92+ # 包间接口
93+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/
94+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hccl
95+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hcomm/ccu
96+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime/
97+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/aicpu/
98+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/runtime/runtime/
99+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/profiling/
100+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/base/
101+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/dump/
102+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/trace/
103+)
64 104 
65if(PRODUCT_SIDE STREQUAL "device")105if(PRODUCT_SIDE STREQUAL "device")
66 add_library(mc2_server SHARED106 add_library(mc2_server SHARED
@@ -99,6 +139,7 @@ if(PRODUCT_SIDE STREQUAL "device")
99 139 
100 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_v2_reduce_scatter_sole_executor.cc140 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_v2_reduce_scatter_sole_executor.cc
101 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_reduce_scatter_parallel_executor.cc141 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_reduce_scatter_parallel_executor.cc
142+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_reduce_scatter_concurrent_executor.cc
102 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_v2_reduce_scatter_sequence_executor_aicpu.cc143 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_v2_reduce_scatter_sequence_executor_aicpu.cc
103 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_v2_reduce_scatter_sequence_executor.cc144 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/executor/ins_v2_reduce_scatter_sequence_executor.cc
104 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/aicpu/ins_temp_reduce_scatter_mesh_1D.cc145 ${CMAKE_CURRENT_SOURCE_DIR}/ops/reduce_scatter/template/aicpu/ins_temp_reduce_scatter_mesh_1D.cc
@@ -110,6 +151,7 @@ if(PRODUCT_SIDE STREQUAL "device")
110 151 
111 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/executor/ins_v2_all_gather_sole_executor.cc152 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/executor/ins_v2_all_gather_sole_executor.cc
112 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/executor/ins_v2_all_gather_parallel_executor.cc153 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/executor/ins_v2_all_gather_parallel_executor.cc
154+ ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/executor/ins_v2_all_gather_concurrent_executor.cc
113 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu/ins_temp_all_gather_mesh_1D.cc155 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu/ins_temp_all_gather_mesh_1D.cc
114 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu/ins_temp_all_gather_mesh_1D_Z_axis_detour.cc156 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu/ins_temp_all_gather_mesh_1D_Z_axis_detour.cc
115 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu/ins_temp_all_gather_nhr.cc157 ${CMAKE_CURRENT_SOURCE_DIR}/ops/all_gather/template/aicpu/ins_temp_all_gather_nhr.cc
@@ -147,7 +189,6 @@ if(PRODUCT_SIDE STREQUAL "device")
147 target_link_libraries(mc2_server PRIVATE189 target_link_libraries(mc2_server PRIVATE
148 -Wl,--no-as-needed190 -Wl,--no-as-needed
149 mc2_kernel_compat191 mc2_kernel_compat
150- -Wl,--no-as-needed
151 mmpa192 mmpa
152 $<BUILD_INTERFACE:acl_rt_headers>193 $<BUILD_INTERFACE:acl_rt_headers>
153 $<BUILD_INTERFACE:error_manager_headers>194 $<BUILD_INTERFACE:error_manager_headers>
@@ -207,7 +248,6 @@ if(NOT KERNEL_MODE AND PRODUCT_SIDE STREQUAL "host")
207 -Wl,-z,relro248 -Wl,-z,relro
208 -Wl,-z,now249 -Wl,-z,now
209 -Wl,-z,noexecstack250 -Wl,-z,noexecstack
210- -Wl,-Bsymbolic-functions
211 $<$<CONFIG:Release>:-s>251 $<$<CONFIG:Release>:-s>
212 )252 )
213 253 
@@ -43,7 +43,9 @@ target_include_directories(ccl_kernel_decoupler_open BEFORE PRIVATE
43 ${OPEN_HCCL_SRC_ROOT}/ops/op_common/inc43 ${OPEN_HCCL_SRC_ROOT}/ops/op_common/inc
44 ${OPEN_HCCL_SRC_ROOT}/common44 ${OPEN_HCCL_SRC_ROOT}/common
45 ${OPEN_HCCL_SRC_ROOT}/common/hcomm_dlsym45 ${OPEN_HCCL_SRC_ROOT}/common/hcomm_dlsym
46+ ${HCCL_HCOMM_HEADER_DIR}/ccu
46 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu47 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu
48+ ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu_new
47 49 
48 ${MC2_SERVER_CCL_INCLUDE_LIST}50 ${MC2_SERVER_CCL_INCLUDE_LIST}
49 ${MC2_SERVER_ORION_HEAD_LIST}51 ${MC2_SERVER_ORION_HEAD_LIST}
@@ -95,7 +97,9 @@ target_include_directories(ccl_kernel_decoupler_open_exec BEFORE PRIVATE
95 ${HCCL_BASE_DIR}/pub_inc97 ${HCCL_BASE_DIR}/pub_inc
96 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc98 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc
97 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hccl99 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hccl
100+ ${HCCL_HCOMM_HEADER_DIR}/ccu
98 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu101 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu
102+ ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu_new
99)103)
100 104 
101target_link_libraries(ccl_kernel_decoupler_open_exec PRIVATE105target_link_libraries(ccl_kernel_decoupler_open_exec PRIVATE
@@ -118,10 +122,15 @@ if(TARGET mc2_server)
118 $<TARGET_PROPERTY:asc_ccl_kernel,INTERFACE_COMPILE_OPTIONS>122 $<TARGET_PROPERTY:asc_ccl_kernel,INTERFACE_COMPILE_OPTIONS>
119 )123 )
120 124 
121- target_include_directories(mc2_server_decoupler PRIVATE125+ target_include_directories(mc2_server_decoupler BEFORE PRIVATE
126+ ${HCCL_BASE_DIR}/pub_inc
122 ${HCCL_HCOMM_HEADER_DIR}/../127 ${HCCL_HCOMM_HEADER_DIR}/../
123 ${OPEN_HCCL_SRC_ROOT}/ops/op_common/inc128 ${OPEN_HCCL_SRC_ROOT}/ops/op_common/inc
129+ ${OPEN_HCCL_SRC_ROOT}/common/hcomm_dlsym
130+ ${OPEN_HCCL_SRC_ROOT}/common/hcomm_dlsym/ccu
131+ ${HCCL_HCOMM_HEADER_DIR}/ccu
124 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu132 ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu
133+ ${HCCL_HCOMM_HEADER_DIR}/pkg_inc/hcomm/ccu_new
125 ${HCCL_BASE_DIR}/legacy/unified_platform/resource/stream/aicpu134 ${HCCL_BASE_DIR}/legacy/unified_platform/resource/stream/aicpu
126 135 
127 ${MC2_SERVER_CCL_INCLUDE_LIST}136 ${MC2_SERVER_CCL_INCLUDE_LIST}
@@ -19,6 +19,7 @@ using namespace HcclApi;
19 19 
20extern "C" __attribute__((visibility("default"))) uint32_t Mc2ServerKernel(void* args[])20extern "C" __attribute__((visibility("default"))) uint32_t Mc2ServerKernel(void* args[])
21{21{
22+ HCCL_INFO("[Mc2ServerKernel]Start Mc2ServerKernel.");
22 if (args == nullptr) {23 if (args == nullptr) {
23 HCCL_ERROR("args is null.");24 HCCL_ERROR("args is null.");
24 return HCCL_E_PARA;25 return HCCL_E_PARA;
@@ -28,5 +29,6 @@ extern "C" __attribute__((visibility("default"))) uint32_t Mc2ServerKernel(void*
28 uint64_t descValue = reinterpret_cast<uint64_t>(args[DESC_POS]);29 uint64_t descValue = reinterpret_cast<uint64_t>(args[DESC_POS]);
29 auto* desc = reinterpret_cast<CommKfcParamDesc*>(&descValue);30 auto* desc = reinterpret_cast<CommKfcParamDesc*>(&descValue);
30 AicpuKfcUtils::PrintHcclCommParamDesc(*desc);31 AicpuKfcUtils::PrintHcclCommParamDesc(*desc);
32+ HCCL_INFO("[Mc2ServerKernel]Finish Mc2ServerKernel.");
31 return CommKfcDispatcher::Run(&(args[1]), desc->itemNum);33 return CommKfcDispatcher::Run(&(args[1]), desc->itemNum);
32}34}
@@ -12,6 +12,7 @@
12 12 
13#include <cstdint>13#include <cstdint>
14#include <algorithm>14#include <algorithm>
15+#include <map>
15 16 
16#include "hccl/base.h"17#include "hccl/base.h"
17#include "exception_util.h"18#include "exception_util.h"
@@ -23,7 +24,7 @@ class BinaryStream {
23public:24public:
24 static constexpr std::ios_base::openmode DEFAULT_IOS_MODE = std::ios_base::in | std::ios_base::out;25 static constexpr std::ios_base::openmode DEFAULT_IOS_MODE = std::ios_base::in | std::ios_base::out;
25 26 
26- explicit BinaryStream(std::ios_base::openmode mode = DEFAULT_IOS_MODE) : stream(mode | std::ios_base::binary){};27+ explicit BinaryStream(std::ios_base::openmode mode = DEFAULT_IOS_MODE) : stream(mode | std::ios_base::binary) {};
27 28 
28 explicit BinaryStream(std::vector<char>& buf, std::ios_base::openmode mode = DEFAULT_IOS_MODE)29 explicit BinaryStream(std::vector<char>& buf, std::ios_base::openmode mode = DEFAULT_IOS_MODE)
29 : stream(mode | std::ios_base::binary)30 : stream(mode | std::ios_base::binary)
@@ -13,7 +13,7 @@
13#include <vector>13#include <vector>
14#include "hccl/base.h"14#include "hccl/base.h"
15#include "enum_factory.h"15#include "enum_factory.h"
16-#include "binary_stream.h"16+#include "../../../common/binary_stream.h"
17namespace Hccl {17namespace Hccl {
18 18 
19constexpr u32 MODULE_NAME_LEN = 128;19constexpr u32 MODULE_NAME_LEN = 128;
@@ -0,0 +1,168 @@
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+#ifndef MC2_OPS_HCCL_SRC_COMMON_ALG_TYPE
11+#define MC2_OPS_HCCL_SRC_COMMON_ALG_TYPE
12+ 
13+#include <string>
14+#include <map>
15+ 
16+namespace mc2_ops_hccl {
17+ 
18+// HCCL通信算法类型
19+enum class HcclAlgoType {
20+ HCCL_ALGO_TYPE_DEFAULT = 0, // 默认算法,配置为此时,使用HCCL内藏算法选择逻辑
21+ HCCL_ALGO_TYPE_RING,
22+ HCCL_ALGO_TYPE_PIPELINE,
23+ HCCL_ALGO_TYPE_FULLMESH,
24+ HCCL_ALGO_TYPE_HDR,
25+ HCCL_ALGO_TYPE_PAIRWISE,
26+ HCCL_ALGO_TYPE_NHR,
27+ HCCL_ALGO_TYPE_NHR_V1,
28+ HCCL_ALGO_TYPE_NB,
29+ HCCL_ALGO_TYPE_NULL,
30+ HCCL_ALGO_TYPE_NA,
31+ HCCL_ALGO_TYPE_AHC,
32+ HCCL_ALGO_TYPE_AHC_BROKE
33+};
34+ 
35+// 对内拓扑算法枚举
36+enum class AlgTypeLevel0 {
37+ ALG_LEVEL0_WHOLE_RING = 0, // 单层拓扑, 所有level均为Whole ring时,组成一个大环
38+ ALG_LEVEL0_8P_RING, // 拓扑组合0层, Ring 节点内4个固定stream
39+ ALG_LEVEL0_4P_MESH, // 拓扑组合0层, Mesh 节点内3个固定stream
40+ ALG_LEVEL0_2P_MESH, // 拓扑组合0层, Mesh
41+ ALG_LEVEL0_1P_MESH, // 拓扑组合0层, Mesh
42+ ALG_LEVEL0_4P_RING, // 拓扑组合0层, Ring
43+ ALG_LEVEL0_NP_SINGLE_RING, // 拓扑组合0层, Ring
44+ ALG_LEVEL0_NP_DOUBLE_RING, // 拓扑组合0层, double Ring
45+ ALG_LEVEL0_NP_MESH, // 拓扑组合0层, 服务器内3~8p rank组成MESH
46+ ALG_LEVEL0_NP_HD, // 拓扑组合0层, HD
47+ ALG_LEVEL0_NP_STAR,
48+ ALG_LEVEL0_PAIRWISE,
49+ ALG_LEVEL0_RESERVED
50+};
51+ 
52+enum class AlgTypeLevel1 {
53+ ALG_LEVEL1_WHOLE_RING = 0, // 单层拓扑, 所有level均为Whole ring时,组成一个大环
54+ ALG_LEVEL1_HD, // 拓扑组合1层, HDR
55+ ALG_LEVEL1_RING, // 拓扑组合1层, Ring
56+ ALG_LEVEL1_PIPELINE, // 拓扑组合1层, Pipeline
57+ ALG_LEVEL1_STAR,
58+ ALG_LEVEL1_NHR, // 拓扑组合1层,NHR
59+ ALG_LEVEL1_NHR_V1, // 拓扑组合1层,NHR_V1
60+ ALG_LEVEL1_NB, // 拓扑组合1层,NB
61+ ALG_LEVEL1_AHC, // 拓扑组合1层,AHC
62+ ALG_LEVEL1_AHC_BROKE, // 拓扑组合1层,AHC_BROKE
63+ ALG_LEVEL1_RESERVED
64+};
65+ 
66+enum class AlgTypeLevel2 {
67+ ALG_LEVEL2_WHOLE_RING = 0, // 单层拓扑, 所有leve2均为Whole ring时,组成一个大环
68+ ALG_LEVEL2_HD, // 拓扑组合2层, HDR
69+ ALG_LEVEL2_RING, // 拓扑组合2层, Ring
70+ ALG_LEVEL2_NHR, // 拓扑组合2层, NHR
71+ ALG_LEVEL2_NB, // 拓扑组合2层, NB
72+ ALG_LEVEL2_RESERVED
73+};
74+ 
75+using AlgType = struct TagAlgType {
76+ AlgTypeLevel0 algoLevel0;
77+ AlgTypeLevel1 algoLevel1;
78+ AlgTypeLevel2 algoLevel2;
79+ TagAlgType()
80+ : algoLevel0(AlgTypeLevel0::ALG_LEVEL0_WHOLE_RING),
81+ algoLevel1(AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING),
82+ algoLevel2(AlgTypeLevel2::ALG_LEVEL2_WHOLE_RING)
83+ {}
84+ 
85+ explicit TagAlgType(AlgTypeLevel0 algoLevel0)
86+ : algoLevel0(algoLevel0),
87+ algoLevel1(AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING),
88+ algoLevel2(AlgTypeLevel2::ALG_LEVEL2_WHOLE_RING)
89+ {}
90+ TagAlgType(AlgTypeLevel0 algoLevel0, AlgTypeLevel1 algoLevel1)
91+ : algoLevel0(algoLevel0), algoLevel1(algoLevel1), algoLevel2(AlgTypeLevel2::ALG_LEVEL2_WHOLE_RING)
92+ {}
93+ 
94+ TagAlgType(AlgTypeLevel0 algoLevel0, AlgTypeLevel2 algoLevel2)
95+ : algoLevel0(algoLevel0), algoLevel1(AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING), algoLevel2(algoLevel2)
96+ {}
97+ 
98+ TagAlgType(AlgTypeLevel0 algoLevel0, AlgTypeLevel1 algoLevel1, AlgTypeLevel2 algoLevel2)
99+ : algoLevel0(algoLevel0), algoLevel1(algoLevel1), algoLevel2(algoLevel2)
100+ {}
101+ explicit TagAlgType(AlgTypeLevel1 algoLevel1)
102+ : algoLevel0(AlgTypeLevel0::ALG_LEVEL0_WHOLE_RING),
103+ algoLevel1(algoLevel1),
104+ algoLevel2(AlgTypeLevel2::ALG_LEVEL2_WHOLE_RING)
105+ {}
106+ 
107+ TagAlgType(AlgTypeLevel1 algoLevel1, AlgTypeLevel2 algoLevel2)
108+ : algoLevel0(AlgTypeLevel0::ALG_LEVEL0_WHOLE_RING), algoLevel1(algoLevel1), algoLevel2(algoLevel2)
109+ {}
110+ 
111+ explicit TagAlgType(AlgTypeLevel2 algoLevel2)
112+ : algoLevel0(AlgTypeLevel0::ALG_LEVEL0_WHOLE_RING),
113+ algoLevel1(AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING),
114+ algoLevel2(algoLevel2)
115+ {}
116+ 
117+ static TagAlgType Reserved()
118+ {
119+ return TagAlgType(
120+ AlgTypeLevel0::ALG_LEVEL0_RESERVED, AlgTypeLevel1::ALG_LEVEL1_RESERVED, AlgTypeLevel2::ALG_LEVEL2_RESERVED);
121+ }
122+ 
123+ TagAlgType(const TagAlgType& that)
124+ : algoLevel0(that.algoLevel0), algoLevel1(that.algoLevel1), algoLevel2(that.algoLevel2)
125+ {}
126+ 
127+ TagAlgType& operator=(const TagAlgType& that)
128+ {
129+ if (&that != this) {
130+ algoLevel0 = that.algoLevel0;
131+ algoLevel1 = that.algoLevel1;
132+ algoLevel2 = that.algoLevel2;
133+ }
134+ return *this;
135+ }
136+};
137+ 
138+const std::map<AlgTypeLevel0, std::string> HCCL_ALGO_LEVEL0_NAME_MAP = {
139+ {AlgTypeLevel0::ALG_LEVEL0_NP_DOUBLE_RING, "ring"}, {AlgTypeLevel0::ALG_LEVEL0_WHOLE_RING, "ring"},
140+ {AlgTypeLevel0::ALG_LEVEL0_8P_RING, "ring"}, {AlgTypeLevel0::ALG_LEVEL0_4P_MESH, "fullmesh"},
141+ {AlgTypeLevel0::ALG_LEVEL0_2P_MESH, "fullmesh"}, {AlgTypeLevel0::ALG_LEVEL0_1P_MESH, "fullmesh"},
142+ {AlgTypeLevel0::ALG_LEVEL0_4P_RING, "ring"}, {AlgTypeLevel0::ALG_LEVEL0_NP_SINGLE_RING, "ring"},
143+ {AlgTypeLevel0::ALG_LEVEL0_NP_MESH, "fullmesh"}, {AlgTypeLevel0::ALG_LEVEL0_NP_HD, "HD"},
144+ {AlgTypeLevel0::ALG_LEVEL0_NP_STAR, "star"}, {AlgTypeLevel0::ALG_LEVEL0_RESERVED, "null"},
145+};
146+ 
147+const std::map<AlgTypeLevel1, std::string> HCCL_ALGO_LEVEL1_NAME_MAP = {
148+ {AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING, "ring"}, {AlgTypeLevel1::ALG_LEVEL1_HD, "H-D"},
149+ {AlgTypeLevel1::ALG_LEVEL1_RING, "ring"}, {AlgTypeLevel1::ALG_LEVEL1_PIPELINE, "pipeline"},
150+ {AlgTypeLevel1::ALG_LEVEL1_NHR, "NHR"}, {AlgTypeLevel1::ALG_LEVEL1_NHR_V1, "NHR_V1"},
151+ {AlgTypeLevel1::ALG_LEVEL1_AHC, "AHC"}, {AlgTypeLevel1::ALG_LEVEL1_AHC_BROKE, "AHC_BROKE"},
152+ {AlgTypeLevel1::ALG_LEVEL1_NB, "NB"}, {AlgTypeLevel1::ALG_LEVEL1_RESERVED, "null"},
153+};
154+ 
155+const std::map<AlgTypeLevel2, std::string> HCCL_ALGO_LEVEL2_NAME_MAP = {
156+ {AlgTypeLevel2::ALG_LEVEL2_WHOLE_RING, "ring"}, {AlgTypeLevel2::ALG_LEVEL2_HD, "H-D"},
157+ {AlgTypeLevel2::ALG_LEVEL2_RING, "ring"}, {AlgTypeLevel2::ALG_LEVEL2_NHR, "NHR"},
158+ {AlgTypeLevel2::ALG_LEVEL2_NB, "NB"}, {AlgTypeLevel2::ALG_LEVEL2_RESERVED, "null"},
159+};
160+ 
161+std::string AlgTypeToStr(const AlgType algType);
162+ 
163+std::string TransferAlgTypeStr(AlgType algType);
164+ 
165+std::string TransferAlgType(AlgType algType);
166+} // namespace mc2_ops_hccl
167+ 
168+#endif
@@ -0,0 +1,165 @@
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+#ifndef HCCL_SERIALIZATION
11+#define HCCL_SERIALIZATION
12+ 
13+#include <vector>
14+#include <cstdint>
15+#include <sstream>
16+#include <algorithm>
17+#include <map>
18+ 
19+#include "log.h"
20+ 
21+namespace mc2_ops_hccl {
22+ 
23+class BinaryStream {
24+public:
25+ static constexpr std::ios_base::openmode DEFAULT_IOS_MODE = std::ios_base::in | std::ios_base::out;
26+ 
27+ explicit BinaryStream(std::ios_base::openmode mode = DEFAULT_IOS_MODE) : stream(mode | std::ios_base::binary) {};
28+ 
29+ explicit BinaryStream(std::vector<char>& buf, std::ios_base::openmode mode = DEFAULT_IOS_MODE)
30+ : stream(mode | std::ios_base::binary)
31+ {
32+ stream.rdbuf()->pubsetbuf(buf.data(), buf.size());
33+ }
34+ 
35+ template <typename T>
36+ BinaryStream& operator<<(const T& t)
37+ {
38+ stream.write(reinterpret_cast<const char*>(&t), sizeof(T));
39+ return *this;
40+ }
41+ 
42+ // 多级vector递归序列化
43+ template <typename T>
44+ BinaryStream& operator<<(const std::vector<T>& vec)
45+ {
46+ size_t size = vec.size();
47+ *this << size;
48+ for (const auto& elem : vec) {
49+ *this << elem;
50+ }
51+ return *this;
52+ }
53+ 
54+ // 对string的输入函数
55+ BinaryStream& operator<<(const std::string& s)
56+ {
57+ size_t size = s.size();
58+ stream.write(reinterpret_cast<const char*>(&size), sizeof(size_t)); // 写入长度
59+ stream.write(s.data(), size); // 写入字符数据
60+ return *this;
61+ }
62+ 
63+ template <typename T>
64+ BinaryStream& operator>>(T& t)
65+ {
66+ stream.read(reinterpret_cast<char*>(&t), sizeof(T));
67+ return *this;
68+ }
69+ 
70+ // 对string的读取函数
71+ BinaryStream& operator>>(std::string& s)
72+ {
73+ size_t size;
74+ stream.read(reinterpret_cast<char*>(&size), sizeof(size)); // 先从流中读取字符串长度
75+ s.resize(size); // 为string分配足够空间
76+ stream.read(&s[0], size); // 直接读取数据到string的缓冲区中,无需再分配内存
77+ return *this;
78+ }
79+ 
80+ // 多级vector递归反序列化
81+ template <typename T>
82+ BinaryStream& operator>>(std::vector<T>& vec)
83+ {
84+ size_t size;
85+ *this >> size;
86+ vec.resize(size);
87+ for (auto& elem : vec) {
88+ *this >> elem;
89+ }
90+ return *this;
91+ }
92+ 
93+ // map序列化
94+ template <typename T1, typename T2>
95+ BinaryStream& operator<<(const std::map<T1, T2>& m)
96+ {
97+ size_t size = m.size();
98+ *this << size;
99+ for (const auto& elem : m) {
100+ *this << elem.first;
101+ *this << elem.second;
102+ }
103+ return *this;
104+ }
105+ 
106+ // map反序列化
107+ template <typename T1, typename T2>
108+ BinaryStream& operator>>(std::map<T1, T2>& m)
109+ {
110+ size_t size;
111+ *this >> size;
112+ for (size_t i = 0; i < size; i++) {
113+ T1 key;
114+ *this >> key;
115+ T2 value;
116+ *this >> value;
117+ m[key] = value;
118+ }
119+ return *this;
120+ }
121+ 
122+ void Dump(std::vector<char>& vec)
123+ {
124+ std::for_each(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>(), [&vec](const char c) {
125+ vec.push_back(c);
126+ });
127+ }
128+ 
129+ void DumpWithRevert(std::vector<char>& vec)
130+ {
131+ std::streampos originalPos = stream.tellg(); // 保存原始位置
132+ std::for_each(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>(), [&vec](const char c) {
133+ vec.push_back(c);
134+ });
135+ stream.seekg(originalPos); // 恢复原始位置
136+ }
137+ 
138+ std::uint64_t GetSize() { return stream.str().size(); }
139+ 
140+ std::string GetString() { return stream.str(); }
141+ 
142+ std::string SplictStream(u64& start, u64& end)
143+ {
144+ std::string temp = stream.str();
145+ if (start >= temp.length()) {
146+ HCCL_ERROR("[SplictStream]start[%llu] is bigger than stream length[%llu]", start, temp.length());
147+ return "";
148+ }
149+ 
150+ // 截取子串
151+ std::string result = temp.substr(start, end - start);
152+ 
153+ // 返回新的 string
154+ return result;
155+ }
156+ 
157+ void Clear() { stream.clear(); }
158+ 
159+private:
160+ std::stringstream stream;
161+};
162+ 
163+} // namespace mc2_ops_hccl
164+ 
165+#endif // HCCL_SERIALIZATION
@@ -20,6 +20,7 @@ if(PRODUCT_SIDE STREQUAL "host")
20 ${CMAKE_CURRENT_SOURCE_DIR}/log.cc20 ${CMAKE_CURRENT_SOURCE_DIR}/log.cc
21 ${CMAKE_CURRENT_SOURCE_DIR}/sal.cc21 ${CMAKE_CURRENT_SOURCE_DIR}/sal.cc
22 ${CMAKE_CURRENT_SOURCE_DIR}/hccl_mc2.cc22 ${CMAKE_CURRENT_SOURCE_DIR}/hccl_mc2.cc
23+ ${CMAKE_CURRENT_SOURCE_DIR}/hccl_alloc_ctx_res.cc
23 ${CMAKE_CURRENT_SOURCE_DIR}/compat.cc24 ${CMAKE_CURRENT_SOURCE_DIR}/compat.cc
24 )25 )
25 26 
@@ -8,13 +8,12 @@
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#include <pthread.h>10#include <pthread.h>
11+#include "log.h"
11#include "hcomm_dlsym.h"12#include "hcomm_dlsym.h"
12 13 
13namespace mc2_ops_hccl {14namespace mc2_ops_hccl {
14-void CompatSymInit(void)15+ 
15-{16+void CompatSymInit(void) { HcommDlInit(); }
16- HcommDlInit(); // 增加强制依赖
17-}
18 17 
19__attribute__((constructor)) void InitCompat()18__attribute__((constructor)) void InitCompat()
20{19{
@@ -0,0 +1,1010 @@
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+#include "hccl_alloc_ctx_res.h"
11+ 
12+using namespace mc2_ops_hccl;
13+using namespace hcomm::CcuRep;
14+ 
15+std::unordered_map<HcclCMDType, OpParamPrepareFunc> opParamPrepareFuncMap = {
16+ {HcclCMDType::HCCL_CMD_ALLGATHER, PrepareParamForAllGather},
17+ {HcclCMDType::HCCL_CMD_ALLREDUCE, PrepareParamForAllReduce},
18+ {HcclCMDType::HCCL_CMD_REDUCE_SCATTER, PrepareParamForReduceScatter},
19+ {HcclCMDType::HCCL_CMD_ALLTOALL, PrepareParamForAlltoAll},
20+ {HcclCMDType::HCCL_CMD_ALLTOALLV, PrepareParamForAlltoAllV},
21+};
22+ 
23+CommEngine OpExecuteConfigToCommEngine(uint8_t commEngine)
24+{
25+ if (static_cast<OpExecuteConfig>(commEngine) == OpExecuteConfig::AICPU_TS) {
26+ return COMM_ENGINE_AICPU;
27+ } else if (static_cast<OpExecuteConfig>(commEngine) == OpExecuteConfig::CCU_SCHED) {
28+ return COMM_ENGINE_CCU;
29+ }
30+ return COMM_ENGINE_RESERVED;
31+}
32+ 
33+HcclResult CheckInputParam(const HcclComm comm, const void* mc2Tiling, const aclrtStream stream)
34+{
35+ // 检查comm是否为空指针
36+ RPT_INPUT_ERR(
37+ comm == nullptr, "EI0003", std::vector<std::string>({"ccl_op", "value", "parameter", "expect"}),
38+ std::vector<std::string>({"HcclAllocComResourceByTiling", "nullptr", "comm", "non-null pointer"}));
39+ CHK_PTR_NULL(comm);
40+ 
41+ // 检查sendBuf是否为空指针
42+ RPT_INPUT_ERR(
43+ mc2Tiling == nullptr, "EI0003", std::vector<std::string>({"ccl_op", "value", "parameter", "expect"}),
44+ std::vector<std::string>({"HcclAllocComResourceByTiling", "nullptr", "mc2Tiling", "non-null pointer"}));
45+ CHK_PTR_NULL(mc2Tiling);
46+ 
47+ // 检查stream是否为空指针
48+ RPT_INPUT_ERR(
49+ stream == nullptr, "EI0003", std::vector<std::string>({"ccl_op", "value", "parameter", "expect"}),
50+ std::vector<std::string>({"HcclAllocComResourceByTiling", "nullptr", "stream", "non-null pointer"}));
51+ CHK_PTR_NULL(stream);
52+ 
53+ return HCCL_SUCCESS;
54+}
55+ 
56+HcclResult HcclGetTilingList(const void* mc2Tiling, const void* p[], uint32_t& cnt)
57+{
58+ const u32* versionPtr = static_cast<const u32*>(mc2Tiling);
59+ const u32 version = *(versionPtr++);
60+ CHK_PRT_RET(version < MC2_TILING_VERSION, HCCL_ERROR("Invalid tiling version %u.", version), HCCL_E_PARA);
61+ 
62+ cnt = *(versionPtr++);
63+ CHK_PRT_RET(cnt > MAX_HCOM_NUM, HCCL_ERROR("Invalid hcom tiling number %u.", cnt), HCCL_E_PARA);
64+ 
65+ u64 serverCfgAddr = reinterpret_cast<u64>(versionPtr) + sizeof(Mc2ServerCfg);
66+ for (uint32_t i = 0U; i < MAX_CC_TILING_NUM; ++i) {
67+ p[i] = reinterpret_cast<const void*>(reinterpret_cast<const u8*>(mc2Tiling) + versionPtr[i]);
68+ }
69+ HCCL_INFO("HcclGetTilingList version[%u] cnt[%u]", version, cnt);
70+ return HCCL_SUCCESS;
71+}
72+ 
73+HcclResult CheckIsReduce(const Mc2CcTilingInner* ccTiling, bool* isReduce)
74+{
75+ if (ccTiling->opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER || ccTiling->opType == HcclCMDType::HCCL_CMD_REDUCE ||
76+ ccTiling->opType == HcclCMDType::HCCL_CMD_ALLREDUCE) {
77+ *isReduce = true;
78+ } else {
79+ *isReduce = false;
80+ }
81+ return HCCL_SUCCESS;
82+}
83+ 
84+HcclResult CheckCommEngine(const void* ccTilingList[], uint32_t tilingNum)
85+{
86+ for (uint32_t i = 0U; i < tilingNum; ++i) {
87+ const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
88+ if (ccTiling->commEngine != static_cast<uint8_t>(COMM_ENGINE_AICPU) &&
89+ ccTiling->commEngine != static_cast<uint8_t>(COMM_ENGINE_CPU)) {
90+ HCCL_ERROR("Invalid commEngine %u.", ccTiling->commEngine);
91+ return HCCL_E_NOT_SUPPORT;
92+ }
93+ }
94+ return HCCL_SUCCESS;
95+}
96+ 
97+HcclResult ObtainCommEngine(const void* ccTilingList[], uint32_t tilingNum, uint8_t& commEngine)
98+{
99+ commEngine = static_cast<uint8_t>(OpExecuteConfig::DEFAULT);
100+ for (uint32_t i = 0U; i < tilingNum; ++i) {
101+ const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
102+ if (commEngine == static_cast<uint8_t>(OpExecuteConfig::DEFAULT)) {
103+ commEngine = ccTiling->commEngine;
104+ }
105+ if (ccTiling->commEngine != commEngine) {
106+ HCCL_ERROR("Invalid commEngine %u.", ccTiling->commEngine);
107+ return HCCL_E_NOT_SUPPORT;
108+ }
109+ }
110+ 
111+ if (commEngine != static_cast<uint8_t>(OpExecuteConfig::AICPU_TS) &&
112+ commEngine != static_cast<uint8_t>(OpExecuteConfig::CCU_SCHED)) {
113+ HCCL_ERROR("Invalid commEngine %u.", commEngine);
114+ return HCCL_E_NOT_SUPPORT;
115+ }
116+ return HCCL_SUCCESS;
117+}
118+ 
119+namespace {
120+bool IsCcuKfcSupportedOp(uint32_t opType)
121+{
122+ return opType == static_cast<uint32_t>(HcclCMDType::HCCL_CMD_ALLGATHER) ||
123+ opType == static_cast<uint32_t>(HcclCMDType::HCCL_CMD_REDUCE_SCATTER);
124+}
125+ 
126+HcclResult GetOrCreateCcuCtx(HcclComm comm, const std::string& tag, uint64_t ctxSize, void** ctx)
127+{
128+ uint64_t actualSize = ctxSize;
129+ if (HcclEngineCtxGet(comm, tag.c_str(), COMM_ENGINE_AIV, ctx, &actualSize) == HCCL_SUCCESS) {
130+ HCCL_INFO(
131+ "[AllocCcuOpResCtx] HcclEngineCtxGet success, tag[%s], ctxAddr[%p], ctxSize[%llu]", tag.c_str(), *ctx,
132+ static_cast<unsigned long long>(actualSize));
133+ return HCCL_SUCCESS;
134+ }
135+ return HcclEngineCtxCreate(comm, tag.c_str(), COMM_ENGINE_AIV, ctxSize, ctx);
136+}
137+} // namespace
138+ 
139+HcclResult CheckCcuKfcFlow(const void* mc2Tiling, const void* ccTilingList[], uint32_t tilingNum)
140+{
141+ CHK_PTR_NULL(mc2Tiling);
142+ CHK_PTR_NULL(ccTilingList);
143+ const auto* initTiling = static_cast<const Mc2InitTilingInner*>(mc2Tiling);
144+ if (initTiling->version != INIT_TILING_CCU_NEW_VERSION) {
145+ HCCL_ERROR("Invalid CCU KFC tiling version %u, expected %u.", initTiling->version, INIT_TILING_CCU_NEW_VERSION);
146+ return HCCL_E_NOT_SUPPORT;
147+ }
148+ if (tilingNum == 0U || tilingNum > MAX_CC_TILING_NUM || tilingNum != initTiling->mc2HcommCnt) {
149+ HCCL_ERROR("Invalid CCU KFC tiling number %u, init tiling number %u.", tilingNum, initTiling->mc2HcommCnt);
150+ return HCCL_E_NOT_SUPPORT;
151+ }
152+ uint32_t expectedOpType = static_cast<uint32_t>(HcclCMDType::HCCL_CMD_INVALID);
153+ for (uint32_t i = 0U; i < tilingNum; ++i) {
154+ const auto* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
155+ CHK_PTR_NULL(ccTiling);
156+ if (expectedOpType == static_cast<uint32_t>(HcclCMDType::HCCL_CMD_INVALID)) {
157+ expectedOpType = ccTiling->opType;
158+ }
159+ if (!IsCcuKfcSupportedOp(ccTiling->opType) ||
160+ ccTiling->commEngine != static_cast<uint8_t>(OpExecuteConfig::CCU_SCHED) ||
161+ ccTiling->opType != expectedOpType) {
162+ HCCL_ERROR(
163+ "Unsupported CCU KFC tiling at index %u, opType %u, commEngine %u.", i, ccTiling->opType,
164+ ccTiling->commEngine);
165+ return HCCL_E_NOT_SUPPORT;
166+ }
167+ }
168+ return HCCL_SUCCESS;
169+}
170+ 
171+// 构建 opResCtx 基础字段
172+HcclResult AllocCcuOpResCtx(HcclComm comm, const std::string& ctxTag, u32 rankSize, u32 userRank, OpResCtx& opResCtx)
173+{
174+ // 1. 分配workspace、scratch、comParam(XN)、comSync(CKE)
175+ constexpr uint32_t comSyncNum = 2;
176+ constexpr uint64_t scratchSize = Hccl::MC2_WORKSPACE_SIZE;
177+ uint64_t comParamBufSize = Hccl::CCU_TASK_NUM_MAX * Hccl::CCU_PARAM_NUM_MAX * Hccl::CCU_ONE_PARAM_SIZE;
178+ uint64_t comSyncBufSize = Hccl::CCU_TASK_NUM_MAX * comSyncNum * Hccl::CCU_ONE_PARAM_SIZE;
179+ 
180+ std::string tagWorkspace = ctxTag + "_ccu_workspace";
181+ std::string tagScratch = ctxTag + "_ccu_scratch";
182+ std::string tagComParam = ctxTag + "_ccu_comParam";
183+ std::string tagComSync = ctxTag + "_ccu_comSync";
184+ 
185+ void* workspacePtr = nullptr;
186+ void* scratchPtr = nullptr;
187+ void* comParamPtr = nullptr;
188+ void* comSyncPtr = nullptr;
189+ 
190+ CHK_RET(GetOrCreateCcuCtx(comm, tagWorkspace, Hccl::MC2_WORKSPACE_SIZE, &workspacePtr));
191+ CHK_RET(GetOrCreateCcuCtx(comm, tagScratch, scratchSize, &scratchPtr));
192+ CHK_RET(GetOrCreateCcuCtx(comm, tagComParam, comParamBufSize, &comParamPtr));
193+ CHK_RET(GetOrCreateCcuCtx(comm, tagComSync, comSyncBufSize, &comSyncPtr));
194+ 
195+ uint64_t ckeTokenInfo = hcomm::CcuRep::GetTokenInfo(reinterpret_cast<uint64_t>(comSyncPtr), comSyncBufSize);
196+ HCCL_INFO(
197+ "[CcuTokenTrace][ComSync] ckeAddr[0x%llx], size[%llu], token[0x%llx]",
198+ reinterpret_cast<unsigned long long>(comSyncPtr), static_cast<unsigned long long>(comSyncBufSize),
199+ static_cast<unsigned long long>(ckeTokenInfo));
200+ 
201+ opResCtx.workSpace = reinterpret_cast<uint64_t>(workspacePtr);
202+ opResCtx.workSpaceSize = Hccl::MC2_WORKSPACE_SIZE;
203+ opResCtx.rankId = userRank;
204+ opResCtx.rankSize = rankSize;
205+ opResCtx.xnAddr = reinterpret_cast<uint64_t>(comParamPtr);
206+ opResCtx.ckeAddr = reinterpret_cast<uint64_t>(comSyncPtr);
207+ // ReduceScatter KFC follows pr_4523 and partitions this fixed 16 MiB buffer as rankSize * sliceSize.
208+ opResCtx.res[0] = reinterpret_cast<uint64_t>(scratchPtr);
209+ 
210+ HCCL_INFO(
211+ "[AllocCcuOpResCtx] workspace[%p], workspaceSize[%llu], scratch[%p], scratchSize[%llu], "
212+ "comParam[%p], comParamBufSize[%llu], comSync[%p], comSyncBufSize[%llu], "
213+ "rankId[%u], rankSize[%u], xnAddr[0x%llx], ckeAddr[0x%llx]",
214+ workspacePtr, Hccl::MC2_WORKSPACE_SIZE, scratchPtr, scratchSize, comParamPtr, comParamBufSize, comSyncPtr,
215+ comSyncBufSize, userRank, rankSize, static_cast<unsigned long long>(opResCtx.xnAddr),
216+ static_cast<unsigned long long>(opResCtx.ckeAddr));
217+ 
218+ return HCCL_SUCCESS;
219+}
220+ 
221+namespace {
222+HcclResult AllocOpParamMemory(
223+ HcclComm comm, const std::string& ctxTag, const std::vector<OpParam>& opParamVec,
224+ const Mc2InitTilingInner* initTiling, const void* ccTilingList[], OpResCtx& resCtx)
225+{
226+ std::vector<uint64_t> opParamAddr(opParamVec.size());
227+ uint64_t opParamSize = sizeof(OpParam);
228+ for (uint32_t i = 0U; i < opParamVec.size(); ++i) {
229+ std::string tagParam = ctxTag + "_" + std::to_string(i);
230+ void* opParamPtr = nullptr;
231+ const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
232+ if (HcclEngineCtxGet(
233+ comm, tagParam.c_str(), OpExecuteConfigToCommEngine(ccTiling->commEngine), &opParamPtr, &opParamSize) ==
234+ HCCL_SUCCESS) {
235+ HCCL_INFO(
236+ "HcclEngineCtxGet success, tagParam[%s], opParamAddr[%p], opParamSize[%u]", tagParam.c_str(),
237+ opParamPtr, opParamSize);
238+ opParamAddr[i] = reinterpret_cast<uint64_t>(opParamPtr);
239+ } else {
240+ CHK_RET(HcclEngineCtxCreate(
241+ comm, tagParam.c_str(), OpExecuteConfigToCommEngine(ccTiling->commEngine), opParamSize, &opParamPtr));
242+ opParamAddr[i] = reinterpret_cast<uint64_t>(opParamPtr);
243+ }
244+ HCCL_INFO(
245+ "HcclAllocOpResCtx the %dth opParam: opParamAddr[%u], opParamSize[%u]", i, opParamAddr[i], opParamSize);
246+ 
247+ aclError aclRet = aclrtMemcpy(
248+ reinterpret_cast<void*>(opParamAddr[i]), opParamSize, &opParamVec[i], opParamSize, aclrtMemcpyKind(1));
249+ CHK_RET(aclRet == ACL_ERROR_NONE ? HCCL_SUCCESS : HCCL_E_RUNTIME);
250+ resCtx.algInfo[i].opParam = opParamAddr[i];
251+ resCtx.algInfo[i].offset = initTiling->offset[i];
252+ }
253+ return HCCL_SUCCESS;
254+}
255+ 
256+HcclResult AllocWorkspaceMemory(
257+ HcclComm comm, const std::string& ctxTag, const Mc2CcTilingInner* ccTiling, OpResCtx& resCtx)
258+{
259+ uint64_t memSize = 20 * 1024 * 1024;
260+ resCtx.workSpaceSize = memSize;
261+ std::string tagWorkSpace = ctxTag + "_workSpace";
262+ void* workSpacePtr = nullptr;
263+ if (HcclEngineCtxGet(
264+ comm, tagWorkSpace.c_str(), OpExecuteConfigToCommEngine(ccTiling->commEngine), &workSpacePtr, &memSize) ==
265+ HCCL_SUCCESS) {
266+ HCCL_INFO(
267+ "HcclEngineCtxGet success, tagWorkSpace[%s], workSpaceAddr[%p], workSpaceSize[%u]", tagWorkSpace.c_str(),
268+ workSpacePtr, memSize);
269+ resCtx.workSpace = reinterpret_cast<uint64_t>(workSpacePtr);
270+ } else {
271+ CHK_RET(HcclEngineCtxCreate(
272+ comm, tagWorkSpace.c_str(), OpExecuteConfigToCommEngine(ccTiling->commEngine), memSize, &workSpacePtr));
273+ resCtx.workSpace = reinterpret_cast<uint64_t>(workSpacePtr);
274+ }
275+ HCCL_INFO("HcclAllocOpResCtx the workSpace: workSpaceAddr[%u], workSpaceSize[%u]", resCtx.workSpace, memSize);
276+ return HCCL_SUCCESS;
277+}
278+ 
279+HcclResult FillRankInfo(HcclComm comm, OpResCtx& resCtx)
280+{
281+ uint32_t rankSize = 0U;
282+ uint32_t rankId = 0U;
283+ CHK_RET(HcclGetRankSize(comm, &rankSize));
284+ CHK_RET(HcclGetRankId(comm, &rankId));
285+ resCtx.rankSize = rankSize;
286+ resCtx.rankId = rankId;
287+ return HCCL_SUCCESS;
288+}
289+ 
290+HcclResult AllocAndCopyOpResCtx(
291+ HcclComm comm, const std::string& ctxTag, const Mc2CcTilingInner* ccTiling, const OpResCtx& resCtx,
292+ void** opResCtxPtr)
293+{
294+ std::string tagOpResCtx = ctxTag + "_opResCtx";
295+ uint64_t opResCtxSize = sizeof(OpResCtx);
296+ if (HcclEngineCtxGet(
297+ comm, tagOpResCtx.c_str(), OpExecuteConfigToCommEngine(ccTiling->commEngine), opResCtxPtr, &opResCtxSize) ==
298+ HCCL_SUCCESS) {
299+ HCCL_INFO(
300+ "HcclEngineCtxGet success, tagOpResCtx[%s], opResCtxAddr[%p], opResCtxSize[%u]", tagOpResCtx.c_str(),
301+ opResCtxPtr, opResCtxSize);
302+ } else {
303+ CHK_RET(HcclEngineCtxCreate(
304+ comm, tagOpResCtx.c_str(), OpExecuteConfigToCommEngine(ccTiling->commEngine), opResCtxSize, opResCtxPtr));
305+ }
306+ 
307+ HCCL_INFO("HcclAllocOpResCtx the opResCtx: opResCtxAddr[%u], opResCtxSize[%u]", opResCtxPtr, opResCtxSize);
308+ 
309+ aclError aclRet = aclrtMemcpy(*opResCtxPtr, opResCtxSize, &resCtx, opResCtxSize, aclrtMemcpyKind(1));
310+ CHK_RET(aclRet == ACL_ERROR_NONE ? HCCL_SUCCESS : HCCL_E_RUNTIME);
311+ return HCCL_SUCCESS;
312+}
313+} // namespace
314+ 
315+HcclResult HcclAllocOpResCtx(
316+ HcclComm comm, const std::string& ctxTag, const std::vector<OpParam>& opParamVec, void* mc2Tiling,
317+ const void* ccTilingList[], void** opResCtxPtr)
318+{
319+ CHK_PTR_NULL(opResCtxPtr);
320+ OpResCtx resCtx{};
321+ const auto* initTiling = static_cast<const Mc2InitTilingInner*>(mc2Tiling);
322+ const auto* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[0]);
323+ 
324+ CHK_RET(AllocOpParamMemory(comm, ctxTag, opParamVec, initTiling, ccTilingList, resCtx));
325+ CHK_RET(AllocWorkspaceMemory(comm, ctxTag, ccTiling, resCtx));
326+ CHK_RET(FillRankInfo(comm, resCtx));
327+ return AllocAndCopyOpResCtx(comm, ctxTag, ccTiling, resCtx, opResCtxPtr);
328+}
329+ 
330+// AllToAll适配AllToAllV
331+HcclResult ConvertAlltoAllParam(
332+ const u64 recvCount, const u32 rankSize, std::vector<u64>& sdispls, std::vector<u64>& rdispls)
333+{
334+ u64 dataCountOffset = 0;
335+ for (u64 i = 0; i < rankSize; i++) {
336+ sdispls[i] = dataCountOffset;
337+ rdispls[i] = dataCountOffset;
338+ dataCountOffset += recvCount;
339+ }
340+ return HCCL_SUCCESS;
341+}
342+ 
343+HcclResult PrepareOpsCommParam(const std::string& tag, OpParam& param)
344+{
345+ param.opMode = OpMode::OPBASE;
346+ DevType deviceType = DevType::DEV_TYPE_COUNT;
347+ CHK_RET(hrtGetDeviceType(deviceType));
348+ 
349+ // topoInfo的tag,所有相同的算子可以共享
350+ int ret = sprintf_s(param.tag, sizeof(param.tag), "%s", tag.c_str());
351+ if (ret <= 0) {
352+ HCCL_ERROR("failed to fill param.tag");
353+ return HCCL_E_INTERNAL;
354+ }
355+ 
356+ param.inputPtr = nullptr;
357+ param.outputPtr = nullptr;
358+ param.inputSize = 0;
359+ param.outputSize = 0;
360+ param.enableDetour = false;
361+ param.deviceType = deviceType;
362+ 
363+ return HCCL_SUCCESS;
364+}
365+ 
366+HcclResult PrintOpsCommParam(OpParam& param)
367+{
368+ HCCL_INFO("commName: %s", param.commName);
369+ HCCL_INFO("tag:%s", param.tag);
370+ HCCL_INFO("stream: %p", param.stream);
371+ HCCL_INFO("inputPtr %p", param.inputPtr);
372+ HCCL_INFO("outputPtr %p", param.outputPtr);
373+ HCCL_INFO("inputSize %lu", param.inputSize);
374+ HCCL_INFO("outputSize %lu", param.outputSize);
375+ HCCL_INFO("opMode %u", static_cast<uint32_t>(param.opMode));
376+ HCCL_INFO("deviceType %u", static_cast<uint32_t>(param.deviceType));
377+ return HCCL_SUCCESS;
378+}
379+ 
380+HcclResult PrepareParamForAllGather(
381+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
382+{
383+ HCCL_INFO("PrepareParamForAllGather, ccTiling[%p]", ccTiling);
384+ u32 userRankSize;
385+ CHK_RET(HcclGetRankSize(comm, &userRankSize)); // 加上,后面计算outputSize可能使用
386+ 
387+ HcclResult ret = PrepareOpsCommParam(tag, param);
388+ if (ret != HCCL_SUCCESS) {
389+ HCCL_ERROR("failed to fill OpsCommParam");
390+ }
391+ 
392+ param.opType = HcclCMDType::HCCL_CMD_ALLGATHER;
393+ param.reduceType = HcclReduceOp::HCCL_REDUCE_SUM;
394+ param.DataDes.dataType = static_cast<HcclDataType>(ccTiling->srcDataType);
395+ param.DataDes.count = 0;
396+ 
397+ HCCL_INFO("Print PrepareParamForAllGather.");
398+ CHK_RET(PrintOpsCommParam(param));
399+ HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
400+ HCCL_INFO("DataDes.dataType %u", static_cast<uint32_t>(param.DataDes.dataType));
401+ HCCL_INFO("DataDes.count %lu", param.DataDes.count);
402+ HCCL_INFO("Execute PrepareParamForAllGather success.");
403+ return HCCL_SUCCESS;
404+}
405+ 
406+HcclResult PrepareParamForAllReduce(
407+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
408+{
409+ HCCL_INFO("PrepareParamForAllReduce, ccTiling[%p]", ccTiling);
410+ u32 userRankSize;
411+ CHK_RET(HcclGetRankSize(comm, &userRankSize)); // 加上,后面计算outputSize可能使用
412+ 
413+ HcclResult ret = PrepareOpsCommParam(tag, param);
414+ if (ret != HCCL_SUCCESS) {
415+ HCCL_ERROR("failed to fill OpsCommParam");
416+ }
417+ 
418+ param.opType = HcclCMDType::HCCL_CMD_ALLREDUCE;
419+ param.reduceType = static_cast<HcclReduceOp>(ccTiling->reduceType);
420+ param.DataDes.dataType = static_cast<HcclDataType>(ccTiling->srcDataType);
421+ param.DataDes.outputType = param.DataDes.dataType;
422+ param.DataDes.count = 0;
423+ 
424+ HCCL_INFO("Print PrepareParamForAllReduce.");
425+ CHK_RET(PrintOpsCommParam(param));
426+ HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
427+ HCCL_INFO("reduceType %u", static_cast<uint32_t>(param.reduceType));
428+ HCCL_INFO("DataDes.dataType %u", static_cast<uint32_t>(param.DataDes.dataType));
429+ HCCL_INFO("DataDes.outputType %u", static_cast<uint32_t>(param.DataDes.outputType));
430+ HCCL_INFO("DataDes.count %lu", param.DataDes.count);
431+ HCCL_INFO("Execute PrepareParamForAllReduce success.");
432+ return HCCL_SUCCESS;
433+}
434+ 
435+HcclResult PrepareParamForReduceScatter(
436+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
437+{
438+ HCCL_INFO("PrepareParamForReduceScatter, ccTiling[%p]", ccTiling);
439+ u32 userRankSize;
440+ CHK_RET(HcclGetRankSize(comm, &userRankSize)); // 加上,后面计算outputSize可能使用
441+ 
442+ HcclResult ret = PrepareOpsCommParam(tag, param);
443+ if (ret != HCCL_SUCCESS) {
444+ HCCL_ERROR("failed to fill OpsCommParam");
445+ }
446+ 
447+ param.opType = HcclCMDType::HCCL_CMD_REDUCE_SCATTER;
448+ param.reduceType = static_cast<HcclReduceOp>(ccTiling->reduceType);
449+ param.DataDes.dataType = static_cast<HcclDataType>(ccTiling->srcDataType);
450+ param.DataDes.count = 0;
451+ 
452+ HCCL_INFO("Print PrepareParamForReduceScatter.");
453+ CHK_RET(PrintOpsCommParam(param));
454+ HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
455+ HCCL_INFO("reduceType %u", static_cast<uint32_t>(param.reduceType));
456+ HCCL_INFO("DataDes.dataType %u", static_cast<uint32_t>(param.DataDes.dataType));
457+ HCCL_INFO("DataDes.count %lu", param.DataDes.count);
458+ HCCL_INFO("Execute PrepareParamForReduceScatter success.");
459+ return HCCL_SUCCESS;
460+}
461+ 
462+HcclResult PrepareParamForAlltoAll(
463+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
464+{
465+ HCCL_INFO("PrepareParamForAlltoAll, ccTiling[%p]", ccTiling);
466+ u32 userRankSize;
467+ CHK_RET(HcclGetRankSize(comm, &userRankSize));
468+ 
469+ HcclResult ret = PrepareOpsCommParam(tag, param);
470+ if (ret != HCCL_SUCCESS) {
471+ HCCL_ERROR("failed to fill OpsCommParam");
472+ }
473+ 
474+ u64 varMemSize = ALL_TO_ALL_V_VECTOR_NUM * userRankSize * sizeof(u64);
475+ param.varMemSize = varMemSize;
476+ param.opType = HcclCMDType::HCCL_CMD_ALLTOALL;
477+ param.all2AllVDataDes.sendType = static_cast<HcclDataType>(ccTiling->srcDataType);
478+ param.all2AllVDataDes.recvType = static_cast<HcclDataType>(ccTiling->dstDataType);
479+ param.all2AllVDataDes.sendCounts = nullptr;
480+ param.all2AllVDataDes.recvCounts = nullptr;
481+ param.all2AllVDataDes.sdispls = nullptr;
482+ param.all2AllVDataDes.rdispls = nullptr;
483+ 
484+ HCCL_INFO("Print PrepareParamForAlltoAll.");
485+ CHK_RET(PrintOpsCommParam(param));
486+ HCCL_INFO("varMemSize %lu", param.varMemSize);
487+ HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
488+ HCCL_INFO("all2AllVDataDes.sendType %u", static_cast<uint32_t>(param.all2AllVDataDes.sendType));
489+ HCCL_INFO("all2AllVDataDes.recvType %u", static_cast<uint32_t>(param.all2AllVDataDes.recvType));
490+ HCCL_INFO("Execute PrepareParamForAlltoAll success.");
491+ return HCCL_SUCCESS;
492+}
493+ 
494+HcclResult PrepareParamForAlltoAllV(
495+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
496+{
497+ HCCL_INFO("PrepareParamForAlltoAllV, ccTiling[%p]", ccTiling);
498+ u32 userRankSize;
499+ CHK_RET(HcclGetRankSize(comm, &userRankSize));
500+ 
501+ HcclResult ret = PrepareOpsCommParam(tag, param);
502+ if (ret != HCCL_SUCCESS) {
503+ HCCL_ERROR("failed to fill OpsCommParam");
504+ }
505+ 
506+ u64 varMemSize = ALL_TO_ALL_V_VECTOR_NUM * userRankSize * sizeof(u64);
507+ param.varMemSize = varMemSize;
508+ param.opType = HcclCMDType::HCCL_CMD_ALLTOALLV;
509+ param.all2AllVDataDes.sendType = static_cast<HcclDataType>(ccTiling->srcDataType);
510+ param.all2AllVDataDes.recvType = static_cast<HcclDataType>(ccTiling->dstDataType);
511+ param.all2AllVDataDes.sendCounts = nullptr;
512+ param.all2AllVDataDes.recvCounts = nullptr;
513+ param.all2AllVDataDes.sdispls = nullptr;
514+ param.all2AllVDataDes.rdispls = nullptr;
515+ 
516+ HCCL_INFO("Print PrepareParamForAlltoAllV.");
517+ CHK_RET(PrintOpsCommParam(param));
518+ HCCL_INFO("varMemSize %lu", param.varMemSize);
519+ HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
520+ HCCL_INFO("all2AllVDataDes.sendType %u", static_cast<uint32_t>(param.all2AllVDataDes.sendType));
521+ HCCL_INFO("all2AllVDataDes.recvType %u", static_cast<uint32_t>(param.all2AllVDataDes.recvType));
522+ return HCCL_SUCCESS;
523+}
524+ 
525+HcclResult PrepareOpParams(HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam)
526+{
527+ auto it = opParamPrepareFuncMap.find(static_cast<HcclCMDType>(ccTiling->opType));
528+ if (it != opParamPrepareFuncMap.end()) {
529+ return it->second(comm, tag, ccTiling, opParam);
530+ }
531+ HCCL_ERROR("PrepareOpParams error, opType[%d] not found", ccTiling->opType);
532+ return HCCL_E_INTERNAL;
533+}
534+ 
535+HcclResult InitOpParamByTiling(
536+ HcclComm comm, void* stream, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam)
537+{
538+ opParam.opType = static_cast<HcclCMDType>(ccTiling->opType);
539+ opParam.stream = reinterpret_cast<aclrtStream>(stream);
540+ opParam.engine = OpExecuteConfigToCommEngine(ccTiling->commEngine);
541+ CHK_RET(HcclGetCommName(comm, opParam.commName));
542+ CHK_RET(PrepareOpParams(comm, tag, ccTiling, opParam));
543+ if (opParam.opType == HcclCMDType::HCCL_CMD_ALLTOALL) {
544+ opParam.all2AllVDataDes.sendType = static_cast<HcclDataType>(ccTiling->srcDataType);
545+ // sendCounts指向的host侧数组由调用方(GetOpParam)持有并填充,此处保持nullptr,
546+ // 避免将数值当作指针使用导致后续解引用非法地址。
547+ }
548+ return HCCL_SUCCESS;
549+}
550+ 
551+HcclResult PrepareTopoInfoForOp(HcclComm comm, OpParam& opParam, std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo)
552+{
553+ HCCL_INFO("[SelectAlgAndPrepareEngine]start SelectAlgAndPrepareEngine!");
554+ opParam.hcclComm = comm;
555+ CHK_RET(HcclGetOpExpansionMode(comm, opParam));
556+ HCCL_INFO("[SelectAlgAndPrepareEngine] successfully!");
557+ CHK_RET(HcclCalcTopoInfo(comm, opParam, topoInfo));
558+ HCCL_INFO("[SelectAlgAndPrepareEngine]HcclCalcTopoInfo successfully!");
559+ return HCCL_SUCCESS;
560+}
561+ 
562+HcclResult PrepareEngineForAlg(OpParam& opParam, const std::string& algName)
563+{
564+ CHK_RET(SetCommEngine(opParam));
565+ if (GetExternalInputHcclAivOnlyMode() && opParam.engine != COMM_ENGINE_AIV) {
566+ HCCL_ERROR(
567+ "[HcclExecOp] opType[%d] currently do not select aiv mode, aiv only not support.",
568+ static_cast<int>(opParam.opType));
569+ return HCCL_E_NOT_SUPPORT;
570+ }
571+ if ((opParam.engine == COMM_ENGINE_AICPU_TS) || (opParam.engine == COMM_ENGINE_CPU)) {
572+ HCCL_DEBUG("[Selector] is aicpu mode");
573+ CHK_RET(LoadAICPUKernel());
574+ }
575+ CHK_RET(SetOpParamAlgTag(opParam, algName));
576+ return HCCL_SUCCESS;
577+}
578+ 
579+std::unique_ptr<InsCollAlgBase> GetAlgExecutorForOp(const OpParam& opParam, const std::string& algName)
580+{
581+ if (UseCannBridge(opParam)) {
582+ return GetAlgExecViaCann(opParam.opType, algName);
583+ }
584+ return CollAlgExecRegistryV2::Instance().GetAlgExec(opParam.opType, algName);
585+}
586+ 
587+HcclResult CheckForcedAlgResource(
588+ HcclComm comm, const OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo, const std::string& algName)
589+{
590+ std::unique_ptr<InsCollAlgBase> executor = GetAlgExecutorForOp(opParam, algName);
591+ CHK_PRT_RET(
592+ executor == nullptr,
593+ HCCL_WARNING(
594+ "[MC2_FORCE_ALG] fallback, algName[%s] is not registered for opType[%u].", algName.c_str(),
595+ static_cast<u32>(opParam.opType)),
596+ HCCL_E_NOT_SUPPORT);
597+ 
598+ AlgHierarchyInfoForAllLevel algHierarchyInfo;
599+ HcclResult ret = executor->CalcAlgHierarchyInfo(comm, topoInfo, algHierarchyInfo);
600+ CHK_PRT_RET(
601+ ret != HCCL_SUCCESS,
602+ HCCL_WARNING(
603+ "[MC2_FORCE_ALG] fallback, CalcAlgHierarchyInfo failed, algName[%s], ret[%d].", algName.c_str(),
604+ static_cast<int>(ret)),
605+ HCCL_E_NOT_SUPPORT);
606+ 
607+ AlgResourceRequest resRequest;
608+ ret = executor->CalcRes(comm, opParam, topoInfo, algHierarchyInfo, resRequest);
609+ CHK_PRT_RET(
610+ ret != HCCL_SUCCESS,
611+ HCCL_WARNING(
612+ "[MC2_FORCE_ALG] fallback, CalcRes failed, algName[%s], ret[%d].", algName.c_str(), static_cast<int>(ret)),
613+ HCCL_E_NOT_SUPPORT);
614+ return HCCL_SUCCESS;
615+}
616+ 
617+bool GetForcedAlgName(const Mc2CcTilingInner* ccTiling, std::string& algName)
618+{
619+ if (ccTiling == nullptr || ccTiling->algConfig[0] == '\0') {
620+ return false;
621+ }
622+ 
623+ std::string algConfig(ccTiling->algConfig);
624+ if (algConfig.find('=') != std::string::npos) {
625+ HCCL_INFO("[MC2_FORCE_ALG] legacy algConfig[%s], use default selector.", algConfig.c_str());
626+ return false;
627+ }
628+ 
629+ algName = algConfig;
630+ return true;
631+}
632+ 
633+HcclResult TryForcedAlgAndPrepareEngine(
634+ HcclComm comm, const Mc2CcTilingInner* ccTiling, OpParam& opParam, std::string& algName,
635+ std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo, bool& forcedAlgAccepted)
636+{
637+ forcedAlgAccepted = false;
638+ std::string forcedAlgName;
639+ if (!GetForcedAlgName(ccTiling, forcedAlgName)) {
640+ return HCCL_SUCCESS;
641+ }
642+ 
643+ OpParam opParamBackup = opParam;
644+ CHK_RET(PrepareTopoInfoForOp(comm, opParam, topoInfo));
645+ HcclResult ret = PrepareEngineForAlg(opParam, forcedAlgName);
646+ if (ret != HCCL_SUCCESS) {
647+ opParam = opParamBackup;
648+ HCCL_ERROR(
649+ "[MC2_FORCE_ALG] prepare engine failed, algName[%s], ret[%d].", forcedAlgName.c_str(),
650+ static_cast<int>(ret));
651+ return ret;
652+ }
653+ 
654+ ret = CheckForcedAlgResource(comm, opParam, topoInfo.get(), forcedAlgName);
655+ if (ret != HCCL_SUCCESS) {
656+ opParam = opParamBackup;
657+ topoInfo = std::make_unique<TopoInfoWithNetLayerDetails>();
658+ algName.clear();
659+ forcedAlgAccepted = false;
660+ HCCL_WARNING(
661+ "[MC2_FORCE_ALG] fallback to default selector, opType[%u], algConfig[%s].",
662+ static_cast<u32>(opParam.opType), forcedAlgName.c_str());
663+ return HCCL_SUCCESS;
664+ }
665+ 
666+ algName = forcedAlgName;
667+ forcedAlgAccepted = true;
668+ HCCL_INFO("[MC2_FORCE_ALG] accepted, opType[%u], algName[%s].", static_cast<u32>(opParam.opType), algName.c_str());
669+ return HCCL_SUCCESS;
670+}
671+ 
672+HcclResult SelectAlgAndPrepareEngine(
673+ HcclComm comm, OpParam& opParam, std::string& algName, std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo)
674+{
675+ CHK_RET(PrepareTopoInfoForOp(comm, opParam, topoInfo));
676+ 
677+ std::shared_ptr<ExecuteSelector> collAlgSelector = std::make_shared<ExecuteSelector>(ExecuteSelector());
678+ CHK_RET(collAlgSelector->Run(opParam, topoInfo.get(), algName));
679+ if (algName.empty()) {
680+ HCCL_ERROR("[Selector] select algname fail!");
681+ return HCCL_E_PTR;
682+ }
683+ 
684+ CHK_RET(PrepareEngineForAlg(opParam, algName));
685+ return HCCL_SUCCESS;
686+}
687+ 
688+HcclResult FillOpParamAlgName(OpParam& opParam, const std::string& algName)
689+{
690+ int result = sprintf_s(opParam.algName, sizeof(opParam.algName), "%s", algName.c_str());
691+ CHK_PRT_RET(result <= 0, HCCL_ERROR("failed to fill opParam.algName"), HCCL_E_INTERNAL);
692+ HCCL_INFO(
693+ "[GetOpParam] prepared opParam, opType[%u], algName[%s], algTag[%s].", static_cast<u32>(opParam.opType),
694+ opParam.algName, opParam.algTag);
695+ return HCCL_SUCCESS;
696+}
697+ 
698+HcclResult HandleSingleRankAndCommMode(HcclComm comm, OpParam& opParam, bool& skipGetRes)
699+{
700+ uint32_t userRankSize = 0;
701+ CHK_RET(HcclGetRankSize(comm, &userRankSize));
702+ if (userRankSize == 1) {
703+ HCCL_WARNING("[%s] ranksize == 1, enter SingleRankProc", __func__);
704+ CHK_RET(SingleRankProc(opParam));
705+ skipGetRes = true;
706+ return HCCL_SUCCESS;
707+ }
708+ 
709+ bool isOpBase = true;
710+ const char* opModeStr = isOpBase ? "_opbase" : "_offload";
711+ auto ret = sprintf_s(opParam.commModeTag, sizeof(opParam.commModeTag), "%s_%s", opParam.commName, opModeStr);
712+ if (ret <= 0) {
713+ HCCL_ERROR("[%s] failed to fill opParam.commModeTag", __func__);
714+ return HCCL_E_INTERNAL;
715+ }
716+ skipGetRes = false;
717+ return HCCL_SUCCESS;
718+}
719+ 
720+static HcclResult AcquireAlgResources(
721+ HcclComm comm, OpParam& opParam, std::unique_ptr<InsCollAlgBase>& executor, TopoInfoWithNetLayerDetails* topoInfo,
722+ std::unique_ptr<AlgResourceCtxSerializable>& resCtxHost, OpResCtx& opResCtx, void** resCtxOut)
723+{
724+ HCCL_INFO("[AcquireAlgResources]start AcquireAlgResources!");
725+ bool isResourceReused = false;
726+ ThreadHandle cpuTsThread{0};
727+ ThreadHandle exportedAicpuTsThread{0};
728+ if ((opParam.engine == COMM_ENGINE_AICPU_TS) || (opParam.engine == COMM_ENGINE_CPU)) {
729+ CHK_RET(HcclThreadAcquireWithStream(comm, COMM_ENGINE_CPU_TS, opParam.stream, 1, &cpuTsThread));
730+ CHK_RET(HcclThreadExportToCommEngine(comm, 1, &cpuTsThread, COMM_ENGINE_AICPU_TS, &exportedAicpuTsThread));
731+ }
732+ if (opParam.engine == COMM_ENGINE_CCU) {
733+ // 填充 kfcServerArgs 的所有6个字段(最后一个为 token 占位符,后续更新)
734+ resCtxHost->kfcServerArgs = {
735+ opResCtx.xnAddr, opResCtx.ckeAddr,
736+ static_cast<uint64_t>(1), // dieNum
737+ static_cast<uint64_t>(1), // missionNum
738+ static_cast<uint64_t>(0), // missionIndex
739+ static_cast<uint64_t>(0), // token 占位符,后续在 GetAlgResCcu 中更新
740+ };
741+ resCtxHost->kfcServerArgSize = 6;
742+ HCCL_INFO(
743+ "[AcquireAlgResources] kfcServerArgs generated: "
744+ "argSize[%u], xnAddr[0x%llx], ckeAddr[0x%llx], dieNum[%llu], "
745+ "missionNum[%llu], missionIndex[%llu], token[%llu]",
746+ resCtxHost->kfcServerArgSize, static_cast<unsigned long long>(resCtxHost->kfcServerArgs[0]),
747+ static_cast<unsigned long long>(resCtxHost->kfcServerArgs[1]),
748+ static_cast<unsigned long long>(resCtxHost->kfcServerArgs[2]),
749+ static_cast<unsigned long long>(resCtxHost->kfcServerArgs[3]),
750+ static_cast<unsigned long long>(resCtxHost->kfcServerArgs[4]),
751+ static_cast<unsigned long long>(resCtxHost->kfcServerArgs[5]));
752+ 
753+ CHK_RET(HcclGetAlgRes(comm, opParam, executor, topoInfo, resCtxHost, resCtxOut, isResourceReused));
754+ opParam.resCtx = *resCtxOut;
755+ } else {
756+ CHK_RET(HcclGetAlgRes(comm, opParam, executor, topoInfo, resCtxHost, resCtxOut, isResourceReused));
757+ opParam.resCtx = *resCtxOut;
758+ }
759+ HCCL_INFO("[AcquireAlgResources]end AcquireAlgResources!");
760+ return HCCL_SUCCESS;
761+}
762+ 
763+HcclResult GetOpParamResCtx(
764+ HcclComm comm, const std::string& algName, OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo,
765+ void** resCtxOut)
766+{
767+ bool useCannResCtx = UseCannBridge(opParam);
768+ std::unique_ptr<InsCollAlgBase> executor = nullptr;
769+ if (useCannResCtx) {
770+ executor = GetAlgExecViaCann(opParam.opType, algName);
771+ } else {
772+ executor = CollAlgExecRegistryV2::Instance().GetAlgExec(opParam.opType, algName);
773+ }
774+ CHK_PRT_RET(
775+ executor.get() == nullptr, HCCL_ERROR("Fail to find executor for algName[%s]", algName.c_str()), HCCL_E_PARA);
776+ std::unique_ptr<AlgResourceCtxSerializable> resCtxHost = std::make_unique<AlgResourceCtxSerializable>();
777+ resCtxHost->isHcommBatchTransferOnThreadSupported = HcommIsSupportHcommBatchTransferOnThread();
778+ HCCL_DEBUG(
779+ "[MC2_BATCH_TRANSFER][HostSupport] opType[%u], algName[%s], supported[%d].",
780+ static_cast<uint32_t>(opParam.opType), algName.c_str(),
781+ static_cast<int>(resCtxHost->isHcommBatchTransferOnThreadSupported));
782+ bool isResourceReused = false;
783+ 
784+ ThreadHandle cpuTsThread{0};
785+ ThreadHandle exportedAicpuTsThread{0};
786+ if ((opParam.engine == COMM_ENGINE_AICPU_TS) || (opParam.engine == COMM_ENGINE_CPU)) {
787+ CHK_RET(HcclThreadAcquireWithStream(comm, COMM_ENGINE_CPU_TS, opParam.stream, 1, &cpuTsThread));
788+ CHK_RET(HcclThreadExportToCommEngine(comm, 1, &cpuTsThread, COMM_ENGINE_AICPU_TS, &exportedAicpuTsThread));
789+ }
790+ CHK_RET(HcclGetAlgRes(comm, opParam, executor, topoInfo, resCtxHost, resCtxOut, isResourceReused));
791+ opParam.cacheValid = isResourceReused;
792+ opParam.resCtx = *resCtxOut;
793+ return HCCL_SUCCESS;
794+}
795+ 
796+HcclResult GetCcuOpParamResCtx(
797+ HcclComm comm, const std::string& algName, OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo,
798+ OpResCtx& opResCtx, void** resCtxOut)
799+{
800+ HCCL_INFO("[GetCcuOpParamResCtx]start GetCcuOpParamResCtx!");
801+ HCCL_INFO(
802+ "[GetCcuOpParamResCtx]received: workspace[%p], size[%llu]", (void*)opResCtx.workSpace, opResCtx.workSpaceSize);
803+ std::unique_ptr<InsCollAlgBase> executor = CollAlgExecRegistryV2::Instance().GetAlgExec(opParam.opType, algName);
804+ HCCL_INFO("[GetCcuOpParamResCtx]Generate executor successfully!");
805+ CHK_PRT_RET(
806+ executor.get() == nullptr, HCCL_ERROR("Fail to find executor for algName[%s]", algName.c_str()), HCCL_E_PARA);
807+ std::unique_ptr<AlgResourceCtxSerializable> resCtxHost = std::make_unique<AlgResourceCtxSerializable>();
808+ return AcquireAlgResources(comm, opParam, executor, topoInfo, resCtxHost, opResCtx, resCtxOut);
809+}
810+ 
811+HcclResult GetOpParam(
812+ HcclComm comm, void* stream, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam)
813+{
814+ CHK_RET(InitOpParamByTiling(comm, stream, tag, ccTiling, opParam));
815+ 
816+ // ALLTOALL场景下sendCounts需指向host侧真实数组,且必须在整个GetOpParam调用链
817+ // (含SelectAlgAndPrepareEngine、GetOpParamResCtx中的GetAlgExecViaCann)期间保持存活。
818+ // 该数组持有在本函数栈帧,覆盖opParam的全部使用范围。
819+ constexpr uint64_t ALLTOALL_DEFAULT_SEND_COUNTS = 200ULL * 1024 * 1024;
820+ std::vector<uint64_t> sendCounts;
821+ void* origSendCounts = opParam.all2AllVDataDes.sendCounts;
822+ if (opParam.opType == HcclCMDType::HCCL_CMD_ALLTOALL) {
823+ uint32_t userRankSize = 0;
824+ CHK_RET(HcclGetRankSize(comm, &userRankSize));
825+ sendCounts.assign(userRankSize, ALLTOALL_DEFAULT_SEND_COUNTS);
826+ opParam.all2AllVDataDes.sendCounts = reinterpret_cast<void*>(sendCounts.data());
827+ }
828+ 
829+ std::string algName;
830+ std::unique_ptr<TopoInfoWithNetLayerDetails> topoInfo = std::make_unique<TopoInfoWithNetLayerDetails>();
831+ bool forcedAlgAccepted = false;
832+ OpParam opParamBeforeAlg = opParam;
833+ CHK_RET(TryForcedAlgAndPrepareEngine(comm, ccTiling, opParam, algName, topoInfo, forcedAlgAccepted));
834+ if (!forcedAlgAccepted) {
835+ CHK_RET(SelectAlgAndPrepareEngine(comm, opParam, algName, topoInfo));
836+ }
837+ CHK_RET(FillOpParamAlgName(opParam, algName));
838+ 
839+ bool skipGetRes = false;
840+ CHK_RET(HandleSingleRankAndCommMode(comm, opParam, skipGetRes));
841+ if (skipGetRes) {
842+ opParam.all2AllVDataDes.sendCounts = origSendCounts;
843+ return HCCL_SUCCESS;
844+ }
845+ 
846+ void* resCtxSequence = nullptr;
847+ HcclResult resRet = GetOpParamResCtx(comm, algName, opParam, topoInfo.get(), &resCtxSequence);
848+ if (resRet != HCCL_SUCCESS && forcedAlgAccepted && resCtxSequence == nullptr) {
849+ HCCL_WARNING(
850+ "[MC2_FORCE_ALG] fallback to default selector after resource failure, algName[%s], ret[%d].",
851+ algName.c_str(), static_cast<int>(resRet));
852+ opParam = opParamBeforeAlg;
853+ algName.clear();
854+ topoInfo = std::make_unique<TopoInfoWithNetLayerDetails>();
855+ CHK_RET(SelectAlgAndPrepareEngine(comm, opParam, algName, topoInfo));
856+ CHK_RET(FillOpParamAlgName(opParam, algName));
857+ CHK_RET(HandleSingleRankAndCommMode(comm, opParam, skipGetRes));
858+ if (skipGetRes) {
859+ opParam.all2AllVDataDes.sendCounts = origSendCounts;
860+ return HCCL_SUCCESS;
861+ }
862+ CHK_RET(GetOpParamResCtx(comm, algName, opParam, topoInfo.get(), &resCtxSequence));
863+ } else {
864+ CHK_RET(resRet);
865+ }
866+ // GetOpParamResCtx执行结束,sendCounts的临时host数组已不再需要,
867+ // 将指向恢复为原值(大概率为nullptr),避免遗留指向本函数栈内vector的悬空指针。
868+ opParam.all2AllVDataDes.sendCounts = origSendCounts;
869+ return HCCL_SUCCESS;
870+}
871+ 
872+HcclResult CcuSelectAlgCheck(const Mc2CcTilingInner* ccTiling, uint32_t tilingIndex)
873+{
874+ HCCL_DEBUG("[CcuSelectAlgCheck] Default function.");
875+ return HCCL_SUCCESS;
876+}
877+ 
878+namespace {
879+void RunCcuSelectAlgCheck(const Mc2CcTilingInner* ccTiling, uint32_t tilingIndex)
880+{
881+ if (CcuSelectAlgCheck(ccTiling, tilingIndex) != HCCL_SUCCESS) {
882+ HCCL_WARNING(
883+ "[CcuSelectAlg] CcuSelectAlgCheck failed for ccTiling[%u], opType[%u]. "
884+ "CCU execution condition not satisfied.",
885+ tilingIndex, ccTiling->opType);
886+ }
887+ HCCL_INFO("[CcuSelectAlg]CcuSelectAlgCheck[%u] successfully!", tilingIndex);
888+}
889+ 
890+HcclResult SelectCcuAlgorithm(
891+ HcclComm comm, void* stream, const std::string& topoTag, const Mc2CcTilingInner* ccTiling, uint32_t tilingIndex,
892+ OpParam& opParam, std::string& algName, std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo,
893+ AlgorithmType& algorithmType)
894+{
895+ CHK_RET(InitOpParamByTiling(comm, stream, topoTag, ccTiling, opParam));
896+ HCCL_INFO("[CcuSelectAlg]InitOpParamByTiling[%u] successfully!", tilingIndex);
897+ 
898+ CHK_RET(SelectAlgAndPrepareEngine(comm, opParam, algName, topoInfo));
899+ HCCL_INFO(
900+ "[CcuSelectAlg]SelectAlgAndPrepareEngine[%u] successfully, algName = [%s]!", tilingIndex, algName.c_str());
901+ 
902+ auto it = algorithmMap.find(algName);
903+ if (it == algorithmMap.end()) {
904+ HCCL_ERROR(
905+ "[CcuSelectAlg] ccTiling[%u] selected nonCCU algorithm[%s] for opType[%u].", tilingIndex, algName.c_str(),
906+ ccTiling->opType);
907+ return HCCL_E_NOT_SUPPORT;
908+ }
909+ algorithmType = it->second;
910+ 
911+ int result = sprintf_s(opParam.algName, sizeof(opParam.algName), "%s", algName.c_str());
912+ CHK_PRT_RET(result <= 0, HCCL_ERROR("failed to fill opParam.algName"), HCCL_E_INTERNAL);
913+ HCCL_INFO(
914+ "[CcuSelectAlg] prepared opParam, opType[%u], algName[%s], algTag[%s].", static_cast<u32>(opParam.opType),
915+ opParam.algName, opParam.algTag);
916+ return HCCL_SUCCESS;
917+}
918+ 
919+void FillCcuAlgorithmInfo(
920+ uint32_t tilingIndex, const Mc2CcTilingInner* ccTiling, const std::string& algName, AlgorithmType algorithmType,
921+ OpParam& opParam, OpResCtx& opResCtx)
922+{
923+ opResCtx.opType[tilingIndex] = ccTiling->opType;
924+ opResCtx.algorithmType[tilingIndex] = algorithmType;
925+ opResCtx.isKfc[tilingIndex] = true;
926+ opParam.isKfc = true;
927+ 
928+ HCCL_INFO(
929+ "[CcuSelectAlg] ccTiling[%u]: opType[%u], algName[%s], algorithmType[%u]", tilingIndex,
930+ opResCtx.opType[tilingIndex], algName.c_str(), opResCtx.algorithmType[tilingIndex]);
931+}
932+ 
933+HcclResult PrepareCcuAlgorithmResource(
934+ HcclComm comm, uint32_t tilingIndex, const std::string& algName, OpParam& opParam,
935+ TopoInfoWithNetLayerDetails* topoInfo, OpResCtx& opResCtx, bool& skipGetRes)
936+{
937+ CHK_RET(HandleSingleRankAndCommMode(comm, opParam, skipGetRes));
938+ if (skipGetRes) {
939+ return HCCL_SUCCESS;
940+ }
941+ HCCL_INFO("[CcuSelectAlg]HandleSingleRankAndCommMode[%u] successfully!", tilingIndex);
942+ 
943+ void* resCtxSequence = nullptr;
944+ CHK_RET(GetCcuOpParamResCtx(comm, algName, opParam, topoInfo, opResCtx, &resCtxSequence));
945+ HCCL_INFO("[CcuSelectAlg]GetCcuOpParamResCtx[%u] successfully!", tilingIndex);
946+ return HCCL_SUCCESS;
947+}
948+ 
949+HcclResult CopyCcuOpParamToDevice(
950+ HcclComm comm, uint32_t tilingIndex, const Mc2InitTilingInner* initTiling, const OpParam& opParam,
951+ OpResCtx& opResCtx)
952+{
953+ std::string tagParam = std::to_string(tilingIndex) + "_" + std::string(opParam.algTag);
954+ void* opParamPtr = nullptr;
955+ uint64_t opParamSize = sizeof(OpParam);
956+ if (HcclEngineCtxGet(comm, tagParam.c_str(), COMM_ENGINE_AIV, &opParamPtr, &opParamSize) == HCCL_SUCCESS) {
957+ HCCL_INFO(
958+ "HcclEngineCtxGet success, tagParam[%s], opParamAddr[%p], opParamSize[%llu]", tagParam.c_str(), opParamPtr,
959+ opParamSize);
960+ } else {
961+ CHK_RET(HcclEngineCtxCreate(comm, tagParam.c_str(), COMM_ENGINE_AIV, opParamSize, &opParamPtr));
962+ }
963+ aclError aclRet = aclrtMemcpy(opParamPtr, opParamSize, &opParam, opParamSize, ACL_MEMCPY_HOST_TO_DEVICE);
964+ CHK_RET(aclRet == ACL_ERROR_NONE ? HCCL_SUCCESS : HCCL_E_RUNTIME);
965+ opResCtx.algInfo[tilingIndex].opParam = reinterpret_cast<uint64_t>(opParamPtr);
966+ opResCtx.algInfo[tilingIndex].offset = initTiling->offset[tilingIndex];
967+ HCCL_INFO(
968+ "[CcuSelectAlg] ccTiling[%u]: opParamAddr[%llu], offset[%u]", tilingIndex,
969+ opResCtx.algInfo[tilingIndex].opParam, opResCtx.algInfo[tilingIndex].offset);
970+ return HCCL_SUCCESS;
971+}
972+ 
973+HcclResult ProcessCcuTiling(
974+ HcclComm comm, void* stream, const std::string& topoTag, const Mc2CcTilingInner* ccTiling, uint32_t tilingIndex,
975+ const Mc2InitTilingInner* initTiling, OpResCtx& opResCtx)
976+{
977+ RunCcuSelectAlgCheck(ccTiling, tilingIndex);
978+ 
979+ OpParam opParam{};
980+ std::string algName;
981+ auto topoInfo = std::make_unique<TopoInfoWithNetLayerDetails>();
982+ AlgorithmType algorithmType;
983+ CHK_RET(
984+ SelectCcuAlgorithm(comm, stream, topoTag, ccTiling, tilingIndex, opParam, algName, topoInfo, algorithmType));
985+ FillCcuAlgorithmInfo(tilingIndex, ccTiling, algName, algorithmType, opParam, opResCtx);
986+ 
987+ bool skipGetRes = false;
988+ CHK_RET(PrepareCcuAlgorithmResource(comm, tilingIndex, algName, opParam, topoInfo.get(), opResCtx, skipGetRes));
989+ if (skipGetRes) {
990+ return HCCL_SUCCESS;
991+ }
992+ return CopyCcuOpParamToDevice(comm, tilingIndex, initTiling, opParam, opResCtx);
993+}
994+} // namespace
995+ 
996+// CCU路径逐算子:算法选择 + 资源准备(参照GetOpParam形式)
997+HcclResult CcuSelectAlg(
998+ HcclComm comm, void* stream, const std::string topoTag[], const void* ccTilingList[], uint32_t tilingNum,
999+ void* mc2Tiling, OpResCtx& opResCtx)
1000+{
1001+ HCCL_INFO("[CcuSelectAlg]start CcuSelectAlg!");
1002+ HCCL_INFO("[CcuSelectAlg]received: workspace[%p], size[%llu]", (void*)opResCtx.workSpace, opResCtx.workSpaceSize);
1003+ Mc2InitTilingInner* initTiling = static_cast<Mc2InitTilingInner*>(mc2Tiling);
1004+ for (uint32_t i = 0U; i < tilingNum; ++i) {
1005+ const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
1006+ CHK_RET(ProcessCcuTiling(comm, stream, topoTag[i], ccTiling, i, initTiling, opResCtx));
1007+ }
1008+ 
1009+ return HCCL_SUCCESS;
1010+}
@@ -20,6 +20,8 @@
20#include "coll_alg_v2_exec_registry.h"20#include "coll_alg_v2_exec_registry.h"
21#include "cann_host_bridge.h"21#include "cann_host_bridge.h"
22#include "hcomm_primitives_dl.h"22#include "hcomm_primitives_dl.h"
23+#include "mc2_type.h"
24+#include "ccu_assist_pub.h"
23 25 
24#include <vector>26#include <vector>
25#include <memory>27#include <memory>
@@ -41,6 +43,7 @@ constexpr uint32_t MC2_TILING_VERSION = 2U;
41constexpr uint32_t MAX_HCOM_NUM = 3U;43constexpr uint32_t MAX_HCOM_NUM = 3U;
42 44 
43constexpr uint32_t INIT_TILING_VERSION = 100U;45constexpr uint32_t INIT_TILING_VERSION = 100U;
46+constexpr uint32_t INIT_TILING_CCU_NEW_VERSION = 101U;
44constexpr uint32_t MAX_CC_TILING_NUM = 8U;47constexpr uint32_t MAX_CC_TILING_NUM = 8U;
45 48 
46struct Mc2ServerCfg {49struct Mc2ServerCfg {
@@ -53,7 +56,7 @@ struct Mc2ServerCfg {
53};56};
54 57 
55struct Mc2InitTilingInner {58struct Mc2InitTilingInner {
56- uint32_t version;59+ uint32_t version; // ccu & alltoall (暂定version 为 原本的version + 1)
57 uint32_t mc2HcommCnt;60 uint32_t mc2HcommCnt;
58 uint32_t offset[MAX_CC_TILING_NUM];61 uint32_t offset[MAX_CC_TILING_NUM];
59 uint8_t debugMode;62 uint8_t debugMode;
@@ -93,650 +96,126 @@ struct OpResCtx {
93 uint64_t rankId;96 uint64_t rankId;
94 uint64_t rankSize;97 uint64_t rankSize;
95 AlgInfo algInfo[MAX_CC_TILING_NUM];98 AlgInfo algInfo[MAX_CC_TILING_NUM];
99+ 
100+ // for ccu
101+ uint64_t xnAddr; // xn寄存器起始地址
102+ uint64_t ckeAddr; // cke寄存器起始地址
103+ uint64_t sprAddr; // spr寄存器起始地址
104+ uint64_t res[Hccl::MC2_MAX_OP_NUM]; // MS地址,预留
105+ uint64_t resCtx; // 资源地址,用于资源下发时的处理
106+ uint32_t opType[Hccl::MC2_MAX_OP_NUM];
107+ uint32_t algorithmType[Hccl::MC2_MAX_OP_NUM];
108+ bool isKfc[Hccl::MC2_MAX_OP_NUM]; // 用于标记是否走kfcServer
96};109};
97 110 
98-HcclResult CheckInputParam(const HcclComm comm, const void* mc2Tiling, const aclrtStream stream)111+enum AlgorithmType {
99-{112+ CcuAllGatherMesh1D = 0,
100- // 检查comm是否为空指针113+ CcuAllGatherMeshMem2Mem1D,
101- RPT_INPUT_ERR(114+ CcuAllGatherMesh2D,
102- comm == nullptr, "EI0003", std::vector<std::string>({"ccl_op", "value", "parameter", "expect"}),115+ CcuReduceScatterMesh1D = 50,
103- std::vector<std::string>({"HcclAllocComResourceByTiling", "nullptr", "comm", "non-null pointer"}));116+ CcuReduceScatterMeshMem2Mem1D,
104- CHK_PTR_NULL(comm);117+ CcuReduceScatterMesh2D,
118+ CcuAllReduceMesh1D = 100,
119+ CcuAllReduceMeshMem2Mem1D,
120+ CcuAllReduceMesh2DOneShot
121+};
105 122 
106- // 检查sendBuf是否为空指针123+static const std::unordered_map<std::string, AlgorithmType> algorithmMap = {
107- RPT_INPUT_ERR(124+ {"CcuAllGatherMesh1DMem2Mem", CcuAllGatherMeshMem2Mem1D},
108- mc2Tiling == nullptr, "EI0003", std::vector<std::string>({"ccl_op", "value", "parameter", "expect"}),125+ {"CcuAllGatherMeshMem2Mem1D", CcuAllGatherMeshMem2Mem1D},
109- std::vector<std::string>({"HcclAllocComResourceByTiling", "nullptr", "mc2Tiling", "non-null pointer"}));126+ {"CcuKfcReduceScatterMesh1DMem2Mem", CcuReduceScatterMeshMem2Mem1D}};
110- CHK_PTR_NULL(mc2Tiling);
111- 
112- // 检查stream是否为空指针
113- RPT_INPUT_ERR(
114- stream == nullptr, "EI0003", std::vector<std::string>({"ccl_op", "value", "parameter", "expect"}),
115- std::vector<std::string>({"HcclAllocComResourceByTiling", "nullptr", "stream", "non-null pointer"}));
116- CHK_PTR_NULL(stream);
117- 
118- return HCCL_SUCCESS;
119-}
120- 
121-HcclResult HcclGetTilingList(const void* mc2Tiling, const void* p[], uint32_t& cnt)
122-{
123- const u32* versionPtr = static_cast<const u32*>(mc2Tiling);
124- const u32 version = *(versionPtr++);
125- CHK_PRT_RET(version < MC2_TILING_VERSION, HCCL_ERROR("Invalid tiling version %u.", version), HCCL_E_PARA);
126- 
127- cnt = *(versionPtr++);
128- CHK_PRT_RET(cnt > MAX_HCOM_NUM, HCCL_ERROR("Invalid hcom tiling number %u.", cnt), HCCL_E_PARA);
129- 
130- u64 serverCfgAddr = reinterpret_cast<u64>(versionPtr) + sizeof(Mc2ServerCfg);
131- for (uint32_t i = 0U; i < MAX_CC_TILING_NUM; ++i) {
132- p[i] = reinterpret_cast<const void*>(reinterpret_cast<const u8*>(mc2Tiling) + versionPtr[i]);
133- }
134- HCCL_INFO("HcclGetTilingList version[%u] cnt[%u]", version, cnt);
135- return HCCL_SUCCESS;
136-}
137- 
138-HcclResult CheckIsReduce(const Mc2CcTilingInner* ccTiling, bool* isReduce)
139-{
140- if (ccTiling->opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER || ccTiling->opType == HcclCMDType::HCCL_CMD_REDUCE ||
141- ccTiling->opType == HcclCMDType::HCCL_CMD_ALLREDUCE) {
142- *isReduce = true;
143- } else {
144- *isReduce = false;
145- }
146- return HCCL_SUCCESS;
147-}
148- 
149-HcclResult CheckCommEngine(const void* ccTilingList[], uint32_t tilingNum)
150-{
151- for (uint32_t i = 0U; i < tilingNum; ++i) {
152- const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
153- if (ccTiling->commEngine != static_cast<uint8_t>(COMM_ENGINE_AICPU) &&
154- ccTiling->commEngine != static_cast<uint8_t>(COMM_ENGINE_CPU)) {
155- HCCL_ERROR("Invalid commEngine %u.", ccTiling->commEngine);
156- return HCCL_E_NOT_SUPPORT;
157- }
158- }
159- return HCCL_SUCCESS;
160-}
161- 
162-HcclResult HcclAllocOpResCtx(
163- HcclComm comm, const std::string& ctxTag, const std::vector<OpParam>& opParamVec, void* mc2Tiling,
164- const void* ccTilingList[], void** opResCtxPtr)
165-{
166- CHK_PTR_NULL(opResCtxPtr);
167- OpResCtx resCtx{};
168- Mc2InitTilingInner* initTiling = static_cast<Mc2InitTilingInner*>(mc2Tiling);
169- 
170- // 1. 申请存放OpParam的内存空间
171- std::vector<uint64_t> opParamAddr(opParamVec.size());
172- uint64_t opParamSize = sizeof(OpParam);
173- for (uint32_t i = 0U; i < opParamVec.size(); ++i) {
174- // 申请硬件内存
175- std::string tagParam = ctxTag + "_" + std::to_string(i);
176- void* opParamPtr = nullptr;
177- const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
178- // 当 commEngine 为 0 (默认值)时,设置为aicpu模式
179- CommEngine commEngine =
180- (ccTiling->commEngine == 0) ? CommEngine::COMM_ENGINE_AICPU : static_cast<CommEngine>(ccTiling->commEngine);
181- if (HcclEngineCtxGet(comm, tagParam.c_str(), commEngine, &opParamPtr, &opParamSize) == HCCL_SUCCESS) {
182- HCCL_INFO(
183- "HcclEngineCtxGet success, tagParam[%s], opParamAddr[%p], opParamSize[%u]", tagParam.c_str(),
184- opParamPtr, opParamSize);
185- opParamAddr[i] = reinterpret_cast<uint64_t>(opParamPtr);
186- } else {
187- CHK_RET(HcclEngineCtxCreate(comm, tagParam.c_str(), commEngine, opParamSize, &opParamPtr));
188- opParamAddr[i] = reinterpret_cast<uint64_t>(opParamPtr);
189- }
190- HCCL_INFO(
191- "HcclAllocOpResCtx the %dth opParam: opParamAddr[%u], opParamSize[%u]", i, opParamAddr[i], opParamSize);
192- 
193- // 复制数据到硬件内存
194- aclError aclRet = aclrtMemcpy(
195- reinterpret_cast<void*>(opParamAddr[i]), opParamSize, &opParamVec[i], opParamSize, aclrtMemcpyKind(1));
196- CHK_RET(aclRet == ACL_ERROR_NONE ? HCCL_SUCCESS : HCCL_E_RUNTIME);
197- // 记录OpParam的地址
198- resCtx.algInfo[i].opParam = opParamAddr[i];
199- // 记录OpParam的偏移量
200- resCtx.algInfo[i].offset = initTiling->offset[i];
201- }
202- 
203- // 2. 申请WorkSpace的内存空间
204- uint64_t memSize = 20 * 1024 * 1024;
205- resCtx.workSpaceSize = memSize;
206- // 申请硬件内存
207- std::string tagWorkSpace = ctxTag + "_workSpace";
208- void* workSpacePtr = nullptr;
209- const Mc2CcTilingInner* ccTiling0 = static_cast<const Mc2CcTilingInner*>(ccTilingList[0]);
210- CommEngine commEngine =
211- (ccTiling0->commEngine == 0) ? CommEngine::COMM_ENGINE_AICPU : static_cast<CommEngine>(ccTiling0->commEngine);
212- if (HcclEngineCtxGet(comm, tagWorkSpace.c_str(), commEngine, &workSpacePtr, &memSize) == HCCL_SUCCESS) {
213- HCCL_INFO(
214- "HcclEngineCtxGet success, tagWorkSpace[%s], workSpaceAddr[%p], workSpaceSize[%u]", tagWorkSpace.c_str(),
215- workSpacePtr, memSize);
216- resCtx.workSpace = reinterpret_cast<uint64_t>(workSpacePtr);
217- } else {
218- CHK_RET(HcclEngineCtxCreate(comm, tagWorkSpace.c_str(), commEngine, memSize, &workSpacePtr));
219- resCtx.workSpace = reinterpret_cast<uint64_t>(workSpacePtr);
220- }
221- HCCL_INFO("HcclAllocOpResCtx the workSpace: workSpaceAddr[%u], workSpaceSize[%u]", resCtx.workSpace, memSize);
222- 
223- // 3. 获取rankID和ranksize
224- uint32_t rankSize = 0U;
225- uint32_t rankId = 0U;
226- CHK_RET(HcclGetRankSize(comm, &rankSize));
227- CHK_RET(HcclGetRankId(comm, &rankId));
228- resCtx.rankSize = rankSize;
229- resCtx.rankId = rankId;
230- 
231- // 4. 申请OpResCtx的内存空间
232- std::string tagOpResCtx = ctxTag + "_opResCtx";
233- uint64_t opResCtxSize = sizeof(OpResCtx);
234- if (HcclEngineCtxGet(comm, tagOpResCtx.c_str(), commEngine, opResCtxPtr, &opResCtxSize) == HCCL_SUCCESS) {
235- HCCL_INFO(
236- "HcclEngineCtxGet success, tagOpResCtx[%s], opResCtxAddr[%p], opResCtxSize[%u]", tagOpResCtx.c_str(),
237- opResCtxPtr, opResCtxSize);
238- } else {
239- CHK_RET(HcclEngineCtxCreate(comm, tagOpResCtx.c_str(), commEngine, opResCtxSize, opResCtxPtr));
240- }
241- 
242- HCCL_INFO("HcclAllocOpResCtx the opResCtx: opResCtxAddr[%u], opResCtxSize[%u]", opResCtxPtr, opResCtxSize);
243- 
244- // 5. 复制OpResCtx到硬件内存
245- aclError aclRet = aclrtMemcpy(*opResCtxPtr, opResCtxSize, &resCtx, opResCtxSize, aclrtMemcpyKind(1));
246- CHK_RET(aclRet == ACL_ERROR_NONE ? HCCL_SUCCESS : HCCL_E_RUNTIME);
247- 
248- return HCCL_SUCCESS;
249-}
250- 
251-// AllToAll适配AllToAllV
252-HcclResult ConvertAlltoAllParam(
253- const u64 recvCount, const u32 rankSize, std::vector<u64>& sdispls, std::vector<u64>& rdispls)
254-{
255- u64 dataCountOffset = 0;
256- for (u64 i = 0; i < rankSize; i++) {
257- sdispls[i] = dataCountOffset;
258- rdispls[i] = dataCountOffset;
259- dataCountOffset += recvCount;
260- }
261- return HCCL_SUCCESS;
262-}
263- 
264-HcclResult PrepareOpsCommParam(const std::string& tag, OpParam& param)
265-{
266- param.opMode = OpMode::OPBASE;
267- DevType deviceType = DevType::DEV_TYPE_COUNT;
268- CHK_RET(hrtGetDeviceType(deviceType));
269- 
270- // topoInfo的tag,所有相同的算子可以共享
271- int ret = sprintf_s(param.tag, sizeof(param.tag), "%s", tag.c_str());
272- if (ret <= 0) {
273- HCCL_ERROR("failed to fill param.tag");
274- return HCCL_E_INTERNAL;
275- }
276- 
277- param.inputPtr = nullptr;
278- param.outputPtr = nullptr;
279- param.inputSize = 0;
280- param.outputSize = 0;
281- param.enableDetour = false;
282- param.deviceType = deviceType;
283- 
284- return HCCL_SUCCESS;
285-}
286- 
287-HcclResult PrintOpsCommParam(OpParam& param)
288-{
289- HCCL_INFO("commName: %s", param.commName);
290- HCCL_INFO("tag:%s", param.tag);
291- HCCL_INFO("stream: %p", param.stream);
292- HCCL_INFO("inputPtr %p", param.inputPtr);
293- HCCL_INFO("outputPtr %p", param.outputPtr);
294- HCCL_INFO("inputSize %lu", param.inputSize);
295- HCCL_INFO("outputSize %lu", param.outputSize);
296- HCCL_INFO("opMode %u", static_cast<uint32_t>(param.opMode));
297- HCCL_INFO("deviceType %u", static_cast<uint32_t>(param.deviceType));
298- return HCCL_SUCCESS;
299-}
300- 
301-HcclResult PrepareParamForAllGather(
302- HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
303-{
304- HCCL_INFO("PrepareParamForAllGather, ccTiling[%p]", ccTiling);
305- u32 userRankSize;
306- CHK_RET(HcclGetRankSize(comm, &userRankSize)); // 加上,后面计算outputSize可能使用
307- 
308- HcclResult ret = PrepareOpsCommParam(tag, param);
309- if (ret != HCCL_SUCCESS) {
310- HCCL_ERROR("failed to fill OpsCommParam");
311- }
312- 
313- param.opType = HcclCMDType::HCCL_CMD_ALLGATHER;
314- param.DataDes.dataType = static_cast<HcclDataType>(ccTiling->srcDataType);
315- param.DataDes.count = 0;
316- 
317- HCCL_INFO("Print PrepareParamForAllGather.");
318- CHK_RET(PrintOpsCommParam(param));
319- HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
320- HCCL_INFO("DataDes.dataType %u", static_cast<uint32_t>(param.DataDes.dataType));
321- HCCL_INFO("DataDes.count %lu", param.DataDes.count);
322- HCCL_INFO("Execute PrepareParamForAllGather success.");
323- return HCCL_SUCCESS;
324-}
325- 
326-HcclResult PrepareParamForAllReduce(
327- HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
328-{
329- HCCL_INFO("PrepareParamForAllReduce, ccTiling[%p]", ccTiling);
330- u32 userRankSize;
331- CHK_RET(HcclGetRankSize(comm, &userRankSize)); // 加上,后面计算outputSize可能使用
332- 
333- HcclResult ret = PrepareOpsCommParam(tag, param);
334- if (ret != HCCL_SUCCESS) {
335- HCCL_ERROR("failed to fill OpsCommParam");
336- }
337- 
338- param.opType = HcclCMDType::HCCL_CMD_ALLREDUCE;
339- param.reduceType = static_cast<HcclReduceOp>(ccTiling->reduceType);
340- param.DataDes.dataType = static_cast<HcclDataType>(ccTiling->srcDataType);
341- param.DataDes.count = 0;
342- 
343- HCCL_INFO("Print PrepareParamForAllReduce.");
344- CHK_RET(PrintOpsCommParam(param));
345- HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
346- HCCL_INFO("reduceType %u", static_cast<uint32_t>(param.reduceType));
347- HCCL_INFO("DataDes.dataType %u", static_cast<uint32_t>(param.DataDes.dataType));
348- HCCL_INFO("DataDes.count %lu", param.DataDes.count);
349- HCCL_INFO("Execute PrepareParamForAllReduce success.");
350- return HCCL_SUCCESS;
351-}
352- 
353-HcclResult PrepareParamForReduceScatter(
354- HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
355-{
356- HCCL_INFO("PrepareParamForReduceScatter, ccTiling[%p]", ccTiling);
357- u32 userRankSize;
358- CHK_RET(HcclGetRankSize(comm, &userRankSize)); // 加上,后面计算outputSize可能使用
359- 
360- HcclResult ret = PrepareOpsCommParam(tag, param);
361- if (ret != HCCL_SUCCESS) {
362- HCCL_ERROR("failed to fill OpsCommParam");
363- }
364- 
365- param.opType = HcclCMDType::HCCL_CMD_REDUCE_SCATTER;
366- param.reduceType = static_cast<HcclReduceOp>(ccTiling->reduceType);
367- param.DataDes.dataType = static_cast<HcclDataType>(ccTiling->srcDataType);
368- param.DataDes.count = 0;
369- 
370- HCCL_INFO("Print PrepareParamForReduceScatter.");
371- CHK_RET(PrintOpsCommParam(param));
372- HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
373- HCCL_INFO("reduceType %u", static_cast<uint32_t>(param.reduceType));
374- HCCL_INFO("DataDes.dataType %u", static_cast<uint32_t>(param.DataDes.dataType));
375- HCCL_INFO("DataDes.count %lu", param.DataDes.count);
376- HCCL_INFO("Execute PrepareParamForReduceScatter success.");
377- return HCCL_SUCCESS;
378-}
379- 
380-HcclResult PrepareParamForAlltoAll(
381- HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
382-{
383- HCCL_INFO("PrepareParamForAlltoAll, ccTiling[%p]", ccTiling);
384- u32 userRankSize;
385- CHK_RET(HcclGetRankSize(comm, &userRankSize));
386- 
387- HcclResult ret = PrepareOpsCommParam(tag, param);
388- if (ret != HCCL_SUCCESS) {
389- HCCL_ERROR("failed to fill OpsCommParam");
390- }
391- 
392- u64 varMemSize = ALL_TO_ALL_V_VECTOR_NUM * userRankSize * sizeof(u64);
393- param.varMemSize = varMemSize;
394- param.opType = HcclCMDType::HCCL_CMD_ALLTOALL;
395- param.all2AllVDataDes.sendType = static_cast<HcclDataType>(ccTiling->srcDataType);
396- param.all2AllVDataDes.recvType = static_cast<HcclDataType>(ccTiling->dstDataType);
397- param.all2AllVDataDes.sendCounts = nullptr;
398- param.all2AllVDataDes.recvCounts = nullptr;
399- param.all2AllVDataDes.sdispls = nullptr;
400- param.all2AllVDataDes.rdispls = nullptr;
401- 
402- HCCL_INFO("Print PrepareParamForAlltoAll.");
403- CHK_RET(PrintOpsCommParam(param));
404- HCCL_INFO("varMemSize %lu", param.varMemSize);
405- HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
406- HCCL_INFO("all2AllVDataDes.sendType %u", static_cast<uint32_t>(param.all2AllVDataDes.sendType));
407- HCCL_INFO("all2AllVDataDes.recvType %u", static_cast<uint32_t>(param.all2AllVDataDes.recvType));
408- HCCL_INFO("Execute PrepareParamForAlltoAll success.");
409- return HCCL_SUCCESS;
410-}
411- 
412-HcclResult PrepareParamForAlltoAllV(
413- HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param)
414-{
415- HCCL_INFO("PrepareParamForAlltoAllV, ccTiling[%p]", ccTiling);
416- u32 userRankSize;
417- CHK_RET(HcclGetRankSize(comm, &userRankSize));
418- 
419- HcclResult ret = PrepareOpsCommParam(tag, param);
420- if (ret != HCCL_SUCCESS) {
421- HCCL_ERROR("failed to fill OpsCommParam");
422- }
423- 
424- u64 varMemSize = ALL_TO_ALL_V_VECTOR_NUM * userRankSize * sizeof(u64);
425- param.varMemSize = varMemSize;
426- param.opType = HcclCMDType::HCCL_CMD_ALLTOALLV;
427- param.all2AllVDataDes.sendType = static_cast<HcclDataType>(ccTiling->srcDataType);
428- param.all2AllVDataDes.recvType = static_cast<HcclDataType>(ccTiling->dstDataType);
429- param.all2AllVDataDes.sendCounts = nullptr;
430- param.all2AllVDataDes.recvCounts = nullptr;
431- param.all2AllVDataDes.sdispls = nullptr;
432- param.all2AllVDataDes.rdispls = nullptr;
433- 
434- HCCL_INFO("Print PrepareParamForAlltoAllV.");
435- CHK_RET(PrintOpsCommParam(param));
436- HCCL_INFO("varMemSize %lu", param.varMemSize);
437- HCCL_INFO("opType %u", static_cast<uint32_t>(param.opType));
438- HCCL_INFO("all2AllVDataDes.sendType %u", static_cast<uint32_t>(param.all2AllVDataDes.sendType));
439- HCCL_INFO("all2AllVDataDes.recvType %u", static_cast<uint32_t>(param.all2AllVDataDes.recvType));
440- return HCCL_SUCCESS;
441-}
442 127 
443typedef HcclResult (*OpParamPrepareFunc)(128typedef HcclResult (*OpParamPrepareFunc)(
444 HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param);129 HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param);
445 130 
446-std::unordered_map<HcclCMDType, OpParamPrepareFunc> opParamPrepareFuncMap = {131+CommEngine OpExecuteConfigToCommEngine(uint8_t commEngine);
447- {HcclCMDType::HCCL_CMD_ALLGATHER, PrepareParamForAllGather},
448- {HcclCMDType::HCCL_CMD_ALLREDUCE, PrepareParamForAllReduce},
449- {HcclCMDType::HCCL_CMD_REDUCE_SCATTER, PrepareParamForReduceScatter},
450- {HcclCMDType::HCCL_CMD_ALLTOALL, PrepareParamForAlltoAll},
451- {HcclCMDType::HCCL_CMD_ALLTOALLV, PrepareParamForAlltoAllV},
452-};
453 132 
454-HcclResult PrepareOpParams(HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam)133+HcclResult CheckInputParam(const HcclComm comm, const void* mc2Tiling, const aclrtStream stream);
455-{134+ 
456- auto it = opParamPrepareFuncMap.find(static_cast<HcclCMDType>(ccTiling->opType));135+HcclResult HcclGetTilingList(const void* mc2Tiling, const void* p[], uint32_t& cnt);
457- if (it != opParamPrepareFuncMap.end()) {136+ 
458- return it->second(comm, tag, ccTiling, opParam);137+HcclResult CheckIsReduce(const Mc2CcTilingInner* ccTiling, bool* isReduce);
459- }138+ 
460- HCCL_ERROR("PrepareOpParams error, opType[%d] not found", ccTiling->opType);139+HcclResult CheckCommEngine(const void* ccTilingList[], uint32_t tilingNum);
461- return HCCL_E_INTERNAL;140+ 
462-}141+HcclResult ObtainCommEngine(const void* ccTilingList[], uint32_t tilingNum, uint8_t& commEngine);
142+ 
143+HcclResult CheckCcuKfcFlow(const void* mc2Tiling, const void* ccTilingList[], uint32_t tilingNum);
144+ 
145+// 构建 opResCtx 基础字段
146+HcclResult AllocCcuOpResCtx(HcclComm comm, const std::string& ctxTag, u32 rankSize, u32 userRank, OpResCtx& opResCtx);
147+ 
148+HcclResult HcclAllocOpResCtx(
149+ HcclComm comm, const std::string& ctxTag, const std::vector<OpParam>& opParamVec, void* mc2Tiling,
150+ const void* ccTilingList[], void** opResCtxPtr);
151+ 
152+// AllToAll适配AllToAllV
153+HcclResult ConvertAlltoAllParam(
154+ const u64 recvCount, const u32 rankSize, std::vector<u64>& sdispls, std::vector<u64>& rdispls);
155+ 
156+HcclResult PrepareOpsCommParam(const std::string& tag, OpParam& param);
157+ 
158+HcclResult PrintOpsCommParam(OpParam& param);
159+ 
160+HcclResult PrepareParamForAllGather(
161+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param);
162+ 
163+HcclResult PrepareParamForAllReduce(
164+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param);
165+ 
166+HcclResult PrepareParamForReduceScatter(
167+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param);
168+ 
169+HcclResult PrepareParamForAlltoAll(
170+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param);
171+ 
172+HcclResult PrepareParamForAlltoAllV(
173+ HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& param);
174+ 
175+HcclResult PrepareOpParams(HcclComm comm, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam);
463 176 
464HcclResult InitOpParamByTiling(177HcclResult InitOpParamByTiling(
465- HcclComm comm, void* stream, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam)178+ HcclComm comm, void* stream, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam);
466-{
467- opParam.opType = static_cast<HcclCMDType>(ccTiling->opType);
468- opParam.stream = reinterpret_cast<aclrtStream>(stream);
469- opParam.engine = static_cast<CommEngine>(ccTiling->commEngine);
470- CHK_RET(HcclGetCommName(comm, opParam.commName));
471- CHK_RET(PrepareOpParams(comm, tag, ccTiling, opParam));
472- if (opParam.opType == HcclCMDType::HCCL_CMD_ALLTOALL) {
473- opParam.all2AllVDataDes.sendType = static_cast<HcclDataType>(ccTiling->srcDataType);
474- // sendCounts指向的host侧数组由调用方(GetOpParam)持有并填充,此处保持nullptr,
475- // 避免将数值当作指针使用导致后续解引用非法地址。
476- }
477- return HCCL_SUCCESS;
478-}
479 179 
480-HcclResult PrepareTopoInfoForOp(HcclComm comm, OpParam& opParam, std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo)180+HcclResult PrepareTopoInfoForOp(
481-{181+ HcclComm comm, OpParam& opParam, std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo);
482- opParam.hcclComm = comm;
483- CHK_RET(HcclGetOpExpansionMode(comm, opParam));
484- CHK_RET(HcclCalcTopoInfo(comm, opParam, topoInfo));
485- return HCCL_SUCCESS;
486-}
487 182 
488-HcclResult PrepareEngineForAlg(OpParam& opParam, const std::string& algName)183+HcclResult PrepareEngineForAlg(OpParam& opParam, const std::string& algName);
489-{
490- CHK_RET(SetCommEngine(opParam));
491- if (GetExternalInputHcclAivOnlyMode() && opParam.engine != COMM_ENGINE_AIV) {
492- HCCL_ERROR(
493- "[HcclExecOp] opType[%d] currently do not select aiv mode, aiv only not support.",
494- static_cast<int>(opParam.opType));
495- return HCCL_E_NOT_SUPPORT;
496- }
497- if ((opParam.engine == COMM_ENGINE_AICPU_TS) || (opParam.engine == COMM_ENGINE_CPU)) {
498- HCCL_DEBUG("[Selector] is aicpu mode");
499- CHK_RET(LoadAICPUKernel());
500- }
501- CHK_RET(SetOpParamAlgTag(opParam, algName));
502- return HCCL_SUCCESS;
503-}
504 184 
505-std::unique_ptr<InsCollAlgBase> GetAlgExecutorForOp(const OpParam& opParam, const std::string& algName)185+std::unique_ptr<InsCollAlgBase> GetAlgExecutorForOp(const OpParam& opParam, const std::string& algName);
506-{
507- if (UseCannBridge(opParam)) {
508- return GetAlgExecViaCann(opParam.opType, algName);
509- }
510- return CollAlgExecRegistryV2::Instance().GetAlgExec(opParam.opType, algName);
511-}
512 186 
513HcclResult CheckForcedAlgResource(187HcclResult CheckForcedAlgResource(
514- HcclComm comm, const OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo, const std::string& algName)188+ HcclComm comm, const OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo, const std::string& algName);
515-{
516- std::unique_ptr<InsCollAlgBase> executor = GetAlgExecutorForOp(opParam, algName);
517- CHK_PRT_RET(
518- executor == nullptr,
519- HCCL_WARNING(
520- "[MC2_FORCE_ALG] fallback, algName[%s] is not registered for opType[%u].", algName.c_str(),
521- static_cast<u32>(opParam.opType)),
522- HCCL_E_NOT_SUPPORT);
523 189 
524- AlgHierarchyInfoForAllLevel algHierarchyInfo;190+bool GetForcedAlgName(const Mc2CcTilingInner* ccTiling, std::string& algName);
525- HcclResult ret = executor->CalcAlgHierarchyInfo(comm, topoInfo, algHierarchyInfo);
526- CHK_PRT_RET(
527- ret != HCCL_SUCCESS,
528- HCCL_WARNING(
529- "[MC2_FORCE_ALG] fallback, CalcAlgHierarchyInfo failed, algName[%s], ret[%d].", algName.c_str(),
530- static_cast<int>(ret)),
531- HCCL_E_NOT_SUPPORT);
532- 
533- AlgResourceRequest resRequest;
534- ret = executor->CalcRes(comm, opParam, topoInfo, algHierarchyInfo, resRequest);
535- CHK_PRT_RET(
536- ret != HCCL_SUCCESS,
537- HCCL_WARNING(
538- "[MC2_FORCE_ALG] fallback, CalcRes failed, algName[%s], ret[%d].", algName.c_str(), static_cast<int>(ret)),
539- HCCL_E_NOT_SUPPORT);
540- return HCCL_SUCCESS;
541-}
542- 
543-bool GetForcedAlgName(const Mc2CcTilingInner* ccTiling, std::string& algName)
544-{
545- if (ccTiling == nullptr || ccTiling->algConfig[0] == '\0') {
546- return false;
547- }
548- 
549- std::string algConfig(ccTiling->algConfig);
550- if (algConfig.find('=') != std::string::npos) {
551- HCCL_INFO("[MC2_FORCE_ALG] legacy algConfig[%s], use default selector.", algConfig.c_str());
552- return false;
553- }
554- 
555- algName = algConfig;
556- return true;
557-}
558 191 
559HcclResult TryForcedAlgAndPrepareEngine(192HcclResult TryForcedAlgAndPrepareEngine(
560 HcclComm comm, const Mc2CcTilingInner* ccTiling, OpParam& opParam, std::string& algName,193 HcclComm comm, const Mc2CcTilingInner* ccTiling, OpParam& opParam, std::string& algName,
561- std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo, bool& forcedAlgAccepted)194+ std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo, bool& forcedAlgAccepted);
562-{
563- forcedAlgAccepted = false;
564- std::string forcedAlgName;
565- if (!GetForcedAlgName(ccTiling, forcedAlgName)) {
566- return HCCL_SUCCESS;
567- }
568- 
569- OpParam opParamBackup = opParam;
570- CHK_RET(PrepareTopoInfoForOp(comm, opParam, topoInfo));
571- HcclResult ret = PrepareEngineForAlg(opParam, forcedAlgName);
572- if (ret != HCCL_SUCCESS) {
573- opParam = opParamBackup;
574- HCCL_ERROR(
575- "[MC2_FORCE_ALG] prepare engine failed, algName[%s], ret[%d].", forcedAlgName.c_str(),
576- static_cast<int>(ret));
577- return ret;
578- }
579- 
580- ret = CheckForcedAlgResource(comm, opParam, topoInfo.get(), forcedAlgName);
581- if (ret != HCCL_SUCCESS) {
582- opParam = opParamBackup;
583- topoInfo = std::make_unique<TopoInfoWithNetLayerDetails>();
584- algName.clear();
585- forcedAlgAccepted = false;
586- HCCL_WARNING(
587- "[MC2_FORCE_ALG] fallback to default selector, opType[%u], algConfig[%s].",
588- static_cast<u32>(opParam.opType), forcedAlgName.c_str());
589- return HCCL_SUCCESS;
590- }
591- 
592- algName = forcedAlgName;
593- forcedAlgAccepted = true;
594- HCCL_INFO("[MC2_FORCE_ALG] accepted, opType[%u], algName[%s].", static_cast<u32>(opParam.opType), algName.c_str());
595- return HCCL_SUCCESS;
596-}
597 195 
598HcclResult SelectAlgAndPrepareEngine(196HcclResult SelectAlgAndPrepareEngine(
599- HcclComm comm, OpParam& opParam, std::string& algName, std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo)197+ HcclComm comm, OpParam& opParam, std::string& algName, std::unique_ptr<TopoInfoWithNetLayerDetails>& topoInfo);
600-{
601- CHK_RET(PrepareTopoInfoForOp(comm, opParam, topoInfo));
602 198 
603- std::shared_ptr<ExecuteSelector> collAlgSelector = std::make_shared<ExecuteSelector>(ExecuteSelector());199+HcclResult FillOpParamAlgName(OpParam& opParam, const std::string& algName);
604- CHK_RET(collAlgSelector->Run(opParam, topoInfo.get(), algName));
605- if (algName.empty()) {
606- HCCL_ERROR("[Selector] select algname fail!");
607- return HCCL_E_PTR;
608- }
609 200 
610- CHK_RET(PrepareEngineForAlg(opParam, algName));201+HcclResult HandleSingleRankAndCommMode(HcclComm comm, OpParam& opParam, bool& skipGetRes);
611- return HCCL_SUCCESS;
612-}
613- 
614-HcclResult FillOpParamAlgName(OpParam& opParam, const std::string& algName)
615-{
616- int result = sprintf_s(opParam.algName, sizeof(opParam.algName), "%s", algName.c_str());
617- CHK_PRT_RET(result <= 0, HCCL_ERROR("failed to fill opParam.algName"), HCCL_E_INTERNAL);
618- HCCL_INFO(
619- "[GetOpParam] prepared opParam, opType[%u], algName[%s], algTag[%s].", static_cast<u32>(opParam.opType),
620- opParam.algName, opParam.algTag);
621- return HCCL_SUCCESS;
622-}
623- 
624-HcclResult HandleSingleRankAndCommMode(HcclComm comm, OpParam& opParam, bool& skipGetRes)
625-{
626- uint32_t userRankSize = 0;
627- CHK_RET(HcclGetRankSize(comm, &userRankSize));
628- if (userRankSize == 1) {
629- HCCL_WARNING("[%s] ranksize == 1, enter SingleRankProc", __func__);
630- CHK_RET(SingleRankProc(opParam));
631- skipGetRes = true;
632- return HCCL_SUCCESS;
633- }
634- 
635- bool isOpBase = true;
636- const char* opModeStr = isOpBase ? "_opbase" : "_offload";
637- auto ret = sprintf_s(opParam.commModeTag, sizeof(opParam.commModeTag), "%s_%s", opParam.commName, opModeStr);
638- if (ret <= 0) {
639- HCCL_ERROR("[%s] failed to fill opParam.commModeTag", __func__);
640- return HCCL_E_INTERNAL;
641- }
642- skipGetRes = false;
643- return HCCL_SUCCESS;
644-}
645 202 
646HcclResult GetOpParamResCtx(203HcclResult GetOpParamResCtx(
647 HcclComm comm, const std::string& algName, OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo,204 HcclComm comm, const std::string& algName, OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo,
648- void** resCtxOut)205+ void** resCtxOut);
649-{
650- bool useCannResCtx = UseCannBridge(opParam);
651 206 
652- std::unique_ptr<InsCollAlgBase> executor = nullptr;207+HcclResult GetCcuOpParamResCtx(
653- if (useCannResCtx) {208+ HcclComm comm, const std::string& algName, OpParam& opParam, TopoInfoWithNetLayerDetails* topoInfo,
654- executor = GetAlgExecViaCann(opParam.opType, algName);209+ OpResCtx& opResCtx, void** resCtxOut);
655- } else {
656- executor = CollAlgExecRegistryV2::Instance().GetAlgExec(opParam.opType, algName);
657- }
658- CHK_PRT_RET(
659- executor.get() == nullptr, HCCL_ERROR("Fail to find executor for algName[%s]", algName.c_str()), HCCL_E_PARA);
660- 
661- std::unique_ptr<AlgResourceCtxSerializable> resCtxHost = std::make_unique<AlgResourceCtxSerializable>();
662- resCtxHost->isHcommBatchTransferOnThreadSupported = HcommIsSupportHcommBatchTransferOnThread();
663- HCCL_DEBUG(
664- "[MC2_BATCH_TRANSFER][HostSupport] opType[%u], algName[%s], supported[%d].",
665- static_cast<uint32_t>(opParam.opType), algName.c_str(),
666- static_cast<int>(resCtxHost->isHcommBatchTransferOnThreadSupported));
667- bool isResourceReused = false;
668- 
669- ThreadHandle cpuTsThread{0};
670- ThreadHandle exportedAicpuTsThread{0};
671- if ((opParam.engine == COMM_ENGINE_AICPU_TS) || (opParam.engine == COMM_ENGINE_CPU)) {
672- CHK_RET(HcclThreadAcquireWithStream(comm, COMM_ENGINE_CPU_TS, opParam.stream, 1, &cpuTsThread));
673- CHK_RET(HcclThreadExportToCommEngine(comm, 1, &cpuTsThread, COMM_ENGINE_AICPU_TS, &exportedAicpuTsThread));
674- }
675- CHK_RET(HcclGetAlgRes(comm, opParam, executor, topoInfo, resCtxHost, resCtxOut, isResourceReused));
676- opParam.cacheValid = isResourceReused;
677- opParam.resCtx = *resCtxOut;
678- return HCCL_SUCCESS;
679-}
680 210 
681HcclResult GetOpParam(211HcclResult GetOpParam(
682- HcclComm comm, void* stream, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam)212+ HcclComm comm, void* stream, const std::string& tag, const Mc2CcTilingInner* ccTiling, OpParam& opParam);
683-{
684- CHK_RET(InitOpParamByTiling(comm, stream, tag, ccTiling, opParam));
685 213 
686- // ALLTOALL场景下sendCounts需指向host侧真实数组,且必须在整个GetOpParam调用链214+HcclResult CcuSelectAlgCheck(const Mc2CcTilingInner* ccTiling, uint32_t tilingIndex);
687- // (含SelectAlgAndPrepareEngine、GetOpParamResCtx中的GetAlgExecViaCann)期间保持存活。
688- // 该数组持有在本函数栈帧,覆盖opParam的全部使用范围。
689- constexpr uint64_t ALLTOALL_DEFAULT_SEND_COUNTS = 200ULL * 1024 * 1024;
690- std::vector<uint64_t> sendCounts;
691- void* origSendCounts = opParam.all2AllVDataDes.sendCounts;
692- if (opParam.opType == HcclCMDType::HCCL_CMD_ALLTOALL) {
693- uint32_t userRankSize = 0;
694- CHK_RET(HcclGetRankSize(comm, &userRankSize));
695- sendCounts.assign(userRankSize, ALLTOALL_DEFAULT_SEND_COUNTS);
696- opParam.all2AllVDataDes.sendCounts = reinterpret_cast<void*>(sendCounts.data());
697- }
698 215 
699- std::string algName;216+// CCU路径逐算子:算法选择 + 资源准备(参照GetOpParam形式)
700- std::unique_ptr<TopoInfoWithNetLayerDetails> topoInfo = std::make_unique<TopoInfoWithNetLayerDetails>();217+HcclResult CcuSelectAlg(
701- bool forcedAlgAccepted = false;218+ HcclComm comm, void* stream, const std::string topoTag[], const void* ccTilingList[], uint32_t tilingNum,
702- OpParam opParamBeforeAlg = opParam;219+ void* mc2Tiling, OpResCtx& opResCtx);
703- CHK_RET(TryForcedAlgAndPrepareEngine(comm, ccTiling, opParam, algName, topoInfo, forcedAlgAccepted));
704- if (!forcedAlgAccepted) {
705- CHK_RET(SelectAlgAndPrepareEngine(comm, opParam, algName, topoInfo));
706- }
707- CHK_RET(FillOpParamAlgName(opParam, algName));
708- 
709- bool skipGetRes = false;
710- CHK_RET(HandleSingleRankAndCommMode(comm, opParam, skipGetRes));
711- if (skipGetRes) {
712- opParam.all2AllVDataDes.sendCounts = origSendCounts;
713- return HCCL_SUCCESS;
714- }
715- 
716- void* resCtxSequence = nullptr;
717- HcclResult resRet = GetOpParamResCtx(comm, algName, opParam, topoInfo.get(), &resCtxSequence);
718- if (resRet != HCCL_SUCCESS && forcedAlgAccepted && resCtxSequence == nullptr) {
719- HCCL_WARNING(
720- "[MC2_FORCE_ALG] fallback to default selector after resource failure, algName[%s], ret[%d].",
721- algName.c_str(), static_cast<int>(resRet));
722- opParam = opParamBeforeAlg;
723- algName.clear();
724- topoInfo = std::make_unique<TopoInfoWithNetLayerDetails>();
725- CHK_RET(SelectAlgAndPrepareEngine(comm, opParam, algName, topoInfo));
726- CHK_RET(FillOpParamAlgName(opParam, algName));
727- CHK_RET(HandleSingleRankAndCommMode(comm, opParam, skipGetRes));
728- if (skipGetRes) {
729- opParam.all2AllVDataDes.sendCounts = origSendCounts;
730- return HCCL_SUCCESS;
731- }
732- CHK_RET(GetOpParamResCtx(comm, algName, opParam, topoInfo.get(), &resCtxSequence));
733- } else {
734- CHK_RET(resRet);
735- }
736- // GetOpParamResCtx执行结束,sendCounts的临时host数组已不再需要,
737- // 将指向恢复为原值(大概率为nullptr),避免遗留指向本函数栈内vector的悬空指针。
738- opParam.all2AllVDataDes.sendCounts = origSendCounts;
739- return HCCL_SUCCESS;
740-}
741 220 
742#endif221#endif
@@ -15,6 +15,9 @@
15#include "param_check.h"15#include "param_check.h"
16#include "hccl_alloc_ctx_res.h"16#include "hccl_alloc_ctx_res.h"
17#include "op_common.h"17#include "op_common.h"
18+#include "ccu_assist_pub.h"
19+#include "hccl_ccu_res.h"
20+#include "adapter_acl.h"
18 21 
19using namespace mc2_ops_hccl;22using namespace mc2_ops_hccl;
20 23 
@@ -188,14 +191,116 @@ HcclResult HcclCreateOpResCtx(HcclComm comm, uint8_t opType, void* opArgs, void*
188 return HCCL_SUCCESS;191 return HCCL_SUCCESS;
189}192}
190 193 
191-HcclResult __attribute__((visibility("default"))) HcclAllocComResourceByTiling(194+// 公共逻辑:构造topoTag/ctxTag并校验ccTiling参数
192- HcclComm comm, void* stream, void* mc2Tiling, void** opResCtx)195+HcclResult BuildTagsAndValidate(
196+ const void* ccTilingList[], uint32_t tilingNum, const char* commName, u32 rankSize, u32 userRank,
197+ std::string topoTag[], std::string& ctxTag)
198+{
199+ for (uint32_t i = 0U; i < tilingNum; ++i) {
200+ const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
201+ topoTag[i] = std::to_string(ccTiling->opType) + "_" + std::to_string(ccTiling->srcDataType) + "_" +
202+ std::string(commName);
203+ CHK_RET(HcclCheckTag(topoTag[i].c_str()));
204+ bool isReduce;
205+ CHK_RET(CheckIsReduce(ccTiling, &isReduce));
206+ CHK_RET(CheckDataType(static_cast<HcclDataType>(ccTiling->srcDataType), isReduce));
207+ 
208+ if (i == 0) {
209+ ctxTag = std::string(ccTiling->groupName) + "_" + std::to_string(ccTiling->opType) + "_" +
210+ std::string(ccTiling->algConfig) + "_" + std::to_string(ccTiling->commEngine);
211+ } else {
212+ ctxTag += "_" + std::to_string(ccTiling->opType) + "_" + std::string(ccTiling->algConfig) + "_" +
213+ std::to_string(ccTiling->commEngine);
214+ }
215+ }
216+ CHK_RET(HcomCheckUserRank(rankSize, userRank));
217+ return HCCL_SUCCESS;
218+}
219+ 
220+// AICPU引擎资源分配流程
221+HcclResult AllocComResourceByTilingAicpu(
222+ HcclComm comm, void* stream, void* mc2Tiling, const void* ccTilingList[], uint32_t tilingNum, const char* commName,
223+ u32 rankSize, u32 userRank, void** opResCtx, std::string& ctxTag)
224+{
225+ std::string topoTag[Hccl::MC2_MAX_OP_NUM];
226+ CHK_RET(BuildTagsAndValidate(ccTilingList, tilingNum, commName, rankSize, userRank, topoTag, ctxTag));
227+ 
228+ std::vector<OpParam> opParamVec(tilingNum);
229+ for (uint32_t i = 0U; i < tilingNum; ++i) {
230+ CHK_RET(
231+ GetOpParam(comm, stream, topoTag[i], static_cast<const Mc2CcTilingInner*>(ccTilingList[i]), opParamVec[i]));
232+ }
233+ 
234+ CHK_RET(HcclAllocOpResCtx(comm, ctxTag, opParamVec, mc2Tiling, ccTilingList, opResCtx));
235+ 
236+ for (uint32_t i = 0U; i < tilingNum; ++i) {
237+ const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
238+ const OpParam& opParam = opParamVec[i];
239+ const HcclDataType srcDataType = static_cast<HcclDataType>(ccTiling->srcDataType);
240+ const HcclDataType dstDataType = static_cast<HcclDataType>(ccTiling->dstDataType);
241+ const std::string srcDataTypeName = GetDataTypeEnumStr(srcDataType);
242+ const std::string dstDataTypeName = GetDataTypeEnumStr(dstDataType);
243+ HCCL_RUN_INFO(
244+ "[MC2_ALG_INFO] rank[%u], group[%s], opType[%s](%u), algName[%s], "
245+ "srcDataType[%s](%u), dstDataType[%s](%u), engine[%u].",
246+ userRank, ccTiling->groupName, GetMc2OpTypeName(opParam.opType), static_cast<uint32_t>(opParam.opType),
247+ opParam.algName, srcDataTypeName.c_str(), static_cast<uint32_t>(srcDataType), dstDataTypeName.c_str(),
248+ static_cast<uint32_t>(dstDataType), static_cast<uint32_t>(opParam.engine));
249+ }
250+ 
251+ return HCCL_SUCCESS;
252+}
253+ 
254+// CCU引擎资源分配流程
255+HcclResult AllocComResourceByTilingCcu(
256+ HcclComm comm, void* stream, void* mc2Tiling, const void* ccTilingList[], uint32_t tilingNum, const char* commName,
257+ u32 rankSize, u32 userRank, void** opResCtx, std::string& ctxTag)
258+{
259+ HCCL_INFO("[AllocComResourceByTilingCcu]start AllocComResourceByTilingCcu!");
260+ std::string topoTag[Hccl::MC2_MAX_OP_NUM];
261+ CHK_RET(BuildTagsAndValidate(ccTilingList, tilingNum, commName, rankSize, userRank, topoTag, ctxTag));
262+ HCCL_INFO("[AllocComResourceByTilingCcu]BuildTagsAndValidate successfully!");
263+ 
264+ // 构建 OpResCtx 基础字段(workspace、XN、CKE等)
265+ OpResCtx resCtx{};
266+ CHK_RET(AllocCcuOpResCtx(comm, ctxTag, rankSize, userRank, resCtx));
267+ HCCL_INFO("[AllocComResourceByTilingCcu]AllocCcuOpResCtx successfully!");
268+ HCCL_INFO(
269+ "[AllocComResourceByTilingCcu]allocated: workspace[%p], size[%llu]", (void*)resCtx.workSpace,
270+ resCtx.workSpaceSize);
271+ 
272+ // 逐算子选择算法 + 资源准备(executor->CalcRes + GetAlgResCcu)
273+ CHK_RET(CcuSelectAlg(comm, stream, topoTag, ccTilingList, tilingNum, mc2Tiling, resCtx));
274+ HCCL_INFO("[AllocComResourceByTilingCcu]CcuSelectAlg successfully!");
275+ 
276+ // 申请OpResCtx硬件内存并写入
277+ std::string tagOpResCtx = ctxTag + "_opResCtx";
278+ uint64_t opResCtxSize = sizeof(OpResCtx);
279+ if (HcclEngineCtxGet(comm, tagOpResCtx.c_str(), COMM_ENGINE_AIV, opResCtx, &opResCtxSize) == HCCL_SUCCESS) {
280+ HCCL_INFO(
281+ "HcclEngineCtxGet success, tagOpResCtx[%s], opResCtxAddr[%p], opResCtxSize[%u]", tagOpResCtx.c_str(),
282+ *opResCtx, opResCtxSize);
283+ } else {
284+ CHK_RET(HcclEngineCtxCreate(comm, tagOpResCtx.c_str(), COMM_ENGINE_AIV, opResCtxSize, opResCtx));
285+ }
286+ aclError aclRet = aclrtMemcpy(*opResCtx, opResCtxSize, &resCtx, opResCtxSize, ACL_MEMCPY_HOST_TO_DEVICE);
287+ HCCL_INFO(
288+ "[CCU_DEBUG] opResCtxPtr=%p, *opResCtx=%p, size=%llu ws=0x%llx wsSize=0x%llx xn=0x%llx cke=0x%llx rankId=%llu "
289+ "rankSize=%llu",
290+ opResCtx, *opResCtx, opResCtxSize, resCtx.workSpace, resCtx.workSpaceSize, resCtx.xnAddr, resCtx.ckeAddr,
291+ resCtx.rankId, resCtx.rankSize);
292+ CHK_RET(aclRet == ACL_ERROR_NONE ? HCCL_SUCCESS : HCCL_E_RUNTIME);
293+ HCCL_INFO("[AllocComResourceByTilingCcu]end AllocComResourceByTilingCcu!");
294+ return HCCL_SUCCESS;
295+}
296+ 
297+namespace {
298+HcclResult HcclAllocComResourceByTilingImpl(HcclComm comm, void* stream, void* mc2Tiling, void** opResCtx)
193{299{
194 HCCL_RUN_INFO(300 HCCL_RUN_INFO(
195- "[MC2_CLIENT_A5_AICPU] enter asc-devkit common HcclAllocComResourceByTiling, "301+ "[MC2_CLIENT_A5] enter asc-devkit common HcclAllocComResourceByTiling, "
196 "comm[%p], stream[%p], tiling[%p].",302 "comm[%p], stream[%p], tiling[%p].",
197 comm, stream, mc2Tiling);303 comm, stream, mc2Tiling);
198- HCCL_INFO("Start to run execute HcclAllocComResourceByTiling");
199 // 记录开始时间,用于性能统计304 // 记录开始时间,用于性能统计
200 HcclUs startut = TIME_NOW();305 HcclUs startut = TIME_NOW();
201 // 获取设备类型306 // 获取设备类型
@@ -227,78 +332,41 @@ HcclResult __attribute__((visibility("default"))) HcclAllocComResourceByTiling(
227 char commName[COMM_INDENTIFIER_MAX_LENGTH];332 char commName[COMM_INDENTIFIER_MAX_LENGTH];
228 CHK_RET(HcclGetCommName(comm, commName));333 CHK_RET(HcclGetCommName(comm, commName));
229 334 
230- const void* ccTilingList[MAX_CC_TILING_NUM];335+ const void* ccTilingList[Hccl::MC2_MAX_OP_NUM];
231 uint32_t tilingNum;336 uint32_t tilingNum;
232 CHK_RET(HcclGetTilingList(mc2Tiling, ccTilingList, tilingNum));337 CHK_RET(HcclGetTilingList(mc2Tiling, ccTilingList, tilingNum));
233 338 
234 // 校验commengine339 // 校验commengine
235- CHK_RET(CheckCommEngine(ccTilingList, tilingNum));340+ uint8_t commEngine;
341+ CHK_RET(ObtainCommEngine(ccTilingList, tilingNum, commEngine));
236 342 
237- // 构造操作标签,用于日志、错误追踪、topo资源管理343+ // 根据commEngine类型分发到对应的资源分配流程
238- // topoTag = ccTilingList->opType + commName
239- // ctxTag = ccTilingList->groupName + "_" + ccTilingList[0]->opType + "_" + ccTilingList[0]->algConfig + "_" +
240- // ccTilingList[0]->commEngine
241- // ctxTag不再统一管理资源,而是根据每个资源opParam、WorkSpace、OpResCtx继续组成tag申请资源
242- std::string topoTag[MAX_CC_TILING_NUM];
243 std::string ctxTag;344 std::string ctxTag;
244- for (uint32_t i = 0U; i < tilingNum; ++i) {345+ if (commEngine == static_cast<uint8_t>(OpExecuteConfig::AICPU_TS)) {
245- const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);346+ HCCL_INFO("[HcclAllocComResourceByTiling]commEngine == AICPU_TS!");
246- topoTag[i] = std::to_string(ccTiling->opType) + "_" + std::to_string(ccTiling->srcDataType) + "_" +347+ CHK_RET(AllocComResourceByTilingAicpu(
247- std::string(commName);348+ comm, stream, mc2Tiling, ccTilingList, tilingNum, commName, rankSize, userRank, opResCtx, ctxTag));
248- // 检查标签的合法性349+ } else if (commEngine == static_cast<uint8_t>(OpExecuteConfig::CCU_SCHED)) {
249- CHK_RET(HcclCheckTag(topoTag[i].c_str()));350+ HCCL_INFO("[HcclAllocComResourceByTiling]commEngine == CCU_SCHED!");
250- // 检查是否为reduce类型351+ CHK_RET(CheckCcuKfcFlow(mc2Tiling, ccTilingList, tilingNum));
251- bool isReduce;352+ CHK_RET(AllocComResourceByTilingCcu(
252- CHK_RET(CheckIsReduce(ccTiling, &isReduce));353+ comm, stream, mc2Tiling, ccTilingList, tilingNum, commName, rankSize, userRank, opResCtx, ctxTag));
253- // 检查数据类型的合法性354+ } else {
254- CHK_RET(CheckDataType(static_cast<HcclDataType>(ccTiling->srcDataType), isReduce));355+ HCCL_ERROR("[%s] unsupported commEngine[%u]", __func__, commEngine);
255- 356+ return HCCL_E_NOT_SUPPORT;
256- if (i == 0) {
257- ctxTag = std::string(ccTiling->groupName) + "_" + std::to_string(ccTiling->opType) + "_" +
258- std::string(ccTiling->algConfig) + "_" + std::to_string(ccTiling->commEngine);
259- } else {
260- ctxTag += "_" + std::to_string(ccTiling->opType) + "_" + std::string(ccTiling->algConfig) + "_" +
261- std::to_string(ccTiling->commEngine);
262- }
263 }357 }
264 358 
265- // TODO:记录接口入口日志,包含所有关键参数信息
266- 
267- // 检查userRank是否在有效范围内
268- CHK_RET(HcomCheckUserRank(rankSize, userRank));
269- 
270- std::vector<OpParam> opParamVec(tilingNum);
271- for (uint32_t i = 0U; i < tilingNum; ++i) {
272- // TODO: 根据topoTag[i] 获取opParam[i]的参数
273- CHK_RET(
274- GetOpParam(comm, stream, topoTag[i], static_cast<const Mc2CcTilingInner*>(ccTilingList[i]), opParamVec[i]));
275- }
276- 
277- // TODO: 根据ctxTag 申请通信资源 ,并返回OpResCtx的地址
278- CHK_RET(HcclAllocOpResCtx(comm, ctxTag, opParamVec, mc2Tiling, ccTilingList, opResCtx));
279- 
280 // 记录退出日志和性能统计信息359 // 记录退出日志和性能统计信息
281 CHK_RET(LogHcclExit("HcclAllocComResourceByTiling", ctxTag.c_str(), startut));360 CHK_RET(LogHcclExit("HcclAllocComResourceByTiling", ctxTag.c_str(), startut));
282- 
283- for (uint32_t i = 0U; i < tilingNum; ++i) {
284- const Mc2CcTilingInner* ccTiling = static_cast<const Mc2CcTilingInner*>(ccTilingList[i]);
285- const OpParam& opParam = opParamVec[i];
286- const HcclDataType srcDataType = static_cast<HcclDataType>(ccTiling->srcDataType);
287- const HcclDataType dstDataType = static_cast<HcclDataType>(ccTiling->dstDataType);
288- const std::string srcDataTypeName = GetDataTypeEnumStr(srcDataType);
289- const std::string dstDataTypeName = GetDataTypeEnumStr(dstDataType);
290- HCCL_RUN_INFO(
291- "[MC2_ALG_INFO] rank[%u], group[%s], opType[%s](%u), algName[%s], "
292- "srcDataType[%s](%u), dstDataType[%s](%u), engine[%u].",
293- userRank, ccTiling->groupName, GetMc2OpTypeName(opParam.opType), static_cast<uint32_t>(opParam.opType),
294- opParam.algName, srcDataTypeName.c_str(), static_cast<uint32_t>(srcDataType), dstDataTypeName.c_str(),
295- static_cast<uint32_t>(dstDataType), static_cast<uint32_t>(opParam.engine));
296- }
297- 
298- HCCL_INFO("End to run execute HcclAllocComResourceByTiling");
299- 
300 return HCCL_SUCCESS;361 return HCCL_SUCCESS;
301}362}
363+} // namespace
364+ 
365+HcclResult __attribute__((visibility("default"))) HcclAllocComResourceByTiling(
366+ HcclComm comm, void* stream, void* mc2Tiling, void** opResCtx)
367+{
368+ return HcclAllocComResourceByTilingImpl(comm, stream, mc2Tiling, opResCtx);
369+}
302 370 
303extern "C" HcclResult __attribute__((visibility("default"))) HcclAllocComResourceByTilingA5Mc2(371extern "C" HcclResult __attribute__((visibility("default"))) HcclAllocComResourceByTilingA5Mc2(
304 HcclComm comm, void* stream, void* mc2Tiling, void** opResCtx)372 HcclComm comm, void* stream, void* mc2Tiling, void** opResCtx)
@@ -307,5 +375,144 @@ extern "C" HcclResult __attribute__((visibility("default"))) HcclAllocComResourc
307 "[MC2_CLIENT_A5_AICPU] enter asc-devkit explicit A5 MC2 resource allocator, "375 "[MC2_CLIENT_A5_AICPU] enter asc-devkit explicit A5 MC2 resource allocator, "
308 "comm[%p], stream[%p], tiling[%p].",376 "comm[%p], stream[%p], tiling[%p].",
309 comm, stream, mc2Tiling);377 comm, stream, mc2Tiling);
310- return HcclAllocComResourceByTiling(comm, stream, mc2Tiling, opResCtx);378+ return HcclAllocComResourceByTilingImpl(comm, stream, mc2Tiling, opResCtx);
379+}
380+ 
381+namespace {
382+CcuResult CopyOpResCtxToHost(void* opResCtx, OpResCtx& opResHost)
383+{
384+ HCCL_INFO("[CcuKernelLaunch]Obtain OpResCtx.");
385+ aclError aclRet = aclrtMemcpy(&opResHost, sizeof(OpResCtx), opResCtx, sizeof(OpResCtx), ACL_MEMCPY_DEVICE_TO_HOST);
386+ CHK_PRT_RET(
387+ aclRet != ACL_SUCCESS,
388+ HCCL_ERROR(
389+ "[CcuKernelLaunch] aclrtMemcpy D2H opResCtx failed, ret[%d], src[%p], size[%zu].", aclRet, opResCtx,
390+ sizeof(OpResCtx)),
391+ CCU_E_INTERNAL);
392+ CHK_PRT_RET(
393+ opResHost.algInfo[0].opParam == 0U,
394+ HCCL_ERROR("invalid ccu op resource ctx, opParam[%llu].", opResHost.algInfo[0].opParam), CCU_E_PARA);
395+ CHK_PRT_RET(
396+ opResHost.workSpace == 0U || opResHost.workSpaceSize == 0U,
397+ HCCL_ERROR(
398+ "invalid ccu op resource ctx, workSpace[%llu], workSpaceSize[%llu].", opResHost.workSpace,
399+ opResHost.workSpaceSize),
400+ CCU_E_PARA);
401+ return CCU_SUCCESS;
402+}
403+ 
404+CcuResult CopyOpParamToHost(const OpResCtx& opResHost, OpParam& opParamHost)
405+{
406+ HCCL_INFO("[CcuKernelLaunch]Obtain OpParam.");
407+ void* opParamDev = reinterpret_cast<void*>(opResHost.algInfo[0].opParam);
408+ aclError aclRet =
409+ aclrtMemcpy(&opParamHost, sizeof(OpParam), opParamDev, sizeof(OpParam), ACL_MEMCPY_DEVICE_TO_HOST);
410+ CHK_PRT_RET(
411+ aclRet != ACL_SUCCESS,
412+ HCCL_ERROR(
413+ "[CcuKernelLaunch] aclrtMemcpy D2H OpParam failed, ret[%d], src[%p], size[%zu].", aclRet, opParamDev,
414+ sizeof(OpParam)),
415+ CCU_E_INTERNAL);
416+ CHK_PRT_RET(
417+ opParamHost.resCtx == nullptr || opParamHost.ctxSize == 0U,
418+ HCCL_ERROR("invalid ccu op resource ctx, resCtx[%p], ctxSize[%llu].", opParamHost.resCtx, opParamHost.ctxSize),
419+ CCU_E_PARA);
420+ return CCU_SUCCESS;
421+}
422+ 
423+CcuResult LoadResourceCtx(const OpParam& opParamHost, AlgResourceCtxSerializable& resourceCtx)
424+{
425+ HCCL_INFO("[CcuKernelLaunch]Obtain resCtx.");
426+ auto* resCtx = static_cast<char*>(opParamHost.resCtx);
427+ std::vector<char> seq(opParamHost.ctxSize);
428+ HCCL_INFO("[CcuKernelLaunch]Start aclrtMemcpy D2H.");
429+ aclError aclRet =
430+ aclrtMemcpy(seq.data(), opParamHost.ctxSize, resCtx, opParamHost.ctxSize, ACL_MEMCPY_DEVICE_TO_HOST);
431+ CHK_PRT_RET(
432+ aclRet != ACL_SUCCESS,
433+ HCCL_ERROR(
434+ "[CcuKernelLaunch] aclrtMemcpy D2H failed, ret[%d], dst[%p], src[%p], size[%llu].", aclRet, seq.data(),
435+ resCtx, opParamHost.ctxSize),
436+ CCU_E_INTERNAL);
437+ HCCL_INFO("[CcuKernelLaunch]Start resourceCtx DeSerialize.");
438+ resourceCtx.DeSerialize(seq);
439+ return CCU_SUCCESS;
440+}
441+ 
442+CcuResult GetLaunchHandles(
443+ const AlgResourceCtxSerializable& resourceCtx, ThreadHandle& threadHandle, CcuKernelHandle& kernelHandle)
444+{
445+ CHK_PRT_RET(resourceCtx.threads.empty(), HCCL_ERROR("empty ccu threads"), CCU_E_PARA);
446+ CHK_PRT_RET(resourceCtx.ccuKernels.empty(), HCCL_ERROR("empty ccu kernels"), CCU_E_PARA);
447+ 
448+ threadHandle = resourceCtx.threads[0];
449+ CHK_PRT_RET(threadHandle == 0, HCCL_ERROR("invalid threadHandle"), CCU_E_PARA);
450+ 
451+ // HcclGetCcuKernel 已根据 isKfc 过滤,isKfc=true 时 ccuKernels[0] 即为 CcuKfcServerKernel
452+ kernelHandle = resourceCtx.ccuKernels[0];
453+ CHK_PRT_RET(kernelHandle == 0, HCCL_ERROR("invalid kernelHandle"), CCU_E_PARA);
454+ CHK_PRT_RET(
455+ resourceCtx.kfcServerArgSize != 0U && resourceCtx.kfcServerArgs.empty(),
456+ HCCL_ERROR("invalid kfcServerArgs, kfcServerArgSize[%u].", resourceCtx.kfcServerArgSize), CCU_E_PTR);
457+ return CCU_SUCCESS;
458+}
459+ 
460+void LogKernelLaunchArgs(
461+ const AlgResourceCtxSerializable& resourceCtx, ThreadHandle threadHandle, CcuKernelHandle kernelHandle)
462+{
463+ if (resourceCtx.kfcServerArgs.size() >= 6U) {
464+ HCCL_INFO(
465+ "[CcuKernelLaunch] HcommCcuKernelLaunch args: "
466+ "threadHandle[0x%llx], kernelHandle[0x%llx], argSize[%u], "
467+ "xnAddr[0x%llx], ckeAddr[0x%llx], dieNum[%llu], missionNum[%llu], "
468+ "missionIndex[%llu], token[%llu]",
469+ static_cast<unsigned long long>(threadHandle), static_cast<unsigned long long>(kernelHandle),
470+ resourceCtx.kfcServerArgSize, static_cast<unsigned long long>(resourceCtx.kfcServerArgs[0]),
471+ static_cast<unsigned long long>(resourceCtx.kfcServerArgs[1]),
472+ static_cast<unsigned long long>(resourceCtx.kfcServerArgs[2]),
473+ static_cast<unsigned long long>(resourceCtx.kfcServerArgs[3]),
474+ static_cast<unsigned long long>(resourceCtx.kfcServerArgs[4]),
475+ static_cast<unsigned long long>(resourceCtx.kfcServerArgs[5]));
476+ } else {
477+ HCCL_INFO(
478+ "[CcuKernelLaunch] HcommCcuKernelLaunch args: "
479+ "threadHandle[0x%llx], kernelHandle[0x%llx], argSize[%u], kfcServerArgsSize[%zu]",
480+ static_cast<unsigned long long>(threadHandle), static_cast<unsigned long long>(kernelHandle),
481+ resourceCtx.kfcServerArgSize, resourceCtx.kfcServerArgs.size());
482+ }
483+}
484+} // namespace
485+ 
486+CcuResult CcuKernelLaunch(HcclComm comm, void* opResCtx)
487+{
488+ CHK_PRT_RET(comm == nullptr, HCCL_ERROR("[%s] comm is nullptr.", __func__), CCU_E_PTR);
489+ CHK_PRT_RET(opResCtx == nullptr, HCCL_ERROR("[%s] opResCtx is nullptr.", __func__), CCU_E_PTR);
490+ 
491+ // HcclEngineCtxCreate分配的OpResCtx、OpParam和序列化资源均位于device,需逐层拷贝到host。
492+ OpResCtx opResHost{};
493+ CcuResult ret = CopyOpResCtxToHost(opResCtx, opResHost);
494+ if (ret != CCU_SUCCESS) {
495+ return ret;
496+ }
497+ OpParam opParamHost{};
498+ ret = CopyOpParamToHost(opResHost, opParamHost);
499+ if (ret != CCU_SUCCESS) {
500+ return ret;
501+ }
502+ AlgResourceCtxSerializable resourceCtx;
503+ ret = LoadResourceCtx(opParamHost, resourceCtx);
504+ if (ret != CCU_SUCCESS) {
505+ return ret;
506+ }
507+ ThreadHandle threadHandle = 0;
508+ CcuKernelHandle kernelHandle = 0;
509+ ret = GetLaunchHandles(resourceCtx, threadHandle, kernelHandle);
510+ if (ret != CCU_SUCCESS) {
511+ return ret;
512+ }
513+ LogKernelLaunchArgs(resourceCtx, threadHandle, kernelHandle);
514+ HCCL_INFO("[CcuKernelLaunch]Start HcommCcuKernelLaunch.");
515+ const void* kfcArgs =
516+ resourceCtx.kfcServerArgs.empty() ? nullptr : static_cast<const void*>(resourceCtx.kfcServerArgs.data());
517+ return HcommCcuKernelLaunch(threadHandle, kernelHandle, kfcArgs, resourceCtx.kfcServerArgSize);
311}518}
@@ -12,10 +12,17 @@ if(BUILD_OPEN_PROJECT)
12 ${HCCL_LOCAL_HEADER_DIRS}12 ${HCCL_LOCAL_HEADER_DIRS}
13 ${HCCL_CC_INCLUDE_DIR}/hcomm13 ${HCCL_CC_INCLUDE_DIR}/hcomm
14 ${HCCL_CC_INCLUDE_DIR}/hcomm/hccl14 ${HCCL_CC_INCLUDE_DIR}/hcomm/hccl
15+ ${HCCL_CC_INCLUDE_DIR}/hcomm/ccu
15 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc/hccl16 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc/hccl
17+ ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc/hcomm/ccu
16 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc18 ${HCCL_CC_INCLUDE_DIR}/hcomm/pkg_inc
17 ${CMAKE_CURRENT_SOURCE_DIR}/..19 ${CMAKE_CURRENT_SOURCE_DIR}/..
20+ ${CMAKE_CURRENT_SOURCE_DIR}/ccu
18 21 
22+ # hcomm头文件
23+ ${ASCEND_CANN_PACKAGE_PATH}/include/ccu
24+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm
25+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm/ccu
19 )26 )
20else()27else()
21 set(INCLUDE_LIST28 set(INCLUDE_LIST
@@ -53,6 +60,7 @@ else()
53 ${TOP_DIR}/hcomm/inc/hccl60 ${TOP_DIR}/hcomm/inc/hccl
54 ${TOP_DIR}/hcomm/pkg_inc61 ${TOP_DIR}/hcomm/pkg_inc
55 ${TOP_DIR}/hcomm/pkg_inc/hccl62 ${TOP_DIR}/hcomm/pkg_inc/hccl
63+ ${TOP_DIR}/hcomm/ccu
56 ${TOP_DIR}/hcomm/pkg_inc/hcomm/ccu64 ${TOP_DIR}/hcomm/pkg_inc/hcomm/ccu
57 ${TOP_DIR}/hcomm/include65 ${TOP_DIR}/hcomm/include
58 ${TOP_DIR}/hcomm/include/hccl66 ${TOP_DIR}/hcomm/include/hccl
@@ -124,6 +132,12 @@ if(PRODUCT_SIDE STREQUAL "host")
124 hcomm_dlsym.cc132 hcomm_dlsym.cc
125 hccl_inner_dl.cc133 hccl_inner_dl.cc
126 hcomm_host_profiling_dl.cc134 hcomm_host_profiling_dl.cc
135+ ccu_primitives_impl_dl.cc
136+ ccu_res_dl.cc
137+ hccl_ccu_res_dl.cc
138+ hccl_res_expt_dl.cc
139+ hccl_host_comm_dl.cc
140+ ccu_launch_dl.cc
127 )141 )
128endif()142endif()
129 143 
@@ -0,0 +1,142 @@
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 CCU_ADDRESS_DL_HPP
12+#define CCU_ADDRESS_DL_HPP
13+ 
14+#if CANN_VERSION_NUM >= 90100000
15+#include "ccu_address.hpp"
16+#else
17+#include <cstdint>
18+#include <type_traits>
19+ 
20+#include "ccu_types_dl.h"
21+#include "ccu_utils_dl.hpp"
22+#include "ccu_primitives_impl_dl.h"
23+#include "ccu_variable_dl.hpp"
24+ 
25+namespace AscendC {
26+namespace ccu {
27+ 
28+class LocalAddr;
29+class RemoteAddr;
30+template <typename U>
31+class Array;
32+ 
33+class Address final {
34+public:
35+ Address() { CCU_THROW_IF_FAILED(CcuAddressAlloc(&this->handle), "CcuAddressAlloc: failed"); }
36+ 
37+ Address(const Address& other) { this->handle = other.handle; }
38+ 
39+ Address(Address&& other) noexcept { this->handle = other.handle; }
40+ 
41+ void operator=(const Address& other) const
42+ {
43+ CCU_THROW_IF_FAILED(
44+ CcuAddressAssignAddr(this->handle, other.handle),
45+ "Address::operator=(Address): CcuAddressAssignAddr failed");
46+ }
47+ 
48+ void operator=(Address&& other) { this->handle = other.handle; }
49+ 
50+ void operator=(uint64_t immediate) const
51+ {
52+ CCU_THROW_IF_FAILED(
53+ CcuAddressAssignImm(this->handle, immediate), "Address::operator=(uint64_t): CcuAddressAssignImm failed");
54+ }
55+ 
56+ void operator=(const Variable& var) const
57+ {
58+ CCU_THROW_IF_FAILED(
59+ CcuAddressAssignVar(this->handle, var.handle), "Address::operator=(Variable): CcuAddressAssignVar failed");
60+ }
61+ 
62+ void operator=(detail::CcuArithmeticOperator<Address, Address> op) const
63+ {
64+ CCU_THROW_IF_FAILED(
65+ CcuAddressAddAddrToAddr(this->handle, op.lhs.handle, op.rhs.handle),
66+ "Address::operator=(Addr+Addr): CcuAddressAddAddrToAddr failed");
67+ }
68+ 
69+ void operator=(detail::CcuArithmeticOperator<Address, Variable> op) const
70+ {
71+ CCU_THROW_IF_FAILED(
72+ CcuAddressAddVarToAddr(this->handle, op.lhs.handle, op.rhs.handle),
73+ "Address::operator=(Addr+Var): CcuAddressAddVarToAddr failed");
74+ }
75+ 
76+ void operator=(detail::CcuArithmeticOperator<Variable, Address> op) const
77+ {
78+ CCU_THROW_IF_FAILED(
79+ CcuAddressAddVarToAddr(this->handle, op.rhs.handle, op.lhs.handle),
80+ "Address::operator=(Var+Addr): CcuAddressAddVarToAddr failed");
81+ }
82+ 
83+ // addr + addr
84+ detail::CcuArithmeticOperator<Address, Address> operator+(const Address& that) const
85+ {
86+ return detail::CcuArithmeticOperator<Address, Address>(
87+ *this, that, detail::CcuArithmeticOperatorType::ADDITION);
88+ }
89+ 
90+ // addr + variable
91+ detail::CcuArithmeticOperator<Address, Variable> operator+(const Variable& var) const
92+ {
93+ return detail::CcuArithmeticOperator<Address, Variable>(
94+ *this, var, detail::CcuArithmeticOperatorType::ADDITION);
95+ }
96+ 
97+ void operator+=(const Variable& var) const
98+ {
99+ CCU_THROW_IF_FAILED(
100+ CcuAddressAddAssignVar(this->handle, var.handle),
101+ "Address::operator+=(Variable): CcuAddressAddAssignVar failed");
102+ }
103+ 
104+ // addr += addr
105+ void operator+=(const Address& other) const
106+ {
107+ CCU_THROW_IF_FAILED(
108+ CcuAddressAddAddrToAddr(this->handle, this->handle, other.handle),
109+ "Address::operator+=(Address): CcuAddressAddAddrToAddr failed");
110+ }
111+ 
112+ CcuAddressHandle handle{0};
113+ 
114+private:
115+ explicit Address(detail::NoAllocTag) {}
116+ template <typename U>
117+ friend class Array;
118+ friend class LocalAddr;
119+ friend class RemoteAddr;
120+};
121+ 
122+// variable + addr(交换律)
123+inline detail::CcuArithmeticOperator<Variable, Address> operator+(const Variable& var, const Address& addr)
124+{
125+ return detail::CcuArithmeticOperator<Variable, Address>(var, addr, detail::CcuArithmeticOperatorType::ADDITION);
126+}
127+ 
128+} // namespace ccu
129+} // namespace AscendC
130+ 
131+template <>
132+inline void AscendC::ccu::detail::CcuArithmeticOperator<AscendC::ccu::Address, AscendC::ccu::Address>::Check() const
133+{}
134+template <>
135+inline void AscendC::ccu::detail::CcuArithmeticOperator<AscendC::ccu::Address, AscendC::ccu::Variable>::Check() const
136+{}
137+template <>
138+inline void AscendC::ccu::detail::CcuArithmeticOperator<AscendC::ccu::Variable, AscendC::ccu::Address>::Check() const
139+{}
140+#endif // CANN_VERSION_NUM >= 90100000
141+ 
142+#endif // CCU_ADDRESS_DL_HPP
@@ -0,0 +1,136 @@
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 CCU_ARRAY_DL_HPP
12+#define CCU_ARRAY_DL_HPP
13+ 
14+#if CANN_VERSION_NUM >= 90100000
15+#include "ccu_array.hpp"
16+#else
17+#include <cstdint>
18+#include <new>
19+#include <vector>
20+ 
21+#include "ccu_types_dl.h"
22+#include "ccu_primitives_impl_dl.h"
23+#include "ccu_utils_dl.hpp"
24+#include "ccu_variable_dl.hpp"
25+#include "ccu_event_dl.hpp"
26+#include "ccu_buffer_dl.hpp"
27+ 
28+namespace AscendC {
29+namespace ccu {
30+ 
31+// 主模板未实现:未特化的资源类型实例化 Array<T> 时编译失败,
32+// 当前期次仅 Variable / Event / Buffer 提供底层 CcuBlock*Alloc C 接口。
33+template <typename T>
34+struct CcuArrayTraits;
35+ 
36+template <>
37+struct CcuArrayTraits<Variable> {
38+ using Handle = CcuVariableHandle;
39+ static CcuResult BlockAlloc(Handle* h, uint32_t n) { return CcuBlockVariableAlloc(h, n); }
40+ static void SetHandle(Variable& v, Handle h) { v.handle = h; }
41+};
42+ 
43+template <>
44+struct CcuArrayTraits<Event> {
45+ using Handle = CcuEventHandle;
46+ static CcuResult BlockAlloc(Handle* h, uint32_t n) { return CcuBlockEventAlloc(h, n); }
47+ static void SetHandle(Event& e, Handle h) { e.handle = h; }
48+};
49+ 
50+template <>
51+struct CcuArrayTraits<CcuBuffer> {
52+ using Handle = CcuBufferHandle;
53+ static CcuResult BlockAlloc(Handle* h, uint32_t n) { return CcuBlockBufferAlloc(h, n); }
54+ static void SetHandle(CcuBuffer& b, Handle h) { b.handle = h; }
55+};
56+ 
57+// 连续资源容器:在构造时一次性 BlockAlloc 出 count 个底层句柄并填充给占位元素。
58+// 元素本身通过 NoAllocTag 私有构造跳过单元 Alloc,避免与 BlockAlloc 双重分配。
59+template <typename T>
60+class Array final {
61+public:
62+ explicit Array(uint32_t count) : count_(count)
63+ {
64+ if (count == 0) {
65+ return;
66+ }
67+ using H = typename CcuArrayTraits<T>::Handle;
68+ std::vector<H> handles(count);
69+ elems_ = static_cast<T*>(::operator new(sizeof(T) * count));
70+ for (uint32_t i = 0; i < count; ++i) {
71+ ::new (static_cast<void*>(&elems_[i])) T(detail::NoAllocTag{});
72+ }
73+ auto ret = CcuArrayTraits<T>::BlockAlloc(handles.data(), count);
74+ if (ret != CcuResult::CCU_SUCCESS) {
75+ for (uint32_t i = 0; i < count; ++i) {
76+ elems_[i].~T();
77+ }
78+ ::operator delete(elems_);
79+ elems_ = nullptr;
80+ count_ = 0;
81+ throw ::AscendC::ccu::detail::CcuException(ret, "Array BlockAlloc: failed");
82+ }
83+ for (uint32_t i = 0; i < count; ++i) {
84+ CcuArrayTraits<T>::SetHandle(elems_[i], handles[i]);
85+ }
86+ }
87+ 
88+ ~Array()
89+ {
90+ if (elems_ == nullptr) {
91+ return;
92+ }
93+ for (uint32_t i = 0; i < count_; ++i) {
94+ elems_[i].~T();
95+ }
96+ ::operator delete(elems_);
97+ }
98+ 
99+ Array(const Array&) = delete;
100+ Array& operator=(const Array&) = delete;
101+ 
102+ Array(Array&& other) noexcept : elems_(other.elems_), count_(other.count_)
103+ {
104+ other.elems_ = nullptr;
105+ other.count_ = 0;
106+ }
107+ 
108+ Array& operator=(Array&& other) noexcept
109+ {
110+ if (this != &other) {
111+ this->~Array();
112+ elems_ = other.elems_;
113+ count_ = other.count_;
114+ other.elems_ = nullptr;
115+ other.count_ = 0;
116+ }
117+ return *this;
118+ }
119+ 
120+ T& operator[](uint32_t i) { return elems_[i]; }
121+ const T& operator[](uint32_t i) const { return elems_[i]; }
122+ T* data() { return elems_; }
123+ const T* data() const { return elems_; }
124+ uint32_t size() const { return count_; }
125+ 
126+private:
127+ T* elems_{nullptr};
128+ uint32_t count_{0};
129+};
130+ 
131+} // namespace ccu
132+} // namespace AscendC
133+ 
134+#endif // CANN_VERSION_NUM >= 90100000
135+ 
136+#endif // CCU_ARRAY_DL_HPP
@@ -0,0 +1,52 @@
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 CCU_BUFFER_DL_HPP
12+#define CCU_BUFFER_DL_HPP
13+ 
14+#if CANN_VERSION_NUM >= 90100000
15+#include "ccu_buffer.hpp"
16+#else
17+#include <cstdint>
18+#include <type_traits>
19+#include "ccu_types_dl.h"
20+#include "ccu_primitives_impl_dl.h"
21+#include "ccu_utils_dl.hpp"
22+ 
23+namespace AscendC {
24+namespace ccu {
25+ 
26+template <typename U>
27+class Array;
28+ 
29+class CcuBuffer final {
30+public:
31+ CcuBuffer() { CCU_THROW_IF_FAILED(CcuBufferAlloc(&this->handle), "CcuBufferAlloc: failed"); }
32+ 
33+ CcuBuffer(const CcuBuffer& other) { this->handle = other.handle; }
34+ 
35+ CcuBuffer(CcuBuffer&& other) noexcept { this->handle = other.handle; }
36+ 
37+ void operator=(CcuBuffer&& other) { this->handle = other.handle; }
38+ 
39+ CcuBufferHandle handle{0};
40+ 
41+private:
42+ explicit CcuBuffer(detail::NoAllocTag) {}
43+ template <typename U>
44+ friend class Array;
45+};
46+ 
47+} // namespace ccu
48+} // namespace AscendC
49+ 
50+#endif // CANN_VERSION_NUM >= 90100000
51+ 
52+#endif // CCU_BUFFER_DL_HPP
@@ -0,0 +1,77 @@
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 CCU_CONTROL_FLOW_MACRO_DL_H
12+#define CCU_CONTROL_FLOW_MACRO_DL_H
13+ 
14+#if CANN_VERSION_NUM >= 90100000
15+#include "ccu_control_flow_macro.h"
16+#else
17+#include "ccu_variable_dl.hpp"
18+#include "ccu_primitives_impl_dl.h"
19+ 
20+#define CCU_CONCAT_INNER(a, b) a##b
21+#define CCU_CONCAT(a, b) CCU_CONCAT_INNER(a, b)
22+#define CCU_STRINGIFY_INNER(x) #x
23+#define CCU_STRINGIFY(x) CCU_STRINGIFY_INNER(x)
24+ 
25+#define CCU_LABEL(uid) (__FILE__ ":" CCU_STRINGIFY(__LINE__) ":" CCU_STRINGIFY(uid))
26+ 
27+#define CCU_WHILE(expr) CCU_WHILE_EXPAND(expr, CCU_CONCAT(__ccu_wh_, __COUNTER__))
28+ 
29+#define CCU_WHILE_EXPAND(expr, uid) CCU_WHILE_IMPL(expr, uid)
30+ 
31+#define CCU_WHILE_IMPL(expr, uid) \
32+ for (::AscendC::ccu::CondExpr uid##_ce = (expr), *uid##_p = &uid##_ce; uid##_p != nullptr; uid##_p = nullptr) \
33+ for (const char *uid##_dwLbl = _CcuDoWhileStackPopForWhile(), *uid##_sen = (const char*)1; \
34+ uid##_sen != nullptr; uid##_sen = nullptr) \
35+ for (int uid##_rc = \
36+ (uid##_dwLbl != nullptr) ? \
37+ (int)CCU_SUCCESS : \
38+ (int)CcuWhileBegin(uid##_ce.var->handle, uid##_ce.imm, uid##_ce.cond, CCU_LABEL(uid)), \
39+ uid##_done = 0; \
40+ uid##_rc == (int)CCU_SUCCESS && !uid##_done; \
41+ uid##_done = 1, uid##_rc = (uid##_dwLbl != nullptr) ? \
42+ (int)CcuDoWhileEnd( \
43+ uid##_ce.var->handle, uid##_ce.imm, uid##_ce.cond, uid##_dwLbl) : \
44+ (int)CcuWhileEnd(CCU_LABEL(uid)))
45+ 
46+#define CCU_IF(expr) CCU_IF_EXPAND(expr, CCU_CONCAT(__ccu_if_, __COUNTER__))
47+ 
48+#define CCU_IF_EXPAND(expr, uid) CCU_IF_IMPL(expr, uid)
49+ 
50+#define CCU_IF_IMPL(expr, uid) \
51+ for (::AscendC::ccu::CondExpr uid##_ce = (expr), *uid##_p = &uid##_ce; uid##_p != nullptr; uid##_p = nullptr) \
52+ for (int uid##_rc = (int)CcuIfBegin(uid##_ce.var->handle, uid##_ce.imm, uid##_ce.cond, CCU_LABEL(uid)), \
53+ uid##_done = (_CcuIfStackPush(CCU_LABEL(uid)), 0); \
54+ uid##_rc == (int)CCU_SUCCESS && uid##_done == 0; \
55+ uid##_done = 1, ((void)CcuFlushPendingIfs(), _CcuIfStackMarkBodyDone(), (void)0))
56+ 
57+#define CCU_ELSE CCU_ELSE_EXPAND(CCU_CONCAT(__ccu_el_, __COUNTER__))
58+ 
59+#define CCU_ELSE_EXPAND(uid) CCU_ELSE_IMPL(uid)
60+ 
61+#define CCU_ELSE_IMPL(uid) \
62+ for (const char *uid##_lbl = _CcuIfStackPopForElse(), *uid##_sen = uid##_lbl; uid##_sen != nullptr; \
63+ uid##_sen = nullptr) \
64+ for (int uid##_rc = (int)CcuIfElse(uid##_lbl), uid##_done = 0; uid##_rc == (int)CCU_SUCCESS && !uid##_done; \
65+ uid##_done = 1, uid##_rc = (int)CcuIfEnd(uid##_lbl))
66+ 
67+#define CCU_DO CCU_DO_EXPAND(CCU_CONCAT(__ccu_dw_, __COUNTER__))
68+ 
69+#define CCU_DO_EXPAND(uid) CCU_DO_IMPL(uid)
70+ 
71+#define CCU_DO_IMPL(uid) \
72+ for (int uid##_rc = (int)CcuDoWhileBegin(CCU_LABEL(uid)), uid##_done = 0; \
73+ uid##_rc == (int)CCU_SUCCESS && !uid##_done; uid##_done = 1, _CcuDoWhileStackPush(CCU_LABEL(uid)))
74+ 
75+#endif // CANN_VERSION_NUM >= 90100000
76+ 
77+#endif // CCU_CONTROL_FLOW_MACRO_DL_H
@@ -0,0 +1,55 @@
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 CCU_EVENT_DL_HPP
12+#define CCU_EVENT_DL_HPP
13+ 
14+#if CANN_VERSION_NUM >= 90100000
15+#include "ccu_event.hpp"
16+#else
17+#include <cstdint>
18+#include <type_traits>
19+ 
20+#include "ccu_types_dl.h"
21+#include "ccu_primitives_impl_dl.h"
22+#include "ccu_utils_dl.hpp"
23+ 
24+namespace AscendC {
25+namespace ccu {
26+ 
27+template <typename U>
28+class Array;
29+ 
30+// Event 退化为纯 handle 持有者:mask 已与 Event 解耦,
31+// 由调用方在每个 EventRecord/Wait/LocalCopy/Read/Write/... API 上独立传入。
32+// 旧的 EventMask 代理类、Event::mask 字段、Event::setMask 接口已废弃删除。
33+class Event final {
34+public:
35+ Event() { CCU_THROW_IF_FAILED(CcuEventAlloc(&this->handle), "CcuEventAlloc: failed"); }
36+ 
37+ Event(const Event& other) : handle(other.handle) {}
38+ 
39+ Event(Event&& other) noexcept : handle(other.handle) {}
40+ 
41+ void operator=(Event&& other) { this->handle = other.handle; }
42+ 
43+ CcuEventHandle handle{0};
44+ 
45+private:
46+ explicit Event(detail::NoAllocTag) {}
47+ template <typename U>
48+ friend class Array;
49+};
50+ 
51+} // namespace ccu
52+} // namespace AscendC
53+ 
54+#endif // CANN_VERSION_NUM >= 90100000
55+#endif // CCU_EVENT_DL_HPP