• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "utils/kernel_util.h"
18 
19 #include <algorithm>
20 #include <map>
21 #include <string>
22 #include <vector>
23 
24 #include "inc/cust_cpu_utils.h"
25 
26 namespace aicpu {
27 namespace {
28 const std::map<Format, std::string> kFormatToStringMap = {
29   {FORMAT_NCHW, "NCHW"},
30   {FORMAT_NHWC, "NHWC"},
31   {FORMAT_ND, "ND"},
32   {FORMAT_NC1HWC0, "NC1HWC0"},
33   {FORMAT_FRACTAL_Z, "FRACTAL_Z"},
34   {FORMAT_NC1C0HWPAD, "NC1C0HWPAD"},
35   {FORMAT_NHWC1C0, "NHWC1C0"},
36   {FORMAT_FSR_NCHW, "FSR_NCHW"},
37   {FORMAT_FRACTAL_DECONV, "FRACTAL_DECONV"},
38   {FORMAT_C1HWNC0, "C1HWNC0"},
39   {FORMAT_FRACTAL_DECONV_TRANSPOSE, "FRACTAL_DECONV_TRANSPOSE"},
40   {FORMAT_FRACTAL_DECONV_SP_STRIDE_TRANS, "FRACTAL_DECONV_SP_STRIDE_TRANS"},
41   {FORMAT_NC1HWC0_C04, "NC1HWC0_C04"},
42   {FORMAT_FRACTAL_Z_C04, "FRACTAL_Z_C04"},
43   {FORMAT_CHWN, "CHWN"},
44   {FORMAT_FRACTAL_DECONV_SP_STRIDE8_TRANS, "DECONV_SP_STRIDE8_TRANS"},
45   {FORMAT_NC1KHKWHWC0, "NC1KHKWHWC0"},
46   {FORMAT_BN_WEIGHT, "BN_WEIGHT"},
47   {FORMAT_FILTER_HWCK, "FILTER_HWCK"},
48   {FORMAT_HWCN, "HWCN"},
49   {FORMAT_HASHTABLE_LOOKUP_LOOKUPS, "LOOKUP_LOOKUPS"},
50   {FORMAT_HASHTABLE_LOOKUP_KEYS, "LOOKUP_KEYS"},
51   {FORMAT_HASHTABLE_LOOKUP_VALUE, "LOOKUP_VALUE"},
52   {FORMAT_HASHTABLE_LOOKUP_OUTPUT, "LOOKUP_OUTPUT"},
53   {FORMAT_HASHTABLE_LOOKUP_HITS, "LOOKUP_HITS"},
54   {FORMAT_MD, "MD"},
55   {FORMAT_NDHWC, "NDHWC"},
56   {FORMAT_NCDHW, "NCDHW"},
57   {FORMAT_DHWCN, "DHWCN"},
58   {FORMAT_DHWNC, "DHWNC"},
59   {FORMAT_NDC1HWC0, "NDC1HWC0"},
60   {FORMAT_FRACTAL_Z_3D, "FRACTAL_Z_3D"},
61   {FORMAT_FRACTAL_Z_3D_TRANSPOSE, "FRACTAL_Z_3D_TRANSPOSE"},
62   {FORMAT_C1HWNCoC0, "C1HWNCoC0"},
63   {FORMAT_FRACTAL_NZ, "FRACTAL_NZ"},
64   {FORMAT_CN, "CN"},
65   {FORMAT_NC, "NC"},
66   {FORMAT_FRACTAL_ZN_LSTM, "FRACTAL_ZN_LSTM"},
67   {FORMAT_FRACTAL_Z_G, "FRACTAL_Z_G"},
68   {FORMAT_RESERVED, "FORMAT_RESERVED"},
69   {FORMAT_ALL, "ALL"},
70   {FORMAT_NULL, "NULL"}};
71 }  // namespace
72 
FormatToSerialString(CpuKernelContext & ctx,Format format)73 std::string FormatToSerialString(CpuKernelContext &ctx, Format format) {
74   auto it = kFormatToStringMap.find(static_cast<Format>(GetPrimaryFormat(static_cast<int32_t>(format))));
75   if (it != kFormatToStringMap.end()) {
76     if (HasSubFormat(static_cast<int32_t>(format))) {
77       return it->second + ":" + std::to_string(GetSubFormat(static_cast<int32_t>(format)));
78     }
79     return it->second;
80   } else {
81     CUST_KERNEL_LOG_ERROR(ctx, "Format not support [%u]", format);
82     return "UNDEFINED";
83   }
84 }
85 
86 const std::map<std::string, DataType> dtype_maps{{"DT_FLOAT", DT_FLOAT},
87                                                  {"DT_FLOAT16", DT_FLOAT16},
88                                                  {"DT_INT8", DT_INT8},
89                                                  {"DT_INT16", DT_INT16},
90                                                  {"DT_UINT16", DT_UINT16},
91                                                  {"DT_UINT8", DT_UINT8},
92                                                  {"DT_INT32", DT_INT32},
93                                                  {"DT_INT64", DT_INT64},
94                                                  {"DT_UINT32", DT_UINT32},
95                                                  {"DT_UINT64", DT_UINT64},
96                                                  {"DT_BOOL", DT_BOOL},
97                                                  {"DT_DOUBLE", DT_DOUBLE},
98                                                  {"DT_STRING", DT_STRING},
99                                                  {"DT_DUAL_SUB_INT8", DT_DUAL_SUB_INT8},
100                                                  {"DT_DUAL_SUB_UINT8", DT_DUAL_SUB_UINT8},
101                                                  {"DT_COMPLEX64", DT_COMPLEX64},
102                                                  {"DT_COMPLEX128", DT_COMPLEX128},
103                                                  {"DT_QINT8", DT_QINT8},
104                                                  {"DT_QINT16", DT_QINT16},
105                                                  {"DT_QINT32", DT_QINT32},
106                                                  {"DT_QUINT8", DT_QUINT8},
107                                                  {"DT_QUINT16", DT_QUINT16},
108                                                  {"DT_RESOURCE", DT_RESOURCE},
109                                                  {"DT_STRING_REF", DT_STRING_REF},
110                                                  {"DT_DUAL", DT_DUAL},
111                                                  {"DT_UNDEFINED", DT_UNDEFINED}};
112 
IsEmptyTensor(Tensor * tensor)113 bool IsEmptyTensor(Tensor *tensor) {
114   auto dims = tensor->GetTensorShape()->GetDimSizes();
115   if (tensor->GetData() == nullptr) {
116     for (uint32_t i = 0; i < dims.size(); i++) {
117       if (dims[i] == 0) {
118         return true;
119       }
120     }
121   }
122   return false;
123 }
124 
NormalMathCheck(CpuKernelContext & ctx)125 uint32_t NormalMathCheck(CpuKernelContext &ctx) {
126   const uint32_t kInputNum = 2;
127   const uint32_t kOutputNum = 1;
128 
129   if ((ctx.GetInputsSize() != kInputNum) || (ctx.GetOutputsSize() != kOutputNum)) {
130     CUST_KERNEL_LOG_ERROR(ctx,
131                           "[%s] Input size or Output size is unexpected,"
132                           "expected input size [%u], real input size [%u],"
133                           "expected output size [%u], real output size [%u]",
134                           ctx.GetOpType().c_str(), kInputNum, ctx.GetInputsSize(), kOutputNum, ctx.GetOutputsSize());
135     return KERNEL_STATUS_PARAM_INVALID;
136   }
137 
138   Tensor *input_0 = ctx.Input(kFirstInputIndex);
139   CUST_KERNEL_CHECK_NULLPTR(ctx, input_0, KERNEL_STATUS_PARAM_INVALID, "[%s] Get input[0] failed",
140                             ctx.GetOpType().c_str());
141   Tensor *input_1 = ctx.Input(kSecondInputIndex);
142   CUST_KERNEL_CHECK_NULLPTR(ctx, input_1, KERNEL_STATUS_PARAM_INVALID, "[%s] Get input[1] failed",
143                             ctx.GetOpType().c_str());
144 
145   if (input_0->GetDataType() != input_1->GetDataType()) {
146     CUST_KERNEL_LOG_ERROR(ctx,
147                           "[%s] dtype of inputs not matched, input[0] data_type is [%d], "
148                           "input[1] data_type is [%d]",
149                           ctx.GetOpType().c_str(), input_0->GetDataType(), input_1->GetDataType());
150     return KERNEL_STATUS_PARAM_INVALID;
151   }
152 
153   Tensor *output = ctx.Output(kFirstOutputIndex);
154   CUST_KERNEL_CHECK_NULLPTR(ctx, output, KERNEL_STATUS_PARAM_INVALID, "[%s] get output failed",
155                             ctx.GetOpType().c_str());
156   return KERNEL_STATUS_OK;
157 }
158 
NormalCheck(CpuKernelContext & ctx,const uint32_t inputs_num,const uint32_t outputs_num)159 uint32_t NormalCheck(CpuKernelContext &ctx, const uint32_t inputs_num, const uint32_t outputs_num) {
160   if (inputs_num != kDynamicInput) {
161     CUST_KERNEL_CHECK_FALSE(ctx, (ctx.GetInputsSize() >= inputs_num), KERNEL_STATUS_PARAM_INVALID,
162                             "[%s] need [%u] inputs, but got [%u].", ctx.GetOpType().c_str(), inputs_num,
163                             ctx.GetInputsSize());
164     for (uint32_t i = 0; i < inputs_num; ++i) {
165       Tensor *input = ctx.Input(i);
166       CUST_KERNEL_CHECK_NULLPTR(ctx, input, KERNEL_STATUS_INNER_ERROR, "[%s] get input[%u] failed.",
167                                 ctx.GetOpType().c_str(), i);
168       auto input_shape = input->GetTensorShape();
169       CUST_KERNEL_CHECK_NULLPTR(ctx, input_shape, KERNEL_STATUS_PARAM_INVALID, "%s input[%u] tensor shape is nullptr.",
170                                 ctx.GetOpType().c_str(), i);
171       if (!IsEmptyTensor(input)) {
172         auto input_data = input->GetData();
173         CUST_KERNEL_CHECK_NULLPTR(ctx, input_data, KERNEL_STATUS_PARAM_INVALID, "%s input[%u] tensor data is nullptr.",
174                                   ctx.GetOpType().c_str(), i);
175       }
176     }
177   }
178 
179   if (outputs_num != kDynamicOutput) {
180     CUST_KERNEL_CHECK_FALSE(ctx, (ctx.GetOutputsSize() == outputs_num), KERNEL_STATUS_PARAM_INVALID,
181                             "[%s] need [%u] outputs, but got [%u].", ctx.GetOpType().c_str(), outputs_num,
182                             ctx.GetOutputsSize());
183     for (uint32_t i = 0; i < outputs_num; ++i) {
184       Tensor *output = ctx.Output(i);
185       CUST_KERNEL_CHECK_NULLPTR(ctx, output, KERNEL_STATUS_INNER_ERROR, "[%s] get output[%u] failed.",
186                                 ctx.GetOpType().c_str(), i);
187       auto output_shape = output->GetTensorShape();
188       CUST_KERNEL_CHECK_NULLPTR(ctx, output_shape, KERNEL_STATUS_PARAM_INVALID,
189                                 "%s output[%u] tensor shape is nullptr.", ctx.GetOpType().c_str(), i);
190       if (!IsEmptyTensor(output)) {
191         auto output_data = output->GetData();
192         CUST_KERNEL_CHECK_NULLPTR(ctx, output_data, KERNEL_STATUS_PARAM_INVALID,
193                                   "%s output[%u] tensor data is nullptr.", ctx.GetOpType().c_str(), i);
194       }
195     }
196   }
197   return KERNEL_STATUS_OK;
198 }
199 
NormalCheck(CpuKernelContext & ctx,const uint32_t inputs_num,const uint32_t outputs_num,const std::vector<std::string> & attr_names)200 uint32_t NormalCheck(CpuKernelContext &ctx, const uint32_t inputs_num, const uint32_t outputs_num,
201                      const std::vector<std::string> &attr_names) {
202   CUST_KERNEL_HANDLE_ERROR(ctx, NormalCheck(ctx, inputs_num, outputs_num), "Check Greater params failed.");
203   for (auto const &attr_name : attr_names) {
204     auto attr = ctx.GetAttr(attr_name);
205     CUST_KERNEL_CHECK_NULLPTR(ctx, attr, KERNEL_STATUS_PARAM_INVALID, "%s get attr[%s] is nullptr.",
206                               ctx.GetOpType().c_str(), attr_name.c_str());
207   }
208   return KERNEL_STATUS_OK;
209 }
210 
IsScalar(const std::vector<int64_t> & shape)211 bool IsScalar(const std::vector<int64_t> &shape) { return (shape.size() == 0); }
212 
IsVector(const std::vector<int64_t> & shape)213 bool IsVector(const std::vector<int64_t> &shape) { return (shape.size() == 1); }
214 
IsMatrix(const std::vector<int64_t> & shape)215 bool IsMatrix(const std::vector<int64_t> &shape) { return (shape.size() == 2); }
216 
IsSquareMatrix(const std::vector<int64_t> & shape)217 bool IsSquareMatrix(const std::vector<int64_t> &shape) { return ((shape.size() == 2) && (shape[0] == shape[1])); }
218 
AddrAlignedCheck(const void * addr,uint64_t alignment)219 bool AddrAlignedCheck(const void *addr, uint64_t alignment) {
220   return reinterpret_cast<uint64_t>(reinterpret_cast<uintptr_t>(addr)) % alignment == 0;
221 }
222 
IsVectorOrHigher(const std::vector<int64_t> & shape)223 bool IsVectorOrHigher(const std::vector<int64_t> &shape) { return (shape.size() >= 1); }
224 
DType(std::string dtype_str)225 DataType DType(std::string dtype_str) {
226   auto iter = dtype_maps.find(dtype_str);
227   if (iter != dtype_maps.end()) {
228     return iter->second;
229   } else {
230     return DT_UNDEFINED;
231   }
232 }
233 
DTypeStr(DataType dtype)234 std::string DTypeStr(DataType dtype) {
235   auto iter =
236     std::find_if(dtype_maps.begin(), dtype_maps.end(),
237                  [dtype](const std::map<std::string, DataType>::value_type &kv) { return (kv.second == dtype); });
238   if (iter != dtype_maps.end()) {
239     return iter->first;
240   } else {
241     return std::string("DT_UNDEFINED");
242   }
243 }
244 
CheckTensorTypeSame(CpuKernelContext & ctx,const std::map<std::string,DataType> & types,const DataType & check_type,const std::string & prim_name)245 uint32_t CheckTensorTypeSame(CpuKernelContext &ctx, const std::map<std::string, DataType> &types,
246                              const DataType &check_type, const std::string &prim_name) {
247   if (types.empty()) {
248     CUST_KERNEL_LOG_ERROR(ctx, "Trying to use the function to check a empty types map!");
249     return KERNEL_STATUS_PARAM_INVALID;
250   }
251   for (const auto type : types) {
252     auto _type_ = type.second;
253     if (_type_ != check_type) {
254       CUST_KERNEL_LOG_ERROR(ctx,
255                             "For primitive[%s]'s input arguments [%s] type should equal to [%s] , "
256                             "but get the real type [%s].",
257                             prim_name.c_str(), type.first.c_str(), DTypeStr(check_type).c_str(),
258                             DTypeStr(_type_).c_str());
259       return KERNEL_STATUS_PARAM_INVALID;
260     }
261   }
262   return KERNEL_STATUS_OK;
263 }
264 
CheckTensorShapeSame(CpuKernelContext & ctx,const std::map<std::string,TensorShapePtr> & shapes,const std::vector<int64_t> & check_shape,const std::string & prim_name)265 uint32_t CheckTensorShapeSame(CpuKernelContext &ctx, const std::map<std::string, TensorShapePtr> &shapes,
266                               const std::vector<int64_t> &check_shape, const std::string &prim_name) {
267   if (shapes.empty()) {
268     CUST_KERNEL_LOG_ERROR(ctx, "Trying to use the function to check a empty types map!");
269     return KERNEL_STATUS_PARAM_INVALID;
270   }
271   for (const auto shape : shapes) {
272     auto _shape_ptr_ = shape.second;
273     CUST_KERNEL_CHECK_NULLPTR(ctx, _shape_ptr_, KERNEL_STATUS_PARAM_INVALID,
274                               "For primitive[%s]'s input arguments [%s] TensorShapePtr "
275                               "should not be nullptr.",
276                               prim_name.c_str(), shape.first.c_str());
277     auto _shape_ = _shape_ptr_->GetDimSizes();
278     if (!ShapeVectorIsSame(_shape_, check_shape)) {
279       CUST_KERNEL_LOG_ERROR(ctx,
280                             "For primitive[%s]'s input arguments [%s] shape should equal to (%s) , "
281                             "but get the real shape (%s).",
282                             prim_name.c_str(), shape.first.c_str(), VectorToString(check_shape).c_str(),
283                             VectorToString(_shape_).c_str());
284       return KERNEL_STATUS_PARAM_INVALID;
285     }
286   }
287   return KERNEL_STATUS_OK;
288 }
289 
290 }  // namespace aicpu
291