chore: import upstream snapshot with attribution
Docker Image CI / build-ubuntu2004 (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:36:55 +08:00
commit c8a779b1bb
1887 changed files with 3245738 additions and 0 deletions
@@ -0,0 +1,72 @@
# Byte-compiled / optimized / DLL files
*/__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Sphinx documentation
docs/_build/
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Crash dumps
core
@@ -0,0 +1,53 @@
# Polygraphy Trtexec Extension Change Log
Dates are in YYYY-MM-DD format.
## vNext
## v0.0.9 (2023-08-21)
### Changed
- Update API usage to accomodate `Polygraphy==0.49.0`.
- Replace `workspace` with `memPoolSize` in `TrtexecRunner`.
- Remove usage of `polygraphy.backend.trt.util` in `polygraphy_trtexec/backend/runner.py`.
## v0.0.8 (2022-09-08)
### Added
- `trtexec-export-times`, `trtexec-export-output`, `trtexec-export-profile` and `trtexec-export-layer-info` flags
- Report e2e Host Latency instead of GPU Compute time
### Changed
- Use latency as the inference metric instead of GPU Compute Time
## v0.0.7 (2022-08-10)
### Fixed
- Fixed README rendering in wheel build
## v0.0.6 (2020-07-21)
### Changed
- Bug fix in reporting inference time
## v0.0.5 (2020-07-21)
### Changed
- Bug fix in handling `refit` flag for `polygraphy<'0.39.0`
## v0.0.4 (2020-07-18)
### Added
- `trtexec-path` flag applies to allow specifying path to a custom `trtexec` binary
## v0.0.3 (2020-07-15)
### Changed
- `refittable` flag applies to `trtexec` backend's `refit` only if `polygraphy>=0.39.0`
- Renamed `no-builder-cache` to `trtexec-no-builder-cache`
- Renamed `profiling-verbosity` to `trtexec-profiling-verbosity`
## v0.0.2 (2020-07-05)
### Added
- `--trtexec-iterations` flag. Avoids unwanted behavior of running N times more iterations than expected when using the --iterations flag
### Changed
- Renamed `trtexec-warm-up` to `trtexec-warmup`
### Fixed
- Bug fix for failing pytests
## v0.0.1 (2022-06-23)
- Initial integration
@@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2020 NVIDIA Corporation
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.
@@ -0,0 +1,35 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
.ONESHELL: # Run all rules in the same shell to make it easier to run tests with environment variables
BUILD_DIR := build
clean:
- rm -rf dist/ $(BUILD_DIR)/ polygraphy_trtexec.egg-info/ polygraphy_trtexec/__pycache__/
build: clean
- python3 setup.py bdist_wheel
install_deps: build
- python3 -m pip install colored wheel
install: install_deps
- python3 -m pip install --force-reinstall --no-deps $(CURDIR)/dist/*.whl
test: install
python3 -m pytest
@@ -0,0 +1,30 @@
# Extending `polygraphy run` to support `trtexec`
## Introduction
`polygraphy run` allows you to run inference with multiple backends, including TensorRT and ONNX-Runtime, and compare outputs.
This extension adds support to run inference with `trtexec`.
## Installation
Follow the steps below to install the extension module. After installation, you should see the `trtexec` options in the help
output of `polygraphy run`:
1. Build using `setup.py`:
```bash
python3 setup.py bdist_wheel
```
2. Install the wheel: The wheel is installed in the `dist` directory. Install the wheel by running the following command
```
python3 -m pip install dist/polygraphy_trtexec-*.whl \
--extra-index-url https://pypi.ngc.nvidia.com
```
*NOTE: You may have to update the above command to install the appropriate version of the wheel*
3. After the installation, you can run it on the trtexec backend by using the `--trtexec` flag as follows:
```bash
polygraphy run sample.onnx --trtexec
```
@@ -0,0 +1,18 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
__version__ = "0.0.9"
@@ -0,0 +1,18 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
from polygraphy_trtexec.args.runner import *
@@ -0,0 +1,366 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
"""
This file defines the `TrtexecRunnerArgs` argument group, which manages
command-line options that control the `TrtexecRunner` runner.
The argument group implements the standard `BaseRunnerArgs` interface, which inherits from `BaseArgs`.
"""
import polygraphy
from polygraphy import mod
from polygraphy.tools.args import ModelArgs, TrtConfigArgs, TrtLoadPluginsArgs, TrtLoadNetworkArgs, TrtSaveEngineBytesArgs, util as args_util
from polygraphy.tools.args.base import BaseRunnerArgs
from polygraphy.tools.script import make_invocable
@mod.export()
class TrtexecRunnerArgs(BaseRunnerArgs):
"""
Trtexec Runner Inference: running inference with the trtexec backend.
Depends on:
ModelArgs
TrtConfigArgs
TrtLoadPluginsArgs
TrtSaveEngineBytesArgs
"""
def get_name_opt_impl(self):
return "Trtexec Runner", "trtexec"
def add_parser_args_impl(self):
"""
Add command-line arguments that trtexec supports
"""
self.group.add_argument(
"--trtexec-path",
help="Path to find trtexec binary. By default, it expects to find it in PATH",
default=None,
)
self.group.add_argument(
"--use-cuda-graph",
help="Use CUDA graph to capture engine execution and then launch inference (default = disabled). This flag may be ignored if the graph capture fails",
action="store_true",
default=False,
)
self.group.add_argument(
"--avg-runs",
help="Report performance measurements averaged over N consecutive iterations (default = 10)",
default=None,
type=int,
)
self.group.add_argument(
"--best",
help="Enable all precisions to achieve the best performance (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--duration",
help="Run performance measurements for at least N seconds wallclock time (default = 3)",
default=None,
type=int,
)
self.group.add_argument(
"--device",
help="Select cuda device N (default = 0)",
default=None,
type=int,
)
self.group.add_argument(
"--streams",
help="Instantiate N engines to use concurrently (default = 1)",
default=None,
type=int,
)
self.group.add_argument(
"--min-timing",
help="Set the minimum number of iterations used in kernel selection (default = 1)",
default=None,
type=int,
)
self.group.add_argument(
"--avg-timing",
help="Set the number of times averaged in each iteration for kernel selection (default = 8)",
default=None,
type=int,
)
self.group.add_argument(
"--expose-dma",
help="Serialize DMA transfers to and from device (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--no-data-transfers",
help="Disable DMA transfers to and from device (default = enabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--trtexec-warmup",
help="Run for N milliseconds on trtexec to warmup before measuring performance (default = 200)",
default=None,
type=int,
)
self.group.add_argument(
"--trtexec-iterations",
help="Run at least N inference iterations on trtexec (default = 10)",
default=None,
type=int,
)
self.group.add_argument(
"--trtexec-export-times",
help="Write the timing results in a json file",
default=None,
)
self.group.add_argument(
"--trtexec-export-output",
help="Write the output tensors to a json file",
default=None,
)
self.group.add_argument(
"--trtexec-export-profile",
help="Write the profile information per layer in a json file",
default=None,
)
self.group.add_argument(
"--trtexec-export-layer-info",
help="Write the layer information of the engine in a json file",
default=None,
)
# Optional
self.group.add_argument(
"--use-spin-wait",
help="Actively synchronize on GPU events. This option may decrease synchronization time but increase CPU usage and power (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--threads",
help="Enable multithreading to drive engines with independent threads or speed up refitting (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--use-managed-memory",
help="Use managed memory instead of separate host and device allocations (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--dump-refit",
help="Print the refittable layers and weights from a refittable engine",
action="store_true",
default=False,
)
self.group.add_argument(
"--dump-output",
help="Print the output tensor(s) of the last inference iteration (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--dump-profile",
help="Print profile information per layer (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--dump-layer-info",
help="Print layer information of the engine to console (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--separate-profile-run",
help="Do not attach the profiler in the benchmark run; if profiling is enabled, a second profile run will be executed (default = disabled)",
action="store_true",
default=False,
)
self.group.add_argument(
"--trtexec-no-builder-cache",
help="Disable timing cache in builder (default is to enable timing cache)",
action="store_true",
default=False,
)
self.group.add_argument(
"--trtexec-profiling-verbosity",
help="Specify profiling verbosity. mode ::= layer_names_only|detailed|none (default = layer_names_only)",
default=False,
)
self.group.add_argument(
"--layer-output-types",
help="""Control per-layer output type constraints. Effective only when precisionConstraints is set to
"obey" or "prefer". (default = none)"
The specs are read left-to-right, and later ones override earlier ones. "*" can be used as a
layerName to specify the default precision for all the unspecified layers. If a layer has more than
one output, then multiple types separated by "+" can be provided for this layer.
Per-layer output type spec ::= layerOutputTypes[","spec]
layerOutputTypes ::= layerName":"type
type ::= "fp32"|"fp16"|"int32"|"int8"["+"type]",
""",
default=None,
)
def parse_impl(self, args):
"""
Parses command-line arguments and populates the following attributes:
"""
# Required options
self.trtexec_path = args_util.get(args, "trtexec_path")
self.use_cuda_graph = args_util.get(args, "use_cuda_graph")
self.avg_runs = args_util.get(args, "avg_runs")
self.best = args_util.get(args, "best")
self.duration = args_util.get(args, "duration")
self.device = args_util.get(args, "device")
self.streams = args_util.get(args, "streams")
self.min_timing = args_util.get(args, "min_timing")
self.avg_timing = args_util.get(args, "avg_timing")
self.expose_dma = args_util.get(args, "expose_dma")
self.no_data_transfers = args_util.get(args, "no_data_transfers")
self.trtexec_warmup = args_util.get(args, "trtexec_warmup")
self.trtexec_iterations = args_util.get(args, "trtexec_iterations")
self.trtexec_export_times = args_util.get(args, "trtexec_export_times")
self.trtexec_export_output = args_util.get(args, "trtexec_export_output")
self.trtexec_export_profile = args_util.get(args, "trtexec_export_profile")
self.trtexec_export_layer_info = args_util.get(args, "trtexec_export_layer_info")
# Optional options
self.use_spin_wait = args_util.get(args, "use_spin_wait")
self.threads = args_util.get(args, "threads")
self.use_managed_memory = args_util.get(args, "use_managed_memory")
self.dump_refit = args_util.get(args, "dump_refit")
self.dump_output = args_util.get(args, "dump_output")
self.dump_profile = args_util.get(args, "dump_profile")
self.dump_layer_info = args_util.get(args, "dump_layer_info")
self.separate_profile_run = args_util.get(args, "separate_profile_run")
self.trtexec_no_builder_cache = args_util.get(args, "trtexec_no_builder_cache")
self.trtexec_profiling_verbosity = args_util.get(args, "trtexec_profiling_verbosity")
self.layer_output_types = args_util.get(args, "layer_output_types")
def add_to_script_impl(self, script):
model_path = self.arg_groups[ModelArgs].path
model_type = self.arg_groups[ModelArgs].model_type
input_shapes = self.arg_groups[ModelArgs].input_shapes or None
profile_dicts = self.arg_groups[TrtConfigArgs].profile_dicts
tf32 = self.arg_groups[TrtConfigArgs].tf32
fp16 = self.arg_groups[TrtConfigArgs].fp16
int8 = self.arg_groups[TrtConfigArgs].int8
allow_gpu_fallback = self.arg_groups[TrtConfigArgs].allow_gpu_fallback
precision_constraints = self.arg_groups[TrtConfigArgs].precision_constraints
mem_pool_size = self.arg_groups[TrtConfigArgs].memory_pool_limits
use_dla = self.arg_groups[TrtConfigArgs].use_dla
if mod.version(polygraphy.__version__) >= mod.version('0.39.0'):
refit = self.arg_groups[TrtConfigArgs].refittable
else:
refit = None
plugins = self.arg_groups[TrtLoadPluginsArgs].plugins
layer_precisions = self.arg_groups[TrtLoadNetworkArgs].layer_precisions
if layer_precisions:
layer_precisions = {layer:str(precision) for (layer, precision) in layer_precisions.items()}
save_engine = self.arg_groups[TrtSaveEngineBytesArgs].path
# Add an import for TensorRT
script.add_import(imports=["tensorrt"], imp_as="trt")
# Add an import for the Trtexec runner.
script.add_import(imports=["TrtexecRunner"], frm="polygraphy_trtexec.backend")
# Add the Trtexec runner using the `Script.add_runner()` API.
script.add_runner(make_invocable(
"TrtexecRunner",
model_path=model_path,
model_type=model_type,
trtexec_path = self.trtexec_path,
use_cuda_graph=self.use_cuda_graph,
avg_runs=self.avg_runs,
best=self.best,
duration=self.duration,
device=self.device,
streams=self.streams,
min_timing=self.min_timing,
avg_timing=self.avg_timing,
expose_dma=self.expose_dma,
no_data_transfers=self.no_data_transfers,
trtexec_warmup=self.trtexec_warmup,
trtexec_iterations=self.trtexec_iterations,
trtexec_export_times=self.trtexec_export_times,
trtexec_export_output=self.trtexec_export_output,
trtexec_export_profile=self.trtexec_export_profile,
trtexec_export_layer_info=self.trtexec_export_layer_info,
# Optional
use_spin_wait=self.use_spin_wait,
threads=self.threads,
use_managed_memory=self.use_managed_memory,
dump_refit=self.dump_refit,
dump_output=self.dump_output,
dump_profile=self.dump_profile,
dump_layer_info=self.dump_layer_info,
refit=refit,
separate_profile_run=self.separate_profile_run,
trtexec_no_builder_cache=self.trtexec_no_builder_cache,
trtexec_profiling_verbosity=self.trtexec_profiling_verbosity,
layer_output_types=self.layer_output_types,
input_shapes=input_shapes,
profile_dicts=profile_dicts,
tf32=tf32,
fp16=fp16,
int8=int8,
allow_gpu_fallback=allow_gpu_fallback,
precision_constraints=precision_constraints,
mem_pool_size=mem_pool_size,
use_dla=use_dla,
layer_precisions=layer_precisions,
plugins=plugins,
save_engine=save_engine,
))
@@ -0,0 +1,20 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
# Since we've used `mod.export()`, we can simply `import *`.
# Only objects which have been decorated by `mod.export()` will be visible.
from polygraphy_trtexec.backend.runner import *
@@ -0,0 +1,395 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
"""
This file defines the `TrtexecRunner` runner, which takes an ONNX model and
runs inference on the trtexec backend.
The runner implements the standard `BaseRunner` interface.
"""
import subprocess
import json
import tempfile
from collections import OrderedDict
import shutil
from polygraphy import mod, util
from polygraphy.backend.base import BaseRunner
from polygraphy.common import TensorMetadata
from polygraphy.datatype import DataType
from polygraphy.logger import G_LOGGER
from polygraphy.backend.onnx import onnx_from_path
from polygraphy.backend.onnx.util import get_input_metadata
from polygraphy.backend.trt import engine_from_bytes
from polygraphy.backend.common import bytes_from_path
trt = mod.lazy_import("tensorrt>=8.5")
np = mod.lazy_import("numpy")
TRTEXEC_DEFAULT_PATH = "trtexec"
MiB = 1024 ** 2
def which(path):
"""
Check whether `path` is an executable available on PATH
"""
return shutil.which(path) is not None
def convert_shape(input_name, trt_spec):
"""
Converts a trt shape spec to a trtexec shape spec
"""
trtexec_spec = '{}:{}'.format(input_name, 'x'.join(map(str, trt_spec)))
return trtexec_spec
def parse_input_shapes(input_shapes):
"""
Generate necessary specs to pass to --minShapes, --optShapes, --maxShapes
for trtexec backend
"""
if not input_shapes:
return None
trtexec_input_shapes = []
for input_name, shape_spec in input_shapes.items():
trtexec_input_shapes.append(convert_shape(input_name, shape_spec.shape))
return ','.join(trtexec_input_shapes)
def parse_profile_dicts(profile_dicts):
"""
Generate necessary specs to pass to --minShapes, --optShapes, --maxShapes
for trtexec backend
"""
if not profile_dicts:
return None, None, None
trtexec_min_shapes, trtexec_opt_shapes, trtexec_max_shapes = [], [], []
for input_name, (min_shapes, opt_shapes, max_shapes) in profile_dicts[0].items():
trtexec_min_shapes.append(convert_shape(input_name, min_shapes))
trtexec_opt_shapes.append(convert_shape(input_name, opt_shapes))
trtexec_max_shapes.append(convert_shape(input_name, max_shapes))
return ','.join(trtexec_min_shapes), ','.join(trtexec_opt_shapes), ','.join(trtexec_max_shapes)
def parse_layer_precisions(layer_precisions):
"""
Generate necessary specs to pass to --layerPrecisions for trtexec backend
"""
if not layer_precisions:
return None
trtexec_layer_precisions = []
for layer, precision in layer_precisions.items():
trtexec_precision = ""
if precision == "trt.float32":
trtexec_precision = "fp32"
elif precision == "trt.float16":
trtexec_precision = "fp16"
elif precision == "trt.int32":
trtexec_precision = "int32"
elif precision == "trt.int8":
trtexec_precision = "int8"
else:
G_LOGGER.critical(f"Unsupported precision type: {precision}")
trtexec_layer_precisions.append(f"{layer}:{trtexec_precision}")
return ','.join(trtexec_layer_precisions)
def get_inference_time(perf_output):
"""
Reads the output from the performance summary generated by the trtexec
binary to extract the required performance statistics
"""
inference_time_stats = {}
for line in perf_output.split('\n'):
index = line.find('Latency:')
if index >= 0:
stats = line[index + len('Latency:'):].split(',')
for stat in stats:
metric, value = stat.split('=')
value = value.strip().split(' ')[0]
inference_time_stats[metric.strip()] = float(value)
return inference_time_stats
G_LOGGER.critical(f"Could not read inference time for trtexec backend. This "
"might cause polygraphy to misbehave")
@mod.export()
class TrtexecRunner(BaseRunner):
"""
Runs inference using custom trtexec. It accepts all ONNX models.
"""
def __init__(self, model_path, model_type=None,
trtexec_path=None, use_cuda_graph=None, avg_runs=None, best=None, duration=None, device=None, streams=None, min_timing=None, avg_timing=None, expose_dma=None, no_data_transfers=None, trtexec_warmup=None, trtexec_iterations=None, trtexec_export_times=None, trtexec_export_output=None, trtexec_export_profile=None, trtexec_export_layer_info=None,
use_spin_wait=None, threads=None, use_managed_memory=None, dump_refit=None, dump_output=None, dump_profile=None, dump_layer_info=None, refit=None, separate_profile_run=None, trtexec_no_builder_cache=None, trtexec_profiling_verbosity=None, layer_output_types=None, use_dla_core=None,
input_shapes=None, profile_dicts=None, tf32=None, fp16=None, int8=None, allow_gpu_fallback=None, precision_constraints=None, mem_pool_size=None, use_dla=None, layer_precisions=None, plugins=None, save_engine=None):
super().__init__(prefix="trtexec-runner")
self.model_path = model_path
self.model_type = model_type
self.trtexec_path = util.default(trtexec_path, TRTEXEC_DEFAULT_PATH)
if not which(self.trtexec_path):
G_LOGGER.critical(f"trtexec not found in given path: {self.trtexec_path}")
self.use_cuda_graph = use_cuda_graph
self.avg_runs = avg_runs
self.best = best
self.duration = duration
self.device = device
self.streams = streams
self.min_timing = min_timing
self.avg_timing = avg_timing
self.expose_dma = expose_dma
self.no_data_transfers = no_data_transfers
self.trtexec_warmup = trtexec_warmup
self.trtexec_iterations = trtexec_iterations
self.trtexec_export_times = trtexec_export_times
self.trtexec_export_output = trtexec_export_output
self.trtexec_export_profile = trtexec_export_profile
self.trtexec_export_layer_info = trtexec_export_layer_info
self.use_spin_wait = use_spin_wait
self.threads = threads
self.use_managed_memory = use_managed_memory
self.dump_refit = dump_refit
self.dump_output = dump_output
self.dump_profile = dump_profile
self.dump_layer_info = dump_layer_info
self.refit = refit
self.separate_profile_run = separate_profile_run
self.trtexec_no_builder_cache = trtexec_no_builder_cache
self.trtexec_profiling_verbosity = trtexec_profiling_verbosity
self.layer_output_types = layer_output_types
self.use_dla_core = use_dla_core
self.input_shapes = parse_input_shapes(input_shapes)
self.min_shapes, self.opt_shapes, self.max_shapes = parse_profile_dicts(profile_dicts)
self.no_tf32 = not tf32
self.fp16 = fp16
self.int8 = int8
self.allow_gpu_fallback = allow_gpu_fallback
self.precision_constraints = precision_constraints
self.use_dla = 0 if use_dla else None
self.plugins = plugins
self.layer_precisions = parse_layer_precisions(layer_precisions)
self.save_engine = save_engine
if mem_pool_size is None:
self.mem_pool_size = None
else:
self.mem_pool_size = ""
for k, v in mem_pool_size.items():
v = v / MiB # Convert bytes into MiB
if int(k) == 0:
self.mem_pool_size += f"workspace:{v},"
elif int(k) == 1:
self.mem_pool_size += f"dlaSRAM:{v},"
elif int(k) == 2:
self.mem_pool_size += f"dlaLocalDRAM:{v},"
elif int(k) == 3:
self.mem_pool_size += f"dlaGlobalDRAM:{v},"
else:
pass
self.mem_pool_size = self.mem_pool_size.rstrip(',')
def activate_impl(self):
"""
Initializes the construction of the command that needs to be run using
the `trtexec` backend.
"""
self.cmd_args = [self.trtexec_path]
self.input_files = []
if self.trtexec_export_output:
self.export_output_file_handle = open(self.trtexec_export_output, 'w+')
else:
self.export_output_file_handle = tempfile.NamedTemporaryFile(delete=False)
self.export_output_file_name = self.trtexec_export_output or self.export_output_file_handle.name
model_type_mapping = self.get_model_type_mapping()
# Mapping the args of polygraphy run to that of trtexec
init_args_mapping = {
**model_type_mapping,
'exportOutput': self.export_output_file_name,
'useCudaGraph': self.use_cuda_graph,
'avgRuns': self.avg_runs,
'best': self.best,
'duration': self.duration,
'device': self.device,
'streams': self.streams,
'minTiming': self.min_timing,
'avgTiming': self.avg_timing,
'exposeDMA': self.expose_dma,
'noDataTransfers': self.no_data_transfers,
'warmUp': self.trtexec_warmup,
'iterations': self.trtexec_iterations,
'exportTimes': self.trtexec_export_times,
'exportProfile': self.trtexec_export_profile,
'exportLayerInfo': self.trtexec_export_layer_info,
'useSpinWait': self.use_spin_wait,
'threads': self.threads,
'useManagedMemory': self.use_managed_memory,
'dumpRefit': self.dump_refit,
'dumpOutput': self.dump_output,
'dumpProfile': self.dump_profile,
'dumpLayerInfo': self.dump_layer_info,
'refit': self.refit,
'separateProfileRun': self.separate_profile_run,
'noBuilderCache': self.trtexec_no_builder_cache,
'profilingVerbosity': self.trtexec_profiling_verbosity,
'layerPrecisions': self.layer_precisions,
'layerOutputTypes': self.layer_output_types,
'useDLACore': self.use_dla,
'shapes': self.input_shapes,
'minShapes': self.min_shapes,
'optShapes': self.opt_shapes,
'maxShapes': self.max_shapes,
'noTF32': self.no_tf32,
'fp16': self.fp16,
'int8': self.int8,
'allowGPUFallback': self.allow_gpu_fallback,
'precisionConstraints': self.precision_constraints,
'memPoolSize': self.mem_pool_size,
'plugins': self.plugins,
'saveEngine': self.save_engine,
'verbose': G_LOGGER.severity <= G_LOGGER.EXTRA_VERBOSE,
}
for arg, value in init_args_mapping.items():
self.add_cmd_args(arg, value)
def add_cmd_args(self, name, value=None):
"""
Add the args to `self.cmd_args`. The function handles both
args and kwargs
"""
if value is None:
return
if isinstance(value, bool):
# For a bool, add the arg only if the corresponding value is `True`
if value:
self.cmd_args.append('--{}'.format(name))
else:
self.cmd_args.append('--{}={}'.format(name, value))
def get_model_type_mapping(self):
"""
Add the required args based on the model type
"""
if self.model_type == 'onnx':
return {
'onnx': self.model_path
}
if self.model_type == 'engine':
return {
'loadEngine':self.model_path
}
G_LOGGER.critical(f"Unsupported model type: {self.model_type}. `trtexec` only supports TensorRT engines and ONNX models")
def generate_load_inputs_spec(self, feed_dict):
"""
Reads the feed_dict metadata input dictionary and generates files to
pass as command line input to trtexec binary
"""
load_inputs_spec = []
for input, values in feed_dict.items():
input_file = tempfile.NamedTemporaryFile(delete=False)
values.tofile(input_file.name)
load_inputs_spec.append('{}:{}'.format(input, input_file.name))
self.input_files.append(input_file)
self.load_inputs_spec = ','.join(load_inputs_spec)
def read_output_file(self):
"""
Reads the output from the output file generated by the trtexec binary
"""
outputs = OrderedDict()
content = json.load(self.export_output_file_handle)
for entry in content:
name, dimensions, values = entry['name'], entry['dimensions'], entry['values']
dimensions = [int(d) for d in dimensions.split('x')]
outputs[name] = np.array(values).reshape(*dimensions)
return outputs
def get_input_metadata_impl(self):
# Input metadata is used by Polygraphy's default data loader to
# determine the required shapes and datatypes of the input buffers.
if self.model_type == 'onnx':
model = onnx_from_path(self.model_path)
return get_input_metadata(model.graph)
if self.model_type =='engine':
engine = engine_from_bytes(bytes_from_path(self.model_path))
meta = TensorMetadata()
for idx in range(engine.num_io_tensors):
name = engine.get_tensor_name(idx)
if engine.get_tensor_mode(name) != trt.TensorIOMode.INPUT:
continue
meta.add(name=name, dtype=DataType.from_dtype(engine.get_tensor_dtype(name), "tensorrt"), shape=engine.get_tensor_shape(name))
return meta
def infer_impl(self, feed_dict):
outputs = OrderedDict()
# Adds other args that need to generated during inference. For example,
# `feed_dict` is used to generate the args for `loadInputs`
self.construct_final_cmd(feed_dict)
G_LOGGER.info(f"The trtexec command being run: {self.cmd_args}")
perf_output = subprocess.run(self.cmd_args, stdout=subprocess.PIPE, text=True).\
stdout
self.inference_time_stats = get_inference_time(perf_output)
G_LOGGER.verbose(f"Inference time statistics: {self.inference_time_stats}")
outputs = self.read_output_file()
# inference_time_stats records time in 'ms'. However, polygraphy
# expects time in seconds.
self.inference_time = self.inference_time_stats['median'] / 1000
return outputs
def last_inference_time_stats(self):
"""
Provides the inference time statistics
"""
return self.inference_time_stats
def construct_final_cmd(self, feed_dict):
"""
Constructs the complete command to run inference on trtexec backend.
Adds any other args that need to generated during inference.
"""
self.generate_load_inputs_spec(feed_dict)
self.add_cmd_args('loadInputs', self.load_inputs_spec)
def deactivate_impl(self):
# Close the temporary files that are created. Python automatically
# deletes temporary files after they are closed
self.export_output_file_handle.close()
for input_file in self.input_files:
input_file.close()
@@ -0,0 +1,28 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
"""
This file defines the entry point that will be exported by our extension module.
`polygraphy run` will use this to add our custom argument groups.
"""
from polygraphy_trtexec.args import TrtexecRunnerArgs
def export_argument_groups():
return [
TrtexecRunnerArgs(),
]
@@ -0,0 +1,15 @@
 backend-test:[

xy"Identity
test_identityZ
x




b
y




@@ -0,0 +1,56 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
from setuptools import find_packages, setup
import polygraphy_trtexec
import os
def main():
# We change to the project root directory so that `setup.py` is usable from any directory.
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
os.chdir(ROOT_DIR)
setup(
name="polygraphy_trtexec",
version=polygraphy_trtexec.__version__,
description="Polygraphy Trtexec: Extension to run on trtexec backend",
long_description=open("README.md", "r", encoding="utf-8").read(),
long_description_content_type='text/markdown',
url="https://github.com/NVIDIA/TensorRT/tree/main/tools/Polygraphy",
author="NVIDIA",
author_email="svc_tensorrt@nvidia.com",
classifiers=[
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
],
license="Apache 2.0",
install_requires=[
"polygraphy>=0.49.0",
],
packages=find_packages(exclude=("tests", "tests.*")),
entry_points={
"polygraphy.run.plugins": [
"trtexec-runner=polygraphy_trtexec.export:export_argument_groups",
]
},
zip_safe=True,
python_requires=">=3.6",
)
if __name__ == "__main__":
main()
@@ -0,0 +1,16 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
@@ -0,0 +1,85 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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 os
import subprocess as sp
from polygraphy import util
import argparse
import time
TEST_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
# Paramaters to run test on when testing trtexec args mapping
TRTEXEC_PATH_PARAMS = ["trtexec"]
TRTEXEC_EXPORT_TIMES_PARAMS = ["times.json"]
TRTEXEC_EXPORT_OUTPUT_PARAMS = ["output.json"]
TRTEXEC_EXPORT_PROFILE_PARAMS = ["profile.json"]
TRTEXEC_EXPORT_LAYER_INFO_PARAMS = ["layer_info.json"]
def poly_run(args):
"""
Helper function to run the `polygraphy run` command with nececssary args
"""
cmd_args = ["polygraphy", "run"] + args
output = sp.run(cmd_args, stdout=sp.PIPE).stdout.decode('utf-8')
return 'PASSED' in output
def is_file_non_empty(path):
return os.stat(path).st_size != 0
class ArgGroupTestHelper:
def __init__(self, arg_group, deps=None):
self.deps = util.default(deps, [])
self.arg_group = arg_group
self.parser = argparse.ArgumentParser()
arg_groups = {type(self.arg_group): self.arg_group}
arg_groups.update({type(dep): dep for dep in self.deps})
for dep in self.deps:
dep.register(arg_groups)
self.arg_group.register(arg_groups)
for dep in self.deps:
dep.add_parser_args(self.parser)
self.arg_group.add_parser_args(self.parser)
def parse_args(self, cli_args):
args = self.parser.parse_args(cli_args)
for dep in self.deps:
dep.parse(args)
self.arg_group.parse(args)
return args
def __getattr__(self, name):
if name in ["arg_group", "parser"]:
return super().__getattr__(name)
return getattr(self.arg_group, name)
def time_func(func, warm_up=10, iters=50):
for _ in range(warm_up):
func()
total = 0
for _ in range(iters):
start = time.time()
func()
end = time.time()
total += end - start
return total / float(iters)
@@ -0,0 +1,15 @@
 backend_test:y

XY"Identityonnx_dynamic_identityZ&
X!



height
widthb&
Y!



height
widthB
@@ -0,0 +1,15 @@
 backend-test:[

xy"Identity
test_identityZ
x




b
y




@@ -0,0 +1,26 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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 os
META_DIR = os.path.dirname(os.path.abspath(__file__))
# Path to models used for testing
ONNX_MODELS_PATH = {
'identity': os.path.join(META_DIR, "identity.onnx"),
'dynamic_identity': os.path.join(META_DIR, "dynamic_identity.onnx"),
}
@@ -0,0 +1,7 @@
colored
polygraphy==0.49.0
onnx==1.14.0
onnxruntime==1.15.0
protobuf==3.20.2
pytest
wheel
@@ -0,0 +1,195 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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 pytest
from polygraphy.tools.args import (
ModelArgs,
TrtConfigArgs,
TrtLoadPluginsArgs,
TrtLoadNetworkArgs,
TrtSaveEngineBytesArgs,
)
from polygraphy.tools.script import Script
from tests.models.meta import ONNX_MODELS_PATH
from tests.helper import *
from polygraphy.tools.args import util as args_util
from polygraphy_trtexec.args import TrtexecRunnerArgs
@pytest.fixture()
def trtexec_runner_args():
return ArgGroupTestHelper(
TrtexecRunnerArgs(),
deps=[
ModelArgs(),
TrtConfigArgs(),
TrtLoadPluginsArgs(),
TrtLoadNetworkArgs(),
TrtSaveEngineBytesArgs(),
],
)
class TestTrtexecRunnerArgs:
@pytest.mark.parametrize("trtexec_path_params", TRTEXEC_PATH_PARAMS)
def test_trtexec_path(self, trtexec_runner_args, trtexec_path_params):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--trtexec-path={trtexec_path_params}"])
assert trtexec_runner_args.trtexec_path == trtexec_path_params
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].trtexec_path == trtexec_path_params
def test_use_cuda_graph(self, trtexec_runner_args):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--use-cuda-graph"])
assert trtexec_runner_args.use_cuda_graph
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].use_cuda_graph
@pytest.mark.parametrize("num_avg_runs", range(1, 16, 5))
def test_avg_runs(self, trtexec_runner_args, num_avg_runs):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--avg-runs={num_avg_runs}"])
assert trtexec_runner_args.avg_runs == num_avg_runs
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].avg_runs == num_avg_runs
def test_best(self, trtexec_runner_args):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--best"])
assert trtexec_runner_args.best
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].best
@pytest.mark.parametrize("num_duration", range(1, 16, 5))
def test_duration(self, trtexec_runner_args, num_duration):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--duration={num_duration}"])
assert trtexec_runner_args.duration == num_duration
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].duration == num_duration
@pytest.mark.parametrize("num_device", range(0, 3))
def test_device(self, trtexec_runner_args, num_device):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--device={num_device}"])
assert trtexec_runner_args.device == num_device
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].device == num_device
@pytest.mark.parametrize("num_streams", range(1, 4))
def test_streams(self, trtexec_runner_args, num_streams):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--streams={num_streams}"])
assert trtexec_runner_args.streams == num_streams
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].streams == num_streams
@pytest.mark.parametrize("num_min_timing", range(1, 4))
def test_min_timing(self, trtexec_runner_args, num_min_timing):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--min-timing={num_min_timing}"])
assert trtexec_runner_args.min_timing == num_min_timing
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].min_timing == num_min_timing
@pytest.mark.parametrize("num_avg_timing", range(1, 4))
def test_avg_timing(self, trtexec_runner_args, num_avg_timing):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--avg-timing={num_avg_timing}"])
assert trtexec_runner_args.avg_timing == num_avg_timing
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].avg_timing == num_avg_timing
def test_expose_dma(self, trtexec_runner_args):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--expose-dma"])
assert trtexec_runner_args.expose_dma
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].expose_dma
def test_no_data_transfers(self, trtexec_runner_args):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--no-data-transfers"])
assert trtexec_runner_args.no_data_transfers
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].no_data_transfers
@pytest.mark.parametrize("num_warmup", range(100, 400, 100))
def test_trtexec_warmup(self, trtexec_runner_args, num_warmup):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--trtexec-warmup={num_warmup}"])
assert trtexec_runner_args.trtexec_warmup == num_warmup
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].trtexec_warmup == num_warmup
@pytest.mark.parametrize("num_iterations", range(100, 400, 100))
def test_trtexec_iterations(self, trtexec_runner_args, num_iterations):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--trtexec-iterations={num_iterations}"])
assert trtexec_runner_args.trtexec_iterations == num_iterations
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].trtexec_iterations == num_iterations
@pytest.mark.parametrize("trtexec_export_times_params", TRTEXEC_EXPORT_TIMES_PARAMS)
def test_trtexec_export_times(self, trtexec_runner_args, trtexec_export_times_params):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--trtexec-export-times={trtexec_export_times_params}"])
assert trtexec_runner_args.trtexec_export_times == trtexec_export_times_params
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].trtexec_export_times == trtexec_export_times_params
@pytest.mark.parametrize("trtexec_export_output_params", TRTEXEC_EXPORT_OUTPUT_PARAMS)
def test_trtexec_export_output_params(self, trtexec_runner_args, trtexec_export_output_params):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--trtexec-export-output={trtexec_export_output_params}"])
assert trtexec_runner_args.trtexec_export_output == trtexec_export_output_params
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].trtexec_export_output == trtexec_export_output_params
@pytest.mark.parametrize("trtexec_export_profile_params", TRTEXEC_EXPORT_PROFILE_PARAMS)
def test_trtexec_export_profile_params(self, trtexec_runner_args, trtexec_export_profile_params):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--trtexec-export-profile={trtexec_export_profile_params}"])
assert trtexec_runner_args.trtexec_export_profile == trtexec_export_profile_params
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].trtexec_export_profile == trtexec_export_profile_params
@pytest.mark.parametrize("trtexec_export_layer_info_params", TRTEXEC_EXPORT_LAYER_INFO_PARAMS)
def test_trtexec_export_layer_info_params(self, trtexec_runner_args, trtexec_export_layer_info_params):
trtexec_runner_args.parse_args([ONNX_MODELS_PATH["identity"], f"--trtexec-export-layer-info={trtexec_export_layer_info_params}"])
assert trtexec_runner_args.trtexec_export_layer_info == trtexec_export_layer_info_params
script = Script()
runners = args_util.run_script(trtexec_runner_args.add_to_script)
assert runners[0].trtexec_export_layer_info == trtexec_export_layer_info_params
@@ -0,0 +1,43 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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.
#
from polygraphy_trtexec.backend.runner import TrtexecRunner, TRTEXEC_DEFAULT_PATH
from tests.models.meta import ONNX_MODELS_PATH
class TestTrtRunner:
def test_basic(self):
with TrtexecRunner(ONNX_MODELS_PATH["identity"], model_type="onnx") as runner:
assert runner.trtexec_path is TRTEXEC_DEFAULT_PATH
assert runner.use_cuda_graph is None
assert runner.avg_runs is None
assert runner.best is None
assert runner.duration is None
assert runner.device is None
assert runner.streams is None
assert runner.min_timing is None
assert runner.avg_timing is None
assert runner.expose_dma is None
assert runner.no_data_transfers is None
assert runner.trtexec_warmup is None
assert runner.trtexec_iterations is None
assert runner.trtexec_export_times is None
assert runner.trtexec_export_output is None
assert runner.trtexec_export_profile is None
assert runner.trtexec_export_layer_info is None
assert runner.is_active
assert not runner.is_active
@@ -0,0 +1,85 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2022 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 os
import onnx
import pytest
from polygraphy import util, mod
from tests.helper import TEST_DIR, poly_run, is_file_non_empty
from tests.models.meta import ONNX_MODELS_PATH
class TestModelEngine:
def test_load_onnx_model(self):
# Load an onnx model and run inference
assert poly_run([ONNX_MODELS_PATH['identity'], "--trtexec"])
def test_save_load_engine(self):
# Save an engine and check if file exists. Run inference with saved engine
with util.NamedTemporaryFile() as outpath:
assert poly_run([ONNX_MODELS_PATH['identity'], "--trtexec", "--save-engine", outpath.name])
assert is_file_non_empty(outpath.name)
assert poly_run(["--trtexec", outpath.name, "--model-type=engine"])
class TestProfileShapes:
def test_input_shape(self):
assert poly_run([ONNX_MODELS_PATH['dynamic_identity'],
"--trtexec",
"--input-shapes", "X:[1,2,3,3]",
])
def test_explicit_profile(self):
assert poly_run([ ONNX_MODELS_PATH['dynamic_identity'],
"--trtexec",
"--input-shapes", "X:[1,2,1,1]",
"--trt-min-shapes", "X:[1,2,1,1]",
"--trt-opt-shapes", "X:[1,2,1,1]",
"--trt-max-shapes", "X:[1,2,1,1]",
])
def test_explicit_profile_opt_runtime_shapes_differ(self):
assert poly_run([ONNX_MODELS_PATH['dynamic_identity'],
"--trtexec",
"--input-shapes", "X:[1,2,2,2]",
"--trt-min-shapes", "X:[1,2,1,1]",
"--trt-opt-shapes", "X:[1,2,3,3]",
"--trt-max-shapes", "X:[1,2,4,4]",
])
class TestParameterMapping:
def test_args(self):
assert poly_run([ONNX_MODELS_PATH['identity'],
"--trtexec",
"--fp16", "--int8", "--best", "--tf32",
"--use-cuda-graph", "--no-data-transfers",
])
def test_kwargs(self):
assert poly_run([ONNX_MODELS_PATH['identity'],
"--trtexec",
"--memory-pool-limit=workspace:1M", "--streams=2", "--device=0",
"--avg-runs=1", "--min-timing=1", "--avg-timing=3",
"--trtexec-iterations=1", "--trtexec-warmup=1", "--duration=1",
])
class TestAccuracyComparision:
def test_trtexec_trt(self):
# Compare inference results between trtexec and trt
assert poly_run([ONNX_MODELS_PATH['identity'], "--trtexec", "--trt"])
def test_trtexec_onnxrt(self):
# Compare inference results between trtexec and onnxrt
assert poly_run([ONNX_MODELS_PATH['identity'], "--trtexec", "--onnxrt"])