Line data Source code
1 : /**
2 : * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #ifndef __KFC_DUMP_SINGLE_CORE_H__
12 : #define __KFC_DUMP_SINGLE_CORE_H__
13 :
14 : #include "kfc_dump_op_base.h"
15 :
16 : namespace KfcDumpStat {
17 : using namespace AscendC;
18 :
19 : // 单核模板:统计项按核均分,每个核独立完成分配到的整组统计
20 : template <typename T>
21 : class KfcDumpStatSingleCore : public KfcDumpStatOpBase<T> {
22 : public:
23 : using KfcDumpStatOpBase<T>::KfcDumpStatOpBase;
24 : // 模板基类成员在派生类中不可见,统一引入
25 : using KfcDumpStatOpBase<T>::pPipe_;
26 : using KfcDumpStatOpBase<T>::maskBuf_;
27 : using KfcDumpStatOpBase<T>::cacheBuf1_;
28 : using KfcDumpStatOpBase<T>::blockIdx_;
29 : using KfcDumpStatOpBase<T>::blockOffset_;
30 : using KfcDumpStatOpBase<T>::aiCoreNum_;
31 : using KfcDumpStatOpBase<T>::xDtypeSize_;
32 : using KfcDumpStatOpBase<T>::dumpStatClass_;
33 : using KfcDumpStatOpBase<T>::statNum_;
34 : using KfcDumpStatOpBase<T>::workspace_;
35 : using KfcDumpStatOpBase<T>::sMsg_;
36 : using KfcDumpStatOpBase<T>::rMsg_;
37 : using KfcDumpStatOpBase<T>::RunStatCompute;
38 : using KfcDumpStatOpBase<T>::CopyOutStatResult;
39 : using KfcDumpStatOpBase<T>::SyncAllCores;
40 : using KfcDumpStatOpBase<T>::UpdateStatOutput;
41 : using KfcDumpStatOpBase<T>::InitCacheBuf;
42 : using KfcDumpStatOpBase<T>::ubSize_;
43 : using KfcDumpStatOpBase<T>::totalCount_;
44 : using KfcDumpStatOpBase<T>::maxProcCount_;
45 : using KfcDumpStatOpBase<T>::perBlockCount_;
46 : using KfcDumpStatOpBase<T>::tileNumMean_;
47 : using KfcDumpStatOpBase<T>::tileLengthMean_;
48 : using KfcDumpStatOpBase<T>::tileLengthEnd_;
49 : using KfcDumpStatOpBase<T>::tileNumEnd_;
50 : using KfcDumpStatOpBase<T>::innerLoopTime_;
51 :
52 30 : __aicore__ inline KfcDumpStatSingleCore(
53 : TPipe* pipe, __gm__ KfcDumpStatMsg* rMsg, __gm__ KfcDumpStatMsg* sMsg, KfcDumpContext* kfcDumpContext)
54 30 : : KfcDumpStatOpBase<T>(pipe, rMsg, sMsg, kfcDumpContext)
55 : {
56 : // Tiling 计算:单核模板每次都是计算所有数据
57 30 : blockOffset_ = 0;
58 30 : maxProcCount_ = CalculateMaxProcCount(xDtypeSize_, ubSize_);
59 30 : perBlockCount_ = BLOCK_SIZE / xDtypeSize_;
60 30 : tileLengthMean_ = maxProcCount_ / BUFFER_NUM;
61 30 : tileNumMean_ = totalCount_ / tileLengthMean_;
62 30 : tileLengthEnd_ = totalCount_ % tileLengthMean_;
63 30 : tileNumEnd_ = tileLengthEnd_ == 0 ? 0 : 1;
64 30 : innerLoopTime_ = tileNumMean_;
65 30 : }
66 :
67 30 : __aicore__ inline void Init()
68 : {
69 30 : KfcDumpStatOpBase<T>::Init();
70 : // 单核模板 mask 固定大小
71 30 : pPipe_->InitBuffer(maskBuf_, MAX_MASK_NUM * BLOCK_SIZE);
72 30 : InitCacheBuf();
73 30 : }
74 :
75 30 : __aicore__ inline void Process()
76 : {
77 : // 无使能统计项或核数为 0 时 eachCoreStatNum 为 0,直接回消息返回,避免除零
78 30 : int64_t eachCoreStatNum = (statNum_ == 0 || aiCoreNum_ == 0) ? 0 : CeilDiv(statNum_, aiCoreNum_);
79 30 : if (eachCoreStatNum == 0) {
80 1 : SyncAllCores();
81 1 : if (blockIdx_ == 0) {
82 1 : UpdateMsg(sMsg_, rMsg_, true);
83 : }
84 1 : SyncAllCores();
85 1 : return;
86 : }
87 29 : int64_t enabledStatNum = 0; // 已遍历的使能统计项个数
88 232 : for (int64_t processStatIdx = 0; processStatIdx < MAX_STAT_NUM && enabledStatNum < statNum_; ++processStatIdx) {
89 203 : if ((dumpStatClass_ & (1ULL << processStatIdx)) == 0) {
90 5 : continue;
91 : }
92 : // 单核模板按核序划分统计项:仅当该统计项落在当前核的分片内才执行
93 198 : if (IsStatOwner(enabledStatNum, eachCoreStatNum)) {
94 198 : RunStatCompute(processStatIdx);
95 198 : CopyOutStatResult(processStatIdx, enabledStatNum);
96 : }
97 198 : ++enabledStatNum;
98 : }
99 :
100 29 : SyncAllCores();
101 29 : CoreReduce(eachCoreStatNum);
102 29 : SyncAllCores();
103 : }
104 :
105 : private:
106 : // 统计项使能序号 enabledStatIdx 是否属于当前核(每核承担 eachCoreStatNum 个统计项)
107 198 : __aicore__ inline bool IsStatOwner(int64_t enabledStatIdx, int64_t eachCoreStatNum) const
108 : {
109 198 : if (eachCoreStatNum == 0) { // 除零防护,正常流程不会为 0
110 0 : return false;
111 : }
112 198 : int64_t coreIdx = enabledStatIdx / eachCoreStatNum;
113 198 : return coreIdx == blockIdx_;
114 : }
115 :
116 29 : __aicore__ inline void CoreReduce(int64_t eachCoreStatNum)
117 : {
118 29 : if (blockIdx_ != 0 || eachCoreStatNum == 0) { // eachCoreStatNum 为 0 时无输出可汇总
119 0 : return;
120 : }
121 29 : int64_t curCoreStart = 0;
122 1885 : for (int64_t processStatIdx = 0; processStatIdx < MAX_STAT_NUM; ++processStatIdx) {
123 1856 : if ((dumpStatClass_ & (1ULL << processStatIdx)) != 0) {
124 198 : auto coreIdx = curCoreStart / eachCoreStatNum;
125 198 : uint64_t curWorkSpaceAddr = workspace_ + coreIdx * (statNum_ * MAX_WORKSPACE_BYTE_SIZE) +
126 198 : curCoreStart * MAX_WORKSPACE_BYTE_SIZE;
127 198 : UpdateStatOutput(processStatIdx, curWorkSpaceAddr);
128 198 : curCoreStart += 1;
129 : }
130 : }
131 :
132 29 : UpdateMsg(sMsg_, rMsg_, true);
133 : }
134 : };
135 :
136 : } // namespace KfcDumpStat
137 :
138 : #endif // __KFC_DUMP_SINGLE_CORE_H__
|