• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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