1 /**
2 * Copyright 2020 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 #include <queue>
17 #include <memory>
18 #include "src/mindrt_executor.h"
19 #include "src/lite_mindrt.h"
20 #include "include/errorcode.h"
21 #include "src/common/tensor_util.h"
22 #include "nnacl/base/cast_base.h"
23
24 namespace mindspore::lite {
PrepareInputData(const std::vector<kernel::LiteKernel * > & kernels,const std::vector<Tensor * > & inputs)25 int MindrtExecutor::PrepareInputData(const std::vector<kernel::LiteKernel *> &kernels,
26 const std::vector<Tensor *> &inputs) {
27 for (size_t j = 0; j < kernels.size(); ++j) {
28 auto in_tensor_size = kernels[j]->in_tensors().size();
29 for (size_t k = 0; k < in_tensor_size; ++k) {
30 auto tensor = kernels[j]->in_tensors()[k];
31 if (!tensor->IsGraphInput()) {
32 continue;
33 }
34 size_t idx = std::find(inputs.begin(), inputs.end(), tensor) - inputs.begin();
35 if (idx == inputs.size()) {
36 MS_LOG(ERROR) << "The input is not found.";
37 return RET_ERROR;
38 }
39 auto data = std::make_shared<OpData<Tensor>>(op_actors_[j]->GetAID(), inputs.at(idx), static_cast<int>(k));
40 if (data == nullptr) {
41 MS_LOG(ERROR) << "new opdata failed.";
42 return RET_NULL_PTR;
43 }
44 input_data_.emplace_back(data);
45 }
46 }
47 return RET_OK;
48 }
49
PrepareOutputData(const std::vector<kernel::LiteKernel * > & kernels,const std::vector<Tensor * > & outputs)50 int MindrtExecutor::PrepareOutputData(const std::vector<kernel::LiteKernel *> &kernels,
51 const std::vector<Tensor *> &outputs) {
52 for (size_t i = 0; i < outputs.size(); ++i) {
53 Tensor *graph_output_tensor = outputs[i];
54 if (graph_output_tensor->IsGraphInput()) {
55 continue;
56 }
57 auto current_output_map =
58 std::find_if(output_tensor_map_->begin(), output_tensor_map_->end(), [&](const auto output_map_tensor) {
59 if (graph_output_tensor == output_map_tensor.second) {
60 return true;
61 }
62 return false;
63 });
64 MS_ASSERT(current_output_map != output_tensor_map_->end());
65 Tensor *subgraph_output_tensor = current_output_map->first;
66
67 for (size_t j = 0; j < kernels.size(); ++j) {
68 auto out_tensor_size = kernels[j]->out_tensors().size();
69 for (size_t k = 0; k < out_tensor_size; ++k) {
70 if (subgraph_output_tensor != kernels[j]->out_tensors()[k]) {
71 continue;
72 }
73 auto data =
74 std::make_shared<OpData<Tensor>>(op_actors_[j]->GetAID(), subgraph_output_tensor, static_cast<int>(k));
75 if (data == nullptr) {
76 MS_LOG(ERROR) << "new opdata failed.";
77 return RET_NULL_PTR;
78 }
79 op_actors_[j]->AddResultIndex(output_data_.size());
80 output_data_.emplace_back(data);
81 }
82 }
83 }
84 return RET_OK;
85 }
86
Resize(const std::vector<mindspore::tensor::MSTensor * > & inputs,const std::vector<std::vector<int>> & dims)87 int MindrtExecutor::Resize(const std::vector<mindspore::tensor::MSTensor *> &inputs,
88 const std::vector<std::vector<int>> &dims) {
89 for (auto actor : op_actors_) {
90 actor->ResizeGraphInput(inputs, dims);
91 }
92 return RET_OK;
93 }
94
Prepare(const std::vector<kernel::LiteKernel * > & kernels,const std::vector<Tensor * > & inputs,const std::vector<Tensor * > & outputs,const lite::InnerContext * ctx)95 int MindrtExecutor::Prepare(const std::vector<kernel::LiteKernel *> &kernels, const std::vector<Tensor *> &inputs,
96 const std::vector<Tensor *> &outputs, const lite::InnerContext *ctx) {
97 MS_ASSERT(ctx != nullptr);
98 ctx_ = ctx;
99 auto ret = MindrtInit();
100 if (ret != RET_OK) {
101 MS_LOG(ERROR) << "MindrtInit failed";
102 return ret;
103 }
104 op_actors_ = CreateOpActor(kernels, ctx);
105 if (op_actors_.size() != kernels.size()) {
106 MS_LOG(ERROR) << "CreateOpActor failed";
107 return RET_ERROR;
108 }
109
110 ret = PrepareInputData(kernels, inputs);
111 if (ret != RET_OK) {
112 MS_LOG(ERROR) << "PrepareInputData failed";
113 return ret;
114 }
115
116 ret = PrepareOutputData(kernels, outputs);
117 if (ret != RET_OK) {
118 MS_LOG(ERROR) << "PrepareOutputData failed";
119 return ret;
120 }
121
122 for (auto actor : op_actors_) {
123 ret = actor->LiteActorInit(&op_actors_);
124 if (ret != RET_OK) {
125 MS_LOG(ERROR) << "LiteActorInit failed, actor aid: " << actor->GetAID();
126 return ret;
127 }
128 }
129
130 return RET_OK;
131 }
132
TransferGraphOutput()133 void MindrtExecutor::TransferGraphOutput() {
134 for (auto tensor_map : *output_tensor_map_) {
135 auto dst_tensor = tensor_map.second;
136 auto src_tensor = tensor_map.first;
137 dst_tensor->set_shape(src_tensor->shape());
138 /* dst tensor free in FreeOutputTensor */
139
140 if (src_tensor->data_type() == kNumberTypeFloat16) {
141 dst_tensor->MallocData();
142 Fp16ToFloat32(reinterpret_cast<uint16_t *>(src_tensor->MutableData()),
143 reinterpret_cast<float *>(dst_tensor->data()), dst_tensor->ElementsNum());
144 } else {
145 dst_tensor->set_data(src_tensor->data());
146 src_tensor->set_data(nullptr);
147 }
148 src_tensor->DecRefCount();
149 }
150 return;
151 }
152
FreeOutputTensor()153 void MindrtExecutor::FreeOutputTensor() {
154 for (auto tensor_map : *output_tensor_map_) {
155 auto src_tensor = tensor_map.first;
156 auto dst_tensor = tensor_map.second;
157 if (dst_tensor->allocator() != nullptr) {
158 dst_tensor->FreeData();
159 } else {
160 if (dst_tensor->data_type() == src_tensor->data_type()) {
161 /* user set graph-output-tensor from outside */
162 src_tensor->set_data(dst_tensor->data());
163 src_tensor->set_own_data(false);
164 src_tensor->set_allocator(nullptr);
165 }
166 }
167 }
168 return;
169 }
170
Run(const std::vector<Tensor * > & in_tensors,const std::vector<Tensor * > & out_tensors,const std::vector<kernel::LiteKernel * > & kernels,const KernelCallBack & before,const KernelCallBack & after)171 int MindrtExecutor::Run(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors,
172 const std::vector<kernel::LiteKernel *> &kernels, const KernelCallBack &before,
173 const KernelCallBack &after) {
174 CHECK_NULL_RETURN(ctx_);
175 auto thread_pool = ctx_->thread_pool();
176 CHECK_NULL_RETURN(thread_pool);
177 if (ctx_->delegate == nullptr) {
178 thread_pool->SetSpinCountMaxValue();
179 }
180
181 FreeOutputTensor();
182
183 auto ret = MindrtRun<Tensor>(input_data_, &output_data_, &before, &after);
184 if (ret != RET_OK) {
185 MS_LOG(ERROR) << "MindrtRun failed";
186 return ret;
187 }
188
189 TransferGraphOutput();
190
191 thread_pool->SetSpinCountMinValue();
192 return RET_OK;
193 }
194 } // namespace mindspore::lite
195