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 "operator_kernel_check_input_tensor_desc.h"
12 :
13 : #include "aicpusd_status.h"
14 : #include "aicpusd_model_execute.h"
15 : #include "aicpusd_model_statistic.h"
16 : #include "operator_kernel_common.h"
17 :
18 :
19 : namespace AicpuSchedule {
20 : namespace {
21 : const std::string KERNEL_CHECK_INPUT_TENSOR_DESC = "checkInputTensorDesc";
22 : } // namespace
23 :
24 7 : int32_t OperatorKernelCheckInputTensorDesc::Compute(const AicpuTaskInfo &kernelTaskInfo, const RunContext &taskContext)
25 : {
26 : // check whether the data is empty.
27 7 : const auto model = AicpuModelManager::GetInstance().GetModel(taskContext.modelId);
28 7 : if ((model != nullptr) && (model->GetNullDataFlag())) {
29 1 : aicpusd_info("null data, no need check static shape");
30 1 : return AICPU_SCHEDULE_OK;
31 : }
32 6 : ShapeValidationInfo *allTensorDesc = PtrToPtr<void, ShapeValidationInfo>(ValueToPtr(kernelTaskInfo.paraBase));
33 6 : if (allTensorDesc == nullptr) {
34 1 : aicpusd_err("Model check input tensor para is nullptr, modelId[%u], streamId[%u], taskId[%u]",
35 : taskContext.modelId, taskContext.streamId, kernelTaskInfo.taskID);
36 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
37 : }
38 5 : aicpusd_info("tensor nums[%u], modelId[%u], streamId[%u], taskId[%u]",
39 : allTensorDesc->inputNums, taskContext.modelId, taskContext.streamId, kernelTaskInfo.taskID);
40 :
41 5 : const uint64_t tensorDescNums = allTensorDesc->inputNums;
42 5 : std::vector<ModelConfigTensorDesc> tensorDescArr;
43 : const int32_t result =
44 5 : AicpuModelManager::GetInstance().GetModelConfigShape(taskContext.modelId, tensorDescArr);
45 5 : if ((result != AICPU_SCHEDULE_OK) || tensorDescArr.empty()) {
46 : // check aicpu model has tensor info
47 1 : aicpusd_warn("aicpumodel task has not tensordesc, no need check");
48 1 : return AICPU_SCHEDULE_OK;
49 : }
50 :
51 : // check tensor desc nums
52 4 : if (tensorDescArr.size() != tensorDescNums) {
53 1 : aicpusd_err("tensorDesc number is not as expected. the expected number is[%zu], but is[%u]",
54 : tensorDescArr.size(), tensorDescNums);
55 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
56 : }
57 3 : std::vector<uint64_t> inputSizeList;
58 4 : for (uint64_t i = 0UL; i < tensorDescNums; i++) {
59 3 : uint64_t curSize = 0UL;
60 3 : const int32_t ret = CheckInputTensorDesc(allTensorDesc->shapeValidationAddr, i, tensorDescArr[i], curSize);
61 3 : if (ret != AICPU_SCHEDULE_OK) {
62 2 : aicpusd_err(
63 : "check static shape failed, modelId[%u], streamId[%u], taskId[%u], i = %llu, tensorDescNums = %llu",
64 : taskContext.modelId, taskContext.streamId, kernelTaskInfo.taskID, i, tensorDescNums);
65 2 : return ret;
66 : }
67 1 : inputSizeList.emplace_back(curSize);
68 : }
69 1 : AicpuSdModelStatistic::GetInstance().StatNNModelInput(taskContext.modelId, inputSizeList, tensorDescArr);
70 1 : aicpusd_info("check static shape success");
71 1 : return AICPU_SCHEDULE_OK;
72 5 : }
73 :
74 9 : int32_t OperatorKernelCheckInputTensorDesc::CheckInputTensorDesc(const uint64_t shapeValidationAddr,
75 : const uint64_t index,
76 : const ModelConfigTensorDesc &modelTensorDesc,
77 : uint64_t &curSize) const
78 : {
79 : ShapeValidation *const shapeInfo =
80 9 : PtrToPtr<void, ShapeValidation>(ValueToPtr(shapeValidationAddr + sizeof(ShapeValidation) * index));
81 9 : if (shapeInfo == nullptr) {
82 1 : aicpusd_err("input shape info is nullptr");
83 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
84 : }
85 8 : aicpusd_info("shapeInfo offset = %u", shapeInfo->offset);
86 8 : const auto msgTypeCheckRet = CheckMsgType(PtrToPtr<void, Mbuf*>(ValueToPtr(shapeInfo->mbufAddrs)));
87 8 : if (msgTypeCheckRet != AICPU_SCHEDULE_OK) {
88 2 : return msgTypeCheckRet;
89 : }
90 :
91 6 : uint64_t dataSize = 0UL;
92 6 : int32_t ret = OperatorKernelCommon::GetMbufDataSize(shapeInfo->mbufAddrs, dataSize);
93 6 : if (ret != AICPU_SCHEDULE_OK) {
94 0 : aicpusd_err("Failed to get mbuf data size, ret = %d.", ret);
95 0 : return ret;
96 : }
97 :
98 6 : void *dataPtr = nullptr;
99 6 : ret = OperatorKernelCommon::GetMbufDataPtr(shapeInfo->mbufAddrs, &dataPtr);
100 6 : if (ret != AICPU_SCHEDULE_OK) {
101 1 : aicpusd_err("Failed to get mbuf data addr. srcAddr is [%lu].", shapeInfo->mbufAddrs);
102 1 : return ret;
103 : }
104 :
105 5 : if (shapeInfo->offset > 0) {
106 3 : uint64_t totalOffset = 0UL;
107 3 : ret = OperatorKernelCommon::UpdateDataPtr(shapeInfo->mbufAddrs, static_cast<int32_t>(shapeInfo->offset),
108 : dataPtr, totalOffset);
109 3 : if (ret != AICPU_SCHEDULE_OK) {
110 1 : aicpusd_err("Failed to update data addr. fusion offset[%llu], totalOffset[%llu]",
111 : shapeInfo->offset, totalOffset);
112 1 : return ret;
113 : }
114 : }
115 :
116 4 : RuntimeTensorDesc *const tensorDesc = PtrToPtr<void, RuntimeTensorDesc>(dataPtr);
117 4 : if (tensorDesc == nullptr) {
118 1 : aicpusd_err("tensorDesc is nullptr");
119 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
120 : }
121 3 : aicpusd_info("index[%llu], dtype[%u], shape[0] = %u, datasize:%llu",
122 : index, tensorDesc->dtype, tensorDesc->shape[0], tensorDesc->dataSize);
123 3 : ret = CheckShapeInfo(modelTensorDesc, *tensorDesc);
124 3 : if (ret != AICPU_SCHEDULE_OK) {
125 2 : aicpusd_err("check tensor info failed, tensor index = %llu", index);
126 2 : return ret;
127 : }
128 1 : curSize = tensorDesc->dataSize;
129 1 : return AICPU_SCHEDULE_OK;
130 : }
131 :
132 5 : int32_t OperatorKernelCheckInputTensorDesc::CheckMsgType(Mbuf **const mbufPtr) const
133 : {
134 5 : if ((mbufPtr == nullptr) || (*mbufPtr == nullptr)) {
135 1 : aicpusd_err("Invalid mbuf.");
136 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
137 : }
138 4 : uint32_t headSize = 0U;
139 4 : void *headBuf = nullptr;
140 4 : const auto drvRet = halMbufGetPrivInfo(*mbufPtr, &headBuf, &headSize);
141 4 : if ((drvRet != static_cast<int32_t>(DRV_ERROR_NONE)) || (headBuf == nullptr) ||
142 4 : (static_cast<size_t>(headSize) < sizeof(MbufHeadMsg))) {
143 0 : aicpusd_err("Failed to get mbuf head, ret[%d], headSize[%u].", drvRet, headSize);
144 0 : return AICPU_SCHEDULE_ERROR_FROM_DRV;
145 : }
146 :
147 4 : const MbufHeadMsg * const msg = PtrToPtr<uint8_t, MbufHeadMsg>(PtrAdd<uint8_t>(PtrToPtr<void, uint8_t>(headBuf),
148 4 : static_cast<size_t>(headSize), static_cast<size_t>(headSize) - sizeof(MbufHeadMsg)));
149 4 : if ((msg->msgType == static_cast<uint16_t>(MsgType::MSG_TYPE_RAW_MSG)) ||
150 3 : (msg->msgType >= static_cast<uint16_t>(MsgType::MSG_TYPE_USER_DEFINE_START))) {
151 2 : aicpusd_err("Invalid msg_type[%d].", msg->msgType);
152 2 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
153 : }
154 :
155 2 : return AICPU_SCHEDULE_OK;
156 : }
157 :
158 4 : int32_t OperatorKernelCheckInputTensorDesc::CheckShapeInfo(const ModelConfigTensorDesc &modelTensorDesc,
159 : const RuntimeTensorDesc &tensorDesc) const
160 : {
161 4 : if (modelTensorDesc.dtype != tensorDesc.dtype) {
162 0 : aicpusd_err("Failed to check modelTensorDesc dtype. modelTensorDesc.dtype[%lld], tensorDesc.dtype[%lld]",
163 : modelTensorDesc.dtype, tensorDesc.dtype);
164 0 : PrintErrShapeInfo(modelTensorDesc, tensorDesc);
165 0 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
166 : }
167 :
168 4 : if (modelTensorDesc.shape[0] > MAX_DIM_SIZE + 1) {
169 1 : aicpusd_err("Failed to check modelTensorDesc shape. shape size[%d] should less than %d",
170 : modelTensorDesc.shape[0], MAX_DIM_SIZE + 1);
171 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
172 : }
173 6 : for (int64_t index = 0; index <= modelTensorDesc.shape[0]; index++) {
174 5 : if (modelTensorDesc.shape[index] != tensorDesc.shape[index]) {
175 2 : aicpusd_err("Failed to check shape. expect shape[%lld] = [%lld], but is [%lld]",
176 : index, modelTensorDesc.shape[index], tensorDesc.shape[index]);
177 2 : PrintErrShapeInfo(modelTensorDesc, tensorDesc);
178 2 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
179 : }
180 : }
181 1 : return AICPU_SCHEDULE_OK;
182 : }
183 :
184 2 : void OperatorKernelCheckInputTensorDesc::PrintErrShapeInfo(const ModelConfigTensorDesc &modelTensorDesc,
185 : const RuntimeTensorDesc &tensorDesc) const
186 : {
187 2 : if ((modelTensorDesc.shape[0] > MAX_DIM_SIZE + 1) || (tensorDesc.shape[0] > MAX_DIM_SIZE + 1)) {
188 0 : aicpusd_err("Failed to check modelTensorDesc shape. shape size[%d] should less than %d",
189 : modelTensorDesc.shape[0], MAX_DIM_SIZE + 1);
190 0 : return;
191 : }
192 2 : std::ostringstream oss;
193 2 : oss << "expect dtype = " << AicpuUtil::GetDTypeString(static_cast<ge::DataType>(modelTensorDesc.dtype));
194 2 : oss << ", actual dtype = " << AicpuUtil::GetDTypeString(static_cast<ge::DataType>(tensorDesc.dtype));
195 2 : oss << ", expect dims = " << modelTensorDesc.shape[0] << ", actual dims = " << tensorDesc.shape[0];
196 2 : oss << ", and expect shape = [ ";
197 2 : if (modelTensorDesc.shape[0] > 0) {
198 5 : for (int64_t index = 1; index <= modelTensorDesc.shape[0]; index++) {
199 3 : oss << modelTensorDesc.shape[index] << " ";
200 : }
201 : }
202 :
203 2 : oss << "], actual shape = [ ";
204 2 : if (tensorDesc.shape[0] > 0) {
205 8 : for (int64_t index = 1; index <= tensorDesc.shape[0]; index++) {
206 6 : oss << tensorDesc.shape[index] << " ";
207 : }
208 : }
209 2 : oss << "]";
210 2 : aicpusd_err("%s", oss.str().c_str());
211 2 : }
212 :
213 :
214 6 : REGISTER_OPERATOR_KERNEL(KERNEL_CHECK_INPUT_TENSOR_DESC, OperatorKernelCheckInputTensorDesc);
215 : } // namespace AicpuSchedule
|