• 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 #ifndef MINDSPORE_LITE_SRC_RUNTIME_DELEGATE_DELEGATE_UTILS_H_
17 #define MINDSPORE_LITE_SRC_RUNTIME_DELEGATE_DELEGATE_UTILS_H_
18 #include <vector>
19 #include "include/api/delegate.h"
20 #include "src/common/log_adapter.h"
21 #include "include/errorcode.h"
22 #include "nnacl/op_base.h"
23 
24 namespace mindspore::lite {
25 bool IsSubGraphInputTensor(const std::vector<mindspore::MSTensor> &inputs, mindspore::MSTensor input);
26 
27 void PackNHWCToNCHWFp32(const void *src, void *dst, int batches, int plane, int channel);
28 
29 void PackNCHWToNHWCFp32(const void *src, void *dst, int batch, int plane, int channel);
30 
31 int MaskDataNHWC2NCHWBinary(int mask);
32 
33 void BinaryMaskData2Bool(int src_mask, bool *dst_mask, size_t mask_size);
34 
35 template <typename T>
AssistDataNHWC2NCHW(void * raw_data,size_t unit_size)36 void AssistDataNHWC2NCHW(void *raw_data, size_t unit_size) {
37   MS_ASSERT(raw_data != nullptr);
38   auto data = reinterpret_cast<T *>(raw_data);
39   for (size_t i = 0; i < unit_size; ++i) {
40     int org_c = data[kNHWC_C * unit_size + i];
41     // n h w c
42     // n c h w
43     data[kNCHW_W * unit_size + i] = data[kNHWC_W * unit_size + i];
44     data[kNCHW_H * unit_size + i] = data[kNHWC_H * unit_size + i];
45     data[kNCHW_C * unit_size + i] = org_c;
46   }
47 }
48 
49 template <typename T>
GetGraphInTensors(std::vector<T * > ops,std::vector<size_t> * input_index)50 std::vector<mindspore::MSTensor> GetGraphInTensors(std::vector<T *> ops, std::vector<size_t> *input_index) {
51   std::vector<mindspore::MSTensor> inputs;
52   auto is_op_output = [&](mindspore::MSTensor tensor) -> bool {
53     for (auto op : ops) {
54       auto out_tensors = op->outputs();
55       if (std::find(out_tensors.begin(), out_tensors.end(), tensor) != out_tensors.end()) {
56         return true;
57       }
58     }
59     return false;
60   };
61 
62   for (auto op : ops) {
63     for (auto in_tensor : op->inputs()) {
64       if (in_tensor.Data() == nullptr && !is_op_output(in_tensor)) {
65         // remove the repeated input.
66         size_t idx = std::find(inputs.begin(), inputs.end(), in_tensor) - inputs.begin();
67         if (idx == inputs.size()) {
68           inputs.push_back(in_tensor);
69         }
70         if (input_index != nullptr) {
71           input_index->push_back(idx);
72         }
73       }
74     }
75   }
76   return inputs;
77 }
78 
79 template <typename T>
GetGraphOutTensors(const std::vector<T * > & ops)80 std::vector<mindspore::MSTensor> GetGraphOutTensors(const std::vector<T *> &ops) {
81   std::vector<mindspore::MSTensor> outputs;
82   auto is_op_input = [&](const mindspore::MSTensor tensor) -> bool {
83     for (auto op : ops) {
84       auto in_tensors = op->inputs();
85       if (std::find(in_tensors.begin(), in_tensors.end(), tensor) != in_tensors.end()) {
86         return true;
87       }
88     }
89     return false;
90   };
91 
92   for (auto op : ops) {
93     for (auto out_tensor : op->outputs()) {
94       if (!is_op_input(out_tensor)) {
95         outputs.push_back(out_tensor);
96       }
97     }
98   }
99 
100   for (auto op : ops) {
101     for (auto out_op : op->out_ops()) {
102       if (std::find(ops.begin(), ops.end(), out_op) == ops.end()) {
103         // visit the out op that is not in the subgraph
104         for (auto tensor : op->outputs()) {
105           if (std::find(out_op->inputs().begin(), out_op->inputs().end(), tensor) != out_op->inputs().end() &&
106               std::find(outputs.begin(), outputs.end(), tensor) == outputs.end()) {
107             // find the connected tensor
108             outputs.push_back(tensor);
109             break;
110           }
111         }
112       }
113     }
114   }
115   return outputs;
116 }
117 
118 template <typename T>
GraphInTensors(const std::vector<T * > & ops,DelegateModel<schema::Primitive> * model,KernelIter from,KernelIter end)119 std::vector<mindspore::MSTensor> GraphInTensors(const std::vector<T *> &ops, DelegateModel<schema::Primitive> *model,
120                                                 KernelIter from, KernelIter end) {
121   auto in_tensors = GetGraphInTensors(ops, nullptr);
122   std::vector<mindspore::MSTensor> all_in_tensors;
123   for (auto op : ops) {
124     for (auto in_tensor : op->inputs()) {
125       if (in_tensor.Data() != nullptr &&
126           std::find(in_tensors.begin(), in_tensors.end(), in_tensor) == in_tensors.end()) {
127         all_in_tensors.push_back(in_tensor);
128       }
129     }
130   }
131 
132   for (auto iter = model->BeginKernelIterator(); iter != model->EndKernelIterator(); iter++) {
133     if (iter >= from && iter <= end) {
134       continue;
135     }
136     // The output of other kernels is the input of the current subgraph kernel.
137     for (auto out_tensor : (*iter)->outputs()) {
138       if (std::find(all_in_tensors.begin(), all_in_tensors.end(), out_tensor) != all_in_tensors.end()) {
139         in_tensors.push_back(out_tensor);
140       }
141     }
142   }
143   return in_tensors;
144 }
145 
146 template <typename T>
GraphOutTensors(const std::vector<T * > & ops,DelegateModel<schema::Primitive> * model,KernelIter from,KernelIter end)147 std::vector<mindspore::MSTensor> GraphOutTensors(const std::vector<T *> &ops, DelegateModel<schema::Primitive> *model,
148                                                  KernelIter from, KernelIter end) {
149   auto out_tensors = GetGraphOutTensors(ops);
150   std::vector<mindspore::MSTensor> all_out_tensors;
151   for (auto op : ops) {
152     for (auto out_tensor : op->outputs()) {
153       if (std::find(out_tensors.begin(), out_tensors.end(), out_tensor) == out_tensors.end()) {
154         all_out_tensors.push_back(out_tensor);
155       }
156       if (std::find(model->outputs().begin(), model->outputs().end(), out_tensor) != model->outputs().end() &&
157           std::find(out_tensors.begin(), out_tensors.end(), out_tensor) == out_tensors.end()) {
158         out_tensors.push_back(out_tensor);
159       }
160     }
161   }
162 
163   for (auto iter = model->BeginKernelIterator(); iter != model->EndKernelIterator(); iter++) {
164     if (iter >= from && iter <= end) {
165       continue;
166     }
167     // The input of other kernels is the output of the current subgraph kernel.
168     for (auto in_tensor : (*iter)->inputs()) {
169       if (std::find(all_out_tensors.begin(), all_out_tensors.end(), in_tensor) != all_out_tensors.end() &&
170           std::find(out_tensors.begin(), out_tensors.end(), in_tensor) == out_tensors.end()) {
171         out_tensors.push_back(in_tensor);
172       }
173     }
174   }
175   return out_tensors;
176 }
177 
178 template <typename T>
FindPreOps(T * cur_op,std::vector<T * > all_ops)179 std::vector<T *> FindPreOps(T *cur_op, std::vector<T *> all_ops) {
180   std::vector<T *> in_ops;
181   for (auto in_tensor : cur_op->inputs()) {
182     for (auto op : all_ops) {
183       if (std::find(op->outputs().begin(), op->outputs().end(), in_tensor) != op->outputs().end()) {
184         in_ops.push_back(op);
185       }
186     }
187   }
188   return in_ops;
189 }
190 
191 template <typename T>
FindNextOps(T * cur_op,std::vector<T * > all_ops)192 std::vector<T *> FindNextOps(T *cur_op, std::vector<T *> all_ops) {
193   std::vector<T *> out_ops;
194   for (auto out_tensor : cur_op->outputs()) {
195     for (auto op : all_ops) {
196       if (std::find(op->inputs().begin(), op->inputs().end(), out_tensor) != op->inputs().end()) {
197         out_ops.push_back(op);
198       }
199     }
200   }
201   return out_ops;
202 }
203 
204 template <typename T>
FindPreNextOps(std::vector<T * > all_ops)205 void FindPreNextOps(std::vector<T *> all_ops) {
206   for (auto op : all_ops) {
207     auto in_ops = FindPreOps(op, all_ops);
208     op->set_in_ops(in_ops);
209     auto out_ops = FindNextOps(op, all_ops);
210     op->set_out_ops(out_ops);
211   }
212 }
213 
214 template <typename T>
GetGraphInOutOps(const std::vector<mindspore::MSTensor> & inputs,const std::vector<mindspore::MSTensor> & outputs,std::vector<T * > * in_ops,std::vector<T * > * out_ops,const std::vector<T * > & all_ops)215 int GetGraphInOutOps(const std::vector<mindspore::MSTensor> &inputs, const std::vector<mindspore::MSTensor> &outputs,
216                      std::vector<T *> *in_ops, std::vector<T *> *out_ops, const std::vector<T *> &all_ops) {
217   for (auto in_tensor : inputs) {
218     for (auto op : all_ops) {
219       if (std::find(op->inputs().begin(), op->inputs().end(), in_tensor) != op->inputs().end() &&
220           std::find(in_ops->begin(), in_ops->end(), op) == in_ops->end()) {
221         in_ops->push_back(op);
222       }
223     }
224   }
225   if (in_ops->empty()) {
226     MS_LOG(ERROR) << "Can't find the input ops for delegate sub graph.";
227     return RET_ERROR;
228   }
229 
230   for (auto out_tensor : outputs) {
231     for (auto op : all_ops) {
232       if (std::find(op->outputs().begin(), op->outputs().end(), out_tensor) != op->outputs().end() &&
233           std::find(out_ops->begin(), out_ops->end(), op) == out_ops->end()) {
234         out_ops->push_back(op);
235       }
236     }
237   }
238   if (out_ops->empty()) {
239     MS_LOG(ERROR) << "Can't find the output ops for delegate sub graph.";
240     return RET_ERROR;
241   }
242   return RET_OK;
243 }
244 }  // namespace mindspore::lite
245 
246 #endif  // MINDSPORE_LITE_SRC_RUNTIME_DELEGATE_DELEGATE_UTILS_H_
247