| 393 | |
| 394 | template <typename T> |
| 395 | bool Engine<T>::build(std::string onnxModelPath, const std::array<float, 3> &subVals, const std::array<float, 3> &divVals, bool normalize) { |
| 396 | // Create our engine builder. |
| 397 | auto builder = std::unique_ptr<nvinfer1::IBuilder>(nvinfer1::createInferBuilder(m_logger)); |
| 398 | if (!builder) { |
| 399 | return false; |
| 400 | } |
| 401 | |
| 402 | // Define an explicit batch size and then create the network (implicit batch |
| 403 | // size is deprecated). More info here: |
| 404 | // https://docs.nvidia.com/deeplearning/tensorrt/developer-guide/index.html#explicit-implicit-batch |
| 405 | auto explicitBatch = 1U << static_cast<uint32_t>(nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH); |
| 406 | auto network = std::unique_ptr<nvinfer1::INetworkDefinition>(builder->createNetworkV2(explicitBatch)); |
| 407 | if (!network) { |
| 408 | return false; |
| 409 | } |
| 410 | |
| 411 | // Create a parser for reading the onnx file. |
| 412 | auto parser = std::unique_ptr<nvonnxparser::IParser>(nvonnxparser::createParser(*network, m_logger)); |
| 413 | if (!parser) { |
| 414 | return false; |
| 415 | } |
| 416 | |
| 417 | // We are going to first read the onnx file into memory, then pass that buffer |
| 418 | // to the parser. Had our onnx model file been encrypted, this approach would |
| 419 | // allow us to first decrypt the buffer. |
| 420 | std::ifstream file(onnxModelPath, std::ios::binary | std::ios::ate); |
| 421 | std::streamsize size = file.tellg(); |
| 422 | file.seekg(0, std::ios::beg); |
| 423 | |
| 424 | std::vector<char> buffer(size); |
| 425 | if (!file.read(buffer.data(), size)) { |
| 426 | throw std::runtime_error("Unable to read engine file"); |
| 427 | } |
| 428 | |
| 429 | // Parse the buffer we read into memory. |
| 430 | auto parsed = parser->parse(buffer.data(), buffer.size()); |
| 431 | if (!parsed) { |
| 432 | return false; |
| 433 | } |
| 434 | |
| 435 | // Ensure that all the inputs have the same batch size |
| 436 | const auto numInputs = network->getNbInputs(); |
| 437 | if (numInputs < 1) { |
| 438 | throw std::runtime_error("Error, model needs at least 1 input!"); |
| 439 | } |
| 440 | const auto input0Batch = network->getInput(0)->getDimensions().d[0]; |
| 441 | for (int32_t i = 1; i < numInputs; ++i) { |
| 442 | if (network->getInput(i)->getDimensions().d[0] != input0Batch) { |
| 443 | throw std::runtime_error("Error, the model has multiple inputs, each " |
| 444 | "with differing batch sizes!"); |
| 445 | } |
| 446 | } |
| 447 | |
| 448 | // Check to see if the model supports dynamic batch size or not |
| 449 | bool doesSupportDynamicBatch = false; |
| 450 | if (input0Batch == -1) { |
| 451 | doesSupportDynamicBatch = true; |
| 452 | std::cout << "Model supports dynamic batch size" << std::endl; |
nothing calls this directly
no test coverage detected