chore: import upstream snapshot with attribution
Docker Image CI / build-ubuntu2004 (push) Has been cancelled
Docker Image CI / build-ubuntu2004 (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: Copyright (c) 1993-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
add_executable(sample_named_dimensions sampleNamedDimensions.cpp)
|
||||
target_link_libraries(sample_named_dimensions PRIVATE trt_samples_common TRT_SAMPLES::tensorrt)
|
||||
add_dependencies(tensorrt_samples sample_named_dimensions)
|
||||
|
||||
installLibraries(
|
||||
TARGETS sample_named_dimensions
|
||||
OPTIONAL
|
||||
COMPONENT internal
|
||||
)
|
||||
@@ -0,0 +1,113 @@
|
||||
# Working with ONNX models with named input dimensions
|
||||
|
||||
|
||||
**Table Of Contents**
|
||||
- [Description](#description)
|
||||
- [Running the sample](#running-the-sample)
|
||||
- [Additional resources](#additional-resources)
|
||||
- [License](#license)
|
||||
- [Changelog](#changelog)
|
||||
- [Known issues](#known-issues)
|
||||
|
||||
## Description
|
||||
|
||||
This sample, `sampleNamedDimensions`, illustrates how to work with ONNX models with named input dimensions in TensorRT.
|
||||
|
||||
ONNX has a notion of named dimension parameters: two network inputs with the same named dimension parameter are considered equal. TensorRT supports this feature by checking that in the optimization profile these dimensions have overlapping intervals and that at runtime they have the same value.
|
||||
|
||||
Here, we synthetically create an ONNX model consisting of a single [Concat](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Concat) layer with two 2D input tensors:
|
||||
```
|
||||
input0 input1
|
||||
\ /
|
||||
\ /
|
||||
--------
|
||||
|Concat|
|
||||
--------
|
||||
|
|
||||
|
|
||||
output
|
||||
```
|
||||
Concatenation is performed on the zeroth axis, so only the first dimensions of the input tensors are required to be the same. However, since both inputs have dimension `[n_rows, 8]`, the named dimensions `n_rows` additionally require the zeroth dimensions of the two input tensors to match as well.
|
||||
|
||||
|
||||
## Running the sample
|
||||
|
||||
1. The sample gets compiled when building the TensorRT OSS following the [instructions](https://github.com/NVIDIA/TensorRT). The binary named `sample_named_dimensions` will be created in the output directory.
|
||||
|
||||
2. Generate the ONNX model file by running this command:
|
||||
```
|
||||
python3 create_model.py
|
||||
```
|
||||
This will create a file named `concat_layer.onnx`.
|
||||
|
||||
3. Run the sample to build and run the engine from the ONNX model.
|
||||
```
|
||||
./sample_named_dimensions [-h or --help] [-d or --datadir=<path to data directory>]
|
||||
```
|
||||
|
||||
3. Verify that the sample has run successfully. If successful you should see output similar to the following:
|
||||
```
|
||||
&&&& RUNNING TensorRT.sample_named_dimensions [TensorRT v8500] # build/x86_64-gnu/sample_named_dimensions
|
||||
[I] [TRT] ----------------------------------------------------------------
|
||||
[I] [TRT] Input filename: ../trt/samples/sampleNamedDimensions/concat_layer.onnx
|
||||
[I] [TRT] ONNX IR version: 0.0.7
|
||||
[I] [TRT] Opset version: 11
|
||||
[I] [TRT] Producer name:
|
||||
[I] [TRT] Producer version:
|
||||
[I] [TRT] Domain:
|
||||
[I] [TRT] Model version: 0
|
||||
[I] [TRT] Doc string:
|
||||
[I] [TRT] ----------------------------------------------------------------
|
||||
[I] Input0:
|
||||
-4.17896 4.21201 -8.6982 9.33153 -4.90741 1.1953 9.45208 1.04329
|
||||
-5.47509 0.150872 -4.29573 1.72331 3.69642 5.73303 -4.89766 5.00559
|
||||
|
||||
[I] Input1:
|
||||
9.01907 3.57581 -1.36986 -3.22044 -5.90874 -8.11433 2.38472 -0.0868187
|
||||
0.842402 -1.75138 4.55962 -6.38946 -7.73614 -1.26044 -4.23012 4.33806
|
||||
|
||||
[I] Output:
|
||||
-4.17896 4.21201 -8.6982 9.33153 -4.90741 1.1953 9.45208 1.04329
|
||||
-5.47509 0.150872 -4.29573 1.72331 3.69642 5.73303 -4.89766 5.00559
|
||||
9.01907 3.57581 -1.36986 -3.22044 -5.90874 -8.11433 2.38472 -0.0868187
|
||||
0.842402 -1.75138 4.55962 -6.38946 -7.73614 -1.26044 -4.23012 4.33806
|
||||
|
||||
&&&& PASSED TensorRT.sample_named_dimensions [TensorRT v8500] # build/x86_64-gnu/sample_named_dimensions
|
||||
```
|
||||
|
||||
|
||||
### Sample `--help` options
|
||||
|
||||
To see the full list of available options and their descriptions, use the `-h` or `--help` command line option.
|
||||
|
||||
|
||||
# Additional resources
|
||||
|
||||
The following resources provide a deeper understanding about the named input dimensions feature in the ONNX project:
|
||||
|
||||
**ONNX**
|
||||
- [GitHub: ONNX](https://github.com/onnx/onnx)
|
||||
- [Github: ONNX-TensorRT Open source parser](https://github.com/onnx/onnx-tensorrt)
|
||||
|
||||
**Documentation**
|
||||
- [Introduction To NVIDIA’s TensorRT Samples](https://docs.nvidia.com/deeplearning/sdk/tensorrt-sample-support-guide/index.html#samples)
|
||||
- [Working With TensorRT Using The C++ API](https://docs.nvidia.com/deeplearning/sdk/tensorrt-developer-guide/index.html#c_topics)
|
||||
- [NVIDIA’s TensorRT Documentation Library](https://docs.nvidia.com/deeplearning/sdk/tensorrt-archived/index.html)
|
||||
|
||||
# License
|
||||
|
||||
For terms and conditions for use, reproduction, and distribution, see the [TensorRT Software License Agreement](https://docs.nvidia.com/deeplearning/sdk/tensorrt-sla/index.html) documentation.
|
||||
|
||||
|
||||
# Changelog
|
||||
|
||||
October 2025
|
||||
Migrate to strongly typed APIs.
|
||||
|
||||
June 2022
|
||||
This `README.md` file was recreated, updated and reviewed.
|
||||
|
||||
|
||||
# Known issues
|
||||
|
||||
There are no known issues in this sample.
|
||||
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: Copyright (c) 1993-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
import numpy as np
|
||||
import onnx
|
||||
import onnx_graphsurgeon as gs
|
||||
|
||||
def main():
|
||||
input0 = gs.Variable(name="input0", dtype=np.float32, shape=('n_rows', 8))
|
||||
input1 = gs.Variable(name="input1", dtype=np.float32, shape=('n_rows', 8))
|
||||
output = gs.Variable(name="output", dtype=np.float32, )
|
||||
|
||||
node = gs.Node(op="Concat", inputs=[input0, input1], outputs=[output], attrs={"axis": 0})
|
||||
|
||||
graph = gs.Graph(nodes=[node], inputs=[input0, input1], outputs=[output])
|
||||
|
||||
model = gs.export_onnx(graph)
|
||||
onnx.save(model, "concat_layer.onnx")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//!
|
||||
//! sampleNamedDimensions.cpp
|
||||
//! This file contains the implementation of the named dimensions sample. It creates the network using
|
||||
//! a synthetic ONNX model with named input dimensions.
|
||||
//! It can be run with the following command line:
|
||||
//! Command: ./sample_named_dimensions [-h or --help] [-d=/path/to/data/dir or --datadir=/path/to/data/dir]
|
||||
//!
|
||||
|
||||
// Define TRT entrypoints used in common code
|
||||
#define DEFINE_TRT_ENTRYPOINTS 1
|
||||
|
||||
#include "argsParser.h"
|
||||
#include "buffers.h"
|
||||
#include "common.h"
|
||||
#include "logger.h"
|
||||
#include "parserOnnxConfig.h"
|
||||
|
||||
#include "NvInfer.h"
|
||||
#include <cuda_runtime_api.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
using namespace nvinfer1;
|
||||
|
||||
std::string const gSampleName = "TensorRT.sample_named_dimensions";
|
||||
|
||||
//! \brief The SampleNamedDimensions class implements a sample with named input dimensions
|
||||
//!
|
||||
//! \details It creates the network using an ONNX model
|
||||
//!
|
||||
class SampleNamedDimensions
|
||||
{
|
||||
public:
|
||||
SampleNamedDimensions(samplesCommon::OnnxSampleParams const& params)
|
||||
: mParams(params)
|
||||
, mEngine(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Adds an optimization profile for dynamic shapes
|
||||
void setNamedDimension(int32_t dim);
|
||||
|
||||
//!
|
||||
//! \brief Function builds the network engine
|
||||
//!
|
||||
bool build();
|
||||
|
||||
//!
|
||||
//! \brief Runs the TensorRT inference engine for this sample
|
||||
//!
|
||||
bool infer();
|
||||
|
||||
private:
|
||||
samplesCommon::OnnxSampleParams mParams; //!< The parameters for the sample.
|
||||
|
||||
std::vector<nvinfer1::Dims> mInputDims; //!< The dimensions of the inputs to the network.
|
||||
std::vector<nvinfer1::Dims> mOutputDims; //!< The dimensions of the outputs to the network.
|
||||
|
||||
int32_t mNamedDimension; //!< The value of the named dimension.
|
||||
|
||||
//! Input Tensors.
|
||||
std::vector<float> mInput0;
|
||||
std::vector<float> mInput1;
|
||||
|
||||
std::unique_ptr<IRuntime> mRuntime{}; //!< The TensorRT Runtime used to deserialize the engine.
|
||||
std::shared_ptr<nvinfer1::ICudaEngine> mEngine; //!< The TensorRT engine used to run the network
|
||||
|
||||
//!
|
||||
//! \brief Parses a synthetic ONNX model and creates a TensorRT network
|
||||
//!
|
||||
bool constructNetwork(std::unique_ptr<nvinfer1::IBuilder>& builder,
|
||||
std::unique_ptr<nvinfer1::INetworkDefinition>& network, std::unique_ptr<nvinfer1::IBuilderConfig>& config,
|
||||
std::unique_ptr<nvonnxparser::IParser>& parser);
|
||||
|
||||
//!
|
||||
//! \brief Adds an optimization profile for dynamic shapes
|
||||
//!
|
||||
void addOptimizationProfile(
|
||||
std::unique_ptr<nvinfer1::IBuilderConfig>& config, std::unique_ptr<nvinfer1::IBuilder>& builder);
|
||||
|
||||
//!
|
||||
//! \brief Reads the input and stores the result in a managed buffer
|
||||
//!
|
||||
bool processInput(samplesCommon::BufferManager const& buffers);
|
||||
|
||||
//!
|
||||
//! \brief Classifies digits and verify result
|
||||
//!
|
||||
bool verifyOutput(samplesCommon::BufferManager const& buffers);
|
||||
};
|
||||
|
||||
//!
|
||||
//! \brief Sets the value of the named input dimension
|
||||
//!
|
||||
void SampleNamedDimensions::setNamedDimension(int32_t dim)
|
||||
{
|
||||
mNamedDimension = dim;
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Creates the network, configures the builder and creates the network engine
|
||||
//!
|
||||
//! \details This function creates the network definition by parsing the Onnx model and builds
|
||||
//! the engine that will be used to run the model (mEngine)
|
||||
//!
|
||||
//! \return true if the engine was created successfully and false otherwise
|
||||
//!
|
||||
bool SampleNamedDimensions::build()
|
||||
{
|
||||
auto builder = std::unique_ptr<nvinfer1::IBuilder>(nvinfer1::createInferBuilder(sample::gLogger.getTRTLogger()));
|
||||
if (!builder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NetworkDefinitionCreationFlags flags = 1U << static_cast<uint32_t>(NetworkDefinitionCreationFlag::kSTRONGLY_TYPED);
|
||||
auto network = std::unique_ptr<nvinfer1::INetworkDefinition>(builder->createNetworkV2(flags));
|
||||
if (!network)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto config = std::unique_ptr<nvinfer1::IBuilderConfig>(builder->createBuilderConfig());
|
||||
if (!config)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto parser
|
||||
= std::unique_ptr<nvonnxparser::IParser>(nvonnxparser::createParser(*network, sample::gLogger.getTRTLogger()));
|
||||
if (!parser)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto constructed = constructNetwork(builder, network, config, parser);
|
||||
if (!constructed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT(network->getNbInputs() == 2);
|
||||
mInputDims.push_back(network->getInput(0)->getDimensions());
|
||||
mInputDims.push_back(network->getInput(1)->getDimensions());
|
||||
ASSERT(mInputDims[0].nbDims == 2);
|
||||
ASSERT(mInputDims[1].nbDims == 2);
|
||||
|
||||
ASSERT(network->getNbOutputs() == 1);
|
||||
mOutputDims.push_back(network->getOutput(0)->getDimensions());
|
||||
ASSERT(mOutputDims[0].nbDims == 2);
|
||||
|
||||
// CUDA stream used for profiling by the builder.
|
||||
auto profileStream = samplesCommon::makeCudaStream();
|
||||
if (!profileStream)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
config->setProfileStream(*profileStream);
|
||||
|
||||
addOptimizationProfile(config, builder);
|
||||
|
||||
std::unique_ptr<nvinfer1::ITimingCache> timingCache{};
|
||||
|
||||
// Load timing cache
|
||||
if (!mParams.timingCacheFile.empty())
|
||||
{
|
||||
timingCache
|
||||
= samplesCommon::buildTimingCacheFromFile(sample::gLogger.getTRTLogger(), *config, mParams.timingCacheFile);
|
||||
}
|
||||
|
||||
std::unique_ptr<IHostMemory> plan{builder->buildSerializedNetwork(*network, *config)};
|
||||
if (!plan)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timingCache != nullptr && !mParams.timingCacheFile.empty())
|
||||
{
|
||||
samplesCommon::updateTimingCacheFile(
|
||||
sample::gLogger.getTRTLogger(), mParams.timingCacheFile, timingCache.get(), *builder);
|
||||
}
|
||||
|
||||
if (!mRuntime)
|
||||
{
|
||||
mRuntime = std::unique_ptr<IRuntime>(createInferRuntime(sample::gLogger.getTRTLogger()));
|
||||
}
|
||||
|
||||
if (!mRuntime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mEngine = std::shared_ptr<nvinfer1::ICudaEngine>(mRuntime->deserializeCudaEngine(plan->data(), plan->size()));
|
||||
if (!mEngine)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Uses ONNX parser to create the ONNX Network and marks the output layers
|
||||
//!
|
||||
bool SampleNamedDimensions::constructNetwork(std::unique_ptr<nvinfer1::IBuilder>& builder,
|
||||
std::unique_ptr<nvinfer1::INetworkDefinition>& network, std::unique_ptr<nvinfer1::IBuilderConfig>& config,
|
||||
std::unique_ptr<nvonnxparser::IParser>& parser)
|
||||
{
|
||||
auto parsed = parser->parseFromFile(samplesCommon::locateFile(mParams.onnxFileName, mParams.dataDirs).c_str(),
|
||||
static_cast<int32_t>(sample::gLogger.getReportableSeverity()));
|
||||
if (!parsed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Adds an optimization profile for dynamic shapes
|
||||
//!
|
||||
void SampleNamedDimensions::addOptimizationProfile(
|
||||
std::unique_ptr<nvinfer1::IBuilderConfig>& config, std::unique_ptr<nvinfer1::IBuilder>& builder)
|
||||
{
|
||||
auto const input0ProfileDims = Dims2(mNamedDimension, mInputDims[0].d[1]);
|
||||
auto profile = builder->createOptimizationProfile();
|
||||
profile->setDimensions("input0", OptProfileSelector::kMIN, input0ProfileDims);
|
||||
profile->setDimensions("input0", OptProfileSelector::kMAX, input0ProfileDims);
|
||||
profile->setDimensions("input0", OptProfileSelector::kOPT, input0ProfileDims);
|
||||
|
||||
auto input1ProfileDims = Dims2(mNamedDimension, mInputDims[1].d[1]);
|
||||
profile->setDimensions("input1", OptProfileSelector::kMIN, input1ProfileDims);
|
||||
profile->setDimensions("input1", OptProfileSelector::kMAX, input1ProfileDims);
|
||||
profile->setDimensions("input1", OptProfileSelector::kOPT, input1ProfileDims);
|
||||
|
||||
config->addOptimizationProfile(profile);
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Runs the TensorRT inference engine for this sample
|
||||
//!
|
||||
//! \details This function is the main execution function of the sample. It allocates the buffer,
|
||||
//! sets inputs and executes the engine.
|
||||
//!
|
||||
bool SampleNamedDimensions::infer()
|
||||
{
|
||||
// Create RAII buffer manager object
|
||||
samplesCommon::BufferManager buffers(mEngine);
|
||||
|
||||
auto context = std::unique_ptr<nvinfer1::IExecutionContext>(mEngine->createExecutionContext());
|
||||
if (!context)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int32_t i = 0, e = mEngine->getNbIOTensors(); i < e; i++)
|
||||
{
|
||||
auto const name = mEngine->getIOTensorName(i);
|
||||
context->setTensorAddress(name, buffers.getDeviceBuffer(name));
|
||||
}
|
||||
|
||||
// Read the input data into the managed buffers
|
||||
ASSERT(mParams.inputTensorNames.size() == 2);
|
||||
if (!processInput(buffers))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Memcpy from host input buffers to device input buffers
|
||||
buffers.copyInputToDevice();
|
||||
|
||||
bool status = context->executeV2(buffers.getDeviceBindings().data());
|
||||
if (!status)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Memcpy from device output buffers to host output buffers
|
||||
buffers.copyOutputToHost();
|
||||
|
||||
// Verify results
|
||||
if (!verifyOutput(buffers))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Reads the input and stores the result in a managed buffer
|
||||
//!
|
||||
bool SampleNamedDimensions::processInput(samplesCommon::BufferManager const& buffers)
|
||||
{
|
||||
int32_t const input0H = mNamedDimension;
|
||||
int32_t const input0W = mInputDims[0].d[1];
|
||||
int32_t const input1H = mNamedDimension;
|
||||
int32_t const input1W = mInputDims[1].d[1];
|
||||
|
||||
// Generate random input
|
||||
mInput0.resize(input0H * input0W);
|
||||
mInput1.resize(input1H * input1W);
|
||||
std::default_random_engine generator(static_cast<uint32_t>(time(nullptr)));
|
||||
std::uniform_real_distribution<float> unif_real_distr(-10., 10.);
|
||||
|
||||
sample::gLogInfo << "Input0:\n";
|
||||
for (int32_t i = 0; i < input0H * input0W; i++)
|
||||
{
|
||||
mInput0[i] = unif_real_distr(generator);
|
||||
sample::gLogInfo << mInput0[i] << (((i + 1) % input0W) ? " " : "\n");
|
||||
}
|
||||
sample::gLogInfo << std::endl;
|
||||
|
||||
sample::gLogInfo << "Input1:\n";
|
||||
for (int32_t i = 0; i < input1H * input1W; i++)
|
||||
{
|
||||
mInput1[i] = unif_real_distr(generator);
|
||||
sample::gLogInfo << mInput1[i] << (((i + 1) % input1W) ? " " : "\n");
|
||||
}
|
||||
sample::gLogInfo << std::endl;
|
||||
|
||||
auto* hostInput0Buffer = static_cast<float*>(buffers.getHostBuffer(mParams.inputTensorNames[0]));
|
||||
std::copy(mInput0.begin(), mInput0.begin() + input0H * input0W, hostInput0Buffer);
|
||||
|
||||
auto* hostInput1Buffer = static_cast<float*>(buffers.getHostBuffer(mParams.inputTensorNames[1]));
|
||||
std::copy(mInput1.begin(), mInput1.begin() + input1H * input1W, hostInput1Buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Verify the result of concatenation
|
||||
//!
|
||||
//! \return whether the concatenated tesnor matches reference
|
||||
//!
|
||||
bool SampleNamedDimensions::verifyOutput(samplesCommon::BufferManager const& buffers)
|
||||
{
|
||||
int32_t const outputH = 2 * mNamedDimension;
|
||||
int32_t const outputW = mOutputDims[0].d[1];
|
||||
int32_t const outputSize = outputH * outputW;
|
||||
|
||||
auto* output = static_cast<float*>(buffers.getHostBuffer(mParams.outputTensorNames[0]));
|
||||
|
||||
sample::gLogInfo << "Output:\n";
|
||||
for (int32_t i = 0; i < outputSize; i++)
|
||||
{
|
||||
sample::gLogInfo << output[i] << (((i + 1) % outputW) ? " " : "\n");
|
||||
}
|
||||
sample::gLogInfo << std::endl;
|
||||
|
||||
mInput0.insert(mInput0.end(), mInput1.begin(), mInput1.end());
|
||||
|
||||
for (int32_t i = 0; i < outputH * outputW; i++)
|
||||
{
|
||||
auto const reference_value = i > outputSize / 2 ? mInput1[i - outputSize / 2] : mInput0[i];
|
||||
if (fabs(output[i] - reference_value) > std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Initializes members of the params struct using the command line args
|
||||
//!
|
||||
samplesCommon::OnnxSampleParams initializeSampleParams(samplesCommon::Args const& args)
|
||||
{
|
||||
samplesCommon::OnnxSampleParams params;
|
||||
if (args.dataDirs.empty()) // Use default directories if user hasn't provided directory paths
|
||||
{
|
||||
params.dataDirs.push_back("trt/samples/sampleNamedDimensions/");
|
||||
}
|
||||
else // Use the data directory provided by the user
|
||||
{
|
||||
params.dataDirs = args.dataDirs;
|
||||
}
|
||||
params.onnxFileName = "concat_layer.onnx";
|
||||
params.inputTensorNames.push_back("input0");
|
||||
params.inputTensorNames.push_back("input1");
|
||||
params.outputTensorNames.push_back("output");
|
||||
params.timingCacheFile = params.timingCacheFile;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
//!
|
||||
//! \brief Prints the help information for running this sample
|
||||
//!
|
||||
void printHelpInfo()
|
||||
{
|
||||
std::cout << "Usage: ./sample_named_dimensions [-h or --help] [-d or --datadir=<path to data directory>] "
|
||||
<< "[--timingCacheFile=<path to timing cache file>]" << std::endl;
|
||||
std::cout << "--help Display help information" << std::endl;
|
||||
std::cout << "--datadir Specify path to a data directory, overriding the default. This option can be used "
|
||||
"multiple times to add multiple directories. If no data directories are given, the default is to use "
|
||||
"(trt/samples/sampleNamedDimensions)"
|
||||
<< std::endl;
|
||||
std::cout << "--timingCacheFile Specify path to a timing cache file. If it does not already exist, it will be "
|
||||
<< "created." << std::endl;
|
||||
}
|
||||
|
||||
int32_t main(int32_t argc, char** argv)
|
||||
{
|
||||
samplesCommon::Args args;
|
||||
bool argsOK = samplesCommon::parseArgs(args, argc, argv);
|
||||
if (!argsOK)
|
||||
{
|
||||
sample::gLogError << "Invalid arguments" << std::endl;
|
||||
printHelpInfo();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (args.help)
|
||||
{
|
||||
printHelpInfo();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
auto sampleTest = sample::gLogger.defineTest(gSampleName, argc, argv);
|
||||
|
||||
sample::gLogger.reportTestStart(sampleTest);
|
||||
|
||||
SampleNamedDimensions sample(initializeSampleParams(args));
|
||||
|
||||
sample::gLogInfo << "Building and running a GPU inference engine for synthetic ONNX model" << std::endl;
|
||||
|
||||
sample.setNamedDimension(2);
|
||||
|
||||
if (!sample.build())
|
||||
{
|
||||
return sample::gLogger.reportFail(sampleTest);
|
||||
}
|
||||
if (!sample.infer())
|
||||
{
|
||||
return sample::gLogger.reportFail(sampleTest);
|
||||
}
|
||||
|
||||
return sample::gLogger.reportPass(sampleTest);
|
||||
}
|
||||
Reference in New Issue
Block a user