1 /**
2 * Copyright 2019-2023 Huawei Technologies Co., Ltd
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 #ifndef MINDSPORE_CCSRC_KERNEL_COMMON_UTILS_H_
17 #define MINDSPORE_CCSRC_KERNEL_COMMON_UTILS_H_
18
19 #include <dirent.h>
20 #include <sstream>
21 #include <limits>
22 #include <functional>
23 #include <memory>
24 #include <unordered_map>
25 #include <unordered_set>
26 #include <map>
27 #include <set>
28 #include <string>
29 #include <algorithm>
30 #include <vector>
31 #include <utility>
32 #include <tuple>
33 #include "include/common/utils/utils.h"
34 #include "kernel/kernel.h"
35 #include "kernel/kash/kernel_pack.h"
36 #include "kernel/kernel_build_info.h"
37 #include "ops/base_operator.h"
38
39 namespace mindspore {
40 namespace kernel {
41 constexpr auto kProcessorAiCore = "aicore";
42 constexpr auto kProcessorAiCpu = "aicpu";
43 constexpr auto kProcessorCuda = "cuda";
44 constexpr auto kProcessorCpu = "cpu";
45 constexpr auto kProcessorUnknown = "unknown";
46 constexpr unsigned int AUTODIFF_COMPILE_OVERTIME = 600;
47
48 // an enum to indicate a vector or matrix alignment direction.
49 // real_data: [1,2,3] left_align: [1,2,3,0] right_align:[0,1,2,3]
50 namespace MatrixDiag {
51 enum Alignment { RIGHT = 0, LEFT = 1 };
52 } // namespace MatrixDiag
53
54 struct KernelMetaInfo {
55 uintptr_t func_stub_;
56 uint32_t block_dim_;
57 };
58 using KernelMetaPtr = std::shared_ptr<KernelMetaInfo>;
59
60 class MatrixInfo {
61 public:
MatrixInfo(size_t max_index,const ShapeVector & matrix_shapes)62 explicit MatrixInfo(size_t max_index, const ShapeVector &matrix_shapes)
63 : max_index_(max_index), shapes_(matrix_shapes) {
64 current_indexes_.resize(shapes_.size(), 0);
65 }
66 ~MatrixInfo() = default;
SetIndex(size_t start,size_t end)67 bool SetIndex(size_t start, size_t end) {
68 // Check data from start to end whether valid.
69 if (start < min_index || end > max_index_ || start >= end) {
70 return false;
71 }
72 // Initial current indexes.
73 int last_rank = SizeToInt(current_indexes_.size()) - 1;
74 for (int i = last_rank; i >= 0; --i) {
75 size_t position = IntToSize(i);
76 current_indexes_[position] = start % LongToSize(shapes_.at(position));
77 start = start / LongToSize(shapes_.at(position));
78 if (start == 0) {
79 break;
80 }
81 }
82 return true;
83 }
IndexIterator()84 std::vector<size_t> IndexIterator() {
85 if (is_first_iterator_) {
86 is_first_iterator_ = false;
87 return current_indexes_;
88 }
89 size_t last_rank = current_indexes_.size() - 1;
90 current_indexes_[last_rank]++;
91 for (size_t i = last_rank; current_indexes_.at(i) >= LongToSize(shapes_.at(i)) && i > 0; --i) {
92 current_indexes_[i] = 0;
93 current_indexes_[i - 1] += 1;
94 }
95 is_first_iterator_ = false;
96 return current_indexes_;
97 }
98
99 private:
100 bool is_first_iterator_{true};
101 size_t min_index{0};
102 size_t max_index_{1};
103 ShapeVector shapes_;
104 std::vector<size_t> current_indexes_;
105 };
106 using MatrixInfoPtr = std::shared_ptr<MatrixInfo>;
107 int CalDiagOffset(int diag_index, int max_diag_len, int inner_rows, int inner_cols,
108 const std::pair<MatrixDiag::Alignment, MatrixDiag::Alignment> &alignment);
109 TypeId DtypeToTypeId(const std::string &dtypes);
110 std::string Dtype2ShortType(const std::string &dtype);
111 BACKEND_EXPORT size_t GetDtypeNbyte(const std::string &dtype);
112 BACKEND_EXPORT bool IsSameShape(const ShapeVector &shape_a, const ShapeVector &shape_b);
113 BACKEND_EXPORT bool CheckShapesSame(const ShapeArray &shape_array);
114 std::string GetProcessorStr(const AnfNodePtr &anf_node);
115 template <typename T>
116 struct AsymmetricFunc {
operatorAsymmetricFunc117 T operator()(const T &new_x, const int &old_length, const int &new_length) const {
118 return new_length != 0 ? new_x * old_length / new_length : 0;
119 }
120 };
121
122 template <template <typename, typename, typename...> typename M, typename T>
Map2Str(const M<std::string,T> value)123 inline std::string Map2Str(const M<std::string, T> value) {
124 std::stringstream ss;
125 ss << "(";
126 for (auto it = value.begin(); it != value.end(); it++) {
127 if (it == value.begin()) {
128 ss << it->first;
129 } else {
130 ss << ", " << it->first;
131 }
132 }
133 ss << ")";
134 return ss.str();
135 }
136
137 struct DataType {
138 explicit DataType(const TypeId &dtype, const string &format = kOpFormat_DEFAULT,
139 const TypeId &object_type = kObjectTypeTensorType, bool is_optional = false)
dtypeDataType140 : dtype(dtype), format(format), object_type(object_type), is_optional(is_optional) {}
141 TypeId dtype;
142 std::string format;
143 TypeId object_type;
144 bool is_optional;
145 };
146
147 class BACKEND_EXPORT KernelAttr {
148 public:
149 KernelAttr() = default;
150 ~KernelAttr() = default;
151
152 KernelAttr &AddInputAttr(const TypeId &ms_type, const std::string &format = kOpFormat_DEFAULT);
153 KernelAttr &AddOptionalInputAttr(const TypeId &ms_type, const std::string &format = kOpFormat_DEFAULT);
154 KernelAttr &AddOutputAttr(const TypeId &ms_type, const std::string &format = kOpFormat_DEFAULT);
155 KernelAttr &AddInputAttr(const TypeId &object_type, const TypeId &ms_type,
156 const std::string &formatt = kOpFormat_DEFAULT);
157 KernelAttr &AddOptionalInputAttr(const TypeId &object_type, const TypeId &ms_type,
158 const std::string &formatt = kOpFormat_DEFAULT);
159 KernelAttr &AddOutputAttr(const TypeId &object_type, const TypeId &ms_type,
160 const std::string &formatt = kOpFormat_DEFAULT);
161 KernelAttr &AddAllSameAttr(bool all_same, size_t all_same_input_num = 1, bool group_allsame = false);
162 KernelAttr &AddSkipCheckAttr(bool skip_check);
163 KernelAttr &AddRealTuple(const bool &is_real_tuple);
164 KernelAttr &AddOutInRef(size_t output_index, size_t input_index);
165 KernelAttr &AddAllOutInRef(bool all_out_in_ref);
166
GetInputAttr(const size_t index)167 const DataType &GetInputAttr(const size_t index) const { return input_type_[index]; }
GetOutputAttr(const size_t index)168 const DataType &GetOutputAttr(const size_t index) const { return output_type_[index]; }
GetAllSame()169 bool GetAllSame() const { return all_same_; }
GetSkipCheck()170 bool GetSkipCheck() const { return skip_check_; }
GetRealTuple()171 const bool &GetRealTuple() const { return is_real_tuple_; }
GetGroupAllSame()172 bool GetGroupAllSame() const { return is_group_allsame_; }
GetAllSameInputNum()173 size_t GetAllSameInputNum() const { return all_same_input_num_; }
GetInputSize()174 size_t GetInputSize() const { return input_type_.size(); }
GetOutputSize()175 size_t GetOutputSize() const { return output_type_.size(); }
GetOutInRefMap()176 const OutputInputRefMap &GetOutInRefMap() const { return out_in_ref_map_; }
GetAllOutInRef()177 bool GetAllOutInRef() const { return all_out_in_ref_; }
178
179 void SetInputAttr(const size_t index, const TypeId &ms_type, const std::string &format);
180 void SetOutputAttr(const size_t index, const TypeId &ms_type, const std::string &format);
181 void SetInputAttrList(const std::vector<DataType> &addr_list);
182 void SetOutputAttrList(const std::vector<DataType> &addr_list);
183
input_type()184 const std::vector<DataType> &input_type() const { return input_type_; }
output_type()185 const std::vector<DataType> &output_type() const { return output_type_; }
186
187 private:
188 std::vector<DataType> input_type_;
189 std::vector<DataType> output_type_;
190 bool all_same_{false};
191 bool skip_check_{false};
192 bool is_real_tuple_{false};
193 bool is_group_allsame_{false};
194 size_t all_same_input_num_{0};
195
196 // The map between kernel's output and input ref relationship.
197 OutputInputRefMap out_in_ref_map_;
198
199 // The reference for all outputs and inputs of the same index.
200 bool all_out_in_ref_{false};
201 };
202
203 BACKEND_EXPORT size_t GetOutputNum(const AnfNodePtr &node);
204 BACKEND_EXPORT std::ostream &operator<<(std::ostream &os, KernelAttr kernel_attr);
205
206 BACKEND_EXPORT std::pair<bool, size_t> MatchKernelAttr(const KernelAttr &kernel_attr,
207 const std::vector<KernelAttr> &kernel_attr_list);
208 BACKEND_EXPORT std::pair<bool, size_t> MatchKernelAttrStrict(const KernelAttr &kernel_attr,
209 const std::vector<KernelAttr> &kernel_attr_list);
210 BACKEND_EXPORT KernelAttr GetKernelAttrFromBuildInfo(const KernelBuildInfoPtr &build_info);
211 BACKEND_EXPORT KernelAttr GetKernelAttrFromNode(const AnfNodePtr &kernel_node);
212 BACKEND_EXPORT bool IsFoldKernelBuildInfo(const KernelBuildInfoPtr &kernel_build_info);
213 BACKEND_EXPORT KernelAttr GetKernelAttrFromTensors(const std::vector<KernelTensor *> &inputs,
214 const std::vector<KernelTensor *> &outputs);
215 void SetCpuRefMapToKernelInfo(const CNodePtr &apply_kernel, const std::vector<KernelAttr> &apply_kernel_attrs);
216 // Synchronize the output and input reference map between two kernel attrs.
217 void SyncOutInRef(const KernelAttr &from_kernel_attr, KernelAttr *to_kernel_attr);
218 BACKEND_EXPORT std::string FetchPrintInfoByKernelAttr(KernelAttr selected_kernel_attr);
219 std::vector<TypeId> GetInputObjectTypeListFromKernelAttr(const KernelAttr &kernel_attr);
220 std::vector<TypeId> GetOutputObjectTypeListFromKernelAttr(const KernelAttr &kernel_attr);
221 // The related interfaces of kernel object type.
222 BACKEND_EXPORT void SetKernelObjectTypeBuildInfo(const AnfNodePtr &kernel_node,
223 const std::vector<KernelObjectType> &input_kernel_object_types,
224 const std::vector<KernelObjectType> &output_kernel_object_types);
225 BACKEND_EXPORT void SetKernelObjectTypeWithSelectedAttr(const CNodePtr &kernel_node,
226 const kernel::KernelAttr &selected_kernel_attr);
227 BACKEND_EXPORT bool SelectKernelByObjectType(const CNodePtr &kernel_node,
228 const std::vector<KernelAttr> ®istered_kernel_attrs,
229 std::vector<KernelAttr> *selected_kernel_attrs);
230 // Tuple --> Tuple.
231 BACKEND_EXPORT KernelObjectType TypeIdToKernelObjectType(const TypeId &type_id);
232 BACKEND_EXPORT std::vector<KernelObjectType> TypeIdToKernelObjectType(const std::vector<TypeId> &type_ids);
233 // Tuple --> TupleUnfold.
234 BACKEND_EXPORT KernelObjectType TypeIdToKernelObjectTypeForTupleUnfold(const TypeId &type_id);
235 BACKEND_EXPORT std::vector<KernelObjectType> TypeIdToKernelObjectTypeForTupleUnfold(
236 const std::vector<TypeId> &type_ids);
237 BACKEND_EXPORT TypeId KernelObjectTypeToTypeId(const KernelObjectType &object_type);
238
239 BACKEND_EXPORT bool CheckAttrForAllSameInput(const size_t input_num, const std::vector<mindspore::TypeId> &input_types,
240 const KernelAttr &cur_kernel_attr);
241
242 BACKEND_EXPORT void SetKernelObjectTypeBuildInfo(
243 const AnfNodePtr &kernel_node, const std::vector<KernelObjectType> &input_kernel_object_types,
244 const std::vector<KernelObjectType> &output_kernel_object_types,
245 const std::vector<KernelObjectType> &output_elements_kernel_object_types);
246
247 template <typename Derived>
248 class MatchKernelHelper {
249 public:
250 MatchKernelHelper() = default;
251 virtual ~MatchKernelHelper() = default;
252
253 using KernelRunFunc = std::function<bool(Derived *, const std::vector<KernelTensor *> &,
254 const std::vector<KernelTensor *> &, const std::vector<KernelTensor *> &)>;
255 virtual const std::vector<std::pair<KernelAttr, KernelRunFunc>> &GetFuncList() const = 0;
256
257 protected:
OpSupport()258 std::vector<KernelAttr> OpSupport() const {
259 auto &func_list = static_cast<const Derived *>(this)->GetFuncList();
260 std::vector<KernelAttr> support_list;
261 (void)std::transform(func_list.begin(), func_list.end(), std::back_inserter(support_list),
262 [](const std::pair<KernelAttr, KernelRunFunc> &pair) { return pair.first; });
263 return support_list;
264 }
265
MatchKernelFunc(const std::string & kernel_name,const std::vector<KernelTensor * > & inputs,const std::vector<KernelTensor * > & outputs)266 bool MatchKernelFunc(const std::string &kernel_name, const std::vector<KernelTensor *> &inputs,
267 const std::vector<KernelTensor *> &outputs) {
268 auto kernel_attr = GetKernelAttrFromTensors(inputs, outputs);
269 auto &func_list = static_cast<Derived *>(this)->GetFuncList();
270 auto [is_match, index] = MatchKernelAttr(kernel_attr, OpSupport());
271 if (!is_match) {
272 MS_LOG(ERROR) << "The kernel '" << kernel_name << "' does not support this kernel data type: " << kernel_attr;
273 return false;
274 }
275 kernel_func_ = func_list[index].second;
276 return true;
277 }
278
279 KernelRunFunc kernel_func_;
280 };
281
282 namespace math {
283 BACKEND_EXPORT void SinCosf(float x, float *sinv, float *cosv);
284 }
285
GetRawAddress(const std::vector<AddressPtr> & addrs,std::vector<void * > * raw_addrs)286 inline void GetRawAddress(const std::vector<AddressPtr> &addrs, std::vector<void *> *raw_addrs) {
287 (void)std::transform(std::begin(addrs), std::end(addrs), std::back_inserter(*raw_addrs),
288 [](const AddressPtr &address) -> void * {
289 MS_EXCEPTION_IF_NULL(address);
290 return address->addr;
291 });
292 }
293
294 #define CHECK_KERNEL_INPUTS_NUM(actual_inputs_num, expect_inputs_num, kernel_name) \
295 do { \
296 if ((actual_inputs_num) != (expect_inputs_num)) { \
297 MS_LOG(EXCEPTION) << (kernel_name) << " requires " << (expect_inputs_num) << " inputs, but got " \
298 << (actual_inputs_num) << "."; \
299 } \
300 } while (0)
301
302 #define CHECK_KERNEL_OUTPUTS_NUM(actual_outputs_num, expect_outputs_num, kernel_name) \
303 do { \
304 if ((actual_outputs_num) != (expect_outputs_num)) { \
305 MS_LOG(EXCEPTION) << (kernel_name) << " should have " << (expect_outputs_num) << " outputs, but got " \
306 << (actual_outputs_num) << "."; \
307 } \
308 } while (0)
309 } // namespace kernel
310 } // namespace mindspore
311
312 #endif // MINDSPORE_CCSRC_KERNEL_COMMON_UTILS_H_
313