Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "reduce_operator.h"
12 :
13 : namespace hccl {
14 :
15 1 : ReduceOperator::ReduceOperator(
16 : AlgConfigurator* algConfigurator, CCLBufferManager& cclBufferManager, HcclDispatcher dispatcher,
17 1 : std::unique_ptr<TopoMatcher>& topoMatcher)
18 1 : : CollAlgOperator(algConfigurator, cclBufferManager, dispatcher, topoMatcher, HcclCMDType::HCCL_CMD_REDUCE)
19 : {
20 3 : if (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR || algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR_V1
21 3 : || algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NB
22 3 : || algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_PIPELINE) {
23 0 : HCCL_WARNING("[ReduceOperator][ReduceOperator] nonuniform-hierachical-ring and nonuniform-bruck and pipeline "
24 : "algorithms do not support Reduce yet, reset algo to halving-doubling");
25 0 : algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_HD;
26 : }
27 3 : }
28 :
29 8 : ReduceOperator::~ReduceOperator() {}
30 :
31 : HcclResult
32 4 : ReduceOperator::SelectAlg(const std::string& tag, const OpParam& param, std::string& algName, std::string& newTag)
33 : {
34 4 : HcclResult ret = HCCL_SUCCESS;
35 :
36 4 : if (userRankSize_ == 1) {
37 0 : algName = "ReduceSingleExecutor";
38 0 : HCCL_INFO("[SelectAlg] Reduce SelectAlg is algName [%s]", algName.c_str());
39 0 : return HCCL_SUCCESS;
40 : }
41 :
42 4 : newTag = param.tag;
43 4 : if (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE
44 4 : && (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD
45 0 : || algType_.algoLevel2 == AlgTypeLevel2::ALG_LEVEL2_HD)) {
46 4 : std::string appendTag = "";
47 4 : u32 serverNumPerSuperPod = superPodNum_ == 0 ? moduleNum_ : moduleNum_ / superPodNum_;
48 4 : HCCL_DEBUG("[ReduceOperator][SelectAlg]serverNumPerSuperPod is %u", serverNumPerSuperPod);
49 4 : if (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD) {
50 4 : u32 part1Size = FACTOR_TWO * (serverNumPerSuperPod - (1 << static_cast<u32>(log2(serverNumPerSuperPod))));
51 4 : u32 rootId = param.root / deviceNumPerAggregation_ % serverNumPerSuperPod;
52 4 : appendTag += "L1_" + std::to_string((rootId >= part1Size) || ((rootId % FACTOR_TWO) == 0));
53 : }
54 4 : HCCL_DEBUG("[ReduceOperator]SelectAlg for algoLevel1");
55 4 : if (algType_.algoLevel2 == AlgTypeLevel2::ALG_LEVEL2_HD) {
56 0 : u32 part1Size = FACTOR_TWO * (superPodNum_ - (1 << static_cast<u32>(log2(superPodNum_))));
57 0 : u32 rootId = param.root / deviceNumPerAggregation_ / serverNumPerSuperPod;
58 0 : appendTag += (appendTag.empty() ? "L2_" : "_L2_")
59 0 : + std::to_string((rootId >= part1Size) || ((rootId % FACTOR_TWO) == 0));
60 : }
61 4 : HCCL_DEBUG("[ReduceOperator][SelectAlg]tag is [%s]", tag.c_str());
62 4 : newTag = newTag + '_' + appendTag;
63 4 : if (GetExternalInputHcclEnableEntryLog() && param.opBaseAtraceInfo != nullptr) {
64 0 : CHK_RET(param.opBaseAtraceInfo->SavealgtypeTraceInfo(appendTag, param.tag));
65 : }
66 3 : }
67 :
68 4 : if (isDiffDeviceType_) {
69 0 : HCCL_ERROR("[ReduceOperator][SelectAlg] Reduce not support diffDeviceType");
70 0 : return HCCL_E_NOT_SUPPORT;
71 4 : } else if (deviceType_ == DevType::DEV_TYPE_910) {
72 0 : ret = SelectAlgfor910A(param, algName);
73 4 : } else if (deviceType_ == DevType::DEV_TYPE_910B) {
74 4 : ret = SelectAlgfor910B(param, algName);
75 0 : } else if (deviceType_ == DevType::DEV_TYPE_910_93) {
76 0 : ret = SelectAlgfor91093(param, algName);
77 : } else {
78 0 : HCCL_ERROR("ReduceOperator[SelectAlg] device type[%d] is out of range for selector.", deviceType_);
79 0 : return HCCL_E_NOT_SUPPORT;
80 : }
81 4 : CHK_PRT_RET(
82 : ret != HCCL_SUCCESS,
83 : HCCL_ERROR("[ReduceSelector][SelectAlg]tag[%s], reduce failed, return[%d]", tag.c_str(), ret), ret);
84 :
85 4 : if (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
86 4 : auto level1Iter = HCCL_ALGO_LEVEL1_NAME_MAP.find(algType_.algoLevel1);
87 3 : CHK_PRT_RET(
88 : level1Iter == HCCL_ALGO_LEVEL1_NAME_MAP.end(),
89 : HCCL_ERROR("level1: algType1[%u] is invalid.", algType_.algoLevel1), HCCL_E_INTERNAL);
90 3 : newTag = newTag + level1Iter->second + algName;
91 : }
92 3 : newTag += (param.aicpuUnfoldMode ? "_device" : "_host");
93 3 : return ret;
94 : }
95 :
96 0 : HcclResult ReduceOperator::SelectAlgfor910A(const OpParam& param, std::string& algName)
97 : {
98 : (void)param;
99 0 : bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_4P_MESH || topoType_ == TopoType::TOPO_TYPE_2P_MESH;
100 0 : bool isRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING || topoType_ == TopoType::TOPO_TYPE_8P_RING;
101 :
102 0 : if (isMeshTopo) {
103 0 : algName = "ReduceMeshExecutor";
104 0 : } else if (isRingTopo) {
105 0 : algName = "ReduceRingPlusHd";
106 : } else {
107 0 : algName = "ReduceComm";
108 : }
109 :
110 0 : HCCL_INFO("[SelectAlgfor910A] reduce SelectAlgfor910A is algName[%s].", algName.c_str());
111 0 : return HCCL_SUCCESS;
112 : }
113 :
114 4 : HcclResult ReduceOperator::SelectAlgfor910B(const OpParam& param, std::string& algName)
115 : {
116 : (void)param;
117 0 : bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_NP_MESH || topoType_ == TopoType::TOPO_TYPE_4P_MESH
118 4 : || topoType_ == TopoType::TOPO_TYPE_2P_MESH || topoType_ == TopoType::TOPO_TYPE_1P_MESH;
119 4 : bool isRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING;
120 :
121 4 : if (isMeshTopo) {
122 4 : algName = "ReduceMeshExecutor";
123 0 : } else if (isRingTopo) {
124 0 : algName = "ReduceRingPlusHd";
125 : } else {
126 0 : algName = "ReduceComm";
127 : }
128 :
129 4 : HCCL_INFO("[SelectAlgfor910B] reduce SelectAlgfor910B is algName [%s].", algName.c_str());
130 4 : return HCCL_SUCCESS;
131 : }
132 :
133 0 : HcclResult ReduceOperator::SelectAlgfor91093(const OpParam& param, std::string& algName)
134 : {
135 0 : bool isRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING;
136 0 : bool isDoubleRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_DOUBLE_RING;
137 0 : u32 unitSize = SIZE_TABLE[param.DataDes.dataType];
138 0 : u64 dataSize = param.DataDes.count * unitSize; // 单位:字节
139 0 : if (dataSize >= cclBufferManager_.GetInCCLbufferSize()) {
140 0 : HCCL_WARNING(
141 : "The current inCCLbufferSize is [%llu] bytes, change the HCCL_BUFFSIZE environment variable "
142 : "to be greater than the current data volume[%llu] bytes to improve the performance of the 91093 "
143 : "environment.",
144 : cclBufferManager_.GetInCCLbufferSize(), dataSize);
145 : }
146 :
147 0 : if (multiModuleDiffDeviceNumMode_ || multiSuperPodDiffServerNumMode_) {
148 0 : algName = "ReduceComm";
149 0 : } else if (isRingTopo || isDoubleRingTopo) {
150 0 : algName = "ReduceRingFor91093Executor";
151 : } else {
152 0 : algName = "ReduceComm";
153 : }
154 0 : if ((!(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_RING)
155 0 : && !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD))
156 0 : || (!(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD) && topoMatcher_->GetTopoInfo().superPodNum > 1)
157 0 : || !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING)) {
158 0 : algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_RING;
159 0 : HCCL_WARNING("[ReduceOperator][SelectAlgfor91093][Superpod] inter-server only support ring yet, "
160 : "default is algType=RING.");
161 : }
162 0 : HCCL_INFO("[SelectAlgfor91093] reduce SelectAlgfor91093 is algName [%s].", algName.c_str());
163 0 : return HCCL_SUCCESS;
164 : }
165 :
166 : REGISTER_OP(HcclCMDType::HCCL_CMD_REDUCE, Reduce, ReduceOperator);
167 :
168 : } // namespace hccl
|