Apollo 11.0
自动驾驶开放平台
onnx_single_batch_infer.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2020 The Apollo Authors. All Rights Reserved.
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#ifdef NV_TENSORRT_MAJOR
17#if NV_TENSORRT_MAJOR == 8
19#endif
20#endif
21
22#include <sys/stat.h>
23
24#include <fstream>
25
26#include <cuda_runtime_api.h>
27
28#include "absl/strings/str_cat.h"
29
30#include "cyber/common/log.h"
32
33#if GPU_PLATFORM == NVIDIA
34// Logger for TensorRT info/warning/errors
35class OnnxLogger : public nvinfer1::ILogger {
36 void log(Severity severity, const char* msg) noexcept override {
37 switch (severity) {
38 case Severity::kINTERNAL_ERROR:
39 case Severity::kERROR:
40 AERROR << msg;
41 break;
42 case Severity::kWARNING:
43 AWARN << msg;
44 break;
45 case Severity::kINFO:
46 case Severity::kVERBOSE:
47 ADEBUG << msg;
48 break;
49 default:
50 break;
51 }
52 }
54#elif GPU_PLATFORM == AMD
55class OnnxLogger : {
57namespace nvinfer1 {
58class ICudaEngine {};
59class IExecutionContext {};
60} // namespace nvinfer1
61#endif
62
63namespace apollo {
64namespace perception {
65namespace inference {
66
68
69#define GPU_CHECK(ans) \
70 { GPUAssert((ans), __FILE__, __LINE__); }
71inline void GPUAssert(cudaError_t code, const char* file, int line,
72 bool abort = true) {
73 if (code != cudaSuccess) {
74 fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file,
75 line);
76 if (abort) exit(code);
77 }
78}
79
81 auto iter = blobs_.find(name);
82 if (iter == blobs_.end()) {
83 return nullptr;
84 }
85 return iter->second;
86}
87
89 const std::string& model_file, const float score_threshold,
90 const std::vector<std::string>& outputs,
91 const std::vector<std::string>& inputs)
92 : model_file_(model_file),
93 score_threshold_(score_threshold),
94 output_names_(outputs),
95 input_names_(inputs) {}
96
98 const std::string& model_file, const std::vector<std::string>& outputs,
99 const std::vector<std::string>& inputs)
100 : model_file_(model_file), output_names_(outputs), input_names_(inputs) {}
101
103
104bool SingleBatchInference::LoadCache(const std::string& path) {
105 struct stat buffer;
106 if (stat(path.c_str(), &buffer) != 0) {
107 AERROR << "[INFO] cannot find model cache : " << path
108 << ", it will take minutes to generate...";
109 return false;
110 }
111 return true;
112}
113
115 const std::map<std::string, std::vector<int>>& shapes) {
116 BASE_GPU_CHECK(cudaSetDevice(gpu_id_));
117 BASE_GPU_CHECK(cudaStreamCreate(&stream_));
118
119 // create a TensorRT model from the onnx model and load it into an engine
120 OnnxToTRTModel(model_file_);
121
122 if (engine_ == nullptr) {
123 AERROR << "Fail to load obstacle ONNX model";
124 return false;
125 }
126
127 // create execution context from the engine
128#if GPU_PLATFORM == NVIDIA
129 context_ = engine_->createExecutionContext();
130 if (context_ == nullptr) {
131 AERROR << "Fail to create Exceution Context";
132 return false;
133 }
134
135 for (const auto& name : output_names_) {
136 auto iter = shapes.find(name);
137 if (iter != shapes.end()) {
138 auto blob = std::make_shared<Blob<float>>(iter->second);
139 blobs_.emplace(name, blob);
140 }
141 }
142
143 for (const auto& name : input_names_) {
144 auto iter = shapes.find(name);
145 if (iter != shapes.end()) {
146 auto blob = std::make_shared<Blob<float>>(iter->second);
147 blobs_.emplace(name, blob);
148 }
149 }
150 buffers_.resize(input_names_.size() + output_names_.size());
151
152 init_blob(&input_names_);
153 init_blob(&output_names_);
154
155#elif GPU_PLATFORM == AMD
156 assert(0 && "OnnxObstacleDetector::Init() is not implemented yet");
157#endif
158 return true;
159}
160
161bool SingleBatchInference::OnnxToTRTModel(const std::string& model_file) {
162#if GPU_PLATFORM == NVIDIA
163 int verbosity = static_cast<int>(nvinfer1::ILogger::Severity::kVERBOSE);
164 kBatchSize = 1;
165
166 if (gpu_id_ < 0) {
167 AERROR << "must use gpu mode";
168 return false;
169 }
170 // create the builder
171 nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(onnx_gLogger);
172 nvinfer1::INetworkDefinition* network = builder->createNetworkV2(
173 1U << static_cast<int>(
174 nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH));
175
176 // parse onnx model
177 nvonnxparser::IParser* parser =
178 nvonnxparser::createParser(*network, onnx_gLogger);
179
180 const char* onnx_filename = model_file.c_str();
181 parser->parseFromFile(onnx_filename, verbosity);
182
183 // Build the engine
184 builder->setMaxBatchSize(kBatchSize);
185 nvinfer1::IBuilderConfig* config = builder->createBuilderConfig();
186 bool use_fp16 = builder->platformHasFastFp16();
187 if (use_fp16) {
188 config->setFlag(nvinfer1::BuilderFlag::kFP16);
189 }
190 config->setMaxWorkspaceSize(1 << 30);
191
192 auto trt_cache_path = model_file + ".trt.engine";
193
194 if (!LoadCache(trt_cache_path)) {
195 engine_ = builder->buildEngineWithConfig(*network, *config);
196
197 if (engine_->serialize()) {
198 nvinfer1::IHostMemory* serialized_model(engine_->serialize());
199 std::ofstream f(trt_cache_path, std::ios::binary);
200
201 f.write(reinterpret_cast<char*>(serialized_model->data()),
202 serialized_model->size());
203 serialized_model->destroy();
204 AERROR << "Saving serialized model file to " << trt_cache_path;
205 }
206 } else {
207 AINFO << "Loading TensorRT engine from serialized model file...";
208 std::ifstream planFile(trt_cache_path);
209
210 if (!planFile.is_open()) {
211 AERROR << "Could not open serialized model";
212 return false;
213 }
214 initLibNvInferPlugins(&onnx_gLogger, "");
215
216 AINFO << "success open serialized model";
217 std::stringstream planBuffer;
218 planBuffer << planFile.rdbuf();
219 std::string plan = planBuffer.str();
220 nvinfer1::IRuntime* runtime = nvinfer1::createInferRuntime(onnx_gLogger);
221
222 engine_ = runtime->deserializeCudaEngine(
223 static_cast<const void*>(plan.data()), plan.size(), nullptr);
224 runtime->destroy();
225 }
226 return true;
227#elif GPU_PLATFORM == AMD
228 assert(0 && "OnnxObstacleDetector::OnnxToTRTModel() is not implemented yet");
229#endif
230}
231
232void SingleBatchInference::init_blob(std::vector<std::string>* names) {
233 for (auto name : *names) {
234 auto blob = get_blob(name);
235
236 std::vector<int> shape(blob->shape().begin(), blob->shape().end());
237
238 buffers_[bindingIndex_] = blob->mutable_gpu_data();
239 bindingIndex_ += 1;
240 }
241}
242
244 BASE_GPU_CHECK(cudaSetDevice(gpu_id_));
245 BASE_GPU_CHECK(cudaStreamSynchronize(stream_));
246
247 for (auto name : input_names_) {
248 auto blob = get_blob(name);
249 if (blob != nullptr) {
250 blob->gpu_data();
251 }
252 }
253 // If `out_blob->mutable_cpu_data()` is invoked outside,
254 // HEAD will be set to CPU, and `out_blob->mutable_gpu_data()`
255 // after `enqueue` will copy data from CPU to GPU,
256 // which will overwrite the `inference` results.
257 // `out_blob->gpu_data()` will set HEAD to SYNCED,
258 // then no copy happends after `enqueue`.
259 for (auto name : output_names_) {
260 auto blob = get_blob(name);
261 if (blob != nullptr) {
262 blob->gpu_data();
263 }
264 }
265
266 {
267 std::lock_guard<std::mutex> lock(mutex_);
268 context_->enqueue(max_batch_size_, &buffers_[0], stream_, nullptr);
269 }
270
271 for (auto name : output_names_) {
272 auto blob = get_blob(name);
273 if (blob != nullptr) {
274 blob->mutable_gpu_data();
275 }
276 }
277}
278
279} // namespace inference
280} // namespace perception
281} // namespace apollo
double f
A wrapper around SyncedMemory holders serving as the basic computational unit for images,...
Definition blob.h:88
base::BlobPtr< float > get_blob(const std::string &name) override
bool Init(const std::map< std::string, std::vector< int > > &shapes) override
SingleBatchInference(const std::string &model_file, const float score_threshold, const std::vector< std::string > &outputs, const std::vector< std::string > &inputs)
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
std::shared_ptr< Blob< Dtype > > BlobPtr
Definition blob.h:313
class register implement
Definition arena_queue.h:37
OnnxLogger onnx_gLogger