• 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 "src/delegate/npu/npu_executor.h"
18 #include <unordered_map>
19 #include "include/errorcode.h"
20 #include "src/delegate/npu/npu_manager.h"
21 #include "src/common/log_adapter.h"
22 
23 namespace mindspore {
~NPUExecutor()24 NPUExecutor::~NPUExecutor() {
25   client_.reset();
26   for (auto t : npu_input_tensors_) {
27     t.reset();
28   }
29   npu_input_tensors_.clear();
30   for (auto t : npu_output_tensors_) {
31     t.reset();
32   }
33   npu_output_tensors_.clear();
34 }
35 
Prepare()36 int NPUExecutor::Prepare() {
37   MS_ASSERT(npu_manager_ != nullptr);
38   this->client_ = npu_manager_->GetClient(model_name_);
39   if (this->client_ == nullptr) {
40     MS_LOG(ERROR) << "client is nullptr.";
41     return RET_ERROR;
42   }
43   if (GetIOTensorVec() != RET_OK) {
44     MS_LOG(ERROR) << "NPUExecutor GetIOTensorVec failed.";
45     return RET_ERROR;
46   }
47   return RET_OK;
48 }
49 
GetNpuTensorShape(int dim,std::shared_ptr<hiai::AiTensor> npu_tensor)50 std::vector<int64_t> GetNpuTensorShape(int dim, std::shared_ptr<hiai::AiTensor> npu_tensor) {
51   std::vector<int64_t> npu_shape;
52   if (dim > 0) {
53     npu_shape.push_back(npu_tensor->GetTensorDimension().GetNumber());
54   }
55   if (dim > 1) {
56     npu_shape.push_back(npu_tensor->GetTensorDimension().GetChannel());
57   }
58   if (dim > 2) {
59     npu_shape.push_back(npu_tensor->GetTensorDimension().GetHeight());
60   }
61   if (dim > 3) {
62     npu_shape.push_back(npu_tensor->GetTensorDimension().GetWidth());
63   }
64   return npu_shape;
65 }
66 
IsSameShapeTensor(mindspore::MSTensor tensor,const std::shared_ptr<hiai::AiTensor> & npu_tensor)67 bool IsSameShapeTensor(mindspore::MSTensor tensor, const std::shared_ptr<hiai::AiTensor> &npu_tensor) {
68   if (tensor.Shape().size() > NPU_SHAPE_SIZE) {
69     MS_LOG(ERROR) << "Npu does not support output tensor dims greater than 4";
70     return false;
71   }
72   return GetNpuTensorShape(tensor.Shape().size(), npu_tensor) == tensor.Shape();
73 }
74 
Run(const std::vector<mindspore::MSTensor> & in_tensors,const std::vector<mindspore::MSTensor> & out_tensors,const std::vector<NPUOp * > & in_ops)75 int NPUExecutor::Run(const std::vector<mindspore::MSTensor> &in_tensors,
76                      const std::vector<mindspore::MSTensor> &out_tensors, const std::vector<NPUOp *> &in_ops) {
77   hiai::AiContext context;
78   for (size_t i = 0; i < npu_input_tensors_.size(); ++i) {
79     auto data = in_tensors[i].Data();
80     if (data == nullptr) {
81       MS_LOG(ERROR) << "For " << model_name_ << ", the input tensor " << in_tensors[i].Name() << " data is nullptr";
82       return RET_ERROR;
83     }
84     memcpy(npu_input_tensors_[i]->GetBuffer(), data.get(), in_tensors[i].DataSize());
85   }
86   context.AddPara("model_name", model_name_);
87   if (this->client_ == nullptr) {
88     MS_LOG(ERROR) << "NPU client is nullptr";
89     return RET_ERROR;
90   }
91   int stamp;
92   int ret = this->client_->Process(context, this->npu_input_tensors_, this->npu_output_tensors_, 1000, stamp);
93   if (ret != hiai::AI_SUCCESS) {
94     MS_LOG(ERROR) << "NPU Process failed. code is " << ret;
95     return RET_ERROR;
96   }
97 
98   if (npu_output_tensors_.size() != out_tensors.size()) {
99     MS_LOG(ERROR) << "The output count is not euqal to ms tensor.";
100     return RET_ERROR;
101   }
102   for (size_t i = 0; i < npu_output_tensors_.size(); ++i) {
103     mindspore::MSTensor out_tensor = out_tensors[i];
104     auto data = out_tensor.MutableData();
105     if (data == nullptr) {
106       MS_LOG(ERROR) << "For " << model_name_ << ", the output tensor " << out_tensors[i].Name() << " data is nullptr";
107       return RET_ERROR;
108     }
109 
110     memcpy(data, npu_output_tensors_[i]->GetBuffer(), npu_output_tensors_[i]->GetSize());
111   }
112   return RET_OK;
113 }
114 
GetIOTensorVec()115 int NPUExecutor::GetIOTensorVec() {
116   std::vector<hiai::TensorDimension> input_dimension;
117   std::vector<hiai::TensorDimension> output_dimension;
118   input_dimension.clear();
119   output_dimension.clear();
120   if (this->client_ == nullptr) {
121     MS_LOG(ERROR) << "client is nullptr.";
122     return RET_ERROR;
123   }
124   auto ret = this->client_->GetModelIOTensorDim(model_name_, input_dimension, output_dimension);
125   if (ret != hiai::AI_SUCCESS) {
126     MS_LOG(ERROR) << "Get model input and output tensor dims failed." << ret;
127     return RET_ERROR;
128   }
129   ret = UpdateInputTensorVec(input_dimension);
130   if (ret != RET_OK) {
131     MS_LOG(ERROR) << "Update input tensor vector failed. " << ret;
132     return RET_ERROR;
133   }
134   ret = UpdateOutputTensorVec(output_dimension);
135   if (ret != RET_OK) {
136     MS_LOG(ERROR) << "Update output tensor vector failed. " << ret;
137     return RET_ERROR;
138   }
139   return RET_OK;
140 }
141 
UpdateInputTensorVec(const std::vector<hiai::TensorDimension> & input_dimension)142 int NPUExecutor::UpdateInputTensorVec(const std::vector<hiai::TensorDimension> &input_dimension) {
143   if (input_dimension.empty()) {
144     MS_LOG(ERROR) << "npu input tensor dimension is empty.";
145     return RET_ERROR;
146   }
147   npu_input_tensors_.resize(input_dimension.size());
148   npu_input_tensors_.clear();
149   for (const auto &inDim : input_dimension) {
150     std::shared_ptr<hiai::AiTensor> input = std::make_shared<hiai::AiTensor>();
151     if (input->Init(&inDim) != hiai::AI_SUCCESS) {
152       MS_LOG(ERROR) << "Input AiTensor init failed.";
153       return RET_ERROR;
154     }
155     npu_input_tensors_.push_back(input);
156   }
157   if (npu_input_tensors_.empty()) {
158     MS_LOG(ERROR) << "NPU input tensor is empty.";
159     return RET_ERROR;
160   }
161   return RET_OK;
162 }
163 
UpdateOutputTensorVec(const std::vector<hiai::TensorDimension> & output_dimension)164 int NPUExecutor::UpdateOutputTensorVec(const std::vector<hiai::TensorDimension> &output_dimension) {
165   if (output_dimension.empty()) {
166     MS_LOG(ERROR) << "output_dimension_ is empty.";
167     return RET_ERROR;
168   }
169   npu_output_tensors_.resize(output_dimension.size());
170   npu_output_tensors_.clear();
171   for (const auto &outDim : output_dimension) {
172     std::shared_ptr<hiai::AiTensor> output = std::make_shared<hiai::AiTensor>();
173     int ret = output->Init(&outDim);
174     if (ret != hiai::AI_SUCCESS) {
175       return RET_ERROR;
176     }
177     npu_output_tensors_.push_back(output);
178   }
179   if (npu_output_tensors_.empty()) {
180     MS_LOG(ERROR) << "NPU output tensor is empty.";
181     return RET_ERROR;
182   }
183   return RET_OK;
184 }
185 }  // namespace mindspore
186