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 <ios>
12 : #include <iostream>
13 :
14 : #include "log.h"
15 :
16 : #include "ccu_instruction_reduce_scatter_mesh2d_mem2mem.h"
17 : #include "ccu_rank_group.h"
18 : #include "ccu_ctx_creator_registry.h"
19 : #include "ccu_ins_group.h"
20 : #include "ccu_context_reduce_scatter_mesh2d_mem2mem.h"
21 : #include "ccu_temp_reduce_scatter_mesh_2D_mem2mem.h"
22 :
23 : namespace Hccl {
24 : constexpr u32 MESH_2D_DIMENSION_NUM = 2;
25 :
26 : static CcuInstRegister<CcuContextReduceScatterMeshMem2Mem2D>
27 : g_registrarReduceScatterMeshMem2Mem2D(CcuInstType::CCU_REDUCE_SCATTER_MESH_2D_MEM2MEM);
28 :
29 0 : CcuTempReduceScatterMeshMem2Mem2D::CcuTempReduceScatterMeshMem2Mem2D(
30 : const RankId virtualRank, const u32 tempRankSize, const std::vector<std::vector<RankId>>& tempVTopo,
31 0 : const std::map<RankId, u32>& tempVirtRankMap)
32 0 : : CcuAlgTemplateBase(virtualRank, tempRankSize, tempVTopo, tempVirtRankMap)
33 : {
34 0 : if (tempVTopo_.size() != MESH_2D_DIMENSION_NUM || tempVTopo_[0].size() <= 1
35 0 : || tempVTopo_[1].size() <= 1) { // concurrmesh的topoMatch返回的vTopo大小应当为2,对应X轴和Y轴的大小
36 0 : THROW<InvalidParamsException>(StringFormat(
37 : "[CcuTempReducescatterMeshMem2Mem2D] Rank[%d], Invalid tempVTopo "
38 : "Size[%u] or Invalid tempVTopo[0] size [%u] or tempVTopo[1] size [%u].",
39 0 : myRank_, tempVTopo_.size(), tempVTopo_[0].size(), tempVTopo_[1].size()));
40 : }
41 0 : dimSize_.emplace_back(tempVTopo[0].size());
42 0 : dimSize_.emplace_back(tempVTopo[1].size());
43 0 : }
44 :
45 0 : CcuTempReduceScatterMeshMem2Mem2D::~CcuTempReduceScatterMeshMem2Mem2D() {}
46 :
47 0 : void CcuTempReduceScatterMeshMem2Mem2D::InitReduceInfo(const ReduceOp& reduceOp, const DataType& dataType)
48 : {
49 0 : reduceOp_ = reduceOp;
50 0 : dataType_ = dataType;
51 0 : }
52 :
53 0 : HcclResult CcuTempReduceScatterMeshMem2Mem2D::CalcSliceInfo(
54 : const AllignInfo& allignInfo, const u64 dataSize, RankSliceInfo& sliceInfoVec)
55 : {
56 0 : std::vector<SliceInfo> tmp(tempVTopo_.size());
57 0 : sliceInfoVec.resize(tempRankSize_, tmp);
58 0 : CHK_RET(CalcRsAgSliceInfoMesh(myRank_, tempRankSize_, allignInfo, dataSize, sliceInfoVec));
59 0 : return HcclResult::HCCL_SUCCESS;
60 0 : }
61 :
62 0 : HcclResult CcuTempReduceScatterMeshMem2Mem2D::CalcRes(AlgTempResReq& tempResReq)
63 : {
64 : // 按照IODienum来确定stream数量,支持2D和2D的template
65 0 : tempResReq.queNum = 1; // 只申请一个insQue,填充一个insGroup,由框架将其中的ins放在多个stream上
66 0 : tempResReq.streamNum = tempResReq.queNum + 1; // 多申请一个stream给ccuInsGroup
67 0 : uint32_t dieNum = tempVTopo_.size();
68 0 : if (dieNum != 2) { // concurrmesh的topoMatch返回的vTopo大小应当为2,对应X轴和Y轴的大小
69 0 : HCCL_ERROR("[CcuTempReduceScatterMeshMem2Mem2D] Rank[%d], Invalid IODieNum[%zu].", myRank_, tempVTopo_.size());
70 0 : return HcclResult::HCCL_E_PARA;
71 : }
72 0 : HCCL_INFO(
73 : "[CcuTempReduceScatterMeshMem2Mem2D] Rank[%d] requiredQueNum[%u] VtopoSize[%u], VtopoSize0[%u] VtopoSize1[%u].",
74 : myRank_, tempResReq.queNum, tempVTopo_.size(), tempVTopo_[0].size(), tempVTopo_[1].size());
75 :
76 : uint32_t myAlgRank;
77 0 : for (u32 dim = 0; dim < tempVTopo_.size(); dim++) {
78 0 : CHK_RET(GetAlgRank(myRank_, tempVTopo_[dim], myAlgRank));
79 0 : for (u32 queIdx = 0; queIdx < tempVTopo_[dim].size() - 1; queIdx++) {
80 : // find neighbors -> virtualRank
81 0 : u32 neighborAlgRank = (myAlgRank + 1 + queIdx) % (tempVTopo_[dim].size());
82 0 : RankId neighborRank = tempVTopo_[dim][neighborAlgRank];
83 0 : HCCL_INFO(
84 : "[CollAlgFactory] [CcuTempReducescatterMeshMem2Mem2D] Rank[%d], Dim[%u], NeighborRank[%d].", myRank_,
85 : dim, neighborRank);
86 :
87 : // LinkNum
88 0 : tempResReq.links[neighborRank] = 1;
89 : }
90 : }
91 0 : return HcclResult::HCCL_SUCCESS;
92 : }
93 :
94 0 : HcclResult CcuTempReduceScatterMeshMem2Mem2D::Run(
95 : const TempFuncs& tempFuncs, const RankSliceInfo& sliceInfoVec, const BuffInfo& buffInfo, const ResLinks& tempLinks,
96 : std::vector<InsQuePtr>& tempInsQues)
97 : {
98 0 : opMode_ = tempFuncs.opMode;
99 0 : buffInfo_ = buffInfo;
100 :
101 : // 分别记录两个Die上的link,构造rankGroup
102 0 : for (auto& pair : tempLinks) {
103 0 : if (pair.second.size() == 0 || pair.second[0].GetHop() != 1) {
104 0 : THROW<InvalidParamsException>(StringFormat(
105 0 : "[CcuTempAlltoAllMeshMem2Mem2D] Rank[%d]--Peer[%d], InvalidHop[%u].", myRank_, pair.first,
106 0 : pair.second[0].GetHop()));
107 : }
108 0 : if ((pair.first / dimSize_[0] == myRank_ / dimSize_[0]) && pair.second[0].GetHop() == 1) {
109 0 : HCCL_INFO(
110 : "[CcuTempReduceScatterMeshMem2Mem2D][Run] Rank[%d] insert link to Rank[%d] in linksX", myRank_,
111 : pair.first);
112 0 : linksX_.emplace_back(pair.second[0]);
113 0 : } else if ((pair.first % dimSize_[0] == myRank_ % dimSize_[0]) && pair.second[0].GetHop() == 1) {
114 0 : HCCL_INFO(
115 : "[CcuTempReduceScatterMeshMem2Mem2D][Run] Rank[%d] insert link to Rank[%d] in linksY", myRank_,
116 : pair.first);
117 0 : linksY_.emplace_back(pair.second[0]);
118 : } else {
119 0 : THROW<InvalidParamsException>(StringFormat(
120 0 : "[CcuTempAlltoAllMeshMem2Mem2D] Rank[%d], Unexpected peerRank[%d] in tempLinks.", myRank_, pair.first));
121 : }
122 : }
123 :
124 0 : RankGroup rankGroupX;
125 0 : RankGroup rankGroupY;
126 0 : AddRanksToGroup(tempVTopo_, rankGroupX, rankGroupY);
127 :
128 : uint64_t inputAddr;
129 : uint64_t outputAddr;
130 : uint64_t offset;
131 0 : uint64_t outputSize = static_cast<uint64_t>(op_.outputMem->GetSize());
132 0 : if (opMode_ == OpMode::OPBASE) {
133 0 : if (tempFuncs.isForepart) {
134 0 : inputAddr = BufferTypeToAddr(tempFuncs.usrData.usrInSlices[myRank_].GetType());
135 : // 当前loop的size大小
136 0 : offset = tempFuncs.usrData.usrOutSlices[0].GetOffset();
137 : } else {
138 0 : inputAddr = BufferTypeToAddr(buffInfo_.inBuffType) + buffInfo_.inBuffBaseOff;
139 : // 从inBuff获取数据,只需要加上rank偏移
140 0 : offset = sliceInfoVec[myRank_][0].offset;
141 : }
142 0 : if (tempFuncs.isBottom) {
143 0 : outputAddr = BufferTypeToAddr(tempFuncs.usrData.usrOutSlices[0].GetType())
144 0 : + tempFuncs.usrData.usrOutSlices[0].GetOffset();
145 : } else {
146 0 : outputAddr = BufferTypeToAddr(buffInfo_.outBuffType) + buffInfo_.outBuffBaseOff;
147 : }
148 : } else {
149 0 : inputAddr = BufferTypeToAddr(buffInfo_.inBuffType) + buffInfo_.inBuffBaseOff;
150 0 : outputAddr = BufferTypeToAddr(buffInfo_.outBuffType) + buffInfo_.outBuffBaseOff
151 0 : + tempFuncs.usrData.usrOutSlices[0].GetOffset();
152 0 : offset = tempFuncs.usrData.usrOutSlices[0].GetOffset();
153 : }
154 0 : uint64_t sliceSize = sliceInfoVec[myRank_][0].size; // 获取本rank需要处理的数据量
155 :
156 : uint64_t token;
157 0 : CHK_RET(GetToken(op_, token));
158 :
159 0 : std::unique_ptr<CcuInsGroup> insGroupPtr = std::make_unique<CcuInsGroup>();
160 :
161 0 : for (uint32_t axisId = 0; axisId < 2; axisId++) { // 2D算法需要执行两次
162 : // 计算每次编译的偏移量和数据量
163 0 : uint64_t sliceCount = sliceSize / DataTypeSizeGet(dataType_);
164 : uint64_t xAxisSize
165 0 : = (sliceCount * dimSize_[0] / (dimSize_[axisId] + dimSize_[1 - axisId])) * DataTypeSizeGet(dataType_);
166 0 : uint64_t yAxisSize = sliceSize - xAxisSize;
167 :
168 0 : CcuInstructionReduceScatterMeshMem2Mem2D ccuInsReduceScatterMeshMem2Mem2D;
169 :
170 0 : ccuInsReduceScatterMeshMem2Mem2D.Init(
171 0 : dimSize_, static_cast<uint32_t>(myRank_), inputAddr, outputAddr, axisId, outputSize, xAxisSize, yAxisSize,
172 0 : offset, token, op_, tempVTopo_);
173 :
174 0 : HCCL_INFO(
175 : "[CcuTempReduceScatterMeshMem2Mem2D] Init: dimSize0[%llu], dimSize1[%llu], myRank_[%d], inputAddr[%llu],"
176 : "outputAddr[%llu], sliceSize[%llu], xAxisSize[%llu], yAxisSize[%llu], offset[%llu],",
177 : dimSize_[0], dimSize_[1], myRank_, inputAddr, outputAddr, outputSize, xAxisSize, yAxisSize, offset);
178 :
179 0 : ccuInsReduceScatterMeshMem2Mem2D.SetLinks(axisId == 0 ? linksX_ : linksY_);
180 0 : ccuInsReduceScatterMeshMem2Mem2D.SetRankGroup(axisId == 0 ? rankGroupX : rankGroupY);
181 0 : u32 ckeNum = 5;
182 0 : ccuInsReduceScatterMeshMem2Mem2D.SetCntCkeNum(ckeNum); // 每个transport使用4个CKE
183 0 : ccuInsReduceScatterMeshMem2Mem2D.Describe();
184 0 : insGroupPtr->Append(
185 0 : std::move(std::make_unique<CcuInstructionReduceScatterMeshMem2Mem2D>(ccuInsReduceScatterMeshMem2Mem2D)));
186 0 : }
187 0 : tempInsQues[0]->Append(std::move(insGroupPtr)); // 只有1条流
188 0 : return HcclResult::HCCL_SUCCESS;
189 0 : }
190 : } // namespace Hccl
|