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