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 <cstdint>
12 : #include <cstdlib>
13 :
14 : #include "op_unfold_cache_entry.h"
15 :
16 : #include "aicpu_hccl_sqcq.h"
17 : #include "aicpu_hccl_sqcqv1.h"
18 : #include "aicpu_hccl_sqcqv2.h"
19 : #include "dispatcher_pub.h" // HCCL_SDMA_MAX_COUNT_4GB
20 : #include "log.h"
21 : #include "sal.h"
22 :
23 : namespace hccl {
24 :
25 : // struct OpUnfoldMemRange
26 :
27 0 : OpUnfoldMemRange::OpUnfoldMemRange() : isValid(false), baseAddr(0), memSize(0) {}
28 :
29 0 : OpUnfoldMemRange::OpUnfoldMemRange(const uint64_t curBaseAddr, const uint64_t curMemSize)
30 0 : : isValid(true),
31 0 : baseAddr(curBaseAddr),
32 0 : memSize(curMemSize)
33 : {
34 : // 检查地址有效性
35 0 : CHK_PRT_CONT(curBaseAddr == 0, HCCL_ERROR("[OpUnfoldMemRange][OpUnfoldMemRange] curBaseAddr is 0"));
36 0 : }
37 :
38 0 : OpUnfoldMemRange::OpUnfoldMemRange(const OpUnfoldMemRange& other)
39 0 : : isValid(other.isValid),
40 0 : baseAddr(other.baseAddr),
41 0 : memSize(other.memSize)
42 0 : {}
43 :
44 0 : OpUnfoldMemRange::~OpUnfoldMemRange() {}
45 :
46 0 : const OpUnfoldMemRange& OpUnfoldMemRange::operator=(const OpUnfoldMemRange& other)
47 : {
48 0 : if (this != &other) {
49 0 : isValid = other.isValid;
50 0 : baseAddr = other.baseAddr;
51 0 : memSize = other.memSize;
52 : }
53 0 : return *this;
54 : }
55 :
56 0 : HcclResult OpUnfoldMemRange::GetEndAddr(uint64_t& endAddr) const
57 : {
58 : // 检查地址是否溢出
59 0 : CHK_PRT_RET(
60 : baseAddr + memSize < baseAddr,
61 : HCCL_ERROR("[OpUnfoldMemRange][InRange] baseAddr[0x%016llx] + memSize[%llu] overflows", baseAddr, memSize),
62 : HCCL_E_INTERNAL);
63 :
64 0 : endAddr = baseAddr + memSize;
65 0 : return HCCL_SUCCESS;
66 : }
67 :
68 0 : HcclResult OpUnfoldMemRange::InRange(const uint64_t addr, bool& isInRange) const
69 : {
70 0 : uint64_t endAddr = 0;
71 0 : CHK_RET(GetEndAddr(endAddr));
72 :
73 0 : if (isValid && addr >= baseAddr && addr < endAddr) {
74 0 : isInRange = true;
75 : } else {
76 0 : isInRange = false;
77 : }
78 :
79 0 : return HCCL_SUCCESS;
80 : }
81 :
82 : // struct RefreshAddrInfo
83 :
84 0 : RefreshAddrInfo::RefreshAddrInfo() : rankId(INVALID_VALUE_RANKID), memType(RefreshAddrInfo::INVALID_MEMTYPE) {}
85 :
86 0 : RefreshAddrInfo::RefreshAddrInfo(const uint32_t curRankId, const uint8_t curMemType)
87 0 : : rankId(curRankId),
88 0 : memType(curMemType)
89 : {
90 : // 注意: rankId可以为INVALID_VALUE_RANKID, 表示访问本地rank
91 0 : CHK_PRT_CONT(memType == INVALID_MEMTYPE, HCCL_ERROR("[RefreshAddrInfo][RefreshAddrInfo] invalid memType"));
92 0 : }
93 :
94 0 : RefreshAddrInfo::RefreshAddrInfo(const RefreshAddrInfo& other) : rankId(other.rankId), memType(other.memType) {}
95 :
96 0 : RefreshAddrInfo::~RefreshAddrInfo() {}
97 :
98 0 : const RefreshAddrInfo& RefreshAddrInfo::operator=(const RefreshAddrInfo& other)
99 : {
100 0 : if (this != &other) {
101 0 : rankId = other.rankId;
102 0 : memType = other.memType;
103 : }
104 0 : return *this;
105 : }
106 :
107 : // struct AlltoallvMetadata
108 :
109 33 : AlltoallvMetadata::AlltoallvMetadata()
110 : {
111 33 : sdmaDataBlockSize = 0;
112 33 : hcclInputMemRanges.clear();
113 33 : notifyIdRankRflagMap.clear();
114 33 : signalAddrRankRflagMap.clear();
115 :
116 33 : hcclOffsetDstRanksIdxMap.clear();
117 33 : }
118 :
119 0 : void AlltoallvMetadata::Clear()
120 : {
121 0 : sdmaDataBlockSize = 0;
122 0 : hcclInputMemRanges.clear();
123 0 : notifyIdRankRflagMap.clear();
124 0 : signalAddrRankRflagMap.clear();
125 0 : hcclOffsetDstRanksIdxMap.clear();
126 0 : return;
127 : }
128 :
129 0 : HcclResult AlltoallvMetadata::Check(const bool afterFirstOrch) const
130 : {
131 0 : CHK_PRT_RET(
132 : sdmaDataBlockSize == 0, HCCL_ERROR("[AlltoallvMetadata][Check] sdmaDataBlockSize is zero"), HCCL_E_INTERNAL);
133 :
134 0 : const uint32_t rankSize = hcclInputMemRanges.size();
135 0 : CHK_PRT_RET(rankSize == 0, HCCL_ERROR("[AlltoallvMetadata][Check] empty hcclInputMemRanges"), HCCL_E_INTERNAL);
136 : // 注意: 每个remote rank各有两个NotifyId/SignalAddr分别用于send/recv count对应的Wait/Record同步
137 0 : CHK_PRT_RET(
138 : notifyIdRankRflagMap.size() != 2 * (rankSize - 1),
139 : HCCL_ERROR(
140 : "[AlltoallvMetadata][Check] notifyIdRankRflagMap.size[%u] != rankSize-1[%u]", notifyIdRankRflagMap.size(),
141 : 2 * (rankSize - 1)),
142 : HCCL_E_INTERNAL);
143 0 : CHK_PRT_RET(
144 : signalAddrRankRflagMap.size() != 2 * (rankSize - 1),
145 : HCCL_ERROR(
146 : "[AlltoallvMetadata][Check] signalAddrRankRflagMap.size[%u] != rankSize-1[%u]",
147 : signalAddrRankRflagMap.size(), 2 * (rankSize - 1)),
148 : HCCL_E_INTERNAL);
149 :
150 : // 注意: 只有在第一次cache miss的executor->Orchestrate之后, 相关mapping才会被初始化
151 0 : if (afterFirstOrch) {
152 0 : CHK_PRT_RET(
153 : ((rankSize > 1) && (hcclOffsetDstRanksIdxMap.size() == 0)),
154 : HCCL_ERROR("[AlltoallvMetadata][Check] empty hcclOffsetDstRanksIdxMap for rankSize[%u]", rankSize),
155 : HCCL_E_INTERNAL); // 注意: 只有当rankSize为1时, hcclOffsetDstRanksIdxMap的size才可以是0
156 : }
157 :
158 0 : return HCCL_SUCCESS;
159 : }
160 :
161 : // struct AlltoallvSendRecvInfo
162 :
163 0 : AlltoallvSendRecvInfo::AlltoallvSendRecvInfo()
164 : {
165 0 : sendType = HcclDataType::HCCL_DATA_TYPE_RESERVED;
166 0 : recvType = HcclDataType::HCCL_DATA_TYPE_RESERVED;
167 0 : sendCounts.clear();
168 0 : recvCounts.clear();
169 0 : sendOffsets.clear();
170 0 : recvOffsets.clear();
171 :
172 0 : return;
173 : }
174 :
175 0 : HcclResult AlltoallvSendRecvInfo::Check() const
176 : {
177 0 : CHK_PRT_RET(
178 : sendType == HcclDataType::HCCL_DATA_TYPE_RESERVED,
179 : HCCL_ERROR("[AlltoallvSendRecvInfo][Check] sendType is reserved"), HCCL_E_INTERNAL);
180 0 : CHK_PRT_RET(
181 : recvType == HcclDataType::HCCL_DATA_TYPE_RESERVED,
182 : HCCL_ERROR("[AlltoallvSendRecvInfo][Check] recvType is reserved"), HCCL_E_INTERNAL);
183 :
184 0 : const uint32_t rankSize = sendCounts.size();
185 0 : CHK_PRT_RET(rankSize == 0, HCCL_ERROR("[AlltoallvSendRecvInfo][Check] empty sendCounts"), HCCL_E_INTERNAL);
186 0 : CHK_PRT_RET(
187 : recvCounts.size() != rankSize,
188 : HCCL_ERROR("[AlltoallvSendRecvInfo][Check] recvCounts.size[%u] != rankSize[%u]", recvCounts.size(), rankSize),
189 : HCCL_E_INTERNAL);
190 0 : CHK_PRT_RET(
191 : sendOffsets.size() != rankSize,
192 : HCCL_ERROR("[AlltoallvSendRecvInfo][Check] sendOffsets.size[%u] != rankSize[%u]", sendOffsets.size(), rankSize),
193 : HCCL_E_INTERNAL);
194 0 : CHK_PRT_RET(
195 : recvOffsets.size() != rankSize,
196 : HCCL_ERROR("[AlltoallvSendRecvInfo][Check] recvOffsets.size[%u] != rankSize[%u]", recvOffsets.size(), rankSize),
197 : HCCL_E_INTERNAL);
198 :
199 0 : return HCCL_SUCCESS;
200 : }
201 :
202 : // class OpUnfoldCacheEntry
203 :
204 0 : OpUnfoldCacheEntry::OpUnfoldCacheEntry(
205 0 : const std::vector<OpUnfoldMemRange>& userInputMemRanges, const std::vector<OpUnfoldMemRange>& userOutputMemRanges)
206 0 : : userInputMemRanges_(userInputMemRanges),
207 0 : userOutputMemRanges_(userOutputMemRanges)
208 : {
209 0 : HCCL_INFO(
210 : "[OpUnfoldCacheEntry][OpUnfoldCacheEntry] create a cache entry with %llu userInputMemRanges and %llu "
211 : "userOutputMemRanges",
212 : userInputMemRanges_.size(), userOutputMemRanges_.size());
213 0 : }
214 :
215 0 : OpUnfoldCacheEntry::~OpUnfoldCacheEntry()
216 : {
217 0 : size_t sqeArrayCount = sqeArrays_.size();
218 0 : size_t totalSqeCount = 0;
219 0 : for (size_t arrayIdx = 0; arrayIdx < sqeArrayCount; ++arrayIdx) {
220 0 : totalSqeCount += srcRefreshAddrInfoArrays_[arrayIdx].size();
221 :
222 : // 如果存在当前这段连续的SQE数组,则指向内容必不为空
223 : // 因为SQE数量为0时, DispatcherAicpu::LaunchTask()会直接返回, 不会添加SQE到OpUnfoldCache中
224 0 : uint8_t* curSqeArray = sqeArrays_[arrayIdx];
225 :
226 : // 释放当前SQE数组
227 0 : if (UNLIKELY(curSqeArray == nullptr)) { // 不能使用CHK_PTR_NULL,因为会return HcclResult
228 0 : HCCL_ERROR("[OpUnfoldCacheEntry][~OpUnfoldCacheEntry] curSqeArray is nullptr");
229 : } else {
230 0 : free(curSqeArray);
231 0 : curSqeArray = nullptr;
232 : }
233 :
234 : // 同理释放其他空间
235 :
236 : // 释放当前SQE type数组
237 0 : uint8_t* curSqeTypeArray = sqeTypeArrays_[arrayIdx];
238 0 : if (UNLIKELY(curSqeTypeArray == nullptr)) {
239 0 : HCCL_ERROR("[OpUnfoldCacheEntry][~OpUnfoldCacheEntry] curSqeTypeArray is nullptr");
240 : } else {
241 0 : free(curSqeTypeArray);
242 0 : curSqeTypeArray = nullptr;
243 : }
244 :
245 : // 释放当前SQE DfxInfo数组
246 0 : AicpuDfxInfo* curSqeDfxInfoArray = sqeDfxInfoArrays_[arrayIdx];
247 0 : if (UNLIKELY(curSqeDfxInfoArray == nullptr)) {
248 0 : HCCL_ERROR("[OpUnfoldCacheEntry][~OpUnfoldCacheEntry] curSqeDfxInfoArray is nullptr");
249 : } else {
250 0 : free(curSqeDfxInfoArray);
251 0 : curSqeDfxInfoArray = nullptr;
252 : }
253 : }
254 :
255 0 : HCCL_INFO(
256 : "[OpUnfoldCacheEntry][~OpUnfoldCacheEntry] release %u SQE arrays (%u SQEs in total) from the cache entry",
257 : sqeArrayCount, totalSqeCount);
258 0 : }
259 :
260 0 : HcclResult OpUnfoldCacheEntry::GetSqeArrayCount(size_t& sqeArrayCount) const
261 : {
262 0 : sqeArrayCount = sqeArrays_.size();
263 0 : CHK_PRT_RET(
264 : sqeArrayCount == 0, HCCL_ERROR("[OpUnfoldCacheEntry][OpUnfoldCacheEntry] sqeArrayCount is 0"), HCCL_E_INTERNAL);
265 0 : return HCCL_SUCCESS;
266 : }
267 :
268 0 : HcclResult OpUnfoldCacheEntry::AllocSqeArray(const size_t sqeCount, const int32_t streamId, size_t& arrayIdx)
269 : {
270 : // Allocate a new SQE array
271 0 : const size_t sqeBytes = sqeCount * HCCL_SQE_SIZE;
272 0 : uint8_t* newSqeArray = reinterpret_cast<uint8_t*>(malloc(sqeBytes));
273 0 : CHK_PTR_NULL(newSqeArray);
274 0 : sqeArrays_.emplace_back(newSqeArray);
275 :
276 : // Allocate a new SQE type array
277 0 : const size_t sqeTypeBytes = sqeCount * sizeof(uint8_t);
278 0 : uint8_t* newSqeTypeArray = reinterpret_cast<uint8_t*>(malloc(sqeTypeBytes));
279 0 : CHK_PTR_NULL(newSqeTypeArray);
280 0 : sqeTypeArrays_.emplace_back(newSqeTypeArray);
281 :
282 : // Allocate a new SQE DFX info array
283 0 : const size_t sqeDfxInfoBytes = sqeCount * sizeof(AicpuDfxInfo);
284 0 : AicpuDfxInfo* newSqeDfxInfoArray = reinterpret_cast<AicpuDfxInfo*>(malloc(sqeDfxInfoBytes));
285 0 : CHK_PTR_NULL(newSqeDfxInfoArray);
286 0 : sqeDfxInfoArrays_.emplace_back(newSqeDfxInfoArray);
287 :
288 : // Copy stream pointer
289 0 : CHK_PRT_RET(
290 : streamId < 0, HCCL_ERROR("[OpUnfoldCacheEntry][AllocSqeArray] streamId %d < 0", streamId), HCCL_E_INTERNAL);
291 0 : streamIds_.emplace_back(streamId);
292 :
293 : // 注意: streamSeqIdxes_在cache miss LaunchTask()结束后, HcclCommAicpu通过CalcStreamSeqIdxes更新
294 :
295 : // 初始化src/dst RefreshAddrInfo
296 0 : srcRefreshAddrInfoArrays_.emplace_back(sqeCount);
297 0 : dstRefreshAddrInfoArrays_.emplace_back(sqeCount);
298 :
299 : // Set index of allocated array
300 0 : arrayIdx = sqeArrays_.size() - 1;
301 :
302 0 : HCCL_INFO(
303 : "[OpUnfoldCacheEntry][AllocSqeArray] allocate %uth sqe array with sqeCount of %u and streamId of %d", arrayIdx,
304 : sqeCount, streamId);
305 :
306 0 : return HCCL_SUCCESS;
307 : }
308 :
309 0 : HcclResult OpUnfoldCacheEntry::MemcpySqeArray(
310 : const size_t arrayIdx, const size_t sqeStartIdx, const size_t sqeCount, const uint8_t* sqeArray,
311 : const uint8_t* sqeTypeArray, const AicpuDfxInfo* sqeDfxInfoArray, const bool isAlltoallv,
312 : const AlltoallvMetadata* alltoallvMetadataPtr)
313 : {
314 : // Copy sqeArray[0:sqeCount) -> sqeArrays_[arrayIdx][sqeStartIdx:sqeStartIdx+sqeCount)
315 :
316 : // 检验入参
317 0 : CHK_PRT_RET(
318 : arrayIdx >= sqeArrays_.size(),
319 : HCCL_ERROR(
320 : "[OpUnfoldCacheEntry][MemcpySqeArray] arrayIdx %u is out of range [0, %u)", arrayIdx, sqeArrays_.size()),
321 : HCCL_E_INTERNAL);
322 0 : const size_t totalSqeCount = srcRefreshAddrInfoArrays_[arrayIdx].size();
323 0 : CHK_PRT_RET(
324 : sqeStartIdx + sqeCount - 1 >= totalSqeCount,
325 : HCCL_ERROR(
326 : "[OpUnfoldCacheEntry][MemcpySqeArray] sqeStartIdx %u + sqeCount %u - 1 is out of range [0, %u)",
327 : sqeStartIdx, sqeCount, totalSqeCount),
328 : HCCL_E_INTERNAL);
329 0 : CHK_PTR_NULL(sqeArray);
330 0 : CHK_PTR_NULL(sqeTypeArray);
331 0 : CHK_PTR_NULL(sqeDfxInfoArray);
332 0 : if (isAlltoallv) {
333 0 : CHK_PTR_NULL(alltoallvMetadataPtr);
334 0 : CHK_RET(alltoallvMetadataPtr->Check(false));
335 : }
336 :
337 0 : HCCL_INFO(
338 : "[OpUnfoldCacheEntry][MemcpySqeArray] memcpy %uth sqe array[%u:%u]; isAlltoallv[%u]", arrayIdx, sqeStartIdx,
339 : sqeStartIdx + sqeCount - 1, isAlltoallv);
340 :
341 : // Copy SQE content
342 0 : const size_t sqeBytes = sqeCount * HCCL_SQE_SIZE;
343 0 : uint8_t* dstSqeArray = sqeArrays_[arrayIdx];
344 0 : CHK_PTR_NULL(dstSqeArray);
345 0 : CHK_SAFETY_FUNC_RET(memcpy_s(
346 : dstSqeArray + sqeStartIdx * HCCL_SQE_SIZE, (totalSqeCount - sqeStartIdx) * HCCL_SQE_SIZE, sqeArray, sqeBytes));
347 :
348 : // Copy SQE type
349 0 : const size_t sqeTypeBytes = sqeCount * sizeof(uint8_t);
350 0 : uint8_t* dstSqeTypeArray = sqeTypeArrays_[arrayIdx];
351 0 : CHK_PTR_NULL(dstSqeTypeArray);
352 0 : CHK_SAFETY_FUNC_RET(memcpy_s(
353 : dstSqeTypeArray + sqeStartIdx, (totalSqeCount - sqeStartIdx) * sizeof(uint8_t), sqeTypeArray, sqeTypeBytes));
354 :
355 : // Copy SQE DFX info
356 0 : const size_t sqeDfxInfoBytes = sqeCount * sizeof(AicpuDfxInfo);
357 0 : AicpuDfxInfo* dstSqeDfxInfoArray = sqeDfxInfoArrays_[arrayIdx];
358 0 : CHK_PTR_NULL(dstSqeDfxInfoArray);
359 0 : CHK_SAFETY_FUNC_RET(memcpy_s(
360 : dstSqeDfxInfoArray + sqeStartIdx, (totalSqeCount - sqeStartIdx) * sizeof(AicpuDfxInfo), sqeDfxInfoArray,
361 : sqeDfxInfoBytes));
362 :
363 : // 遍历SQE, 根据type更新src/dst RefreshAddrInfo
364 0 : std::vector<RefreshAddrInfo>& srcRefreshAddrInfoArray = srcRefreshAddrInfoArrays_[arrayIdx];
365 0 : std::vector<RefreshAddrInfo>& dstRefreshAddrInfoArray = dstRefreshAddrInfoArrays_[arrayIdx];
366 0 : uint64_t sqeSrcAddr = 0;
367 0 : uint64_t sqeDstAddr = 0;
368 0 : const uint8_t* sqePtr = sqeArray;
369 0 : for (size_t tmpSqeIdx = 0; tmpSqeIdx < sqeCount; tmpSqeIdx++) {
370 0 : const size_t cacheSqeIdx = sqeStartIdx + tmpSqeIdx;
371 :
372 : // 获得当前SQE的信息
373 : // 注意: 不使用sqeDfxInfoArray[tmpSqeIdx].remoteRank来准备RefreshAddrInfo,
374 : // 因为DfxInfo.remoteRank某些整网用例下存在维护异常
375 0 : const uint8_t sqeType = sqeTypeArray[tmpSqeIdx];
376 :
377 : // 根据SQE type更新RefreshAddrInfo
378 0 : switch (sqeType) {
379 0 : case SqeType::NOTIFY_SQE:
380 : case SqeType::EVENT_SQE: {
381 : // No need to update src/dst RefreshAddrInfo due to no addr fields
382 0 : break;
383 : }
384 0 : case SqeType::WRITE_VALUE_SQE:
385 : case SqeType::RDMA_DB_SEND_SQE: {
386 0 : const rtStarsWriteValueSqe_t* writeValueSqePtr
387 : = reinterpret_cast<const rtStarsWriteValueSqe_t*>(sqePtr);
388 :
389 0 : CombineUint32ToUint64(sqeDstAddr, writeValueSqePtr->write_addr_high, writeValueSqePtr->write_addr_low);
390 0 : CHK_RET(CheckAndPrepareRefreshAddrInfo(
391 : sqeDstAddr, dstRefreshAddrInfoArray[cacheSqeIdx], false,
392 : nullptr)); // 注意: alltoallv算子有WRITE_VALUE_SQE, 但不会存在对于HCCL input buffer的访问,
393 : // 无需确认HCCL input buffer对应的rank id进行地址刷新
394 :
395 0 : break;
396 : }
397 0 : case SqeType::MEMCPY_ASYNC_SQE: {
398 0 : const rtStarsMemcpyAsyncSqe_t* memcpyAsyncSqePtr
399 : = reinterpret_cast<const rtStarsMemcpyAsyncSqe_t*>(sqePtr);
400 :
401 0 : CombineUint32ToUint64(sqeSrcAddr, memcpyAsyncSqePtr->src_addr_high, memcpyAsyncSqePtr->src_addr_low);
402 0 : CHK_RET(CheckAndPrepareRefreshAddrInfo(
403 : sqeSrcAddr, srcRefreshAddrInfoArray[cacheSqeIdx], isAlltoallv, alltoallvMetadataPtr));
404 :
405 0 : CombineUint32ToUint64(sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
406 0 : CHK_RET(CheckAndPrepareRefreshAddrInfo(
407 : sqeDstAddr, dstRefreshAddrInfoArray[cacheSqeIdx], isAlltoallv, alltoallvMetadataPtr));
408 :
409 0 : break;
410 : }
411 0 : case SqeType::CCORE_WAIT_START_SQE: {
412 0 : HCCL_ERROR("[OpUnfoldCacheEntry][MemcpySqeArray] SqeType::CCORE_WAIT_START_SQE is not supported in A3");
413 0 : return HCCL_E_NOT_SUPPORT;
414 : }
415 0 : case SqeType::CCORE_WRITE_VALUE_SQE: {
416 0 : HCCL_ERROR(
417 : "[OpUnfoldCacheEntry][MemcpySqeArray] SqeType::CCORE_WRITE_VALUE_SQE is not supported in A3");
418 0 : return HCCL_E_NOT_SUPPORT;
419 : }
420 0 : case SqeType::NOTIFY_SQE_V2: {
421 0 : HCCL_ERROR("[OpUnfoldCacheEntry][MemcpySqeArray] SqeType::NOTIFY_SQE_V2 is not supported in A3");
422 0 : return HCCL_E_NOT_SUPPORT;
423 : }
424 0 : case SqeType::WRITE_VALUE_SQE_V2: {
425 0 : HCCL_ERROR("[OpUnfoldCacheEntry][MemcpySqeArray] SqeType::WRITE_VALUE_SQE_V2 is not supported in A3");
426 0 : return HCCL_E_NOT_SUPPORT;
427 : }
428 0 : case SqeType::EVENT_SQE_V2: {
429 0 : HCCL_ERROR("[OpUnfoldCacheEntry][MemcpySqeArray] SqeType::EVENT_SQE_V2 is not supported in A3");
430 0 : return HCCL_E_NOT_SUPPORT;
431 : }
432 0 : case SqeType::MEMCPY_ASYNC_SQE_V2: {
433 0 : HCCL_ERROR("[OpUnfoldCacheEntry][MemcpySqeArray] SqeType::MEMCPY_ASYNC_SQE_V2 is not supported in A3");
434 0 : return HCCL_E_NOT_SUPPORT;
435 : }
436 0 : case SqeType::FLIP_PLACEHOLDER_SQE: {
437 0 : HCCL_ERROR(
438 : "[OpUnfoldCacheEntry][MemcpySqeArray] placeholder should not be cached, sqeType[%u] tmpSqeIdx[%u] "
439 : "cacheSqeIdx[%u]",
440 : sqeType, tmpSqeIdx, cacheSqeIdx);
441 0 : return HCCL_E_INTERNAL;
442 : }
443 0 : case SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE: {
444 : // 注意: 只有alltoallv算子在cache时才会有此类SQE
445 0 : CHK_PRT_RET(
446 : !isAlltoallv,
447 : HCCL_ERROR("[OpUnfoldCacheEntry][MemcpySqeArray] non-alltoallv op should not dispatch "
448 : "CACHE_MEMCPY_PLACEHOLDER_SQE"),
449 : HCCL_E_INTERNAL);
450 :
451 0 : const rtStarsPlaceHolderSqe_t* placeholderSqePtr
452 : = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqePtr);
453 0 : const struct rtCacheMemcpyTaskTag_t& unfoldCacheTaskTag = placeholderSqePtr->u.cache_memcpy_task_info;
454 :
455 0 : CombineUint32ToUint64(sqeSrcAddr, unfoldCacheTaskTag.src_addr_high, unfoldCacheTaskTag.src_addr_low);
456 0 : CHK_RET(CheckAndPrepareRefreshAddrInfo(
457 : sqeSrcAddr, srcRefreshAddrInfoArray[cacheSqeIdx], isAlltoallv, alltoallvMetadataPtr));
458 :
459 0 : CombineUint32ToUint64(sqeDstAddr, unfoldCacheTaskTag.dst_addr_high, unfoldCacheTaskTag.dst_addr_low);
460 0 : CHK_RET(CheckAndPrepareRefreshAddrInfo(
461 : sqeDstAddr, dstRefreshAddrInfoArray[cacheSqeIdx], isAlltoallv, alltoallvMetadataPtr));
462 :
463 0 : break;
464 : }
465 0 : case SqeType::CACHE_NOTIFY_PLACEHOLDER_SQE:
466 : case SqeType::CACHE_WRITE_VALUE_PLACEHOLDER_SQE:
467 : case SqeType::CACHE_MEMCPY_RECORD_PLACEHOLDER_SQE: {
468 : // Cache-notify placeholder: 无地址字段, 不需要更新src/dst RefreshAddrInfo
469 : // Cache-write placeholder: 对应WriteValueRecord SQE, 地址为硬件映射的固定内存, 无需更新RefreshAddrInfo
470 : // Cache-memcpy-record placeholder: 对应MemcpyRecord SQE, 地址为硬件映射的固定内存,
471 : // 无需更新RefreshAddrInfo
472 0 : break;
473 : }
474 0 : default: {
475 0 : HCCL_WARNING("[OpUnfoldCacheEntry][MemcpySqeArray] sqeType %u is unsupported", sqeType);
476 0 : return HCCL_E_NOT_SUPPORT;
477 : }
478 : }
479 :
480 0 : sqePtr += HCCL_SQE_SIZE;
481 : }
482 :
483 0 : return HCCL_SUCCESS;
484 : }
485 :
486 0 : HcclResult OpUnfoldCacheEntry::CalcStreamSeqIdxes(Stream& mainStream, std::vector<Stream>& slaveStreams)
487 : {
488 0 : const size_t streamIdCount = streamIds_.size();
489 0 : HCCL_INFO(
490 : "[OpUnfoldCacheEntry][CalcStreamSeqIdxes] calculate stream sequential indexes for %u stream ids",
491 : streamIdCount);
492 :
493 : // 对每个stream id找到对应的sequential stream index
494 0 : streamSeqIdxes_.resize(streamIdCount);
495 0 : for (size_t i = 0; i < streamIdCount; ++i) {
496 0 : const int32_t curStreamId = streamIds_[i];
497 :
498 0 : if (curStreamId == mainStream.GetHcclStreamInfo().actualStreamId) { // 主流
499 0 : streamSeqIdxes_[i] = 0;
500 : } else { // 遍历从流
501 0 : bool isFound = false;
502 0 : for (size_t j = 0; j < slaveStreams.size(); ++j) {
503 0 : if (curStreamId == slaveStreams[j].GetHcclStreamInfo().actualStreamId) { // 匹配某个从流
504 0 : streamSeqIdxes_[i] = j + 1;
505 0 : isFound = true;
506 0 : break;
507 : }
508 : }
509 :
510 : // No stream can match the stream id
511 0 : if (!isFound) {
512 0 : HCCL_ERROR(
513 : "[OpUnfoldCacheEntry][CalcStreamSeqIdxes] cannot find any stream to match streamId %u",
514 : curStreamId);
515 0 : return HCCL_E_INTERNAL;
516 : }
517 : }
518 : }
519 :
520 0 : return HCCL_SUCCESS;
521 : }
522 :
523 : HcclResult
524 0 : OpUnfoldCacheEntry::UpdateRefreshAddrInfoForAlltoallv(const uint32_t curRank, AlltoallvMetadata& alltoallvMetadata)
525 : {
526 : // 校验入参
527 0 : CHK_RET(alltoallvMetadata.Check(true));
528 :
529 : // 获得rankSize
530 0 : const uint32_t rankSize = alltoallvMetadata.hcclInputMemRanges.size();
531 0 : CHK_PRT_RET(
532 : curRank >= rankSize,
533 : HCCL_ERROR(
534 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] curRank[%u] >= rankSize[%u]", curRank, rankSize),
535 : HCCL_E_INTERNAL);
536 :
537 0 : HCCL_RUN_INFO(
538 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] curRank[%u] rankSize[%u]", curRank, rankSize);
539 :
540 : // 遍历每一段SQE数组
541 0 : const size_t sqeArrayCnt = dstRefreshAddrInfoArrays_.size();
542 0 : for (size_t arrayIdx = 0; arrayIdx < sqeArrayCnt; ++arrayIdx) {
543 : // 准备当前SQE数组的相关metadata
544 0 : const uint8_t* sqeArray = sqeArrays_[arrayIdx];
545 0 : CHK_PTR_NULL(sqeArray);
546 0 : const uint8_t* sqeTypeArray = sqeTypeArrays_[arrayIdx];
547 0 : CHK_PTR_NULL(sqeTypeArray);
548 0 : std::vector<RefreshAddrInfo>& srcRefreshAddrInfoArray = srcRefreshAddrInfoArrays_[arrayIdx];
549 0 : std::vector<RefreshAddrInfo>& dstRefreshAddrInfoArray = dstRefreshAddrInfoArrays_[arrayIdx];
550 :
551 : // 遍历数组中的每个SQE
552 0 : const size_t sqeCount = dstRefreshAddrInfoArray.size();
553 0 : HCCL_INFO(
554 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] sqeArrayIdx[%u] sqeCount[%u]", arrayIdx, sqeCount);
555 0 : for (size_t sqeIdx = 0; sqeIdx < sqeCount; ++sqeIdx) {
556 : // 准备当前SQE的相关metadata
557 0 : const uint8_t* sqePtr = sqeArray + sqeIdx * HCCL_SQE_SIZE;
558 0 : const uint8_t sqeType = sqeTypeArray[sqeIdx];
559 0 : RefreshAddrInfo& srcRefreshAddrInfo = srcRefreshAddrInfoArray[sqeIdx];
560 0 : RefreshAddrInfo& dstRefreshAddrInfo = dstRefreshAddrInfoArray[sqeIdx];
561 :
562 : // 只有memcpy / cache-memcpy placeholder SQE可能需要更新RefreshAddrInfo
563 0 : if (sqeType != SqeType::MEMCPY_ASYNC_SQE && sqeType != SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE) {
564 0 : continue;
565 : }
566 :
567 : // 跳过memcpy record SQE (src/dst memType为invalid)
568 0 : const uint8_t srcMemType = srcRefreshAddrInfo.memType;
569 0 : const uint8_t dstMemType = dstRefreshAddrInfo.memType;
570 0 : if (sqeType == SqeType::MEMCPY_ASYNC_SQE && srcMemType == RefreshAddrInfo::INVALID_MEMTYPE
571 0 : && dstMemType == RefreshAddrInfo::INVALID_MEMTYPE) {
572 0 : const rtStarsMemcpyAsyncSqe_t* memcpySqePtr = reinterpret_cast<const rtStarsMemcpyAsyncSqe_t*>(sqePtr);
573 0 : HCCL_DEBUG(
574 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] skip memcpy-record SQE: "
575 : "streamId[%u] taskId[%u] srcMemType[%u] dstMemType[%u]",
576 : memcpySqePtr->header.rtStreamId, memcpySqePtr->header.taskId, srcMemType, dstMemType);
577 0 : continue;
578 0 : }
579 :
580 : // (i) 更新invalid memType
581 :
582 : // 只有cache-memcpy placeholder才有可能存在user input/output endAddr导致的src/dst invalid memType
583 0 : if (sqeType == SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE) {
584 : // 校验src/dst memType
585 0 : const rtStarsPlaceHolderSqe_t* placeholderSqePtr
586 : = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqePtr);
587 0 : const uint16_t placeholderStreamId = placeholderSqePtr->header.rtStreamId;
588 0 : const uint16_t placeholderTaskId = placeholderSqePtr->header.taskId;
589 0 : if (srcMemType == RefreshAddrInfo::INVALID_MEMTYPE && dstMemType != RefreshAddrInfo::INVALID_MEMTYPE) {
590 : // LocalCopy/PrepareIntraData: dst一定是local user output
591 : // PrepareIntraData: 虽然dst RefreshAddrInfo的rank尚未更新 (see当前函数的第(ii)部分),
592 : // memType一定是(local) hccl input
593 0 : CHK_PRT_RET(
594 : dstMemType != RefreshAddrInfo::USER_OUTPUT_MEMTYPE
595 : && dstMemType != RefreshAddrInfo::HCCL_INPUT_MEMTYPE,
596 : HCCL_ERROR(
597 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] cache-memcpy placeholder: "
598 : "streamId[%u] taskId[%u] dstMemType[%u] != RefreshAddrInfo::HCCL_INPUT_MEMTYPE[%u]",
599 : placeholderStreamId, placeholderTaskId, dstMemType, RefreshAddrInfo::HCCL_INPUT_MEMTYPE),
600 : HCCL_E_INTERNAL);
601 0 : } else if (
602 0 : srcMemType != RefreshAddrInfo::INVALID_MEMTYPE && dstMemType == RefreshAddrInfo::INVALID_MEMTYPE) {
603 : // LocalCopy/RemoteCopy: src一定是local user input
604 : // RemoteCopy: src memType一定是(remote) hccl input
605 0 : CHK_PRT_RET(
606 : srcMemType != RefreshAddrInfo::USER_INPUT_MEMTYPE
607 : && srcMemType != RefreshAddrInfo::HCCL_INPUT_MEMTYPE,
608 : HCCL_ERROR(
609 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] cache-memcpy placeholder: "
610 : "streamId[%u] taskId[%u] srcMemType[%u] != RefreshAddrInfo::HCCL_INPUT_MEMTYPE[%u]",
611 : placeholderStreamId, placeholderTaskId, srcMemType, RefreshAddrInfo::HCCL_INPUT_MEMTYPE),
612 : HCCL_E_INTERNAL);
613 : }
614 :
615 : // 更新src/dst memType
616 0 : const struct rtCacheMemcpyTaskTag_t& cacheMemcpyTaskInfo = placeholderSqePtr->u.cache_memcpy_task_info;
617 0 : if (srcMemType == RefreshAddrInfo::INVALID_MEMTYPE) { // LocalCopy/PrepareIntraData
618 : // srcAddr一定是local user input的end addr
619 0 : uint64_t sqeSrcAddr = 0;
620 0 : CombineUint32ToUint64(
621 0 : sqeSrcAddr, cacheMemcpyTaskInfo.src_addr_high, cacheMemcpyTaskInfo.src_addr_low);
622 0 : uint64_t localUserInputEndAddr = 0;
623 0 : CHK_RET(userInputMemRanges_[curRank].GetEndAddr(localUserInputEndAddr));
624 0 : CHK_PRT_RET(
625 : sqeSrcAddr != localUserInputEndAddr,
626 : HCCL_ERROR(
627 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] sqeSrcAddr[0x%016llx]"
628 : "!= localUserInputEndAddr[0x%016llx]",
629 : sqeSrcAddr, localUserInputEndAddr),
630 : HCCL_E_INTERNAL);
631 :
632 : // 更新src memType和rank, 即local user input
633 0 : srcRefreshAddrInfo.memType = RefreshAddrInfo::USER_INPUT_MEMTYPE;
634 0 : srcRefreshAddrInfo.rankId = curRank;
635 0 : HCCL_INFO(
636 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] update invalid src "
637 : "RefreshAddrInfo for cache-memcpy placeholder: streamId[%u] taskId[%u] memType[%u] rankId[%u]",
638 : placeholderStreamId, placeholderTaskId, srcRefreshAddrInfo.memType, srcRefreshAddrInfo.rankId);
639 : }
640 0 : if (dstMemType == RefreshAddrInfo::INVALID_MEMTYPE) { // LocalCopy/RemoteCopy
641 : // dstAddr一定是local user output的end addr
642 0 : uint64_t sqeDstAddr = 0;
643 0 : CombineUint32ToUint64(
644 0 : sqeDstAddr, cacheMemcpyTaskInfo.dst_addr_high, cacheMemcpyTaskInfo.dst_addr_low);
645 0 : uint64_t localUserOutputEndAddr = 0;
646 0 : CHK_RET(userOutputMemRanges_[curRank].GetEndAddr(localUserOutputEndAddr));
647 0 : CHK_PRT_RET(
648 : sqeDstAddr != localUserOutputEndAddr,
649 : HCCL_ERROR(
650 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] sqeDstAddr[0x%016llx]"
651 : "!= localUserOutputEndAddr[0x%016llx]",
652 : sqeDstAddr, localUserOutputEndAddr),
653 : HCCL_E_INTERNAL);
654 :
655 : // 更新dst memType和rank, 即local user output
656 0 : dstRefreshAddrInfo.memType = RefreshAddrInfo::USER_OUTPUT_MEMTYPE;
657 0 : dstRefreshAddrInfo.rankId = curRank;
658 0 : HCCL_INFO(
659 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] update invalid dst "
660 : "RefreshAddrInfo for cache-memcpy placeholder: streamId[%u] taskId[%u] memType[%u] rankId[%u]",
661 : placeholderStreamId, placeholderTaskId, dstRefreshAddrInfo.memType, dstRefreshAddrInfo.rankId);
662 : }
663 : }
664 :
665 : // (ii) 更新local dst rank (如果dst memType是local hccl input)
666 :
667 : // PrepareIntraData: local user input -> local hccl input
668 : // 注意: invalid memType已经在当前函数的第(i)部分被解决
669 0 : if (srcRefreshAddrInfo.memType == RefreshAddrInfo::USER_INPUT_MEMTYPE
670 0 : && dstRefreshAddrInfo.memType == RefreshAddrInfo::HCCL_INPUT_MEMTYPE) {
671 : // srcRank一定是current rank
672 0 : const uint32_t srcRank = srcRefreshAddrInfo.rankId;
673 0 : CHK_PRT_RET(
674 : srcRank != curRank,
675 : HCCL_ERROR(
676 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] srcRank[%u] != curRank[%u], "
677 : "rankSize[%u]",
678 : srcRank, curRank, rankSize),
679 : HCCL_E_INTERNAL);
680 :
681 : // 注意: 对于alltoallv算子, 原始dstRefreshAddrInfo.rankId在MemcpySqeArray时被刷新
682 : // 因为alltoallvMetadata中的hcclOffsetDstRanksIdxMap要等第一次算子Orchestrate结束后才会被设置
683 : // 而根据范围dstAddr落在local hccl input范围内, 因此当时刷新的rankId一定为current rank
684 0 : CHK_PRT_RET(
685 : dstRefreshAddrInfo.rankId != curRank,
686 : HCCL_ERROR(
687 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] original dstRank[%u] != curRank[%u]",
688 : dstRefreshAddrInfo.rankId, curRank),
689 : HCCL_E_INTERNAL);
690 :
691 : // 根据SQE类型获得dst addr
692 0 : uint64_t sqeDstAddr = 0;
693 0 : if (sqeType == SqeType::MEMCPY_ASYNC_SQE) {
694 0 : const rtStarsMemcpyAsyncSqe_t* memcpyAsyncSqePtr
695 : = reinterpret_cast<const rtStarsMemcpyAsyncSqe_t*>(sqePtr);
696 0 : CombineUint32ToUint64(
697 0 : sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
698 : } else { // cache-memcpy placeholder
699 0 : const rtStarsPlaceHolderSqe_t* placeholderSqePtr
700 : = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqePtr);
701 0 : const struct rtCacheMemcpyTaskTag_t& cacheMemcpyTaskInfo
702 : = placeholderSqePtr->u.cache_memcpy_task_info;
703 0 : CombineUint32ToUint64(
704 0 : sqeDstAddr, cacheMemcpyTaskInfo.dst_addr_high, cacheMemcpyTaskInfo.dst_addr_low);
705 : }
706 :
707 : // 本函数只会在第一次cache miss后处理时调用, dst addr一定落在local hccl input范围内
708 0 : bool isInRange = false;
709 0 : const OpUnfoldMemRange& localHcclInputMemRange = alltoallvMetadata.hcclInputMemRanges[curRank];
710 0 : CHK_RET(localHcclInputMemRange.InRange(sqeDstAddr, isInRange));
711 0 : if (UNLIKELY(!isInRange)) {
712 0 : uint64_t localHcclInputEndAddr = 0;
713 0 : CHK_RET(localHcclInputMemRange.GetEndAddr(localHcclInputEndAddr));
714 0 : HCCL_ERROR(
715 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] sqeDstAddr[0x%016llx] not "
716 : "in localHcclInputMemRange[0x%016llx -- 0x%016llx]",
717 : sqeDstAddr, localHcclInputMemRange.baseAddr, localHcclInputEndAddr);
718 0 : return HCCL_E_INTERNAL;
719 : }
720 :
721 : // 参考alltoallv_direct_fullmesh.cc中的UpdateCurrRankSendInfo
722 :
723 : // 计算local hccl input buffer下的offset
724 : // 注意: 前面isInRange已经校验过必定为true, 即sqeDstAddr一定 >= localHcclInputBaseAddr
725 0 : uint64_t localHcclInputBaseAddr = localHcclInputMemRange.baseAddr;
726 0 : uint64_t hcclOffset = sqeDstAddr - localHcclInputBaseAddr;
727 :
728 : // 根据hcclOffset-dstRanksInfo mapping获得对应的dst rank
729 : std::unordered_map<uint64_t, RanksIdx>::iterator mapIter
730 0 : = alltoallvMetadata.hcclOffsetDstRanksIdxMap.find(hcclOffset);
731 0 : if (mapIter == alltoallvMetadata.hcclOffsetDstRanksIdxMap.end()) {
732 0 : HCCL_ERROR(
733 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] hcclOffset[%u] is not found",
734 : hcclOffset);
735 0 : return HCCL_E_INTERNAL;
736 : }
737 0 : const std::vector<uint32_t>& dstRanks = mapIter->second.first;
738 0 : uint32_t& curIdx = mapIter->second.second;
739 0 : const uint32_t dstRank = dstRanks[curIdx % dstRanks.size()];
740 0 : HCCL_INFO(
741 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] hcclOffset[%llu] dstRanks.size[%u] "
742 : "curIdx[%u] dstRank[%u]",
743 : hcclOffset, dstRanks.size(), curIdx, dstRank);
744 :
745 : // 新的dstRank一定是某个remoteRank, 即不等于curRank
746 0 : CHK_PRT_RET(
747 : dstRank == curRank,
748 : HCCL_ERROR(
749 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv] dstRank[%u] = curRank[%u]", dstRank,
750 : curRank),
751 : HCCL_E_INTERNAL);
752 :
753 : // Prepare for next-round dstRank (if any)
754 0 : curIdx = (curIdx + 1) % dstRanks.size();
755 :
756 : // 更新dst rank
757 0 : dstRefreshAddrInfo.rankId = dstRank;
758 0 : HCCL_INFO(
759 : "[OpUnfoldCacheEntry][UpdateRefreshAddrInfoForAlltoallv]"
760 : "dstRefreshAddrInfoArrays_[%u][%u].rankId[%u -> %u]",
761 : arrayIdx, sqeIdx, curRank, dstRefreshAddrInfo.rankId);
762 : } // PrepareIntraData in alltoallv
763 :
764 : // 刷新memcpy / cache-memcpy placeholder SQE后, 校验src/dst地址字段对应的memType
765 0 : CHK_RET(CheckMemTypeForAlltoallv(sqePtr, sqeType, srcRefreshAddrInfo, dstRefreshAddrInfo));
766 : } // sqeIdx
767 : } // arrayIdx
768 :
769 0 : return HCCL_SUCCESS;
770 : }
771 :
772 0 : HcclResult OpUnfoldCacheEntry::UpdateAndGetSqeArray(
773 : const size_t arrayIdx, const std::vector<OpUnfoldMemRange>& curUserInputMemRanges,
774 : const std::vector<OpUnfoldMemRange>& curUserOutputMemRanges, Stream& mainStream, std::vector<Stream>& slaveStreams,
775 : const uint32_t opRingBufferIdx, size_t& sqeCount, uint8_t** sqeArrayPtr, uint8_t** sqeTypeArrayPtr,
776 : AicpuDfxInfo** sqeDfxInfoArrayPtr, Stream** streamPtrPtr, std::vector<FlipInfo>& flipInfos, const bool profL1Enable,
777 : std::vector<uint64_t>& profTimestamps, const bool isAlltoallv, const AlltoallvMetadata& alltoallvMetadata,
778 : const AlltoallvSendRecvInfo& alltoallvSendRecvInfo)
779 : {
780 0 : HCCL_INFO(
781 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] update and get SQEs from %uth SQE array; isAlltoallv[%u]", arrayIdx,
782 : isAlltoallv);
783 :
784 : // 检验入参
785 0 : CHK_PRT_RET(
786 : arrayIdx >= sqeArrays_.size(),
787 : HCCL_ERROR(
788 : "[OpUnfoldCacheEntry][MemcpySqeArray] arrayIdx %u is out of range [0, %u)", arrayIdx, sqeArrays_.size()),
789 : HCCL_E_INTERNAL);
790 0 : CHK_PRT_RET(
791 : arrayIdx >= streamSeqIdxes_.size(),
792 : HCCL_ERROR(
793 : "[OpUnfoldCacheEntry][MemcpySqeArray] arrayIdx %u is out of range [0, %u)", arrayIdx,
794 : streamSeqIdxes_.size()),
795 : HCCL_E_INTERNAL);
796 : // 检查指针, arrayPtr不应该是null, 但*arrayPtr应该是null
797 0 : CHK_PTRPTR_NULL(sqeArrayPtr);
798 0 : CHK_PTRPTR_NULL(sqeTypeArrayPtr);
799 0 : CHK_PTRPTR_NULL(sqeDfxInfoArrayPtr);
800 0 : CHK_PTRPTR_NULL(streamPtrPtr);
801 : // Double-check alltoallv相关入参
802 0 : if (isAlltoallv) {
803 0 : CHK_RET(alltoallvMetadata.Check(true));
804 0 : CHK_RET(alltoallvSendRecvInfo.Check());
805 : }
806 :
807 : // 设置入参
808 0 : sqeCount = srcRefreshAddrInfoArrays_[arrayIdx].size();
809 0 : *sqeArrayPtr = sqeArrays_[arrayIdx];
810 0 : *sqeTypeArrayPtr = sqeTypeArrays_[arrayIdx];
811 0 : *sqeDfxInfoArrayPtr = sqeDfxInfoArrays_[arrayIdx];
812 0 : flipInfos.clear();
813 0 : if (profL1Enable) {
814 0 : profTimestamps.clear();
815 0 : profTimestamps.reserve(
816 : sqeCount); // 需要额外flip placeholder是小概率事件, 所以只reserve cached SQE个数 (即非flip placeholder类SQE)
817 : }
818 :
819 : // 设置入参的stream pointer
820 0 : const uint32_t streamSeqIdx = streamSeqIdxes_[arrayIdx];
821 0 : if (streamSeqIdx == 0) {
822 0 : *streamPtrPtr = &mainStream;
823 : } else {
824 0 : CHK_PRT_RET(
825 : streamSeqIdx > slaveStreams.size(),
826 : HCCL_ERROR(
827 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] invalid streamSeqIdx %u > slaveStreams.size() %u",
828 : streamSeqIdx, slaveStreams.size()),
829 : HCCL_E_MEMORY);
830 0 : *streamPtrPtr = &(slaveStreams[streamSeqIdx - 1]); // 0 < streamSeqIdx <= slaveStreams.size())
831 : }
832 :
833 : // 从stream中获取SQE刷新需要的当前task id
834 0 : HcclSqeContext* sqeContext = (*streamPtrPtr)->GetSqeContextPtr();
835 0 : CHK_PTR_NULL(sqeContext);
836 0 : SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
837 0 : CHK_PTR_NULL(sqeContextBuffer);
838 0 : uint16_t& curTaskId = sqeContextBuffer->tailSqeTaskId;
839 0 : uint16_t& curFlipNum = sqeContextBuffer->filpNum;
840 0 : HCCL_INFO(
841 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] curTaskId[%u] curFlipNum[%u] from streamId %u for %u cached SQEs",
842 : curTaskId, curFlipNum, (*streamPtrPtr)->GetHcclStreamInfo().actualStreamId, sqeCount);
843 :
844 : // 执行SQE刷新
845 : // 注意: curUserInputMemRanges/curUserOutputMemRanges为当前算子执行时各rank输入输出的user memory range,
846 : // userInputMemRanges_/userOutputMemRanges_为算子缓存时各rank输入输出的user memory range
847 0 : const std::vector<RefreshAddrInfo>& srcRefreshAddrInfoArray = srcRefreshAddrInfoArrays_[arrayIdx];
848 0 : const std::vector<RefreshAddrInfo>& dstRefreshAddrInfoArray = dstRefreshAddrInfoArrays_[arrayIdx];
849 0 : uint64_t sqeSrcAddr = 0;
850 0 : uint64_t sqeDstAddr = 0;
851 0 : uint8_t* sqePtr = (*sqeArrayPtr);
852 0 : for (size_t sqeIdx = 0; sqeIdx < sqeCount; ++sqeIdx) {
853 : // 获取当前SQE的信息
854 0 : uint8_t& sqeType = (*sqeTypeArrayPtr)[sqeIdx];
855 0 : const RefreshAddrInfo& srcRefreshAddrInfo = srcRefreshAddrInfoArray[sqeIdx];
856 0 : const RefreshAddrInfo& dstRefreshAddrInfo = dstRefreshAddrInfoArray[sqeIdx];
857 0 : HCCL_INFO(
858 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] update %uth cached SQE with sqeType[%u] "
859 : "srcRefreshAddrInfo[rankid[%u], memType[%u]] dstRefreshAddrInfo[rankid[%u], memType[%u]] curTaskId[%u]",
860 : sqeIdx, sqeType, srcRefreshAddrInfo.rankId, srcRefreshAddrInfo.memType, dstRefreshAddrInfo.rankId,
861 : dstRefreshAddrInfo.memType, curTaskId);
862 :
863 : // 根据SQE type进行对应刷新 (task id始终要刷新; addr相关字段有条件刷新)
864 0 : switch (sqeType) {
865 0 : case SqeType::NOTIFY_SQE: {
866 0 : rtStarsNotifySqeV1_t* notifySqePtr = reinterpret_cast<rtStarsNotifySqeV1_t*>(sqePtr);
867 0 : if (isAlltoallv && notifySqePtr->header.type == RT_STARS_SQE_TYPE_NOTIFY_WAIT) {
868 : // 针对alltoallv算子, 动态刷新Notify SQE / 将Notify SQE生成为CacheNotifyPlaceholder SQE
869 : // 注意: NotifyRecord SQE不需要针对alltoallv类算子做特殊刷新
870 0 : CHK_RET(UpdateSyncSqeForAlltoallv(
871 : sqePtr, &sqeType, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, alltoallvMetadata,
872 : alltoallvSendRecvInfo));
873 0 : } else {
874 0 : notifySqePtr->header.taskId = curTaskId;
875 : }
876 0 : break;
877 : }
878 0 : case SqeType::WRITE_VALUE_SQE:
879 : case SqeType::RDMA_DB_SEND_SQE: {
880 0 : if (isAlltoallv) { // 针对alltoallv算子, 动态刷新WriteValue SQE / 将WriteValue
881 : // SQE生成为CacheWriteValuePlaceholder SQE
882 0 : CHK_RET(UpdateSyncSqeForAlltoallv(
883 : sqePtr, &sqeType, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, alltoallvMetadata,
884 : alltoallvSendRecvInfo));
885 : } else {
886 0 : rtStarsWriteValueSqe_t* writeValueSqePtr = reinterpret_cast<rtStarsWriteValueSqe_t*>(sqePtr);
887 0 : writeValueSqePtr->header.taskId = curTaskId;
888 :
889 0 : if (dstRefreshAddrInfo.memType != RefreshAddrInfo::INVALID_MEMTYPE) { // 需要刷新地址
890 0 : CombineUint32ToUint64(
891 0 : sqeDstAddr, writeValueSqePtr->write_addr_high, writeValueSqePtr->write_addr_low);
892 0 : if (dstRefreshAddrInfo.memType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // user output
893 0 : CHK_RET(RefreshSqeAddr(
894 : sqeDstAddr, dstRefreshAddrInfo.rankId, userOutputMemRanges_, curUserOutputMemRanges,
895 : false, 0));
896 0 : } else if (dstRefreshAddrInfo.memType == RefreshAddrInfo::USER_INPUT_MEMTYPE) { // user input
897 0 : CHK_RET(RefreshSqeAddr(
898 : sqeDstAddr, dstRefreshAddrInfo.rankId, userInputMemRanges_, curUserInputMemRanges,
899 : false, 0));
900 : } else { // hccl input (alltoallv算子不需要对WRITE_VALUE_SQE刷新hccl地址)
901 0 : HCCL_ERROR(
902 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] isAlltoallv[%u] sqeType[%u]; memType "
903 : "should be user input/output",
904 : isAlltoallv, sqeType);
905 0 : HCCL_ERROR(
906 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] dstRefreshAddrInfo: rankId[%u] memType[%u]",
907 : dstRefreshAddrInfo.rankId, dstRefreshAddrInfo.memType);
908 0 : return HCCL_E_INTERNAL;
909 : }
910 :
911 : // Bit-field member不能直接传引用
912 0 : uint32_t tmpHighAddr = 0;
913 0 : SplitUint64ToUint32(sqeDstAddr, tmpHighAddr, writeValueSqePtr->write_addr_low);
914 0 : writeValueSqePtr->write_addr_high = tmpHighAddr;
915 : }
916 : }
917 0 : break;
918 : }
919 0 : case SqeType::EVENT_SQE: {
920 0 : rtStarsEventSqe_t* eventSqePtr = reinterpret_cast<rtStarsEventSqe_t*>(sqePtr);
921 0 : eventSqePtr->header.taskId = curTaskId;
922 0 : break;
923 : }
924 0 : case SqeType::MEMCPY_ASYNC_SQE: {
925 0 : if (isAlltoallv) { // 针对alltoallv算子
926 0 : if (srcRefreshAddrInfo.memType == RefreshAddrInfo::INVALID_MEMTYPE
927 0 : && dstRefreshAddrInfo.memType == RefreshAddrInfo::INVALID_MEMTYPE) { // MemcpyRecord SQE
928 : // 动态刷新MemcpyRecord SQE / 将MemcpyRecord SQE生成为CacheMemcpyRecordPlaceholder SQE
929 0 : CHK_RET(UpdateSyncSqeForAlltoallv(
930 : sqePtr, &sqeType, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, alltoallvMetadata,
931 : alltoallvSendRecvInfo));
932 0 : } else { // Memcpy SQE
933 : // 动态刷新Memcpy SQE / 将Memcpy SQE生成为CacheMemcpyPlaceholder SQE
934 0 : CHK_RET(UpdateTransferSqeForAlltoallv(
935 : sqePtr, &sqeType, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, curUserInputMemRanges,
936 : curUserOutputMemRanges, alltoallvMetadata, alltoallvSendRecvInfo));
937 : }
938 : } else { // 非V类算子, 动态刷新Memcpy SQE
939 0 : rtStarsMemcpyAsyncSqe_t* memcpyAsyncSqePtr = reinterpret_cast<rtStarsMemcpyAsyncSqe_t*>(sqePtr);
940 0 : memcpyAsyncSqePtr->header.taskId = curTaskId;
941 :
942 0 : if (srcRefreshAddrInfo.memType != RefreshAddrInfo::INVALID_MEMTYPE) { // 需要刷新src addr
943 0 : CombineUint32ToUint64(
944 : sqeSrcAddr, memcpyAsyncSqePtr->src_addr_high, memcpyAsyncSqePtr->src_addr_low);
945 0 : if (srcRefreshAddrInfo.memType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // user output
946 0 : CHK_RET(RefreshSqeAddr(
947 : sqeSrcAddr, srcRefreshAddrInfo.rankId, userOutputMemRanges_, curUserOutputMemRanges,
948 : false, 0));
949 0 : } else if (srcRefreshAddrInfo.memType == RefreshAddrInfo::USER_INPUT_MEMTYPE) { // user input
950 0 : CHK_RET(RefreshSqeAddr(
951 : sqeSrcAddr, srcRefreshAddrInfo.rankId, userInputMemRanges_, curUserInputMemRanges,
952 : false, 0));
953 : } else { // hccl input (非V类算子不需要对MEMCPY_ASYNC_SQE刷新hccl地址)
954 0 : HCCL_ERROR(
955 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] isAlltoallv[%u] sqeType[%u]; memType "
956 : "should be user input/output",
957 : isAlltoallv, sqeType);
958 0 : HCCL_ERROR(
959 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] srcRefreshAddrInfo: rankId[%u] memType[%u]",
960 : srcRefreshAddrInfo.rankId, srcRefreshAddrInfo.memType);
961 0 : return HCCL_E_INTERNAL;
962 : }
963 0 : SplitUint64ToUint32(
964 0 : sqeSrcAddr, memcpyAsyncSqePtr->src_addr_high, memcpyAsyncSqePtr->src_addr_low);
965 : }
966 :
967 0 : if (dstRefreshAddrInfo.memType != RefreshAddrInfo::INVALID_MEMTYPE) { // 需要刷新地址
968 0 : CombineUint32ToUint64(
969 : sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
970 0 : if (dstRefreshAddrInfo.memType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // user output
971 0 : CHK_RET(RefreshSqeAddr(
972 : sqeDstAddr, dstRefreshAddrInfo.rankId, userOutputMemRanges_, curUserOutputMemRanges,
973 : false, 0));
974 0 : } else if (dstRefreshAddrInfo.memType == RefreshAddrInfo::USER_INPUT_MEMTYPE) { // user input
975 0 : CHK_RET(RefreshSqeAddr(
976 : sqeDstAddr, dstRefreshAddrInfo.rankId, userInputMemRanges_, curUserInputMemRanges,
977 : false, 0));
978 : } else { // hccl input (非V类算子不需要对MEMCPY_ASYNC_SQE刷新hccl地址)
979 0 : HCCL_ERROR(
980 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] isAlltoallv[%u] sqeType[%u]; memType "
981 : "should be user input/output",
982 : isAlltoallv, sqeType);
983 0 : HCCL_ERROR(
984 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] dstRefreshAddrInfo: rankId[%u] memType[%u]",
985 : dstRefreshAddrInfo.rankId, dstRefreshAddrInfo.memType);
986 0 : return HCCL_E_INTERNAL;
987 : }
988 0 : SplitUint64ToUint32(
989 0 : sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
990 : }
991 : }
992 :
993 0 : break;
994 : }
995 0 : case SqeType::CCORE_WAIT_START_SQE: {
996 0 : HCCL_ERROR(
997 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] SqeType::CCORE_WAIT_START_SQE is not supported in A3");
998 0 : return HCCL_E_NOT_SUPPORT;
999 : }
1000 0 : case SqeType::CCORE_WRITE_VALUE_SQE: {
1001 0 : HCCL_ERROR(
1002 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] SqeType::CCORE_WRITE_VALUE_SQE is not supported in A3");
1003 0 : return HCCL_E_NOT_SUPPORT;
1004 : }
1005 0 : case SqeType::NOTIFY_SQE_V2: {
1006 0 : HCCL_ERROR("[OpUnfoldCacheEntry][UpdateAndGetSqeArray] SqeType::NOTIFY_SQE_V2 is not supported in A3");
1007 0 : return HCCL_E_NOT_SUPPORT;
1008 : }
1009 0 : case SqeType::WRITE_VALUE_SQE_V2: {
1010 0 : HCCL_ERROR(
1011 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] SqeType::WRITE_VALUE_SQE_V2 is not supported in A3");
1012 0 : return HCCL_E_NOT_SUPPORT;
1013 : }
1014 0 : case SqeType::EVENT_SQE_V2: {
1015 0 : HCCL_ERROR("[OpUnfoldCacheEntry][UpdateAndGetSqeArray] SqeType::EVENT_SQE_V2 is not supported in A3");
1016 0 : return HCCL_E_NOT_SUPPORT;
1017 : }
1018 0 : case SqeType::MEMCPY_ASYNC_SQE_V2: {
1019 0 : HCCL_ERROR(
1020 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] SqeType::MEMCPY_ASYNC_SQE_V2 is not supported in A3");
1021 0 : return HCCL_E_NOT_SUPPORT;
1022 : }
1023 0 : case SqeType::FLIP_PLACEHOLDER_SQE: {
1024 0 : HCCL_ERROR(
1025 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] placeholder should not be cached, sqeType[%u] "
1026 : "sqeIdx[%u]",
1027 : sqeType, sqeIdx);
1028 0 : return HCCL_E_INTERNAL;
1029 : }
1030 0 : case SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE: {
1031 : // 非V类算子, 不应该出现CacheMemcpyPlaceholder SQE
1032 0 : CHK_PRT_RET(
1033 : !isAlltoallv,
1034 : HCCL_ERROR(
1035 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] cache-memcpy placeholder"
1036 : "should be not cached for non-alltoallv op, sqeType[%u] sqeIdx[%u]",
1037 : sqeType, sqeIdx),
1038 : HCCL_E_INTERNAL);
1039 :
1040 : // 针对alltoallv类算子, 动态刷新CacheMemcpyPlaceholder SQE / 将CacheMemcpyPlaceholder SQE生成为Memcpy
1041 : // SQE
1042 0 : CHK_RET(UpdateTransferSqeForAlltoallv(
1043 : sqePtr, &sqeType, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, curUserInputMemRanges,
1044 : curUserOutputMemRanges, alltoallvMetadata, alltoallvSendRecvInfo));
1045 :
1046 0 : break;
1047 : }
1048 0 : case SqeType::CACHE_NOTIFY_PLACEHOLDER_SQE:
1049 : case SqeType::CACHE_WRITE_VALUE_PLACEHOLDER_SQE:
1050 : case SqeType::CACHE_MEMCPY_RECORD_PLACEHOLDER_SQE: {
1051 : // 非V类算子, 不应该出现CacheNotify/Write/MemcpyRecordPlaceholder SQE
1052 0 : CHK_PRT_RET(
1053 : !isAlltoallv,
1054 : HCCL_ERROR(
1055 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] cache-notify/write/memcpy-record placeholder"
1056 : "should be not cached for non-alltoallv op, sqeType[%u] sqeIdx[%u]",
1057 : sqeType, sqeIdx),
1058 : HCCL_E_INTERNAL);
1059 :
1060 : // 针对alltoallv类算子, 动态刷新CacheNotify/WritePlaceholder SQE / 将CacheNotify/WritePlaceholder
1061 : // SQE生成为Notify/Write SQE
1062 0 : CHK_RET(UpdateSyncSqeForAlltoallv(
1063 : sqePtr, &sqeType, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, alltoallvMetadata,
1064 : alltoallvSendRecvInfo));
1065 :
1066 0 : break;
1067 : }
1068 0 : default: {
1069 0 : HCCL_WARNING(
1070 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] sqeType %u is unsupported (sqeIdx[%u] curTaskId[%u])",
1071 : sqeType, sqeIdx, curTaskId);
1072 0 : return HCCL_E_NOT_SUPPORT;
1073 : }
1074 : }
1075 :
1076 : // 记录SQE刷新时间用于profiling
1077 0 : if (profL1Enable) {
1078 0 : const uint64_t curTime = ProfGetCurCpuTimestamp();
1079 0 : profTimestamps.push_back(curTime);
1080 : }
1081 :
1082 : // 刷新taskId和flipNum
1083 0 : if (curTaskId == UINT16_MAX) { // 更新flipNum和taskId
1084 : // 参考stream.cc中的GetNextSqeBufferAddr
1085 0 : curFlipNum += 1;
1086 0 : curTaskId = 0;
1087 0 : } else if (curTaskId == 0 && curFlipNum != 0) { // 更新flipInfos和taskId
1088 : // 参考dispatcher_aicpu.cc中的GetStreamSqeBufferAddr
1089 0 : flipInfos.push_back(FlipInfo(sqeIdx, curFlipNum));
1090 :
1091 : // 为placeholder SQE预留task id = 0
1092 0 : curTaskId = 1;
1093 :
1094 : // Flip placeholder SQE在外侧dispatcher aicpu中生成, 这里记录当前时间作为flip placeholder SQE的生成时间
1095 0 : if (profL1Enable) {
1096 0 : const uint64_t curTime = ProfGetCurCpuTimestamp();
1097 0 : profTimestamps.push_back(curTime);
1098 : }
1099 0 : } else { // 只更新taskid
1100 0 : curTaskId += 1;
1101 : }
1102 :
1103 0 : sqePtr += HCCL_SQE_SIZE;
1104 : }
1105 :
1106 : // 更新每个SQE的DfxInfo中的opRingBufferIdx
1107 0 : HCCL_INFO(
1108 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] update opRingBufferIndx in DfxInfoArray as %u", opRingBufferIdx);
1109 0 : for (size_t sqeIdx = 0; sqeIdx < sqeCount; ++sqeIdx) {
1110 0 : (*sqeDfxInfoArrayPtr)[sqeIdx].opRingBufferIdx = opRingBufferIdx;
1111 : }
1112 :
1113 0 : HCCL_INFO(
1114 : "[OpUnfoldCacheEntry][UpdateAndGetSqeArray] update and get %uth SQE array with %u SQEs, streamId[%u] and %u "
1115 : "flipInfos",
1116 : arrayIdx, sqeCount, (*streamPtrPtr)->GetHcclStreamInfo().actualStreamId, flipInfos.size());
1117 :
1118 0 : return HCCL_SUCCESS;
1119 : }
1120 :
1121 0 : HcclResult OpUnfoldCacheEntry::SetInputOutputMemRanges(
1122 : const std::vector<OpUnfoldMemRange>& curUserInputMemRanges,
1123 : const std::vector<OpUnfoldMemRange>& curUserOutputMemRanges)
1124 : {
1125 0 : CHK_PRT_RET(
1126 : userInputMemRanges_.size() != curUserInputMemRanges.size(),
1127 : HCCL_ERROR(
1128 : "[OpUnfoldCacheEntry][SetInputOutputMemRanges] original rankSize %u != new rankSize %u",
1129 : userInputMemRanges_.size(), curUserInputMemRanges.size()),
1130 : HCCL_E_INTERNAL);
1131 :
1132 0 : userInputMemRanges_ = curUserInputMemRanges;
1133 0 : userOutputMemRanges_ = curUserOutputMemRanges;
1134 :
1135 0 : return HCCL_SUCCESS;
1136 : }
1137 :
1138 0 : HcclResult OpUnfoldCacheEntry::CheckAndPrepareRefreshAddrInfo(
1139 : const uint64_t sqeAddr, RefreshAddrInfo& refreshAddrInfo, const bool isAlltoallv,
1140 : const AlltoallvMetadata* alltoallvMetadataPtr)
1141 : {
1142 : // 遍历per-rank user input memory range
1143 0 : for (size_t rankId = 0; rankId < userInputMemRanges_.size(); ++rankId) {
1144 0 : bool isInRange = false;
1145 0 : CHK_RET(userInputMemRanges_[rankId].InRange(sqeAddr, isInRange));
1146 0 : if (isInRange) {
1147 0 : refreshAddrInfo.rankId = rankId;
1148 0 : refreshAddrInfo.memType = RefreshAddrInfo::USER_INPUT_MEMTYPE;
1149 0 : return HCCL_SUCCESS; // 确实是某rank下的user input mem, 则无需继续搜索output mem
1150 : }
1151 : }
1152 :
1153 : // 遍历per-rank user input memory range
1154 0 : for (size_t rankId = 0; rankId < userOutputMemRanges_.size(); ++rankId) {
1155 0 : bool isInRange = false;
1156 0 : CHK_RET(userOutputMemRanges_[rankId].InRange(sqeAddr, isInRange));
1157 0 : if (isInRange) {
1158 0 : refreshAddrInfo.rankId = rankId;
1159 0 : refreshAddrInfo.memType = RefreshAddrInfo::USER_OUTPUT_MEMTYPE;
1160 0 : return HCCL_SUCCESS;
1161 : }
1162 : }
1163 :
1164 : // 针对alltoallv算子, 遍历HCCL input buffer, 确定rank id
1165 0 : if (isAlltoallv) {
1166 0 : CHK_PTR_NULL(alltoallvMetadataPtr);
1167 0 : CHK_RET(alltoallvMetadataPtr->Check(false));
1168 :
1169 0 : const std::vector<OpUnfoldMemRange>& hcclInputMemRanges = alltoallvMetadataPtr->hcclInputMemRanges;
1170 0 : for (size_t rankId = 0; rankId < hcclInputMemRanges.size(); ++rankId) {
1171 0 : bool isInRange = false;
1172 0 : CHK_RET(hcclInputMemRanges[rankId].InRange(sqeAddr, isInRange));
1173 0 : if (isInRange) {
1174 0 : refreshAddrInfo.rankId = rankId;
1175 0 : refreshAddrInfo.memType = RefreshAddrInfo::HCCL_INPUT_MEMTYPE;
1176 0 : return HCCL_SUCCESS;
1177 : }
1178 : }
1179 : }
1180 :
1181 0 : return HCCL_SUCCESS;
1182 : }
1183 :
1184 0 : HcclResult OpUnfoldCacheEntry::CheckMemTypeForAlltoallv(
1185 : const uint8_t* sqePtr, const uint8_t sqeType, const RefreshAddrInfo& srcRefreshAddrInfo,
1186 : const RefreshAddrInfo& dstRefreshAddrInfo) const
1187 : {
1188 : // 对于所有算子, SQE第一次admit时, 在MemcpySqeArray中, 遍历memory ranges获取每个地址字段对应的rankId和memType
1189 : // 对于alltoallv算子, cache miss后处理时, 在UpdateRefreshAddrInfoForAlltoallv中, 进一步更新memType和dstRank
1190 :
1191 : // 如果src在user memory内, 说明是LocalCopy或者PrepareIntraData, 一定是local user input -> local user output / local
1192 : // hccl input 如果dst在user memory内, 说明是LocalCopy或者RemoteCopy, 一定是local user input / remote hccl input ->
1193 : // local user output
1194 :
1195 : // 获取task id和stream id
1196 0 : uint16_t taskId = 0;
1197 0 : uint16_t streamId = 0;
1198 0 : if (sqeType == SqeType::MEMCPY_ASYNC_SQE) {
1199 0 : const rtStarsMemcpyAsyncSqe_t* memcpyAsyncSqePtr = reinterpret_cast<const rtStarsMemcpyAsyncSqe_t*>(sqePtr);
1200 0 : taskId = memcpyAsyncSqePtr->header.taskId;
1201 0 : streamId = memcpyAsyncSqePtr->header.rtStreamId;
1202 0 : } else if (sqeType == SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE) {
1203 0 : const rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqePtr);
1204 0 : taskId = placeholderSqePtr->header.taskId;
1205 0 : streamId = placeholderSqePtr->header.rtStreamId;
1206 : } else {
1207 0 : HCCL_ERROR("[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] invalid sqeType[%u]", sqeType);
1208 0 : return HCCL_E_INTERNAL;
1209 : }
1210 :
1211 : // memcpy / cache-memcpy placeholder SQE的src/dst memType一定不是invalid
1212 : // 注意: memcpy-record SQE的src/dst一定是invalid, 但不会进入本函数
1213 0 : const uint8_t srcMemType = srcRefreshAddrInfo.memType;
1214 0 : const uint8_t dstMemType = dstRefreshAddrInfo.memType;
1215 0 : CHK_PRT_RET(
1216 : srcMemType == RefreshAddrInfo::INVALID_MEMTYPE || dstMemType == RefreshAddrInfo::INVALID_MEMTYPE,
1217 : HCCL_ERROR(
1218 : "[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] sqeType[%u] streamId[%u] taskId[%u] srcMemType[%u] "
1219 : "dstMemType[%u]",
1220 : sqeType, streamId, taskId, srcMemType, dstMemType),
1221 : HCCL_E_INTERNAL);
1222 :
1223 : // src一定不是user output
1224 0 : CHK_PRT_RET(
1225 : srcMemType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE,
1226 : HCCL_ERROR(
1227 : "[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] sqeType[%u] streamId[%u] taskId[%u] srcMemType[%u]",
1228 : sqeType, streamId, taskId, srcMemType),
1229 : HCCL_E_INTERNAL);
1230 :
1231 : // src是user input时, dst一定是user output / hccl input
1232 : // src是hccl input时, dst一定是user output
1233 0 : if (srcMemType == RefreshAddrInfo::USER_INPUT_MEMTYPE) {
1234 0 : CHK_PRT_RET(
1235 : dstMemType != RefreshAddrInfo::USER_OUTPUT_MEMTYPE && dstMemType != RefreshAddrInfo::HCCL_INPUT_MEMTYPE,
1236 : HCCL_ERROR(
1237 : "[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] sqeType[%u] streamId[%u] taskId[%u] dstMemType[%u]",
1238 : sqeType, streamId, taskId, dstMemType),
1239 : HCCL_E_INTERNAL);
1240 0 : } else if (srcMemType == RefreshAddrInfo::HCCL_INPUT_MEMTYPE) {
1241 0 : CHK_PRT_RET(
1242 : dstMemType != RefreshAddrInfo::USER_OUTPUT_MEMTYPE,
1243 : HCCL_ERROR(
1244 : "[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] sqeType[%u] streamId[%u] taskId[%u] dstMemType[%u]",
1245 : sqeType, streamId, taskId, dstMemType),
1246 : HCCL_E_INTERNAL);
1247 : }
1248 :
1249 : // dst一定不是user input
1250 0 : CHK_PRT_RET(
1251 : dstMemType == RefreshAddrInfo::USER_INPUT_MEMTYPE,
1252 : HCCL_ERROR(
1253 : "[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] sqeType[%u] streamId[%u] taskId[%u] dstMemType[%u]",
1254 : sqeType, streamId, taskId, dstMemType),
1255 : HCCL_E_INTERNAL);
1256 :
1257 : // dst是user output时, src一定是user input / hccl input
1258 : // dst是hccl input时, src一定是user input
1259 0 : if (dstMemType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) {
1260 0 : CHK_PRT_RET(
1261 : srcMemType != RefreshAddrInfo::USER_INPUT_MEMTYPE && srcMemType != RefreshAddrInfo::HCCL_INPUT_MEMTYPE,
1262 : HCCL_ERROR(
1263 : "[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] sqeType[%u] streamId[%u] taskId[%u] srcMemType[%u]",
1264 : sqeType, streamId, taskId, srcMemType),
1265 : HCCL_E_INTERNAL);
1266 0 : } else if (dstMemType == RefreshAddrInfo::HCCL_INPUT_MEMTYPE) {
1267 0 : CHK_PRT_RET(
1268 : srcMemType != RefreshAddrInfo::USER_INPUT_MEMTYPE,
1269 : HCCL_ERROR(
1270 : "[OpUnfoldCacheEntry][CheckMemTypeForAlltoallv] sqeType[%u] streamId[%u] taskId[%u] srcMemType[%u]",
1271 : sqeType, streamId, taskId, srcMemType),
1272 : HCCL_E_INTERNAL);
1273 : }
1274 :
1275 0 : return HCCL_SUCCESS;
1276 : }
1277 :
1278 0 : HcclResult OpUnfoldCacheEntry::UpdateTransferSqeForAlltoallv(
1279 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId, const RefreshAddrInfo& srcRefreshAddrInfo,
1280 : const RefreshAddrInfo& dstRefreshAddrInfo, const std::vector<OpUnfoldMemRange>& curUserInputMemRanges,
1281 : const std::vector<OpUnfoldMemRange>& curUserOutputMemRanges, const AlltoallvMetadata& alltoallvMetadata,
1282 : const AlltoallvSendRecvInfo& alltoallvSendRecvInfo)
1283 : {
1284 0 : HCCL_INFO(
1285 : "[OpUnfoldCacheEntry][UpdateTransferSqeForAlltoallv] curTaskId[%u] srcMemType[%u] dstMemType[%u]", curTaskId,
1286 : srcRefreshAddrInfo.memType, dstRefreshAddrInfo.memType);
1287 :
1288 : // 先判断是否需要刷新此memcpy SQE
1289 0 : if (srcRefreshAddrInfo.memType != RefreshAddrInfo::USER_INPUT_MEMTYPE
1290 0 : && dstRefreshAddrInfo.memType != RefreshAddrInfo::USER_OUTPUT_MEMTYPE) {
1291 : // 注意: 由于alltoallv direct fullmesh不会调用InlineReduceAsync和基于memcpy的SignalRecord
1292 : // 理论上所有的memcpy / cache-memcpy SQE都需要地址刷新, 不会进入当前code block
1293 :
1294 : // 更新task id
1295 0 : if ((*sqeTypePtr) == SqeType::MEMCPY_ASYNC_SQE) {
1296 0 : rtStarsMemcpyAsyncSqe_t* memcpyAsyncSqePtr = reinterpret_cast<rtStarsMemcpyAsyncSqe_t*>(sqePtr);
1297 0 : memcpyAsyncSqePtr->header.taskId = curTaskId;
1298 0 : } else if ((*sqeTypePtr) == SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE) {
1299 0 : rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<rtStarsPlaceHolderSqe_t*>(sqePtr);
1300 0 : placeholderSqePtr->header.taskId = curTaskId;
1301 : } else {
1302 0 : HCCL_ERROR("[OpUnfoldCacheEntry][UpdateTransferSqeForAlltoallv] invalid sqeType[%u]", *sqeTypePtr);
1303 0 : return HCCL_E_INTERNAL;
1304 : }
1305 :
1306 0 : return HCCL_SUCCESS;
1307 : }
1308 : // 注意: 从这里开始, srcAddr为userInput和dstAddr为userOutput至少有一个条件满足
1309 :
1310 : // 校验alltoallv相关参数
1311 0 : CHK_RET(alltoallvMetadata.Check(true));
1312 0 : CHK_RET(alltoallvSendRecvInfo.Check());
1313 0 : const uint32_t rankSize = alltoallvSendRecvInfo.sendOffsets.size();
1314 0 : CHK_PRT_RET(
1315 : rankSize != alltoallvMetadata.hcclInputMemRanges.size(),
1316 : HCCL_ERROR(
1317 : "[OpUnfoldCacheEntry][UpdateTransferSqeForAlltoallv] hcclInputMemRanges.size[%u] != rankSize[%u]",
1318 : alltoallvMetadata.hcclInputMemRanges.size(), rankSize),
1319 : HCCL_E_INTERNAL);
1320 :
1321 : // 获取当前memcpy类SQE对应的count和size
1322 0 : uint64_t count = 0;
1323 0 : uint64_t size = 0; // send/recv bytes
1324 0 : CHK_RET(GetTransferCountForAlltoallv(
1325 : count, size, srcRefreshAddrInfo, dstRefreshAddrInfo, alltoallvMetadata, alltoallvSendRecvInfo));
1326 :
1327 : // 更新/生成相应SQE
1328 0 : if ((*sqeTypePtr) == SqeType::MEMCPY_ASYNC_SQE) {
1329 0 : CHK_RET(UpdateMemcpySqeForAlltoallv(
1330 : sqePtr, sqeTypePtr, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, curUserInputMemRanges,
1331 : curUserOutputMemRanges, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1332 0 : } else if ((*sqeTypePtr) == SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE) {
1333 0 : CHK_RET(UpdateMemcpyPlaceholderSqeForAlltoallv(
1334 : sqePtr, sqeTypePtr, curTaskId, srcRefreshAddrInfo, dstRefreshAddrInfo, curUserInputMemRanges,
1335 : curUserOutputMemRanges, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1336 : } else {
1337 0 : HCCL_ERROR("[OpUnfoldCacheEntry][UpdateTransferSqeForAlltoallv] invalid sqeType[%u]", *sqeTypePtr);
1338 0 : return HCCL_E_INTERNAL;
1339 : }
1340 :
1341 0 : return HCCL_SUCCESS;
1342 : }
1343 :
1344 0 : HcclResult OpUnfoldCacheEntry::GetTransferCountForAlltoallv(
1345 : uint64_t& count, uint64_t& size, const RefreshAddrInfo& srcRefreshAddrInfo,
1346 : const RefreshAddrInfo& dstRefreshAddrInfo, const AlltoallvMetadata& alltoallvMetadata,
1347 : const AlltoallvSendRecvInfo& alltoallvSendRecvInfo) const
1348 : {
1349 : // 注意: 如果对应send count, 一定是LocalCopy或者PrepareIntraData, 即local user input -> local user output / hccl
1350 : // input 注意: 如果对应recv count, 一定是RemoteCopy, 即remote hccl input -> local user output
1351 0 : const uint32_t rankSize = alltoallvSendRecvInfo.sendOffsets.size();
1352 0 : if (srcRefreshAddrInfo.memType == RefreshAddrInfo::USER_INPUT_MEMTYPE) { // LocalCopy/PrepareIntraData
1353 : // 获得local rank
1354 0 : uint32_t localRank = srcRefreshAddrInfo.rankId;
1355 0 : CHK_PRT_RET(
1356 : localRank >= rankSize,
1357 : HCCL_ERROR(
1358 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] localRank[%u] >= rankSize[%u]", localRank,
1359 : rankSize),
1360 : HCCL_E_INTERNAL);
1361 :
1362 : // 获得dst rank
1363 0 : uint32_t dstRank = 0;
1364 0 : if (dstRefreshAddrInfo.memType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // LocalCopy
1365 0 : dstRank = dstRefreshAddrInfo.rankId; // dstRank = localRank
1366 0 : CHK_PRT_RET(
1367 : dstRank != localRank,
1368 : HCCL_ERROR(
1369 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] dstRank[%u] != localRank[%u]", dstRank,
1370 : localRank),
1371 : HCCL_E_INTERNAL);
1372 0 : } else if (dstRefreshAddrInfo.memType == RefreshAddrInfo::HCCL_INPUT_MEMTYPE) { // PrepareIntraData
1373 : // dstRank在第一次cache miss后处理时, 被UpdateRefreshAddrInfoForAlltoallv更新, 一定不等于localRank
1374 0 : dstRank = dstRefreshAddrInfo.rankId;
1375 0 : CHK_PRT_RET(
1376 : dstRank == localRank,
1377 : HCCL_ERROR(
1378 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] dstRank[%u] = localRank[%u]", dstRank,
1379 : localRank),
1380 : HCCL_E_INTERNAL);
1381 : } else {
1382 0 : HCCL_ERROR(
1383 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] invalid dstMemType[%u]",
1384 : dstRefreshAddrInfo.memType);
1385 0 : return HCCL_E_INTERNAL;
1386 : }
1387 :
1388 : // 获得dst rank对应的send count/size
1389 0 : CHK_PRT_RET(
1390 : dstRank >= rankSize,
1391 : HCCL_ERROR(
1392 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] dstRank[%u] >= rankSize[%u]", dstRank, rankSize),
1393 : HCCL_E_INTERNAL);
1394 0 : count = alltoallvSendRecvInfo.sendCounts[dstRank];
1395 0 : size = count * SIZE_TABLE[alltoallvSendRecvInfo.sendType];
1396 :
1397 0 : HCCL_INFO(
1398 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] sendCount[%llu] sendSize[%llu] dstRank[%u]", count,
1399 : size, dstRank);
1400 0 : } else if (dstRefreshAddrInfo.memType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // srcAddr不是user input,
1401 : // 但dstAddr是user output (remote
1402 : // copy: remote hccl input -> local
1403 : // user output)
1404 0 : CHK_PRT_RET(
1405 : srcRefreshAddrInfo.memType != RefreshAddrInfo::HCCL_INPUT_MEMTYPE,
1406 : HCCL_ERROR(
1407 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] invalid srcMemType[%u] for remote copy",
1408 : srcRefreshAddrInfo.memType),
1409 : HCCL_E_INTERNAL);
1410 :
1411 : // 获得src rank对应的recv count/size
1412 0 : uint32_t srcRank = srcRefreshAddrInfo.rankId;
1413 0 : CHK_PRT_RET(
1414 : srcRank >= rankSize,
1415 : HCCL_ERROR(
1416 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] srcRank[%u] >= rankSize[%u]", srcRank, rankSize),
1417 : HCCL_E_INTERNAL);
1418 0 : count = alltoallvSendRecvInfo.recvCounts[srcRank];
1419 0 : size = count * SIZE_TABLE[alltoallvSendRecvInfo.recvType];
1420 :
1421 0 : HCCL_INFO(
1422 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] recvCount[%llu] recvSize[%llu] srcRank[%u]", count,
1423 : size, srcRank);
1424 : } else {
1425 0 : HCCL_ERROR(
1426 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] invalid srcMemType[%u] and dstMemType[%u]",
1427 : srcRefreshAddrInfo.memType, dstRefreshAddrInfo.memType);
1428 0 : return HCCL_E_INTERNAL;
1429 : }
1430 :
1431 : // 一定不是大数据量的alltoallv, 否则会在aicpu communicator侧被拦截, 不会进入cache
1432 0 : CHK_PRT_RET(
1433 : size > alltoallvMetadata.sdmaDataBlockSize || size > HCCL_SDMA_MAX_COUNT_4GB,
1434 : HCCL_ERROR(
1435 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] invalid size[%u] sdmaDataBlockSize[%u] 4GB[%u]", size,
1436 : alltoallvMetadata.sdmaDataBlockSize, HCCL_SDMA_MAX_COUNT_4GB),
1437 : HCCL_E_INTERNAL);
1438 :
1439 0 : return HCCL_SUCCESS;
1440 : }
1441 :
1442 0 : HcclResult OpUnfoldCacheEntry::UpdateMemcpySqeForAlltoallv(
1443 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId, const RefreshAddrInfo& srcRefreshAddrInfo,
1444 : const RefreshAddrInfo& dstRefreshAddrInfo, const std::vector<OpUnfoldMemRange>& curUserInputMemRanges,
1445 : const std::vector<OpUnfoldMemRange>& curUserOutputMemRanges,
1446 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata, const AlltoallvSendRecvInfo& alltoallvSendRecvInfo,
1447 : const uint64_t count, const uint64_t size)
1448 : {
1449 : // 获取src/dst memType
1450 0 : const uint8_t srcMemType = srcRefreshAddrInfo.memType;
1451 0 : const uint8_t dstMemType = dstRefreshAddrInfo.memType;
1452 :
1453 : // 更新SQE (count > 0)或者生成SQE (count = 0)
1454 0 : const uint32_t rankSize = alltoallvSendRecvInfo.sendOffsets.size();
1455 0 : rtStarsMemcpyAsyncSqe_t* memcpyAsyncSqePtr = reinterpret_cast<rtStarsMemcpyAsyncSqe_t*>(sqePtr);
1456 0 : if (count > 0) { // Case 1: memcpy SQE -> memcpy SQE
1457 0 : HCCL_DEBUG(
1458 : "[OpUnfoldCacheEntry][UpdateMemcpySqeForAlltoallv] case 1: memcpy -> memcpy; curTaskId[%u]", curTaskId);
1459 :
1460 : // 校验length
1461 0 : CHK_PRT_RET(
1462 : size == 0,
1463 : HCCL_ERROR("[OpUnfoldCacheEntry][UpdateMemcpySqeForAlltoallv] size[%u] for positive count", size),
1464 : HCCL_E_INTERNAL);
1465 :
1466 : // 更新task id
1467 0 : memcpyAsyncSqePtr->header.taskId = curTaskId;
1468 :
1469 : // 更新length
1470 0 : memcpyAsyncSqePtr->length = static_cast<uint32_t>(size);
1471 :
1472 : // 更新src/dst addr
1473 0 : if (srcMemType == RefreshAddrInfo::USER_INPUT_MEMTYPE) { // LocalCopy/PrepareIntraData
1474 : // 获取send offset
1475 0 : const uint32_t dstRank
1476 : = dstRefreshAddrInfo.rankId; // LocalCopy下是localRank, PrepareIntraData下是remoteRank
1477 0 : CHK_PRT_RET(
1478 : dstRank >= rankSize,
1479 : HCCL_ERROR(
1480 : "[OpUnfoldCacheEntry][UpdateMemcpySqeForAlltoallv] dstRank[%u] >= rankSize[%u]", dstRank, rankSize),
1481 : HCCL_E_INTERNAL);
1482 0 : const uint64_t sendOffset = alltoallvSendRecvInfo.sendOffsets[dstRank];
1483 :
1484 : // 更新src addr (local user input)
1485 0 : uint64_t sqeSrcAddr = 0;
1486 0 : CombineUint32ToUint64(sqeSrcAddr, memcpyAsyncSqePtr->src_addr_high, memcpyAsyncSqePtr->src_addr_low);
1487 0 : CHK_RET(RefreshSqeAddr(
1488 : sqeSrcAddr, srcRefreshAddrInfo.rankId, userInputMemRanges_, curUserInputMemRanges, true, sendOffset));
1489 0 : SplitUint64ToUint32(sqeSrcAddr, memcpyAsyncSqePtr->src_addr_high, memcpyAsyncSqePtr->src_addr_low);
1490 :
1491 : // 只有LocalCopy才需要更新dst addr (hccl addr不用刷新)
1492 0 : if (dstMemType
1493 : == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // LocalCopy (local user input -> local user output)
1494 : // 获取recv offset
1495 0 : const uint64_t recvOffset = alltoallvSendRecvInfo.recvOffsets[dstRank];
1496 :
1497 : // 更新dst addr (local user output)
1498 0 : uint64_t sqeDstAddr = 0;
1499 0 : CombineUint32ToUint64(sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
1500 0 : CHK_RET(RefreshSqeAddr(
1501 : sqeDstAddr, dstRank, userOutputMemRanges_, curUserOutputMemRanges, true, recvOffset));
1502 0 : SplitUint64ToUint32(sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
1503 : }
1504 : } else { // RemoteCopy
1505 : // 获取recv offset
1506 0 : uint32_t srcRank = srcRefreshAddrInfo.rankId;
1507 0 : CHK_PRT_RET(
1508 : srcRank >= rankSize,
1509 : HCCL_ERROR(
1510 : "[OpUnfoldCacheEntry][UpdateMemcpySqeForAlltoallv] srcRank[%u] >= rankSize[%u]", srcRank, rankSize),
1511 : HCCL_E_INTERNAL);
1512 0 : const uint64_t recvOffset = alltoallvSendRecvInfo.recvOffsets[srcRank];
1513 :
1514 : // 更新dst addr (local user output)
1515 0 : uint64_t sqeDstAddr = 0;
1516 0 : CombineUint32ToUint64(sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
1517 0 : CHK_RET(RefreshSqeAddr(
1518 : sqeDstAddr, dstRefreshAddrInfo.rankId, userOutputMemRanges_, curUserOutputMemRanges, true, recvOffset));
1519 0 : SplitUint64ToUint32(sqeDstAddr, memcpyAsyncSqePtr->dst_addr_high, memcpyAsyncSqePtr->dst_addr_low);
1520 : }
1521 : } else { // Case 2: memcpy SQE -> placeholder SQE
1522 0 : HCCL_DEBUG(
1523 : "[OpUnfoldCacheEntry][UpdateMemcpySqeForAlltoallv] case 2: memcpy -> placeholder; curTaskId[%u]",
1524 : curTaskId);
1525 :
1526 : // 校验length
1527 0 : CHK_PRT_RET(
1528 : size != 0, HCCL_ERROR("[OpUnfoldCacheEntry][UpdateMemcpySqeForAlltoallv] size[%u] for zero count", size),
1529 : HCCL_E_INTERNAL);
1530 :
1531 : // 保留original SQE中的相关信息
1532 0 : const uint16_t streamId = memcpyAsyncSqePtr->header.rtStreamId;
1533 0 : const uint8_t kernelCredit = memcpyAsyncSqePtr->kernel_credit;
1534 0 : const uint8_t linkType = memcpyAsyncSqePtr->linkType;
1535 0 : const uint32_t qos = memcpyAsyncSqePtr->qos;
1536 0 : uint32_t dstAddrHigh = 0;
1537 0 : uint32_t dstAddrLow = 0;
1538 0 : bool saveDstAddr = false;
1539 0 : if (srcMemType == RefreshAddrInfo::USER_INPUT_MEMTYPE
1540 0 : && dstMemType == RefreshAddrInfo::HCCL_INPUT_MEMTYPE) { // PrepareIntraData
1541 : // 保留dst addr (local hccl input)
1542 : // 注意: 非PrepraeIntraData case下, dst addr为local user output, 会动态计算, 无需保留在placeholder中
1543 0 : dstAddrHigh = memcpyAsyncSqePtr->dst_addr_high;
1544 0 : dstAddrLow = memcpyAsyncSqePtr->dst_addr_low;
1545 0 : saveDstAddr = true;
1546 : }
1547 0 : uint32_t srcAddrHigh = 0;
1548 0 : uint32_t srcAddrLow = 0;
1549 0 : bool saveSrcAddr = false;
1550 0 : if (srcMemType == RefreshAddrInfo::HCCL_INPUT_MEMTYPE
1551 0 : && dstMemType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // RemoteCopy
1552 : // 保留src addr (remote hccl intput)
1553 : // 注意: 非RemoteCopy case下, src addr为local user input, 会动态计算, 无需保留在placeholder中
1554 0 : srcAddrHigh = memcpyAsyncSqePtr->src_addr_high;
1555 0 : srcAddrLow = memcpyAsyncSqePtr->src_addr_low;
1556 0 : saveSrcAddr = true;
1557 : }
1558 :
1559 : // 清空original SQE
1560 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
1561 :
1562 : // 生成placeholder SQE
1563 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneCacheMemcpyPlaceholderSqeV1
1564 0 : *sqeTypePtr = SqeType::CACHE_MEMCPY_PLACEHOLDER_SQE;
1565 0 : SetCachePlaceholderHeaderForAlltoallv(streamId, curTaskId, sqePtr);
1566 :
1567 : // 注意: 正常情况下无需设置placeholder SQE中的src/dst addr
1568 : // (只用于第一次算子执行发生cache miss时, 根据memory range获得对应的RefreshAddrInfo, 后续不再使用)
1569 0 : rtStarsPlaceHolderSqe_t* const placeholderSqePtr = (rtStarsPlaceHolderSqe_t*)sqePtr;
1570 0 : if (saveDstAddr) { // PrepareIntraData case下需要保留dst addr (local hccl input)
1571 0 : placeholderSqePtr->u.cache_memcpy_task_info.dst_addr_high = dstAddrHigh;
1572 0 : placeholderSqePtr->u.cache_memcpy_task_info.dst_addr_low = dstAddrLow;
1573 : }
1574 0 : if (saveSrcAddr) { // RemoteCopy case下需要保留src addr (remote hccl input)
1575 0 : placeholderSqePtr->u.cache_memcpy_task_info.src_addr_high = srcAddrHigh;
1576 0 : placeholderSqePtr->u.cache_memcpy_task_info.src_addr_low = srcAddrLow;
1577 : }
1578 0 : placeholderSqePtr->u.cache_memcpy_task_info.kernel_credit = kernelCredit;
1579 0 : placeholderSqePtr->u.cache_memcpy_task_info.linkType = linkType;
1580 0 : placeholderSqePtr->u.cache_memcpy_task_info.qos = qos;
1581 : }
1582 :
1583 0 : return HCCL_SUCCESS;
1584 : }
1585 :
1586 0 : HcclResult OpUnfoldCacheEntry::UpdateMemcpyPlaceholderSqeForAlltoallv(
1587 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId, const RefreshAddrInfo& srcRefreshAddrInfo,
1588 : const RefreshAddrInfo& dstRefreshAddrInfo, const std::vector<OpUnfoldMemRange>& curUserInputMemRanges,
1589 : const std::vector<OpUnfoldMemRange>& curUserOutputMemRanges,
1590 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata, const AlltoallvSendRecvInfo& alltoallvSendRecvInfo,
1591 : const uint64_t count, const uint64_t size)
1592 : {
1593 : // 更新SQE (count = 0)或者生成SQE (count > 0)
1594 0 : const uint32_t rankSize = alltoallvSendRecvInfo.sendOffsets.size();
1595 0 : rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<rtStarsPlaceHolderSqe_t*>(sqePtr);
1596 0 : if (count == 0) { // Case 3: placeholder SQE -> placeholder SQE
1597 0 : HCCL_DEBUG(
1598 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] case 3: placeholder -> placeholder; "
1599 : "curTaskId[%u]",
1600 : curTaskId);
1601 :
1602 : // 校验length
1603 0 : CHK_PRT_RET(
1604 : size != 0,
1605 : HCCL_ERROR("[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] size[%u] for zero count", size),
1606 : HCCL_E_INTERNAL);
1607 :
1608 : // 更新task id
1609 0 : placeholderSqePtr->header.taskId = curTaskId;
1610 :
1611 : // 注意: 无需更新placeholder SQE中的src/dst addr (只用于第一次算子执行发生cache miss时, 根据memory
1612 : // range获得对应的RefreshAddrInfo, 后续不再使用)
1613 : } else { // Case 4: placeholder SQE -> memcpy SQE
1614 0 : HCCL_DEBUG(
1615 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] case 4: placeholder -> memcpy; curTaskId[%u]",
1616 : curTaskId);
1617 :
1618 : // 校验length
1619 0 : CHK_PRT_RET(
1620 : size == 0,
1621 : HCCL_ERROR(
1622 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] size[%u] for positive count", size),
1623 : HCCL_E_INTERNAL);
1624 :
1625 : // 保留original SQE中的相关信息
1626 0 : const uint16_t streamId = placeholderSqePtr->header.rtStreamId;
1627 0 : const uint8_t kernelCredit = placeholderSqePtr->u.cache_memcpy_task_info.kernel_credit;
1628 0 : const uint8_t linkType = placeholderSqePtr->u.cache_memcpy_task_info.linkType;
1629 0 : const uint32_t qos = placeholderSqePtr->u.cache_memcpy_task_info.qos;
1630 :
1631 : // 准备src/dst addr
1632 0 : uint64_t sqeSrcAddr = 0;
1633 0 : uint64_t sqeDstAddr = 0;
1634 0 : if (srcRefreshAddrInfo.memType == RefreshAddrInfo::USER_INPUT_MEMTYPE) { // LocalCopy/PrepareIntraData
1635 : // 获取send offset
1636 0 : const uint32_t dstRank
1637 : = dstRefreshAddrInfo.rankId; // LocalCopy下是localRank, PrepareIntraData下是remoteRank
1638 0 : CHK_PRT_RET(
1639 : dstRank >= rankSize,
1640 : HCCL_ERROR(
1641 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] dstRank[%u] >= rankSize[%u]", dstRank,
1642 : rankSize),
1643 : HCCL_E_INTERNAL);
1644 0 : const uint64_t sendOffset = alltoallvSendRecvInfo.sendOffsets[dstRank];
1645 :
1646 : // 获得src addr (local user input)
1647 0 : const uint32_t localRank = srcRefreshAddrInfo.rankId;
1648 0 : CHK_PRT_RET(
1649 : localRank >= rankSize,
1650 : HCCL_ERROR(
1651 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] localRank[%u] >= rankSize[%u]",
1652 : localRank, rankSize),
1653 : HCCL_E_INTERNAL);
1654 0 : const uint64_t localUserInputBaseAddr = curUserInputMemRanges[localRank].baseAddr;
1655 0 : sqeSrcAddr = localUserInputBaseAddr + sendOffset;
1656 :
1657 0 : if (dstRefreshAddrInfo.memType == RefreshAddrInfo::USER_OUTPUT_MEMTYPE) { // LocalCopy
1658 : // 获取recv offset
1659 0 : const uint64_t recvOffset = alltoallvSendRecvInfo.recvOffsets[dstRank]; // dstRank = localRank
1660 :
1661 : // 获得dst addr (local user output)
1662 0 : const uint64_t localUserOutputBaseAddr = curUserOutputMemRanges[dstRank].baseAddr;
1663 0 : sqeDstAddr = localUserOutputBaseAddr + recvOffset;
1664 0 : } else if (dstRefreshAddrInfo.memType == RefreshAddrInfo::HCCL_INPUT_MEMTYPE) { // PrepareIntraData
1665 : // 从placeholder中获取dst addr (local hccl input)
1666 0 : const uint32_t dstAddrHigh = placeholderSqePtr->u.cache_memcpy_task_info.dst_addr_high;
1667 0 : const uint32_t dstAddrLow = placeholderSqePtr->u.cache_memcpy_task_info.dst_addr_low;
1668 0 : CombineUint32ToUint64(sqeDstAddr, dstAddrHigh, dstAddrLow);
1669 : } else {
1670 0 : HCCL_ERROR(
1671 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] invalid srcMemType[%u] "
1672 : "dstMemType[%u]",
1673 : srcRefreshAddrInfo.memType, dstRefreshAddrInfo.memType);
1674 0 : return HCCL_E_INTERNAL;
1675 : }
1676 : } else { // RemoteCopy
1677 : // 从placeholder中获取src addr (remote hccl input)
1678 0 : const uint32_t srcAddrHigh = placeholderSqePtr->u.cache_memcpy_task_info.src_addr_high;
1679 0 : const uint32_t srcAddrLow = placeholderSqePtr->u.cache_memcpy_task_info.src_addr_low;
1680 0 : CombineUint32ToUint64(sqeSrcAddr, srcAddrHigh, srcAddrLow);
1681 :
1682 : // 获得remote src rank
1683 0 : const uint32_t srcRank = srcRefreshAddrInfo.rankId;
1684 0 : CHK_PRT_RET(
1685 : srcRank >= rankSize,
1686 : HCCL_ERROR(
1687 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] srcRank[%u] >= rankSize[%u]", srcRank,
1688 : rankSize),
1689 : HCCL_E_INTERNAL);
1690 :
1691 : // 获得recv offset
1692 0 : const uint64_t recvOffset = alltoallvSendRecvInfo.recvOffsets[srcRank]; // srcRank = remoteRank
1693 :
1694 : // 获得dst addr
1695 0 : const uint32_t localRank = dstRefreshAddrInfo.rankId;
1696 0 : CHK_PRT_RET(
1697 : localRank >= rankSize,
1698 : HCCL_ERROR(
1699 : "[OpUnfoldCacheEntry][UpdateMemcpyPlaceholderSqeForAlltoallv] localRank[%u] >= rankSize[%u]",
1700 : localRank, rankSize),
1701 : HCCL_E_INTERNAL);
1702 0 : const uint64_t localUserOutputBaseAddr = curUserOutputMemRanges[localRank].baseAddr;
1703 0 : sqeDstAddr = localUserOutputBaseAddr + recvOffset;
1704 : }
1705 :
1706 : // 清空original SQE
1707 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
1708 :
1709 : // 生成memcpy SQE
1710 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneMemcpySqeV1
1711 0 : *sqeTypePtr = SqeType::MEMCPY_ASYNC_SQE;
1712 0 : rtStarsMemcpyAsyncSqe_t* memcpySqePtr = reinterpret_cast<rtStarsMemcpyAsyncSqe_t*>(sqePtr);
1713 0 : memcpySqePtr->header.type = RT_STARS_SQE_TYPE_SDMA;
1714 0 : memcpySqePtr->header.rtStreamId = streamId;
1715 0 : memcpySqePtr->header.taskId = curTaskId;
1716 0 : memcpySqePtr->kernel_credit = kernelCredit;
1717 0 : memcpySqePtr->opcode = 0U;
1718 0 : memcpySqePtr->length = static_cast<uint32_t>(size);
1719 0 : SplitUint64ToUint32(sqeSrcAddr, memcpySqePtr->src_addr_high, memcpySqePtr->src_addr_low);
1720 0 : SplitUint64ToUint32(sqeDstAddr, memcpySqePtr->dst_addr_high, memcpySqePtr->dst_addr_low);
1721 0 : memcpySqePtr->sssv = 1U;
1722 0 : memcpySqePtr->dssv = 1U;
1723 0 : memcpySqePtr->sns = 1U;
1724 0 : memcpySqePtr->dns = 1U;
1725 0 : memcpySqePtr->qos = 6; // 6 is HCCL QoS
1726 0 : const uint32_t partId = 0; // 参考dispatcher_aicpu.cc中addOneMemcpySqe_的partId传参始终为0
1727 0 : memcpySqePtr->partid = partId;
1728 0 : memcpySqePtr->linkType = linkType;
1729 0 : memcpySqePtr->qos = qos;
1730 : }
1731 :
1732 0 : return HCCL_SUCCESS;
1733 : }
1734 :
1735 0 : HcclResult OpUnfoldCacheEntry::RefreshSqeAddr(
1736 : uint64_t& sqeAddr, const uint32_t rankId, const std::vector<OpUnfoldMemRange>& cachedMemRanges,
1737 : const std::vector<OpUnfoldMemRange>& curMemRanges, const bool isAlltoallv, const uint64_t offset) const
1738 : {
1739 0 : CHK_PRT_RET(
1740 : rankId == INVALID_VALUE_RANKID, HCCL_ERROR("[OpUnfoldCacheEntry][RefreshSqeAddr] invalid rankId"),
1741 : HCCL_E_INTERNAL);
1742 0 : CHK_PRT_RET(
1743 : rankId >= cachedMemRanges.size(),
1744 : HCCL_ERROR(
1745 : "[OpUnfoldCacheEntry][RefreshSqeAddr] rankId %u exceeds rankSize %u", rankId, cachedMemRanges.size()),
1746 : HCCL_E_INTERNAL);
1747 :
1748 : // 获取缓存的和当前的memory ranges
1749 0 : const OpUnfoldMemRange& cachedMemRange = cachedMemRanges[rankId];
1750 0 : const OpUnfoldMemRange& curMemRange = curMemRanges[rankId];
1751 0 : HCCL_DEBUG(
1752 : "[OpUnfoldCacheEntry][RefreshSqeAddr] cachedMemRange: isValid[%u] baseAddr[0x%016llx] memSize[%llu]; "
1753 : "curMemRange: isValid[%u] baseAddr[0x%016llx] memSize[%llu] isAlltoallv[%u]",
1754 : cachedMemRange.isValid, cachedMemRange.baseAddr, cachedMemRange.memSize, curMemRange.isValid,
1755 : curMemRange.baseAddr, curMemRange.memSize, isAlltoallv);
1756 :
1757 : // 刷新前地址校验
1758 : // (i) user memory: 非V类/alltoallv, SQE addr字段一定在user memory range内, 才需要调用本函数刷新addr
1759 : // (ii) hccl memory: alltoallv, SQE addr一定在hccl memory range内, 才需要调用本函数生成addr
1760 0 : bool isInRange = false;
1761 0 : CHK_RET(cachedMemRange.InRange(sqeAddr, isInRange));
1762 0 : CHK_PRT_RET(
1763 : !isInRange,
1764 : HCCL_ERROR(
1765 : "[OpUnfoldCacheEntry][RefreshSqeAddr] sqeAddr[0x%016llx] not in the range of cachedMemRange[0x%016llx, "
1766 : "0x%016llx)",
1767 : sqeAddr, cachedMemRange.baseAddr, cachedMemRange.baseAddr + cachedMemRange.memSize),
1768 : HCCL_E_INTERNAL);
1769 :
1770 : // 刷新SQE addr
1771 0 : uint64_t curOffset = 0;
1772 0 : if (isAlltoallv) { // alltoallv
1773 0 : curOffset = offset; // 使用给定的offset
1774 : } else { // 非V类算子
1775 0 : curOffset = sqeAddr - cachedMemRange.baseAddr; // 计算缓存的sqe addr相对于缓存的base addr的offset
1776 : }
1777 0 : sqeAddr = curMemRange.baseAddr + curOffset; // 用当前的base addr更新sqe addr
1778 :
1779 : // 刷新后地址校验: 一定在当前的memory range内
1780 0 : isInRange = false;
1781 0 : CHK_RET(curMemRange.InRange(sqeAddr, isInRange));
1782 0 : CHK_PRT_RET(
1783 : !isInRange,
1784 : HCCL_ERROR(
1785 : "[OpUnfoldCacheEntry][RefreshSqeAddr] sqeAddr[0x%016llx] not in the range of curMemRange[0x%016llx, "
1786 : "0x%016llx)",
1787 : sqeAddr, curMemRange.baseAddr, curMemRange.baseAddr + curMemRange.memSize),
1788 : HCCL_E_INTERNAL);
1789 :
1790 0 : return HCCL_SUCCESS;
1791 : }
1792 :
1793 0 : HcclResult OpUnfoldCacheEntry::UpdateSyncSqeForAlltoallv(
1794 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId, const RefreshAddrInfo& srcRefreshAddrInfo,
1795 : const RefreshAddrInfo& dstRefreshAddrInfo, const AlltoallvMetadata& alltoallvMetadata,
1796 : const AlltoallvSendRecvInfo& alltoallvSendRecvInfo)
1797 : {
1798 0 : HCCL_INFO("[OpUnfoldCacheEntry][UpdateSyncSqeForAlltoallv] curTaskId[%u]", curTaskId);
1799 :
1800 : // 校验alltoallv相关参数
1801 0 : CHK_RET(alltoallvMetadata.Check(true));
1802 0 : CHK_RET(alltoallvSendRecvInfo.Check());
1803 0 : const uint32_t rankSize = alltoallvSendRecvInfo.sendOffsets.size();
1804 0 : CHK_PRT_RET(
1805 : rankSize != alltoallvMetadata.hcclInputMemRanges.size(),
1806 : HCCL_ERROR(
1807 : "[OpUnfoldCacheEntry][UpdateSyncSqeForAlltoallv] hcclInputMemRanges.size[%u] != rankSize[%u]",
1808 : alltoallvMetadata.hcclInputMemRanges.size(), rankSize),
1809 : HCCL_E_INTERNAL);
1810 :
1811 : // 对于NotifyWait, 如果不在notifyid-rank map中, 则无需根据count进行处理, 只需要更新taskid
1812 : // 对于WriteValue/MemcpyRecord, 如果不在signaladdr-rank map中, 则无需根据count进行处理, 只需要更新taskid
1813 0 : if ((*sqeTypePtr) == SqeType::NOTIFY_SQE) {
1814 0 : rtStarsNotifySqeV1_t* notifySqePtr = reinterpret_cast<rtStarsNotifySqeV1_t*>(sqePtr);
1815 0 : const uint32_t notifyId = notifySqePtr->notify_id;
1816 0 : if (alltoallvMetadata.notifyIdRankRflagMap.find(notifyId) == alltoallvMetadata.notifyIdRankRflagMap.cend()) {
1817 0 : notifySqePtr->header.taskId = curTaskId;
1818 0 : return HCCL_SUCCESS;
1819 : }
1820 0 : } else if ((*sqeTypePtr) == SqeType::WRITE_VALUE_SQE) {
1821 0 : rtStarsWriteValueSqe_t* writeValueSqePtr = reinterpret_cast<rtStarsWriteValueSqe_t*>(sqePtr);
1822 0 : uint64_t signalAddr = 0;
1823 0 : const uint32_t lowAddr = writeValueSqePtr->write_addr_low;
1824 0 : const uint32_t highAddr = writeValueSqePtr->write_addr_high;
1825 0 : CombineUint32ToUint64(signalAddr, highAddr, lowAddr);
1826 0 : if (alltoallvMetadata.signalAddrRankRflagMap.find(signalAddr)
1827 0 : == alltoallvMetadata.signalAddrRankRflagMap.cend()) {
1828 0 : writeValueSqePtr->header.taskId = curTaskId;
1829 0 : return HCCL_SUCCESS;
1830 : }
1831 0 : } else if ((*sqeTypePtr) == SqeType::MEMCPY_ASYNC_SQE) {
1832 : // Memcpy-record SQE的src/dst memtype一定是invalid
1833 0 : rtStarsMemcpyAsyncSqe_t* memcpySqePtr = reinterpret_cast<rtStarsMemcpyAsyncSqe_t*>(sqePtr);
1834 0 : CHK_PRT_RET(
1835 : srcRefreshAddrInfo.memType != RefreshAddrInfo::INVALID_MEMTYPE
1836 : || dstRefreshAddrInfo.memType != RefreshAddrInfo::INVALID_MEMTYPE,
1837 : HCCL_ERROR(
1838 : "[OpUnfoldCacheEntry][UpdateTransferSqeForAlltoallv] memcpy-record SQE: "
1839 : "streamId[%u] taskId[%u] curTaskId[%u] srcMemType[%u] dstMemType[%u]",
1840 : memcpySqePtr->header.rtStreamId, memcpySqePtr->header.taskId, curTaskId, srcRefreshAddrInfo.memType,
1841 : dstRefreshAddrInfo.memType),
1842 : HCCL_E_INTERNAL);
1843 :
1844 0 : uint64_t dstSignalAddr = 0;
1845 0 : const uint32_t lowAddr = memcpySqePtr->dst_addr_low;
1846 0 : const uint32_t highAddr = memcpySqePtr->dst_addr_high;
1847 0 : CombineUint32ToUint64(dstSignalAddr, highAddr, lowAddr);
1848 0 : if (alltoallvMetadata.signalAddrRankRflagMap.find(dstSignalAddr)
1849 0 : == alltoallvMetadata.signalAddrRankRflagMap.cend()) {
1850 0 : memcpySqePtr->header.taskId = curTaskId;
1851 0 : return HCCL_SUCCESS;
1852 : }
1853 : }
1854 :
1855 : // 获取当前sync类SQE对应的count和size
1856 0 : uint64_t count = 0;
1857 0 : uint64_t size = 0; // send/recv bytes
1858 0 : CHK_RET(GetTransferCountForAlltoallv(count, size, sqePtr, sqeTypePtr, alltoallvMetadata, alltoallvSendRecvInfo));
1859 :
1860 : // 更新/生成相应SQE
1861 0 : if ((*sqeTypePtr) == SqeType::CACHE_NOTIFY_PLACEHOLDER_SQE) {
1862 0 : CHK_RET(UpdateNotifyPlaceholderSqeForAlltoallv(
1863 : sqePtr, sqeTypePtr, curTaskId, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1864 0 : } else if ((*sqeTypePtr) == SqeType::CACHE_WRITE_VALUE_PLACEHOLDER_SQE) {
1865 0 : CHK_RET(UpdateWritePlaceholderSqeForAlltoallv(
1866 : sqePtr, sqeTypePtr, curTaskId, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1867 0 : } else if ((*sqeTypePtr) == SqeType::NOTIFY_SQE) {
1868 0 : CHK_RET(UpdateNotifySqeForAlltoallv(
1869 : sqePtr, sqeTypePtr, curTaskId, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1870 0 : } else if ((*sqeTypePtr) == SqeType::WRITE_VALUE_SQE) {
1871 0 : CHK_RET(UpdateWriteValueSqeForAlltoallv(
1872 : sqePtr, sqeTypePtr, curTaskId, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1873 0 : } else if ((*sqeTypePtr) == SqeType::MEMCPY_ASYNC_SQE) { // MemcpyRecord SQE
1874 0 : CHK_RET(UpdateMemcpyRecordSqeForAlltoallv(
1875 : sqePtr, sqeTypePtr, curTaskId, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1876 0 : } else if ((*sqeTypePtr) == SqeType::CACHE_MEMCPY_RECORD_PLACEHOLDER_SQE) {
1877 0 : CHK_RET(UpdateMemcpyRecordPlaceholderSqeForAlltoallv(
1878 : sqePtr, sqeTypePtr, curTaskId, alltoallvMetadata, alltoallvSendRecvInfo, count, size));
1879 : } else {
1880 0 : HCCL_ERROR("[OpUnfoldCacheEntry][UpdateTransferSqeForAlltoallv] invalid sqeType[%u]", *sqeTypePtr);
1881 0 : return HCCL_E_INTERNAL;
1882 : }
1883 :
1884 0 : return HCCL_SUCCESS;
1885 : }
1886 :
1887 0 : HcclResult OpUnfoldCacheEntry::GetTransferCountForAlltoallv(
1888 : uint64_t& count, uint64_t& size, const uint8_t* sqePtr, const uint8_t* sqeTypePtr,
1889 : const AlltoallvMetadata& alltoallvMetadata, const AlltoallvSendRecvInfo& alltoallvSendRecvInfo) const
1890 : {
1891 : // 获得notifyId或者signalAddr
1892 0 : bool isNotify = false;
1893 0 : uint32_t notifyId = 0;
1894 0 : uint64_t signalAddr = 0;
1895 0 : if ((*sqeTypePtr) == SqeType::NOTIFY_SQE) {
1896 : // 注意: 目前只有NotifyWait可能会生成cache-notify placeholder
1897 0 : const rtStarsNotifySqeV1_t* notifySqePtr = reinterpret_cast<const rtStarsNotifySqeV1_t*>(sqePtr);
1898 0 : CHK_PRT_RET(
1899 : notifySqePtr->header.type != RT_STARS_SQE_TYPE_NOTIFY_WAIT,
1900 : HCCL_ERROR("[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] header.type[%u]", notifySqePtr->header.type),
1901 : HCCL_E_INTERNAL);
1902 :
1903 0 : notifyId = notifySqePtr->notify_id;
1904 0 : isNotify = true;
1905 0 : } else if ((*sqeTypePtr) == SqeType::CACHE_NOTIFY_PLACEHOLDER_SQE) {
1906 : // 注意: 目前只会存在对应NotifyWait的placeholder
1907 0 : const rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqePtr);
1908 0 : CHK_PRT_RET(
1909 : placeholderSqePtr->u.cache_notify_task_info.is_wait != 1,
1910 : HCCL_ERROR(
1911 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] is_wait[%u]",
1912 : placeholderSqePtr->u.cache_notify_task_info.is_wait),
1913 : HCCL_E_INTERNAL);
1914 :
1915 0 : notifyId = placeholderSqePtr->u.cache_notify_task_info.notify_id;
1916 0 : isNotify = true;
1917 0 : } else if ((*sqeTypePtr) == SqeType::WRITE_VALUE_SQE) {
1918 0 : const rtStarsWriteValueSqe_t* writeValueSqePtr = reinterpret_cast<const rtStarsWriteValueSqe_t*>(sqePtr);
1919 0 : const uint32_t lowAddr = writeValueSqePtr->write_addr_low;
1920 0 : const uint32_t highAddr = writeValueSqePtr->write_addr_high;
1921 0 : CombineUint32ToUint64(signalAddr, highAddr, lowAddr);
1922 0 : isNotify = false;
1923 0 : } else if ((*sqeTypePtr) == SqeType::CACHE_WRITE_VALUE_PLACEHOLDER_SQE) {
1924 0 : const rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqePtr);
1925 0 : const uint32_t lowAddr = placeholderSqePtr->u.cache_write_value_task_info.write_addr_low;
1926 0 : const uint32_t highAddr = placeholderSqePtr->u.cache_write_value_task_info.write_addr_high;
1927 0 : CombineUint32ToUint64(signalAddr, highAddr, lowAddr);
1928 0 : isNotify = false;
1929 0 : } else if ((*sqeTypePtr) == SqeType::MEMCPY_ASYNC_SQE) { // MemcpyRecord SQE
1930 0 : const rtStarsMemcpyAsyncSqe_t* memcpySqePtr = reinterpret_cast<const rtStarsMemcpyAsyncSqe_t*>(sqePtr);
1931 0 : const uint32_t lowAddr = memcpySqePtr->dst_addr_low;
1932 0 : const uint32_t highAddr = memcpySqePtr->dst_addr_high;
1933 0 : CombineUint32ToUint64(signalAddr, highAddr, lowAddr);
1934 0 : isNotify = false;
1935 0 : } else if ((*sqeTypePtr) == SqeType::CACHE_MEMCPY_RECORD_PLACEHOLDER_SQE) {
1936 0 : const rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqePtr);
1937 0 : const uint32_t lowAddr = placeholderSqePtr->u.cache_memcpy_record_task_info.dst_addr_low;
1938 0 : const uint32_t highAddr = placeholderSqePtr->u.cache_memcpy_record_task_info.dst_addr_high;
1939 0 : CombineUint32ToUint64(signalAddr, highAddr, lowAddr);
1940 0 : isNotify = false;
1941 : } else {
1942 0 : HCCL_ERROR("[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] invalid sqeType[%u]", *sqeTypePtr);
1943 0 : return HCCL_E_INTERNAL;
1944 : }
1945 0 : HCCL_INFO(
1946 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] notifyId[%u] signalAddr[0x%016llx]", notifyId, signalAddr);
1947 :
1948 : // 获得remoteRank
1949 0 : uint32_t remoteRank = 0;
1950 0 : bool recvFlag = false;
1951 0 : if (isNotify) {
1952 : // 校验notifyId一定在notifyid-rank map中
1953 : std::unordered_map<uint32_t, RankRflag>::const_iterator mapIter
1954 0 : = alltoallvMetadata.notifyIdRankRflagMap.find(notifyId);
1955 0 : CHK_PRT_RET(
1956 : mapIter == alltoallvMetadata.notifyIdRankRflagMap.cend(),
1957 : HCCL_ERROR(
1958 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] notifyId[%u] not in alltoallvMetadata", notifyId),
1959 : HCCL_E_INTERNAL);
1960 :
1961 : // 根据notifyId获得remoteRank
1962 0 : remoteRank = mapIter->second.first;
1963 0 : recvFlag = mapIter->second.second;
1964 : } else {
1965 : // 校验signalAddr一定在signalAddr-rank map中
1966 : std::unordered_map<uint64_t, RankRflag>::const_iterator mapIter
1967 0 : = alltoallvMetadata.signalAddrRankRflagMap.find(signalAddr);
1968 0 : CHK_PRT_RET(
1969 : mapIter == alltoallvMetadata.signalAddrRankRflagMap.cend(),
1970 : HCCL_ERROR(
1971 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] signalAddr[%llu] not in alltoallvMetadata",
1972 : signalAddr),
1973 : HCCL_E_INTERNAL);
1974 :
1975 : // 根据signalAddr获得remoteRank
1976 0 : remoteRank = mapIter->second.first;
1977 0 : recvFlag = mapIter->second.second;
1978 : }
1979 0 : HCCL_INFO("[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] remoteRank[%u] recvFlag[%u]", remoteRank, recvFlag);
1980 :
1981 : // 校验remoteRank (理论上一定不是localRank)
1982 0 : const uint32_t rankSize = alltoallvSendRecvInfo.sendOffsets.size();
1983 0 : CHK_PRT_RET(
1984 : remoteRank >= rankSize,
1985 : HCCL_ERROR(
1986 : "[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] remoteRank[%u] >= rankSize[%u]", remoteRank, rankSize),
1987 : HCCL_E_INTERNAL);
1988 :
1989 : // 根据remoteRank获得count和size
1990 0 : if (recvFlag) {
1991 0 : count = alltoallvSendRecvInfo.recvCounts[remoteRank];
1992 0 : size = count * SIZE_TABLE[alltoallvSendRecvInfo.recvType];
1993 0 : HCCL_INFO("[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] recvCount[%llu] recvSize[%llu]", count, size);
1994 : } else {
1995 0 : count = alltoallvSendRecvInfo.sendCounts[remoteRank];
1996 0 : size = count * SIZE_TABLE[alltoallvSendRecvInfo.sendType];
1997 0 : HCCL_INFO("[OpUnfoldCacheEntry][GetTransferCountForAlltoallv] sendCount[%llu] sendSize[%llu]", count, size);
1998 : }
1999 :
2000 0 : return HCCL_SUCCESS;
2001 : }
2002 :
2003 0 : HcclResult OpUnfoldCacheEntry::UpdateNotifyPlaceholderSqeForAlltoallv(
2004 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId,
2005 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata,
2006 : [[maybe_unused]] const AlltoallvSendRecvInfo& alltoallvSendRecvInfo, const uint64_t count, const uint64_t size)
2007 : {
2008 : UNUSED_PARAM(size);
2009 :
2010 0 : rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<rtStarsPlaceHolderSqe_t*>(sqePtr);
2011 0 : if (count == 0) { // 只需要更新task id
2012 0 : placeholderSqePtr->header.taskId = curTaskId;
2013 : } else { // 需要将cache-notify placeholder转变成NotifyWait
2014 : // 保留original SQE中的相关信息
2015 0 : const uint16_t streamId = placeholderSqePtr->header.rtStreamId;
2016 0 : const uint8_t kernel_credit = placeholderSqePtr->u.cache_notify_task_info.kernel_credit;
2017 0 : const uint32_t timeout = placeholderSqePtr->u.cache_notify_task_info.timeout;
2018 0 : const uint32_t notifyId = placeholderSqePtr->u.cache_notify_task_info.notify_id;
2019 :
2020 : // 清空original SQE
2021 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
2022 :
2023 : // 生成NotifyWait
2024 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneNotifyWaitSqeV1
2025 0 : *sqeTypePtr = SqeType::NOTIFY_SQE;
2026 0 : rtStarsNotifySqeV1_t* const notifySqePtr = (rtStarsNotifySqeV1_t*)sqePtr;
2027 0 : notifySqePtr->header.type = RT_STARS_SQE_TYPE_NOTIFY_WAIT;
2028 0 : notifySqePtr->kernel_credit = kernel_credit;
2029 0 : notifySqePtr->timeout = timeout;
2030 0 : notifySqePtr->header.rtStreamId = streamId;
2031 0 : notifySqePtr->notify_id = notifyId;
2032 0 : notifySqePtr->header.taskId = curTaskId;
2033 : }
2034 :
2035 0 : return HCCL_SUCCESS;
2036 : }
2037 :
2038 0 : HcclResult OpUnfoldCacheEntry::UpdateWritePlaceholderSqeForAlltoallv(
2039 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId,
2040 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata,
2041 : [[maybe_unused]] const AlltoallvSendRecvInfo& alltoallvSendRecvInfo, const uint64_t count, const uint64_t size)
2042 : {
2043 : UNUSED_PARAM(size);
2044 :
2045 0 : rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<rtStarsPlaceHolderSqe_t*>(sqePtr);
2046 0 : if (count == 0) { // 只需要更新task id
2047 0 : placeholderSqePtr->header.taskId = curTaskId;
2048 : } else { // 需要将cache-write placeholder转变成WriteValue
2049 : // 保留original SQE中的相关信息
2050 0 : const uint16_t streamId = placeholderSqePtr->header.rtStreamId;
2051 0 : const uint32_t lowAddr = placeholderSqePtr->u.cache_write_value_task_info.write_addr_low;
2052 0 : const uint32_t highAddr = placeholderSqePtr->u.cache_write_value_task_info.write_addr_high;
2053 :
2054 : // 清空original SQE
2055 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
2056 :
2057 : // 生成WriteValue
2058 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneWriteValueRecordSqeV1
2059 0 : *sqeTypePtr = SqeType::WRITE_VALUE_SQE;
2060 0 : rtStarsWriteValueSqe_t* const writeValueSqePtr = (rtStarsWriteValueSqe_t*)sqePtr;
2061 0 : writeValueSqePtr->header.type = RT_STARS_SQE_TYPE_WRITE_VALUE;
2062 0 : writeValueSqePtr->header.rtStreamId = streamId;
2063 0 : writeValueSqePtr->header.taskId = curTaskId;
2064 0 : writeValueSqePtr->kernel_credit = RT_STARS_DEFAULT_KERNEL_CREDIT;
2065 0 : writeValueSqePtr->awsize = RT_STARS_WRITE_VALUE_SIZE_TYPE_32BIT;
2066 0 : writeValueSqePtr->write_value_part0 = 1U;
2067 0 : writeValueSqePtr->sub_type = RT_STARS_WRITE_VALUE_SUB_TYPE_NOTIFY_RECORD_IPC_NO_PCIE;
2068 0 : writeValueSqePtr->write_addr_low = lowAddr;
2069 0 : writeValueSqePtr->write_addr_high = highAddr;
2070 : }
2071 :
2072 0 : return HCCL_SUCCESS;
2073 : }
2074 :
2075 0 : HcclResult OpUnfoldCacheEntry::UpdateNotifySqeForAlltoallv(
2076 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId,
2077 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata,
2078 : [[maybe_unused]] const AlltoallvSendRecvInfo& alltoallvSendRecvInfo, const uint64_t count, const uint64_t size)
2079 : {
2080 : UNUSED_PARAM(size);
2081 :
2082 0 : rtStarsNotifySqeV1_t* notifySqePtr = reinterpret_cast<rtStarsNotifySqeV1_t*>(sqePtr);
2083 0 : if (count > 0) { // 只需要更新task id
2084 0 : notifySqePtr->header.taskId = curTaskId;
2085 : } else { // 需要将NotifyWait转变成cache-notify placeholder
2086 : // 保留original SQE中的相关信息
2087 0 : const uint16_t streamId = notifySqePtr->header.rtStreamId;
2088 0 : const uint8_t kernel_credit = notifySqePtr->kernel_credit;
2089 0 : const uint32_t timeout = notifySqePtr->timeout;
2090 0 : const uint32_t notifyId = notifySqePtr->notify_id;
2091 :
2092 : // 清空original SQE
2093 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
2094 :
2095 : // 生成cache-notify placeholder
2096 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneCacheNotifyWaitPlaceholderSqeV1
2097 0 : *sqeTypePtr = SqeType::CACHE_NOTIFY_PLACEHOLDER_SQE;
2098 0 : SetCachePlaceholderHeaderForAlltoallv(streamId, curTaskId, sqePtr);
2099 0 : rtStarsPlaceHolderSqe_t* const placeholderSqePtr = (rtStarsPlaceHolderSqe_t*)sqePtr;
2100 0 : placeholderSqePtr->u.cache_notify_task_info.is_wait = 1; // NotifyWait
2101 0 : placeholderSqePtr->u.cache_notify_task_info.kernel_credit = kernel_credit;
2102 0 : placeholderSqePtr->u.cache_notify_task_info.timeout = timeout;
2103 0 : placeholderSqePtr->u.cache_notify_task_info.notify_id = notifyId;
2104 : }
2105 :
2106 0 : return HCCL_SUCCESS;
2107 : }
2108 :
2109 0 : HcclResult OpUnfoldCacheEntry::UpdateWriteValueSqeForAlltoallv(
2110 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId,
2111 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata,
2112 : [[maybe_unused]] const AlltoallvSendRecvInfo& alltoallvSendRecvInfo, const uint64_t count, const uint64_t size)
2113 : {
2114 : UNUSED_PARAM(size);
2115 :
2116 0 : rtStarsWriteValueSqe_t* writeValueSqePtr = reinterpret_cast<rtStarsWriteValueSqe_t*>(sqePtr);
2117 0 : if (count > 0) { // 只需要更新task id
2118 0 : writeValueSqePtr->header.taskId = curTaskId;
2119 : } else { // 需要将WriteValue转变成cache-write placeholder
2120 : // 保留original SQE中的相关信息
2121 0 : const uint16_t streamId = writeValueSqePtr->header.rtStreamId;
2122 0 : const uint32_t lowAddr = writeValueSqePtr->write_addr_low;
2123 0 : const uint32_t highAddr = writeValueSqePtr->write_addr_high;
2124 :
2125 : // 清空original SQE
2126 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
2127 :
2128 : // 生成cache-write placeholder
2129 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneCacheWriteValuePlaceholderSqeV1
2130 0 : *sqeTypePtr = SqeType::CACHE_WRITE_VALUE_PLACEHOLDER_SQE;
2131 0 : SetCachePlaceholderHeaderForAlltoallv(streamId, curTaskId, sqePtr);
2132 0 : rtStarsPlaceHolderSqe_t* const placeholderSqePtr = (rtStarsPlaceHolderSqe_t*)sqePtr;
2133 0 : placeholderSqePtr->u.cache_write_value_task_info.write_addr_low = lowAddr;
2134 0 : placeholderSqePtr->u.cache_write_value_task_info.write_addr_high = highAddr;
2135 : }
2136 :
2137 0 : return HCCL_SUCCESS;
2138 : }
2139 :
2140 0 : HcclResult OpUnfoldCacheEntry::UpdateMemcpyRecordSqeForAlltoallv(
2141 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId,
2142 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata,
2143 : [[maybe_unused]] const AlltoallvSendRecvInfo& alltoallvSendRecvInfo, const uint64_t count, const uint64_t size)
2144 : {
2145 : UNUSED_PARAM(size);
2146 :
2147 0 : rtStarsMemcpyAsyncSqe_t* memcpySqePtr = reinterpret_cast<rtStarsMemcpyAsyncSqe_t*>(sqePtr);
2148 0 : if (count > 0) { // 只需要更新task id
2149 0 : memcpySqePtr->header.taskId = curTaskId;
2150 : } else { // 需要将MemcpyRecord转变成cache-memcpy-record placeholder
2151 : // 保留original SQE中的相关信息
2152 0 : const uint16_t streamId = memcpySqePtr->header.rtStreamId;
2153 0 : const uint8_t kernelCredit = memcpySqePtr->kernel_credit;
2154 0 : const uint32_t opCode = memcpySqePtr->opcode;
2155 0 : const uint32_t length = memcpySqePtr->length;
2156 0 : const uint32_t srcAddrLow = memcpySqePtr->src_addr_low;
2157 0 : const uint32_t srcAddrHigh = memcpySqePtr->src_addr_high;
2158 0 : const uint32_t dstAddrLow = memcpySqePtr->dst_addr_low;
2159 0 : const uint32_t dstAddrHigh = memcpySqePtr->dst_addr_high;
2160 0 : const uint32_t partId = memcpySqePtr->partid;
2161 0 : const uint8_t linkType = memcpySqePtr->linkType;
2162 0 : const uint32_t qos = memcpySqePtr->qos;
2163 :
2164 : // 清空original SQE
2165 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
2166 :
2167 : // 生成cache-memcpy-record placeholder
2168 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneCacheMemcpyRecordPlaceholderSqeV1
2169 0 : *sqeTypePtr = SqeType::CACHE_MEMCPY_RECORD_PLACEHOLDER_SQE;
2170 0 : SetCachePlaceholderHeaderForAlltoallv(streamId, curTaskId, sqePtr);
2171 0 : rtStarsPlaceHolderSqe_t* const placeholderSqePtr = (rtStarsPlaceHolderSqe_t*)sqePtr;
2172 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.kernel_credit = kernelCredit;
2173 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.opcode = opCode;
2174 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.length = length;
2175 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.src_addr_low = srcAddrLow;
2176 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.src_addr_high = srcAddrHigh;
2177 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.dst_addr_low = dstAddrLow;
2178 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.dst_addr_high = dstAddrHigh;
2179 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.partid = partId;
2180 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.linkType = linkType;
2181 0 : placeholderSqePtr->u.cache_memcpy_record_task_info.qos = qos;
2182 : }
2183 :
2184 0 : return HCCL_SUCCESS;
2185 : }
2186 :
2187 0 : HcclResult OpUnfoldCacheEntry::UpdateMemcpyRecordPlaceholderSqeForAlltoallv(
2188 : uint8_t* sqePtr, uint8_t* sqeTypePtr, const uint16_t curTaskId,
2189 : [[maybe_unused]] const AlltoallvMetadata& alltoallvMetadata,
2190 : [[maybe_unused]] const AlltoallvSendRecvInfo& alltoallvSendRecvInfo, const uint64_t count, const uint64_t size)
2191 : {
2192 : UNUSED_PARAM(size);
2193 :
2194 0 : rtStarsPlaceHolderSqe_t* placeholderSqePtr = reinterpret_cast<rtStarsPlaceHolderSqe_t*>(sqePtr);
2195 0 : if (count == 0) { // 只需要更新task id
2196 0 : placeholderSqePtr->header.taskId = curTaskId;
2197 : } else { // 需要将cache-memcpy-record placeholder转变成MemcpyRecord
2198 : // 保留original SQE中的相关信息
2199 0 : const uint16_t streamId = placeholderSqePtr->header.rtStreamId;
2200 0 : const uint8_t kernelCredit = placeholderSqePtr->u.cache_memcpy_record_task_info.kernel_credit;
2201 0 : const uint32_t opCode = placeholderSqePtr->u.cache_memcpy_record_task_info.opcode;
2202 0 : const uint32_t length = placeholderSqePtr->u.cache_memcpy_record_task_info.length;
2203 0 : const uint32_t srcAddrLow = placeholderSqePtr->u.cache_memcpy_record_task_info.src_addr_low;
2204 0 : const uint32_t srcAddrHigh = placeholderSqePtr->u.cache_memcpy_record_task_info.src_addr_high;
2205 0 : const uint32_t dstAddrLow = placeholderSqePtr->u.cache_memcpy_record_task_info.dst_addr_low;
2206 0 : const uint32_t dstAddrHigh = placeholderSqePtr->u.cache_memcpy_record_task_info.dst_addr_high;
2207 0 : const uint32_t partId = placeholderSqePtr->u.cache_memcpy_record_task_info.partid;
2208 0 : const uint32_t linkType = placeholderSqePtr->u.cache_memcpy_record_task_info.linkType;
2209 0 : const uint32_t qos = placeholderSqePtr->u.cache_memcpy_record_task_info.qos;
2210 :
2211 : // 清空original SQE
2212 0 : CHK_SAFETY_FUNC_RET(memset_s(static_cast<void*>(sqePtr), HCCL_SQE_SIZE, 0, HCCL_SQE_SIZE));
2213 :
2214 : // 生成MemcpyRecord
2215 : // 参考aicpu_hccl_sqcqv1.cc中的AddOneMemcpySqeV1
2216 0 : *sqeTypePtr = SqeType::MEMCPY_ASYNC_SQE;
2217 0 : rtStarsMemcpyAsyncSqe_t* const memcpySqePtr = (rtStarsMemcpyAsyncSqe_t*)sqePtr;
2218 0 : memcpySqePtr->header.type = RT_STARS_SQE_TYPE_SDMA;
2219 0 : memcpySqePtr->header.rtStreamId = streamId;
2220 0 : memcpySqePtr->header.taskId = curTaskId;
2221 0 : memcpySqePtr->kernel_credit = kernelCredit;
2222 0 : memcpySqePtr->opcode = opCode;
2223 0 : memcpySqePtr->length = length;
2224 0 : memcpySqePtr->src_addr_low = srcAddrLow;
2225 0 : memcpySqePtr->src_addr_high = srcAddrHigh;
2226 0 : memcpySqePtr->dst_addr_low = dstAddrLow;
2227 0 : memcpySqePtr->dst_addr_high = dstAddrHigh;
2228 0 : memcpySqePtr->sssv = 1U;
2229 0 : memcpySqePtr->dssv = 1U;
2230 0 : memcpySqePtr->sns = 1U;
2231 0 : memcpySqePtr->dns = 1U;
2232 0 : memcpySqePtr->qos = 6; // 6 is HCCL QoS
2233 0 : memcpySqePtr->partid = partId;
2234 0 : memcpySqePtr->linkType = linkType;
2235 0 : memcpySqePtr->qos = qos;
2236 : }
2237 :
2238 0 : return HCCL_SUCCESS;
2239 : }
2240 :
2241 0 : void OpUnfoldCacheEntry::SetCachePlaceholderHeaderForAlltoallv(
2242 : const uint16_t streamId, const uint16_t taskId, uint8_t* sqePtr)
2243 : {
2244 : // 参考aicpu_hccl_sqcqv1.cc中的SetCachePlaceholderHeaderV1
2245 : // 注意: 不直接调用SetCachePlaceholderHeaderV1, 避免libhccl_plf对platform/task/rtsq_interact产生依赖
2246 : // 目前rtsq_interact只编译到ccl_kernel_plf与ccl_kernel_plf_a中
2247 0 : rtStarsPlaceHolderSqe_t* placeholderSqePtr = (rtStarsPlaceHolderSqe_t*)sqePtr;
2248 0 : placeholderSqePtr->header.type = RT_STARS_SQE_TYPE_PLACE_HOLDER;
2249 0 : placeholderSqePtr->header.ie = 0U;
2250 0 : placeholderSqePtr->header.preP = 0U; // 不需要STARS_FW参与任何预处理
2251 0 : placeholderSqePtr->header.postP = 0U;
2252 0 : placeholderSqePtr->header.wrCqe = 0U;
2253 0 : placeholderSqePtr->header.reserved = 0U;
2254 : // NOTE: task type在preP阶段被TASK_FW使用, 而此placeholder无preP阶段, 设置为RT_TASK_TYPE_FLIP不影响功能
2255 0 : placeholderSqePtr->header.blockDim = RT_TASK_TYPE_FLIP;
2256 0 : placeholderSqePtr->header.rtStreamId = streamId;
2257 0 : placeholderSqePtr->header.taskId = taskId;
2258 0 : placeholderSqePtr->kernel_credit = RT_STARS_DEFAULT_KERNEL_CREDIT;
2259 0 : return;
2260 : }
2261 :
2262 : }; // namespace hccl
|