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 "coll_operator.h"
12 : #include <string>
13 : #include <unordered_map>
14 : #include <algorithm>
15 : #include <functional>
16 : #include "op_type.h"
17 : #include "string_util.h"
18 : #include "binary_stream.h"
19 : namespace Hccl {
20 : constexpr u32 MAX_OP_TAG_LEN = 191; // 最大的tag 长度
21 : constexpr u32 MAX_HANDSHAKEMSGPACK_LEN = 1024; // 最大握手消息长度
22 :
23 42 : std::string MemBufferDesc(const BaseCollOperator& collOp)
24 : {
25 42 : std::string memDesc = "";
26 84 : memDesc += "inputMem=" + (collOp.inputMem ? collOp.inputMem->Describe() : "nullptr") + ", ";
27 84 : memDesc += "outputMem=" + (collOp.outputMem ? collOp.outputMem->Describe() : "nullptr") + ", ";
28 84 : memDesc += "scratchMem=" + (collOp.scratchMem ? collOp.scratchMem->Describe() : "nullptr");
29 42 : return memDesc;
30 0 : }
31 :
32 36 : std::string OpDesc(const BaseCollOperator& collOp)
33 : {
34 36 : std::string opDesc = "";
35 36 : opDesc += "opType=" + collOp.opType.Describe() + ", ";
36 36 : opDesc += "opMode=" + collOp.opMode.Describe() + ", ";
37 36 : opDesc += "dataType=" + collOp.dataType.Describe() + ", ";
38 36 : opDesc += "sendRecvRemoteRank=" + std::to_string(collOp.sendRecvRemoteRank) + ", ";
39 36 : opDesc += "Buffers=[" + MemBufferDesc(collOp) + "]";
40 36 : return opDesc;
41 0 : }
42 :
43 2 : std::string DescReduceScatter(const BaseCollOperator& collOp)
44 : {
45 : return StringFormat(
46 4 : "BaseCollOperator[%s, reduceOp=%s, dataCount=%llu]", OpDesc(collOp).c_str(), collOp.reduceOp.Describe().c_str(),
47 6 : collOp.dataCount);
48 : }
49 :
50 24 : std::string DescAllreduce(const BaseCollOperator& collOp)
51 : {
52 : return StringFormat(
53 48 : "BaseCollOperator[%s, reduceOp=%s, dataCount=%llu]", OpDesc(collOp).c_str(), collOp.reduceOp.Describe().c_str(),
54 72 : collOp.dataCount);
55 : }
56 :
57 2 : std::string DescAllgather(const BaseCollOperator& collOp)
58 : {
59 2 : return StringFormat("BaseCollOperator[%s, dataCount=%llu]", OpDesc(collOp).c_str(), collOp.dataCount);
60 : }
61 :
62 2 : std::string DescScatter(const BaseCollOperator& collOp)
63 : {
64 : return StringFormat(
65 2 : "BaseCollOperator[%s, dataCount=%llu, root=%u]", OpDesc(collOp).c_str(), collOp.dataCount, collOp.root);
66 : }
67 :
68 2 : std::string DescAlltoall(const BaseCollOperator& collOp)
69 : {
70 : return StringFormat(
71 : "BaseCollOperator[opType=%s, opMode=%s, sendCount=%llu, recvCount=%llu, sendType=%s, recvType=%s, "
72 : "sendRecvRemoteRank=%u, Buffers=[%s]]",
73 4 : collOp.opType.Describe().c_str(), collOp.opMode.Describe().c_str(), collOp.all2AllDataDes.sendCount,
74 6 : collOp.all2AllDataDes.recvCount, collOp.all2AllDataDes.sendType.Describe().c_str(),
75 10 : collOp.all2AllDataDes.recvType.Describe().c_str(), collOp.sendRecvRemoteRank, MemBufferDesc(collOp).c_str());
76 : }
77 :
78 2 : std::string DescAlltoallV(const BaseCollOperator& collOp)
79 : {
80 : return StringFormat(
81 : "BaseCollOperator[opType=%s, opMode=%s, sendType=%s, recvType=%s, sendRecvRemoteRank=%u, Buffers=[%s]]",
82 6 : collOp.opType.Describe().c_str(), collOp.opMode.Describe().c_str(),
83 4 : collOp.all2AllVDataDes.sendType.Describe().c_str(), collOp.all2AllVDataDes.recvType.Describe().c_str(),
84 10 : collOp.sendRecvRemoteRank, MemBufferDesc(collOp).c_str());
85 : }
86 :
87 2 : std::string DescAlltoallVC(const BaseCollOperator& collOp)
88 : {
89 : return StringFormat(
90 : "BaseCollOperator[opType=%s, opMode=%s, sendType=%s, recvType=%s, sendRecvRemoteRank=%u, Buffers=[%s]]",
91 6 : collOp.opType.Describe().c_str(), collOp.opMode.Describe().c_str(),
92 4 : collOp.all2AllVCDataDes.sendType.Describe().c_str(), collOp.all2AllVCDataDes.recvType.Describe().c_str(),
93 10 : collOp.sendRecvRemoteRank, MemBufferDesc(collOp).c_str());
94 : }
95 :
96 2 : std::string DescSend(const BaseCollOperator& collOp)
97 : {
98 2 : return StringFormat("BaseCollOperator[%s]", OpDesc(collOp).c_str());
99 : }
100 :
101 2 : std::string DescRecv(const BaseCollOperator& collOp)
102 : {
103 2 : return StringFormat("BaseCollOperator[%s]", OpDesc(collOp).c_str());
104 : }
105 :
106 2 : std::string DescReduce(const BaseCollOperator& collOp)
107 : {
108 : return StringFormat(
109 4 : "BaseCollOperator[%s, reduceOp=%s, dataCount=%llu, root=%u]", OpDesc(collOp).c_str(),
110 6 : collOp.reduceOp.Describe().c_str(), collOp.dataCount, collOp.root);
111 : }
112 :
113 0 : std::string DescBroadcast(const BaseCollOperator& collOp)
114 : {
115 : return StringFormat(
116 0 : "BaseCollOperator[%s, dataCount=%llu, root=%u]", OpDesc(collOp).c_str(), collOp.dataCount, collOp.root);
117 : }
118 :
119 0 : std::string DescBatchSendRecv(const BaseCollOperator& collOp)
120 : {
121 : return StringFormat(
122 0 : "BaseCollOperator[%s, dataCount=%llu, root=%u]", OpDesc(collOp).c_str(), collOp.dataCount, collOp.root);
123 : }
124 :
125 0 : std::string DescHalfAlltoAllV(const BaseCollOperator& collOp)
126 : {
127 0 : return StringFormat("BaseCollOperator[%s]", OpDesc(collOp).c_str());
128 : }
129 :
130 0 : std::string DescReduceScatterV(const BaseCollOperator& collOp)
131 : {
132 0 : return StringFormat("BaseCollOperator[%s]", OpDesc(collOp).c_str());
133 : }
134 :
135 0 : std::string DescAllGatherV(const BaseCollOperator& collOp)
136 : {
137 0 : return StringFormat("BaseCollOperator[%s]", OpDesc(collOp).c_str());
138 : }
139 :
140 : std::unordered_map<OpType, std::function<std::string(const BaseCollOperator&)>, std::EnumClassHash> descOpMap{
141 : {OpType::REDUCESCATTER, std::bind(&DescReduceScatter, std::placeholders::_1)},
142 : {OpType::ALLREDUCE, std::bind(&DescAllreduce, std::placeholders::_1)},
143 : {OpType::ALLGATHER, std::bind(&DescAllgather, std::placeholders::_1)},
144 : {OpType::SCATTER, std::bind(&DescScatter, std::placeholders::_1)},
145 : {OpType::ALLTOALL, std::bind(&DescAlltoall, std::placeholders::_1)},
146 : {OpType::ALLTOALLV, std::bind(&DescAlltoallV, std::placeholders::_1)},
147 : {OpType::ALLTOALLVC, std::bind(&DescAlltoallVC, std::placeholders::_1)},
148 : {OpType::SEND, std::bind(&DescSend, std::placeholders::_1)},
149 : {OpType::RECV, std::bind(&DescRecv, std::placeholders::_1)},
150 : {OpType::REDUCE, std::bind(&DescReduce, std::placeholders::_1)},
151 : {OpType::BROADCAST, std::bind(&DescBroadcast, std::placeholders::_1)},
152 : {OpType::BATCHSENDRECV, std::bind(&DescBatchSendRecv, std::placeholders::_1)},
153 : {OpType::HALFALLTOALLV, std::bind(&DescHalfAlltoAllV, std::placeholders::_1)},
154 : {OpType::REDUCESCATTERV, std::bind(&DescReduceScatterV, std::placeholders::_1)},
155 : {OpType::ALLGATHERV, std::bind(&DescAllGatherV, std::placeholders::_1)},
156 : };
157 :
158 43 : std::string CollOpToString(const BaseCollOperator& collOp)
159 : {
160 43 : auto it = descOpMap.find(collOp.opType);
161 43 : if (it != descOpMap.end()) {
162 42 : return it->second.operator()(collOp);
163 : } else {
164 2 : return "unknown";
165 : }
166 : }
167 :
168 26 : inline std::vector<char> DumpByteVector(BinaryStream& binaryStream)
169 : {
170 26 : std::vector<char> byteVector;
171 26 : binaryStream.Dump(byteVector);
172 :
173 26 : auto remainLen = MAX_HANDSHAKEMSGPACK_LEN - byteVector.size();
174 26 : byteVector.insert(byteVector.end(), remainLen, '\0');
175 :
176 26 : return byteVector;
177 0 : }
178 :
179 26 : std::vector<char> opTagToVector(const std::string& opTag)
180 : {
181 26 : std::vector<char> result(MAX_OP_TAG_LEN, '\0');
182 26 : auto copyLen = opTag.size() < MAX_OP_TAG_LEN ? opTag.size() : MAX_OP_TAG_LEN;
183 26 : std::copy_n(opTag.begin(), copyLen, result.begin());
184 :
185 26 : return result;
186 0 : }
187 :
188 7 : std::string vectorToOpTag(const std::vector<char>& opTagvector)
189 : {
190 7 : auto validSize = opTagvector.size() < MAX_OP_TAG_LEN ? opTagvector.size() : MAX_OP_TAG_LEN;
191 7 : auto firstNul = std::find(opTagvector.begin(), opTagvector.begin() + validSize, '\0');
192 :
193 14 : return std::string(opTagvector.begin(), firstNul);
194 : }
195 :
196 26 : std::vector<char> CollOperator::GetUniqueId() const
197 : {
198 78 : HCCL_INFO(
199 : "[CollOperator::%s] opMode[%s], opType[%s], reduceOp[%s], dataType[%s], dataCount[%llu], root[%u], "
200 : "myRank[%d], sendRecvRemoteRank[%d], opTag[%s], staticAddr[%d], staticShape[%d], outputDataType[%s], ",
201 : __func__, opMode.Describe().c_str(), opType.Describe().c_str(), reduceOp.Describe().c_str(),
202 : dataType.Describe().c_str(), dataCount, root, myRank, sendRecvRemoteRank, opTag.c_str(), staticAddr,
203 : staticShape, outputDataType.Describe().c_str());
204 26 : BinaryStream binaryStream;
205 26 : binaryStream << opMode;
206 26 : binaryStream << opType;
207 26 : binaryStream << reduceOp;
208 26 : binaryStream << dataType;
209 26 : binaryStream << dataCount;
210 26 : binaryStream << root;
211 26 : binaryStream << myRank;
212 26 : binaryStream << sendRecvRemoteRank;
213 26 : binaryStream << opTagToVector(opTag);
214 26 : binaryStream << staticAddr;
215 26 : binaryStream << staticShape;
216 26 : binaryStream << outputDataType;
217 :
218 26 : if (opType == OpType::BATCHSENDRECV) {
219 0 : return DumpByteVector(binaryStream);
220 : }
221 :
222 26 : if (opType == OpType::ALLTOALL) {
223 2 : binaryStream << all2AllDataDes.sendType;
224 2 : binaryStream << all2AllDataDes.recvType;
225 2 : binaryStream << all2AllDataDes.sendCount;
226 2 : binaryStream << all2AllDataDes.recvCount;
227 2 : return DumpByteVector(binaryStream);
228 : }
229 :
230 24 : if (opType == OpType::ALLTOALLV) {
231 2 : binaryStream << all2AllVDataDes.sendType;
232 2 : binaryStream << all2AllVDataDes.recvType;
233 2 : return DumpByteVector(binaryStream);
234 : }
235 :
236 22 : if (opType == OpType::ALLTOALLVC) {
237 1 : binaryStream << all2AllVCDataDes.sendType;
238 1 : binaryStream << all2AllVCDataDes.recvType;
239 1 : return DumpByteVector(binaryStream);
240 : }
241 :
242 21 : if (opType == OpType::ALLGATHERV || opType == OpType::REDUCESCATTERV) {
243 2 : binaryStream << vDataDes.dataType;
244 2 : return DumpByteVector(binaryStream);
245 : }
246 :
247 19 : binaryStream << dataDes.dataCount;
248 19 : binaryStream << dataDes.dataType;
249 19 : binaryStream << dataDes.strideCount;
250 :
251 19 : return DumpByteVector(binaryStream);
252 26 : }
253 :
254 7 : CollOperatorDef CollOperator::GetPackedData(std::vector<char>& byteVector)
255 : {
256 7 : CollOperator op;
257 7 : BinaryStream binaryStream(byteVector);
258 7 : std::vector<char> vectorOpTag;
259 7 : binaryStream >> op.opMode;
260 7 : binaryStream >> op.opType;
261 7 : binaryStream >> op.reduceOp;
262 7 : binaryStream >> op.dataType;
263 7 : binaryStream >> op.dataCount;
264 7 : binaryStream >> op.root;
265 7 : binaryStream >> op.myRank;
266 7 : binaryStream >> op.sendRecvRemoteRank;
267 7 : binaryStream >> vectorOpTag;
268 7 : binaryStream >> op.staticAddr;
269 7 : binaryStream >> op.staticShape;
270 7 : binaryStream >> op.outputDataType;
271 :
272 7 : op.opTag = vectorToOpTag(vectorOpTag);
273 :
274 7 : if (op.opType == OpType::BATCHSENDRECV) {
275 0 : return op;
276 : }
277 :
278 7 : if (op.opType == OpType::ALLTOALL) {
279 1 : binaryStream >> op.all2AllDataDes.sendType;
280 1 : binaryStream >> op.all2AllDataDes.recvType;
281 1 : binaryStream >> op.all2AllDataDes.sendCount;
282 1 : binaryStream >> op.all2AllDataDes.recvCount;
283 1 : return op;
284 : }
285 :
286 6 : if (op.opType == OpType::ALLTOALLV) {
287 1 : binaryStream >> op.all2AllVDataDes.sendType;
288 1 : binaryStream >> op.all2AllVDataDes.recvType;
289 1 : return op;
290 : }
291 :
292 5 : if (op.opType == OpType::ALLTOALLVC) {
293 1 : binaryStream >> op.all2AllVCDataDes.sendType;
294 1 : binaryStream >> op.all2AllVCDataDes.recvType;
295 1 : return op;
296 : }
297 :
298 4 : if (op.opType == OpType::ALLGATHERV || op.opType == OpType::REDUCESCATTERV) {
299 1 : binaryStream >> op.vDataDes.dataType;
300 1 : return op;
301 : }
302 :
303 3 : binaryStream >> op.dataDes.dataCount;
304 3 : binaryStream >> op.dataDes.dataType;
305 3 : binaryStream >> op.dataDes.strideCount;
306 :
307 3 : return op;
308 7 : }
309 : } // namespace Hccl
|