1 /**
2 * Copyright 2021 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
17 #include "runtime/device/ascend/executor/tiling/op_tiling_adapter.h"
18 #include "backend/kernel_compiler/tbe/tbe_kernel_build.h"
19 #include "backend/kernel_compiler/tbe/tbe_dynaminc_shape_util.h"
20 #include "backend/session/anf_runtime_algorithm.h"
21 #include "runtime/device/ascend/ge_types_convert.h"
22 #include "utils/utils.h"
23 #include "external/graph/tensor.h"
24 #include "external/register/op_tiling_registry.h"
25 #include "graph/utils/graph_utils.h"
26 #include "common/ge_inner_error_codes.h"
27 #include "graph/utils/op_desc_utils.h"
28
29 namespace mindspore {
30 namespace device {
31 namespace tiling {
32 constexpr auto COMPILE_INFO_KEY = "compile_info_key";
33 constexpr auto COMPILE_INFO_JSON = "compile_info_json";
34 constexpr auto ATOMIC_COMPILE_INFO_KEY = "_atomic_compile_info_key";
35 constexpr auto ATOMIC_COMPILE_INFO_JSON = "_atomic_compile_info_json";
36 constexpr auto ATTR_NAME_OP_INFER_DEPENDS = "_op_infer_depends";
37 constexpr auto CONSTANTOP = "Constant";
38 constexpr auto ATTR_NAME_WEIGHTS = "value";
39 constexpr auto PARAM_DYNAMIC = "dynamic";
40
GetRealOpType(const std::string & op_type)41 std::string OpTilingCalculateAdapter::GetRealOpType(const std::string &op_type) {
42 static const std::map<std::string, std::string> kOpTypeMap = {
43 {"SparseApplyFtrl", "SparseApplyFtrlD"},
44 {"SparseApplyProximalAdagrad", "SparseApplyProximalAdagradD"},
45 {"SparseGatherV2", "Gather"},
46 {"Pad", "PadD"},
47 {"Concat", "ConcatD"},
48 {"Softmax", "SoftmaxV2"},
49 {"DropoutDoMask", "DropOutDoMask"},
50 };
51 auto iter = kOpTypeMap.find(op_type);
52 if (iter == kOpTypeMap.end()) {
53 return op_type;
54 }
55 return iter->second;
56 }
57
GetOutputName(const CNodePtr & node,size_t index)58 std::string OpTilingCalculateAdapter::GetOutputName(const CNodePtr &node, size_t index) {
59 MS_EXCEPTION_IF_NULL(node);
60 if (output_names_.size() < index) {
61 return "unknown_name";
62 }
63 return output_names_[index];
64 }
65
GetInputName(const CNodePtr & node,size_t index)66 std::string OpTilingCalculateAdapter::GetInputName(const CNodePtr &node, size_t index) {
67 MS_EXCEPTION_IF_NULL(node);
68 if (input_names_.size() < index) {
69 return "unknown_name";
70 }
71 return input_names_[index];
72 }
73
ConvertInputShapeAndType(const CNodePtr & node,ge::OpDescPtr * op_desc)74 void OpTilingCalculateAdapter::ConvertInputShapeAndType(const CNodePtr &node, ge::OpDescPtr *op_desc) {
75 MS_EXCEPTION_IF_NULL(node);
76 MS_EXCEPTION_IF_NULL(*op_desc);
77 auto input_size = AnfAlgo::GetInputTensorNum(node);
78 for (size_t i = 0; i < input_size; i++) {
79 // ms info
80 auto real_index = AnfAlgo::GetRealInputIndex(node, i);
81 auto input_node_with_idx = AnfAlgo::GetPrevNodeOutput(node, real_index);
82 auto input_node = input_node_with_idx.first;
83 auto input_index = input_node_with_idx.second;
84 auto ms_ori_shape = AnfAlgo::GetOutputInferShape(input_node, input_index);
85 auto ms_shape = AnfAlgo::GetOutputDeviceShape(input_node, input_index);
86 auto ms_format = AnfAlgo::GetOutputFormat(input_node, input_index);
87 auto ms_dtype = AnfAlgo::GetOutputDeviceDataType(input_node, input_index);
88
89 // ge info
90 std::vector<int64_t> ge_shape;
91 std::vector<int64_t> ge_ori_shape;
92 ge::DataType ge_dtype = ascend::GeTypesConvert::TransTypeIdToGeDataType(ms_dtype);
93 ge::Format ge_format = ascend::GeTypesConvert::GetGeFormat(ms_format, ms_shape.size());
94 std::transform(ms_shape.begin(), ms_shape.end(), std::back_inserter(ge_shape),
95 [](size_t s) { return static_cast<int64_t>(s); });
96 std::transform(ms_ori_shape.begin(), ms_ori_shape.end(), std::back_inserter(ge_ori_shape),
97 [](size_t s) { return static_cast<int64_t>(s); });
98
99 auto input_name = GetInputName(node, real_index);
100 ge::GeTensorDesc ge_tensor_desc;
101 ge_tensor_desc.SetFormat(ge_format);
102 ge_tensor_desc.SetDataType(ge_dtype);
103 ge_tensor_desc.SetShape(ge::GeShape(ge_shape));
104 ge_tensor_desc.SetOriginShape(ge::GeShape(ge_ori_shape));
105 ge_tensor_desc.SetName(input_name);
106 (void)(*op_desc)->AddInputDesc(input_name, ge_tensor_desc);
107 }
108 }
109
ConvertOutputShapeAndType(const CNodePtr & node,ge::OpDescPtr * op_desc)110 void OpTilingCalculateAdapter::ConvertOutputShapeAndType(const CNodePtr &node, ge::OpDescPtr *op_desc) {
111 MS_EXCEPTION_IF_NULL(node);
112 MS_EXCEPTION_IF_NULL(*op_desc);
113 auto output_size = AnfAlgo::GetOutputTensorNum(node);
114 for (size_t i = 0; i < output_size; i++) {
115 auto ms_shape = AnfAlgo::GetOutputDeviceShape(node, i);
116 auto ms_ori_shape = AnfAlgo::GetOutputInferShape(node, i);
117 auto ms_format = AnfAlgo::GetOutputFormat(node, i);
118 auto ms_dtype = AnfAlgo::GetOutputDeviceDataType(node, i);
119
120 std::vector<int64_t> ge_shape;
121 std::vector<int64_t> ge_ori_shape;
122 ge::DataType ge_dtype = ascend::GeTypesConvert::TransTypeIdToGeDataType(ms_dtype);
123 ge::Format ge_format = ascend::GeTypesConvert::GetGeFormat(ms_format, ms_shape.size());
124 std::transform(ms_shape.begin(), ms_shape.end(), std::back_inserter(ge_shape),
125 [](size_t s) { return static_cast<int64_t>(s); });
126 std::transform(ms_ori_shape.begin(), ms_ori_shape.end(), std::back_inserter(ge_ori_shape),
127 [](size_t s) { return static_cast<int64_t>(s); });
128 auto output_name = GetOutputName(node, i);
129 ge::GeTensorDesc ge_tensor_desc;
130 ge_tensor_desc.SetFormat(ge_format);
131 ge_tensor_desc.SetDataType(ge_dtype);
132 ge_tensor_desc.SetShape(ge::GeShape(ge_shape));
133 ge_tensor_desc.SetOriginShape(ge::GeShape(ge_ori_shape));
134 ge_tensor_desc.SetName(output_name);
135 (void)(*op_desc)->AddOutputDesc(output_name, ge_tensor_desc);
136 }
137 }
138
ConvertCompileInfo(const CNodePtr & node,ge::OpDescPtr * op_desc)139 void OpTilingCalculateAdapter::ConvertCompileInfo(const CNodePtr &node, ge::OpDescPtr *op_desc) {
140 MS_EXCEPTION_IF_NULL(node);
141 MS_EXCEPTION_IF_NULL(*op_desc);
142 MS_LOG(INFO) << "For op " << op_name_ << ", get compile_info: " << op_compile_info_;
143 std::string compile_info_key = std::to_string(std::hash<std::string>()(op_compile_info_));
144 (void)ge::AttrUtils::SetStr(*(*op_desc), COMPILE_INFO_KEY, compile_info_key);
145 (void)ge::AttrUtils::SetStr(*(*op_desc), COMPILE_INFO_JSON, op_compile_info_);
146 }
147
NewConstantOp(const CNodePtr & node,const std::string & name,const tensor::TensorPtr & tensor_data,ge::ComputeGraphPtr * ge_graph,size_t index)148 ge::NodePtr OpTilingCalculateAdapter::NewConstantOp(const CNodePtr &node, const std::string &name,
149 const tensor::TensorPtr &tensor_data, ge::ComputeGraphPtr *ge_graph,
150 size_t index) {
151 MS_EXCEPTION_IF_NULL(node);
152 MS_EXCEPTION_IF_NULL(*ge_graph);
153 MS_EXCEPTION_IF_NULL(tensor_data);
154 ge::OpDescPtr op_desc = std::make_shared<ge::OpDesc>(name, CONSTANTOP);
155 auto ms_format = AnfAlgo::GetPrevNodeOutputFormat(node, index);
156 auto ms_ori_shape = AnfAlgo::GetPrevNodeOutputInferShape(node, index);
157 auto ms_dtype = AnfAlgo::GetPrevNodeOutputDeviceDataType(node, index);
158 auto ms_shape = AnfAlgo::GetInputDeviceShape(node, index);
159
160 std::vector<int64_t> ge_shape;
161 std::vector<int64_t> ge_ori_shape;
162 std::transform(ms_shape.begin(), ms_shape.end(), std::back_inserter(ge_shape),
163 [](size_t s) { return static_cast<int64_t>(s); });
164 std::transform(ms_ori_shape.begin(), ms_ori_shape.end(), std::back_inserter(ge_ori_shape),
165 [](size_t s) { return static_cast<int64_t>(s); });
166 ge::DataType ge_dtype = ascend::GeTypesConvert::TransTypeIdToGeDataType(ms_dtype);
167 ge::Format ge_format = ascend::GeTypesConvert::GetGeFormat(ms_format, ms_shape.size());
168 ge::GeTensorDesc ge_tensor_desc;
169 ge_tensor_desc.SetFormat(ge_format);
170 ge_tensor_desc.SetDataType(ge_dtype);
171 ge_tensor_desc.SetShape(ge::GeShape(ge_shape));
172 ge_tensor_desc.SetOriginShape(ge::GeShape(ge_ori_shape));
173 ge_tensor_desc.SetName(name);
174 ge::GeTensorPtr ge_tensor = std::make_shared<ge::GeTensor>(
175 ge_tensor_desc, static_cast<uint8_t *>(tensor_data->data_c()), IntToSize(tensor_data->Size()));
176 (void)op_desc->AddOutputDesc(name, ge_tensor_desc);
177 ge::NodePtr constant_op = (*ge_graph)->AddNode(op_desc);
178 ge::OpDescUtils::SetWeights(constant_op, {ge_tensor});
179 (void)ge::AttrUtils::SetTensor(op_desc, ATTR_NAME_WEIGHTS, ge_tensor);
180 return constant_op;
181 }
182
ConvertDepends(const CNodePtr & node,const std::map<uint32_t,tensor::TensorPtr> & depend_tensor_map,ge::OpDescPtr * op_desc,ge::ComputeGraphPtr * ge_graph)183 std::vector<std::tuple<std::size_t, ge::NodePtr>> OpTilingCalculateAdapter::ConvertDepends(
184 const CNodePtr &node, const std::map<uint32_t, tensor::TensorPtr> &depend_tensor_map, ge::OpDescPtr *op_desc,
185 ge::ComputeGraphPtr *ge_graph) {
186 MS_EXCEPTION_IF_NULL(node);
187 MS_EXCEPTION_IF_NULL(*op_desc);
188 auto depends_list_me = abstract::GetDependsFormMap(node);
189 if (depends_list_me.empty()) {
190 MS_LOG(INFO) << "The node " << op_name_ << " has no infer depend ";
191 return {};
192 }
193 auto has_input_name_attr = AnfAlgo::HasNodeAttr("input_names", node);
194 if (!has_input_name_attr) {
195 MS_LOG(EXCEPTION) << "Node should has attr: input_names. " << node->fullname_with_scope();
196 }
197 auto input_names_attr = AnfAlgo ::GetNodeAttr<std::vector<std::string>>(node, "input_names");
198 std::vector<std::string> op_infer_depends;
199 std::vector<std::tuple<std::size_t, ge::NodePtr>> constant_ops;
200 for (auto index : depends_list_me) {
201 if (LongToSize(index) > input_names_attr.size()) {
202 MS_LOG(EXCEPTION) << "Input index " << index << " should less input_names' size " << input_names_attr.size();
203 }
204 auto iter = depend_tensor_map.find(LongToSize(index));
205 if (iter == depend_tensor_map.end()) {
206 MS_LOG(EXCEPTION) << "Input index " << index << " should less than depend_tensor_map' size "
207 << input_names_attr.size();
208 }
209 auto depend_name = input_names_attr[index];
210 auto const_tensor = iter->second;
211 ge::NodePtr ge_constant_op = NewConstantOp(node, depend_name, const_tensor, ge_graph, index);
212 auto original_index = AnfAlgo::GetOriginalInputIndex(node, index);
213 constant_ops.emplace_back(std::tuple<std::size_t, ge::NodePtr>(original_index, ge_constant_op));
214 op_infer_depends.emplace_back(depend_name);
215 }
216 (void)(*op_desc)->SetOpInferDepends(op_infer_depends);
217 return constant_ops;
218 }
219
AddEdge(const ge::NodePtr & ge_node,const std::vector<std::tuple<std::size_t,ge::NodePtr>> & constant_ops)220 void OpTilingCalculateAdapter::AddEdge(const ge::NodePtr &ge_node,
221 const std::vector<std::tuple<std::size_t, ge::NodePtr>> &constant_ops) {
222 MS_EXCEPTION_IF_NULL(ge_node);
223 MS_LOG(INFO) << "Add edge for op " << op_name_;
224 for (const auto &item : constant_ops) {
225 auto index = std::get<0>(item);
226 auto constant_op = std::get<1>(item);
227 (void)ge_node->AddLinkFrom(index, constant_op);
228 }
229 }
230
InitOpIoName(const CNodePtr & node)231 void OpTilingCalculateAdapter::InitOpIoName(const CNodePtr &node) {
232 MS_EXCEPTION_IF_NULL(node);
233 MS_LOG(INFO) << "Get the every input name of " << op_name_;
234 auto op_info_ptr = mindspore::kernel::tbe::TbeDynamicShapeUtil::FindOp(op_name_, node);
235 MS_EXCEPTION_IF_NULL(op_info_ptr);
236 auto primitive = AnfAlgo::GetCNodePrimitive(node);
237 MS_EXCEPTION_IF_NULL(primitive);
238 auto inputs_ptr = op_info_ptr->inputs_ptr();
239 size_t dynamic_input_index = 0;
240 std::vector<int64_t> dynamic_inputs_list;
241 if (primitive->GetAttr(kAttrDynInputSizes) != nullptr) {
242 dynamic_inputs_list = GetValue<std::vector<int64_t>>(primitive->GetAttr(kAttrDynInputSizes));
243 }
244 for (const auto &item : inputs_ptr) {
245 MS_EXCEPTION_IF_NULL(item);
246 if (item->param_type() == PARAM_DYNAMIC) {
247 if (dynamic_input_index > dynamic_inputs_list.size()) {
248 MS_LOG(EXCEPTION) << "Dynamic input index should less than the dynamic input's size.";
249 }
250 auto real_inputs_num = dynamic_inputs_list[dynamic_input_index];
251 for (auto k = 0; k < real_inputs_num; k++) {
252 std::string input_name = item->name() + "_dynamic_" + std::to_string(k);
253 input_names_.emplace_back(input_name);
254 }
255 dynamic_input_index++;
256 } else {
257 input_names_.emplace_back(item->name());
258 }
259 }
260
261 // output io names
262 auto outputs_ptr = op_info_ptr->outputs_ptr();
263 for (const auto &out_item : outputs_ptr) {
264 MS_EXCEPTION_IF_NULL(out_item);
265 output_names_.emplace_back(out_item->name());
266 }
267 }
268
AnfNodeToGeNodeAdapter(const CNodePtr & node,ge::ComputeGraphPtr * ge_graph,const std::map<uint32_t,tensor::TensorPtr> & depend_tensor_map,const std::string & op_compile_info)269 ge::NodePtr OpTilingCalculateAdapter::AnfNodeToGeNodeAdapter(
270 const CNodePtr &node, ge::ComputeGraphPtr *ge_graph, const std::map<uint32_t, tensor::TensorPtr> &depend_tensor_map,
271 const std::string &op_compile_info) {
272 MS_EXCEPTION_IF_NULL(node);
273 op_name_ = AnfAlgo::GetCNodeName(node);
274 MS_LOG(INFO) << "Convert anf node :" << op_name_ << " to ge node.";
275 op_compile_info_ = op_compile_info;
276 auto op_type = GetRealOpType(op_name_);
277 (void)InitOpIoName(node);
278 ge::OpDescPtr op_desc = std::make_shared<ge::OpDesc>(op_name_, op_type);
279 MS_EXCEPTION_IF_NULL(op_desc);
280 ConvertInputShapeAndType(node, &op_desc);
281 ConvertOutputShapeAndType(node, &op_desc);
282 ConvertCompileInfo(node, &op_desc);
283 std::vector<std::tuple<std::size_t, ge::NodePtr>> constant_ops =
284 ConvertDepends(node, depend_tensor_map, &op_desc, ge_graph);
285 MS_EXCEPTION_IF_NULL(*ge_graph);
286 auto ge_node = (*ge_graph)->AddNode(op_desc);
287 MS_EXCEPTION_IF_NULL(ge_node);
288 AddEdge(ge_node, constant_ops);
289 return ge_node;
290 }
291 } // namespace tiling
292 } // namespace device
293 } // namespace mindspore
294