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 : /*!
12 : * \file kernel_vec_reduce_check.cpp
13 : * \brief
14 : */
15 :
16 : #include "kernel_check_params.h"
17 : #include "kernel_vec_reduce_check.h"
18 :
19 : namespace AscendC {
20 : namespace check {
21 16 : uint32_t TikcppVecReduceCheck::AlignStartPos(const uint32_t startPos, const uint32_t byteLen) const
22 : {
23 16 : if (byteLen == 0) {
24 0 : CHECK_LOG_ERROR("byteLen is %u, it shoule be greater than 0", byteLen);
25 0 : return 0;
26 : }
27 16 : uint32_t resDiv = DivCeil(startPos * byteLen, static_cast<uint32_t>(PlatFormParams::ONE_BLK_SIZE));
28 :
29 16 : return resDiv * static_cast<uint32_t>(PlatFormParams::ONE_BLK_SIZE) / byteLen;
30 : }
31 :
32 40 : bool TikcppVecReduceCheck::CheckAllDtypeBytes(const std::string& errMsg)
33 : {
34 40 : uint32_t dstDtypeBytes = param_.dstDtypeBytes;
35 40 : uint32_t srcDtypeBytes = param_.src0DtypeBytes;
36 40 : uint32_t workDtypeBytes = param_.src1DtypeBytes;
37 40 : if ((dstDtypeBytes != srcDtypeBytes) || (srcDtypeBytes != workDtypeBytes) || (workDtypeBytes != dstDtypeBytes)) {
38 0 : CHECK_LOG_ERROR(
39 : "%s, "
40 : "Reduce need dst data type (%u),dst src type (%u), dst wokr type (%u) should be same",
41 : errMsg.c_str(), dstDtypeBytes, srcDtypeBytes, workDtypeBytes);
42 0 : return false;
43 : }
44 40 : return true;
45 : }
46 :
47 8 : void TikcppVecReduceCheck::ReduceBodyCal(
48 : const std::vector<uint32_t>& paramsArray, uint32_t& outputCount, uint32_t& nextStartPos) const
49 : {
50 : enum class ReduceBodyCalIndex {
51 : PRE_DATA_COUNT = 0,
52 : CUR_START_POS,
53 : ELEMENT_NUM_PER_REP,
54 : TYPE_SIZE,
55 : PER_REP_OUTPUT,
56 : };
57 :
58 8 : uint32_t preDataCount = paramsArray[static_cast<uint32_t>(ReduceBodyCalIndex::PRE_DATA_COUNT)];
59 8 : uint32_t curStartPos = paramsArray[static_cast<uint32_t>(ReduceBodyCalIndex::CUR_START_POS)];
60 8 : uint32_t elementNumPerRep = paramsArray[static_cast<uint32_t>(ReduceBodyCalIndex::ELEMENT_NUM_PER_REP)];
61 8 : uint32_t typeSize = paramsArray[static_cast<uint32_t>(ReduceBodyCalIndex::TYPE_SIZE)];
62 8 : uint32_t perRepOutput = paramsArray[static_cast<uint32_t>(ReduceBodyCalIndex::PER_REP_OUTPUT)];
63 :
64 : uint32_t tailOutputCount;
65 8 : uint32_t bodyRepTimes = preDataCount / elementNumPerRep;
66 8 : uint32_t bodyOutputCount = perRepOutput * bodyRepTimes;
67 8 : bool hasTail = (preDataCount % elementNumPerRep) != 0;
68 8 : if (hasTail) {
69 8 : tailOutputCount = perRepOutput;
70 : } else {
71 0 : tailOutputCount = 0;
72 : }
73 8 : outputCount = bodyOutputCount + tailOutputCount;
74 8 : nextStartPos = AlignStartPos(curStartPos + outputCount, typeSize);
75 8 : return;
76 : }
77 :
78 8 : bool TikcppVecReduceCheck::CheckCheckWorkSize(
79 : const std::string& errMsg, const uint64_t needElements, const uint32_t byteLen)
80 : {
81 8 : uint64_t needSize = static_cast<uint64_t>(needElements * byteLen);
82 8 : if (needSize > param_.src1Size) {
83 0 : CHECK_LOG_ERROR(
84 : "%s, "
85 : "Worktensor's size should be more than %lu, but get %lu",
86 : errMsg.c_str(), needSize, param_.src1Size);
87 0 : return false;
88 : }
89 8 : return true;
90 : }
91 :
92 8 : bool TikcppVecReduceCheck::CheckWorkTensorOffset(const std::string& errMsg)
93 : {
94 : uint32_t resIndex;
95 : uint32_t it2OutputCount;
96 : uint32_t it3StartPos;
97 8 : uint32_t typeSize = param_.src1DtypeBytes;
98 8 : uint32_t perRepOutput = static_cast<uint32_t>(ReduceCheckExtParams::VREDUCE_PER_REP_OUTPUT);
99 8 : uint32_t it1AlignStart = 0;
100 8 : uint32_t it1OutputCount = perRepOutput * param_.repeatTimes; // 2
101 8 : uint64_t needElement = static_cast<uint32_t>(perRepOutput * param_.repeatTimes);
102 :
103 8 : if (!param_.calIndex) {
104 0 : return CheckCheckWorkSize(errMsg, needElement, typeSize);
105 : }
106 :
107 : // iteration1
108 8 : if (it1OutputCount == perRepOutput) {
109 0 : resIndex = it1AlignStart + it1OutputCount;
110 0 : needElement = resIndex;
111 0 : return CheckCheckWorkSize(errMsg, needElement, typeSize);
112 : }
113 :
114 8 : if (typeSize == 0) {
115 0 : CHECK_LOG_ERROR("dtype bytes is zeros");
116 0 : return false;
117 : }
118 :
119 : // iteration2
120 8 : uint32_t it2AlignStart = AlignStartPos(it1OutputCount, typeSize);
121 8 : uint32_t elementNumPerRep = static_cast<uint32_t>(PlatFormParams::ONE_REP_BYTE_SIZE) / typeSize;
122 8 : if (elementNumPerRep == 0) {
123 0 : CHECK_LOG_ERROR(
124 : "%s, "
125 : "elementNumPerRep can not be 0.",
126 : errMsg.c_str());
127 0 : return false;
128 : }
129 16 : ReduceBodyCal(
130 : {it1OutputCount, it2AlignStart, elementNumPerRep, typeSize, perRepOutput}, it2OutputCount, it3StartPos);
131 :
132 8 : if (it2OutputCount == perRepOutput) {
133 8 : it3StartPos = it2AlignStart;
134 8 : resIndex = it3StartPos + 1;
135 : } else {
136 : // iteration3
137 0 : resIndex = it3StartPos + 1;
138 0 : if (it2OutputCount > elementNumPerRep) {
139 : uint32_t tmpVal;
140 : uint32_t it4StartPos;
141 0 : ReduceBodyCal({it2OutputCount, it3StartPos, elementNumPerRep, typeSize, perRepOutput}, tmpVal, it4StartPos);
142 0 : resIndex = it4StartPos + 1;
143 : }
144 : }
145 8 : needElement = resIndex + 1;
146 8 : return CheckCheckWorkSize(errMsg, needElement, typeSize);
147 : }
148 :
149 12 : bool TikcppVecReduceCheck::CheckWorkTensorSizeEqual(const std::string& errMsg)
150 : {
151 12 : uint64_t needSize = static_cast<uint64_t>(param_.repeatTimes * param_.src1DtypeBytes);
152 12 : if (needSize > param_.src1Size) {
153 4 : CHECK_LOG_ERROR(
154 : "%s, "
155 : "Need size: %lu, while tensor size is %lu",
156 : errMsg.c_str(), needSize, param_.src1Size);
157 4 : return false;
158 : }
159 :
160 8 : return true;
161 : }
162 :
163 40 : bool TikcppVecReduceCheck::CheckDstTensorSizeRange(const std::string& errMsg)
164 : {
165 40 : uint32_t needCount = 1;
166 40 : uint64_t needSize = 0;
167 40 : if (param_.calIndex) {
168 24 : needCount = static_cast<uint32_t>(ReduceCheckExtParams::VREDUCE_CALL_INDEX_COUNT);
169 : }
170 40 : needSize = static_cast<uint64_t>(needCount * param_.dstDtypeBytes);
171 :
172 40 : if (needSize > param_.dstSize) {
173 0 : CHECK_LOG_ERROR(
174 : "%s, "
175 : "Need least output size: %lu, while tensor size is %lu",
176 : errMsg.c_str(), needSize, param_.dstSize);
177 0 : return false;
178 : }
179 40 : return true;
180 : }
181 :
182 40 : bool TikcppVecReduceCheck::CheckAddrAlign()
183 : {
184 80 : bool srcRes = CheckTensorAddrAlign(param_.src0Addr, param_.src0Pos, ONE_BLK_SIZE, "src");
185 80 : bool dstRes = CheckTensorAddrAlign(param_.dstAddr, param_.dstPos, param_.dstDtypeBytes, "dst");
186 80 : bool src1Res = CheckTensorAddrAlign(param_.src1Addr, param_.src1Pos, param_.dstDtypeBytes, "work");
187 40 : return srcRes && dstRes && src1Res;
188 : }
189 :
190 40 : bool TikcppVecReduceCheck::CommonCheck()
191 : {
192 80 : ASCENDC_CHECK(CheckAllDtypeBytes("Check Reduce data type"));
193 80 : ASCENDC_CHECK(CheckDstTensorSizeRange("Check Reduce dst data size"));
194 :
195 40 : const std::string supportPos = "VECIN/VECOUT/VECCALC";
196 120 : ASCENDC_CHECK(CheckTensorScope(param_.dstLogicPos, static_cast<uint8_t>(HardWareIndex::UB), "dst", supportPos));
197 120 : ASCENDC_CHECK(CheckTensorScope(param_.src0LogicPos, static_cast<uint8_t>(HardWareIndex::UB), "src", supportPos));
198 120 : ASCENDC_CHECK(CheckTensorScope(param_.src1LogicPos, static_cast<uint8_t>(HardWareIndex::UB), "work", supportPos));
199 :
200 40 : ASCENDC_CHECK(CheckAddrAlign());
201 :
202 120 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
203 : param_.dstSize, GlobalParams::Instance().bufferSizeMap.at(param_.dstPos),
204 : "check dst tensor buffersize failed"));
205 120 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
206 : param_.src0Size, GlobalParams::Instance().bufferSizeMap.at(param_.src0Pos),
207 : "check src tensor buffersize failed"));
208 120 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
209 : param_.src1Size, GlobalParams::Instance().bufferSizeMap.at(param_.src1Pos),
210 : "check work tensor buffersize failed"));
211 40 : return true;
212 40 : }
213 :
214 32 : bool TikcppVecReduceCheck::CheckAllHighLevel()
215 : {
216 : // Only for reduce interface level 2
217 32 : ASCENDC_CHECK(CommonCheck());
218 :
219 96 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, param_.calCount, "src0Local"));
220 12 : if (apiName == "ReduceSum") {
221 8 : ASCENDC_CHECK(CheckWorkTensorSizeEqual("Check Reduce Sum workLocal tensor size"));
222 8 : } else if (apiName == "ReduceMax") {
223 16 : ASCENDC_CHECK(CheckWorkTensorOffset("Check Reduce max workLocal tensor size"));
224 : } else {
225 0 : ASCENDC_CHECK(CheckWorkTensorOffset("Check Reduce min workLocal tensor size"));
226 : }
227 12 : return true;
228 : }
229 :
230 4 : bool TikcppVecReduceCheck::CheckAllHighLevelMode2()
231 : {
232 4 : uint32_t dstDtypeBytes = param_.dstDtypeBytes;
233 4 : uint32_t srcDtypeBytes = param_.src0DtypeBytes;
234 4 : if (dstDtypeBytes != srcDtypeBytes) {
235 4 : CHECK_LOG_ERROR(
236 : "Check Reduce data type, Reduce need dst data type (%u), src data type (%u) should be same", dstDtypeBytes,
237 : srcDtypeBytes);
238 4 : return false;
239 : }
240 :
241 0 : ASCENDC_CHECK(CheckDstTensorSizeRange("Check Reduce dst data size"));
242 :
243 0 : const std::string supportPos = "VECIN/VECOUT/VECCALC";
244 0 : ASCENDC_CHECK(CheckTensorScope(param_.dstLogicPos, static_cast<uint8_t>(HardWareIndex::UB), "dst", supportPos));
245 0 : ASCENDC_CHECK(CheckTensorScope(param_.src0LogicPos, static_cast<uint8_t>(HardWareIndex::UB), "src", supportPos));
246 :
247 0 : bool srcRes = CheckTensorAddrAlign(param_.src0Addr, param_.src0Pos, ONE_BLK_SIZE, "src");
248 0 : bool dstRes = CheckTensorAddrAlign(param_.dstAddr, param_.dstPos, param_.dstDtypeBytes, "dst");
249 0 : ASCENDC_CHECK(srcRes && dstRes);
250 :
251 0 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
252 : param_.dstSize, GlobalParams::Instance().bufferSizeMap.at(param_.dstPos),
253 : "check dst tensor buffersize failed"));
254 0 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
255 : param_.src0Size, GlobalParams::Instance().bufferSizeMap.at(param_.src0Pos),
256 : "check src tensor buffersize failed"));
257 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, param_.calCount, "src0Local"));
258 :
259 0 : return true;
260 0 : }
261 :
262 8 : bool TikcppVecReduceCheck::CheckAllLowLevel(std::vector<uint64_t> maskArray)
263 : {
264 8 : uint32_t maxByteLen = param_.dstDtypeBytes;
265 8 : ASCENDC_CHECK(UpdateMaskArrayAndCheck(maskArray, maxByteLen));
266 8 : ASCENDC_CHECK(CommonCheck());
267 :
268 : TensorOverflowParams params = {
269 8 : param_.src0Size,
270 8 : param_.src0DtypeBytes,
271 8 : static_cast<uint64_t>(param_.repeatTimes),
272 8 : static_cast<uint64_t>(param_.src0BlockStride),
273 8 : static_cast<uint64_t>(param_.src0RepeatStride),
274 8 : false};
275 24 : ASCENDC_CHECK(CheckTensorOverflowLow(maskArray, params, "src0Local"));
276 8 : if (apiName == "ReduceSum") {
277 16 : ASCENDC_CHECK(CheckWorkTensorSizeEqual("Check Reduce sum workLocal tensor size"));
278 0 : } else if (apiName == "ReduceMax") {
279 0 : ASCENDC_CHECK(CheckWorkTensorOffset("Check Reduce max workLocal tensor size"));
280 : } else {
281 0 : ASCENDC_CHECK(CheckWorkTensorOffset("Check Reduce min workLocal tensor size"));
282 : }
283 4 : return true;
284 : }
285 : } // namespace check
286 : } // namespace AscendC
|