chore: import upstream snapshot with attribution
Docker Image CI / build-ubuntu2004 (push) Waiting to run

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
+25
View File
@@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: Copyright (c) 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.
# Note: This subdirectory is added multiple times, once for each binding library target.
# Indirectly call the current ADD_SOURCES_FUNCTION to populate target sources on the bindings lib that currently being setup.
cmake_language(CALL ${ADD_SOURCES_FUNCTION}
pyTensorRT.cpp
utils.cpp
)
add_subdirectory(infer ${SUBDIR_BINARY_DIR_PREFIX}/src/infer)
add_subdirectory(parsers ${SUBDIR_BINARY_DIR_PREFIX}/src/parsers)
+30
View File
@@ -0,0 +1,30 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-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.
# Note: This subdirectory is added multiple times, once for each binding library target.
# Indirectly call the current ADD_SOURCES_FUNCTION to populate target sources on the bindings lib that currently being setup.
cmake_language(CALL ${ADD_SOURCES_FUNCTION}
pyCore.cpp
pyPlugin.cpp
pyFoundationalTypes.cpp
)
# These sources are omitted from the lean/dispatch runtime bindings.
if(${TRT_PYTHON_IS_FULL_BINDINGS})
cmake_language(CALL ${ADD_SOURCES_FUNCTION}
pyGraph.cpp
)
endif()
File diff suppressed because it is too large Load Diff
+318
View File
@@ -0,0 +1,318 @@
/*
* 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.
*/
// This contains the fundamental types, i.e. Dims, Weights, dtype
#include "ForwardDeclarations.h"
#include "utils.h"
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include "infer/pyFoundationalTypesDoc.h"
#include <cuda_runtime_api.h>
namespace tensorrt
{
using namespace nvinfer1;
namespace lambdas
{
// For Weights
static const auto weights_datatype_constructor = [](DataType const& type) { return new Weights{type, nullptr, 0}; };
static const auto weights_pointer_constructor = [](DataType const& type, size_t const ptr, int64_t count) {
return new Weights{type, reinterpret_cast<void*>(ptr), count};
};
static const auto weights_numpy_constructor = [](py::array& arr) {
arr = py::array::ensure(arr);
// In order to construct a weights object, we must have a contiguous C-style array.
PY_ASSERT_VALUE_ERROR(
arr, "Could not convert NumPy array to Weights. Is it using a data type supported by TensorRT?");
PY_ASSERT_VALUE_ERROR((arr.flags() & py::array::c_style),
"Could not convert non-contiguous NumPy array to Weights. Please use numpy.ascontiguousarray() to fix this.");
return new Weights{utils::type(arr.dtype()), arr.data(), arr.size()};
};
// Helper to compare dims with any kind of Python Iterable.
template <typename DimsType, typename PyIterable>
bool dimsEqual(DimsType const& self, PyIterable& other)
{
if (static_cast<int64_t>(other.size()) != self.nbDims)
{
return false;
}
bool eq = true;
std::vector<int64_t> o = other.template cast<std::vector<int64_t>>();
for (int32_t i = 0; i < self.nbDims; ++i)
{
eq = eq && (self.d[i] == o[i]);
}
return eq;
}
// For base Dims class
static const auto dims_vector_constructor = [](std::vector<int64_t> const& in) {
// This is required, because otherwise MAX_DIMS will not be resolved at compile time.
int32_t const maxDims{static_cast<int32_t>(Dims::MAX_DIMS)};
PY_ASSERT_VALUE_ERROR(in.size() <= maxDims,
"Input length " + std::to_string(in.size()) + ". Max expected length is " + std::to_string(maxDims));
// Create the Dims object.
Dims* self = new Dims{};
self->nbDims = in.size();
for (int32_t i = 0; static_cast<size_t>(i) < in.size(); ++i)
self->d[i] = in[i];
return self;
};
static const auto dims_to_str = [](Dims const& self) {
if (self.nbDims == 0)
return std::string("()");
// Length 1 should followed by trailing comma, for tuple-like behavior.
if (self.nbDims == 1)
return "(" + std::to_string(self.d[0]) + ",)";
// Non-zero lengths
std::string temp = "(";
for (int32_t i = 0; i < self.nbDims - 1; ++i)
temp += std::to_string(self.d[i]) + ", ";
temp += std::to_string(self.d[self.nbDims - 1]) + ")";
return temp;
};
static const auto dims_len = [](Dims const& self) { return self.nbDims; };
// TODO: Add slicing support?
static const auto dims_getter = [](Dims const& self, int32_t const pyIndex) -> int64_t const& {
// Without these bounds checks, horrible infinite looping will occur.
int32_t const index{(pyIndex < 0) ? static_cast<int32_t>(self.nbDims) + pyIndex : pyIndex};
PY_ASSERT_INDEX_ERROR(index >= 0 && index < self.nbDims);
return self.d[index];
};
static const auto dims_getter_slice = [](Dims const& self, py::slice slice) {
int64_t start, stop, step, slicelength;
PY_ASSERT_VALUE_ERROR(
slice.compute(self.nbDims, &start, &stop, &step, &slicelength), "Incorrect getter slice dims");
// Disallow out-of-bounds things.
PY_ASSERT_INDEX_ERROR(stop <= self.nbDims);
py::tuple ret{slicelength};
for (int32_t i = start, index = 0; i < stop; i += step, ++index)
ret[index] = self.d[i];
return ret;
};
static const auto dims_setter = [](Dims& self, int32_t const pyIndex, int64_t const item) {
int32_t const index{(pyIndex < 0) ? static_cast<int32_t>(self.nbDims) + pyIndex : pyIndex};
PY_ASSERT_INDEX_ERROR(index >= 0 && index < self.nbDims);
self.d[index] = item;
};
static const auto dims_setter_slice = [](Dims& self, py::slice slice, Dims const& other) {
int64_t start, stop, step, slicelength;
PY_ASSERT_VALUE_ERROR(
slice.compute(self.nbDims, &start, &stop, &step, &slicelength), "Incorrect setter slice dims");
// Disallow out-of-bounds things.
PY_ASSERT_INDEX_ERROR(stop < self.nbDims);
for (int32_t i = start, index = 0; i < stop; i += step, ++index)
self.d[i] = other.d[index];
};
// For Dims2
static const auto dims2_vector_constructor = [](std::vector<int64_t> const& in) {
PY_ASSERT_VALUE_ERROR(in.size() == 2,
"Input length " + std::to_string(in.size()) + " not equal to expected Dims2 length, which is 2");
return new Dims2{in[0], in[1]};
};
// For DimsHW
static const auto dimshw_vector_constructor = [](std::vector<int64_t> const& in) {
PY_ASSERT_VALUE_ERROR(in.size() == 2,
"Input length " + std::to_string(in.size()) + " not equal to expected DimsHW length, which is 2");
return new DimsHW{in[0], in[1]};
};
// For Dims3
static const auto dims3_vector_constructor = [](std::vector<int64_t> const& in) {
PY_ASSERT_VALUE_ERROR(in.size() == 3,
"Input length " + std::to_string(in.size()) + " not equal to expected Dims3 length, which is 3");
return new Dims3{in[0], in[1], in[2]};
};
// For Dims4
static const auto dims4_vector_constructor = [](std::vector<int64_t> const& in) {
PY_ASSERT_VALUE_ERROR(in.size() == 4,
"Input length " + std::to_string(in.size()) + " not equal to expected Dims4 length, which is 4");
return new Dims4{in[0], in[1], in[2], in[3]};
};
// For IHostMemory
static const auto host_memory_buffer_interface = [](IHostMemory& self) -> py::buffer_info {
return py::buffer_info(self.data(), /* Pointer to buffer */
utils::size(self.type()), /* Size of one scalar */
py::format_descriptor<float>::format(), /* Python struct-style format descriptor */
1, /* Number of dimensions */
{self.size()}, /* Buffer dimensions */
{utils::size(self.type())} /* Strides (in bytes) for each index */
);
};
} // namespace lambdas
void bindFoundationalTypes(py::module& m)
{
// Bind the top level DataType enum.
py::enum_<DataType>(m, "DataType", DataTypeDoc::descr, py::module_local())
.value("FLOAT", DataType::kFLOAT, DataTypeDoc::float32)
.value("HALF", DataType::kHALF, DataTypeDoc::float16)
.value("BF16", DataType::kBF16, DataTypeDoc::bfloat16)
.value("INT8", DataType::kINT8, DataTypeDoc::int8)
.value("INT32", DataType::kINT32, DataTypeDoc::int32)
.value("INT64", DataType::kINT64, DataTypeDoc::int64)
.value("BOOL", DataType::kBOOL, DataTypeDoc::boolean)
.value("UINT8", DataType::kUINT8, DataTypeDoc::uint8)
.value("FP8", DataType::kFP8, DataTypeDoc::fp8)
.value("INT4", DataType::kINT4, DataTypeDoc::int4)
.value("FP4", DataType::kFP4, DataTypeDoc::fp4)
.value("E8M0", DataType::kE8M0, DataTypeDoc::e8m0); // DataType
// Also create direct mappings (so we can call trt.float32, for example).
m.attr("float32") = DataType::kFLOAT;
m.attr("float16") = DataType::kHALF;
m.attr("bfloat16") = DataType::kBF16;
m.attr("int8") = DataType::kINT8;
m.attr("int32") = DataType::kINT32;
m.attr("int64") = DataType::kINT64;
m.attr("bool") = DataType::kBOOL;
m.attr("uint8") = DataType::kUINT8;
m.attr("fp8") = DataType::kFP8;
m.attr("int4") = DataType::kINT4;
m.attr("fp4") = DataType::kFP4;
m.attr("e8m0") = DataType::kE8M0;
py::enum_<WeightsRole>(m, "WeightsRole", WeightsRoleDoc::descr, py::module_local())
.value("KERNEL", WeightsRole::kKERNEL, WeightsRoleDoc::KERNEL)
.value("BIAS", WeightsRole::kBIAS, WeightsRoleDoc::BIAS)
.value("SHIFT", WeightsRole::kSHIFT, WeightsRoleDoc::SHIFT)
.value("SCALE", WeightsRole::kSCALE, WeightsRoleDoc::SCALE)
.value("CONSTANT", WeightsRole::kCONSTANT, WeightsRoleDoc::CONSTANT)
.value("ANY", WeightsRole::kANY, WeightsRoleDoc::ANY); // WeightsRole
// Weights
py::class_<Weights>(m, "Weights", WeightsDoc::descr, py::module_local())
// Can construct an empty weights object with type. Defaults to float32.
.def(py::init(lambdas::weights_datatype_constructor), "type"_a = DataType::kFLOAT, WeightsDoc::init_type)
.def(py::init(lambdas::weights_pointer_constructor), "type"_a, "ptr"_a, "count"_a, WeightsDoc::init_ptr)
// Allows for construction through any contiguous numpy array. It then keeps a pointer to that buffer
// (zero-copy).
.def(py::init(lambdas::weights_numpy_constructor), "a"_a, py::keep_alive<1, 2>(), WeightsDoc::init_numpy)
// Expose numpy-like attributes.
.def_property_readonly("dtype", [](Weights const& self) -> DataType { return self.type; })
.def_property_readonly("size", [](Weights const& self) { return self.count; })
.def_property_readonly("nbytes", [](Weights const& self) { return utils::size(self.type) * self.count; })
.def("numpy", utils::weights_to_numpy, py::return_value_policy::reference_internal, WeightsDoc::numpy)
.def("__len__", [](Weights const& self) { return static_cast<size_t>(self.count); }); // Weights
// Also allow implicit construction, so we can pass in numpy arrays instead of Weights.
py::implicitly_convertible<py::array, Weights>();
// Dims
py::class_<Dims>(m, "Dims", DimsDoc::descr, py::module_local())
.def(py::init<>())
// Allows for construction from python lists and tuples.
.def(py::init(lambdas::dims_vector_constructor), "shape"_a)
// static_cast is required here, or MAX_DIMS does not get pulled in until LOAD time.
.def_property_readonly_static(
"MAX_DIMS", [](py::object /*self*/) { return static_cast<int32_t>(Dims::MAX_DIMS); }, DimsDoc::MAX_DIMS)
// Allow for string representations (displays like a python tuple).
.def("__str__", lambdas::dims_to_str)
.def("__repr__", lambdas::dims_to_str)
// Allow direct comparisons with tuples and lists.
.def("__eq__", lambdas::dimsEqual<Dims, py::list>)
.def("__eq__", lambdas::dimsEqual<Dims, py::tuple>)
// These functions allow us to use Dims like an iterable.
.def("__len__", lambdas::dims_len)
.def("__getitem__", lambdas::dims_getter)
.def("__getitem__", lambdas::dims_getter_slice)
.def("__setitem__", lambdas::dims_setter)
.def("__setitem__", lambdas::dims_setter_slice); // Dims
// Make it possible to use tuples/lists in Python in place of Dims.
py::implicitly_convertible<std::vector<int64_t>, Dims>();
// 2D
py::class_<Dims2, Dims>(m, "Dims2", Dims2Doc::descr, py::module_local())
.def(py::init<>())
.def(py::init<int64_t, int64_t>(), "dim0"_a, "dim1"_a)
// Allows for construction from a tuple/list.
.def(py::init(lambdas::dims2_vector_constructor), "shape"_a); // Dims2
py::implicitly_convertible<std::vector<int64_t>, Dims2>();
py::class_<DimsHW, Dims2>(m, "DimsHW", DimsHWDoc::descr, py::module_local())
.def(py::init<>())
.def(py::init<int64_t, int64_t>(), "h"_a, "w"_a)
// Allows for construction from a tuple/list.
.def(py::init(lambdas::dimshw_vector_constructor), "shape"_a)
// Expose these functions as attributes in Python.
.def_property(
"h", [](DimsHW const& dims) { return dims.h(); }, [](DimsHW& dims, int64_t i) { dims.h() = i; })
.def_property(
"w", [](DimsHW const& dims) { return dims.w(); }, [](DimsHW& dims, int64_t i) { dims.w() = i; }); // DimsHW
py::implicitly_convertible<std::vector<int64_t>, DimsHW>();
// 3D
py::class_<Dims3, Dims>(m, "Dims3", Dims3Doc::descr, py::module_local())
.def(py::init<>())
.def(py::init<int64_t, int64_t, int64_t>(), "dim0"_a, "dim1"_a, "dim2"_a)
// Allows for construction from a tuple/list.
.def(py::init(lambdas::dims3_vector_constructor), "shape"_a); // Dims3
py::implicitly_convertible<std::vector<int64_t>, Dims3>();
// 4D
py::class_<Dims4, Dims>(m, "Dims4", Dims4Doc::descr, py::module_local())
.def(py::init<>())
.def(py::init<int64_t, int64_t, int64_t, int64_t>(), "dim0"_a, "dim1"_a, "dim2"_a, "dim3"_a)
// Allows for construction from a tuple/list.
.def(py::init(lambdas::dims4_vector_constructor), "shape"_a); // Dims4
py::implicitly_convertible<std::vector<int64_t>, Dims4>();
py::class_<IHostMemory>(m, "IHostMemory", py::buffer_protocol(), IHostMemoryDoc::descr, py::module_local())
.def_property_readonly("dtype", [](IHostMemory const& mem) { return mem.type(); })
.def_property_readonly("nbytes", [](IHostMemory const& mem) { return mem.size(); })
// Expose buffer interface.
.def_buffer(lambdas::host_memory_buffer_interface)
.def("__del__", &utils::doNothingDel<IHostMemory>); // IHostMemory
py::class_<InterfaceInfo>(m, "InterfaceInfo", InterfaceInfoDoc::descr, py::module_local())
.def_readwrite("kind", &InterfaceInfo::kind)
.def_readwrite("major", &InterfaceInfo::major)
.def_readwrite("minor", &InterfaceInfo::minor);
py::enum_<APILanguage>(m, "APILanguage", APILanguageDoc::descr, py::module_local())
.value("CPP", APILanguage::kCPP)
.value("PYTHON", APILanguage::kPYTHON);
py::class_<IVersionedInterface>(m, "IVersionedInterface", IVersionedInterfaceDoc::descr, py::module_local())
.def_property_readonly("api_language", &IVersionedInterface::getAPILanguage)
.def_property_readonly("interface_info", &IVersionedInterface::getInterfaceInfo);
}
} // namespace tensorrt
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+24
View File
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: Copyright (c) 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.
# Note: This subdirectory is added multiple times, once for each binding library target.
# Indirectly call the current ADD_SOURCES_FUNCTION to populate target sources on the bindings lib that currently being setup.
# The parser is only included by the full "tensorrt" or "tensorrt_rtx" binding module.
if(${TRT_PYTHON_IS_FULL_BINDINGS})
cmake_language(CALL ${ADD_SOURCES_FUNCTION}
pyOnnx.cpp
)
endif()
+278
View File
@@ -0,0 +1,278 @@
/*
* 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.
*/
// Implementation of PyBind11 Binding Code for OnnxParser
#include "ForwardDeclarations.h"
#include "NvOnnxParser.h"
#include "parsers/pyOnnxDoc.h"
#include "utils.h"
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <string>
#include <vector>
using namespace nvonnxparser;
namespace tensorrt
{
// Long lambda functions should go here rather than being inlined into the bindings (1 liners are OK).
namespace lambdas
{
// NOLINTBEGIN(readability-identifier-naming)
static auto const parse = [](IParser& self, py::buffer const& model, char const* path = nullptr) {
py::buffer_info info = model.request();
py::gil_scoped_release releaseGil{};
return self.parse(info.ptr, info.size * info.itemsize, path);
};
static auto const parseFromFile
= [](IParser& self, std::string const& model) { return self.parseFromFile(model.c_str(), 0); };
static auto const supportsModelV2 = [](IParser& self, py::buffer const& model, char const* path = nullptr) {
py::buffer_info info = model.request();
return self.supportsModelV2(info.ptr, info.size * info.itemsize, path);
};
static auto const isSubgraphSupported
= [](IParser& self, int64_t const index) { return self.isSubgraphSupported(index); };
static auto const getSubgraphNodes = [](IParser& self, int64_t const index) {
py::list py_nodes;
int64_t nb_nodes = 0;
int64_t* nodes = self.getSubgraphNodes(index, nb_nodes);
for (int64_t i = 0; i < nb_nodes; i++)
{
py_nodes.append(nodes[i]);
}
return py_nodes;
};
static auto const get_used_vc_plugin_libraries = [](IParser& self) {
std::vector<std::string> vcPluginLibs;
int64_t nbPluginLibs;
auto libCArray = self.getUsedVCPluginLibraries(nbPluginLibs);
if (nbPluginLibs < 0)
{
utils::throwPyError(PyExc_RuntimeError, "Internal error");
}
vcPluginLibs.reserve(nbPluginLibs);
for (int64_t i = 0; i < nbPluginLibs; ++i)
{
vcPluginLibs.emplace_back(std::string{libCArray[i]});
}
return vcPluginLibs;
};
static auto const pLoadModelProto = [](IParser& self, py::buffer const& model, char const* path = nullptr) {
py::buffer_info info = model.request();
return self.loadModelProto(info.ptr, info.size * info.itemsize, path);
};
static auto const pLoadInitializer = [](IParser& self, std::string const& name, size_t const ptr, size_t const count) {
return self.loadInitializer(name.c_str(), reinterpret_cast<void*>(ptr), count);
};
static auto const get_local_function_stack = [](IParserError& self) {
std::vector<std::string> localFunctionStack;
int32_t localFunctionStackSize = self.localFunctionStackSize();
if (localFunctionStackSize > 0)
{
auto localFunctionStackCArray = self.localFunctionStack();
localFunctionStack.reserve(localFunctionStackSize);
for (int32_t i = 0; i < localFunctionStackSize; ++i)
{
localFunctionStack.emplace_back(std::string{localFunctionStackCArray[i]});
}
}
return localFunctionStack;
};
static auto const refitFromBytes = [](IParserRefitter& self, py::buffer const& model, char const* path = nullptr) {
py::buffer_info info = model.request();
py::gil_scoped_release releaseGil{};
return self.refitFromBytes(info.ptr, info.size * info.itemsize, path);
};
static auto const refitFromFile
= [](IParserRefitter& self, std::string const& model) { return self.refitFromFile(model.c_str()); };
static auto const rLoadModelProto = [](IParserRefitter& self, py::buffer const& model, char const* path = nullptr) {
py::buffer_info info = model.request();
return self.loadModelProto(info.ptr, info.size * info.itemsize, path);
};
static auto const rLoadInitializer
= [](IParserRefitter& self, std::string const& name, size_t const ptr, size_t const count) {
return self.loadInitializer(name.c_str(), reinterpret_cast<void*>(ptr), count);
};
// NOLINTEND(readability-identifier-naming)
} // namespace lambdas
// Copies of functions from ONNX Parser code used for the Python Bindings.
namespace pyonnx2trt
{
inline char const* errorCodeStr(ErrorCode code)
{
switch (code)
{
case ErrorCode::kSUCCESS: return "SUCCESS";
case ErrorCode::kINTERNAL_ERROR: return "INTERNAL_ERROR";
case ErrorCode::kMEM_ALLOC_FAILED: return "MEM_ALLOC_FAILED";
case ErrorCode::kMODEL_DESERIALIZE_FAILED: return "MODEL_DESERIALIZE_FAILED";
case ErrorCode::kINVALID_VALUE: return "INVALID_VALUE";
case ErrorCode::kINVALID_GRAPH: return "INVALID_GRAPH";
case ErrorCode::kINVALID_NODE: return "INVALID_NODE";
case ErrorCode::kUNSUPPORTED_GRAPH: return "UNSUPPORTED_GRAPH";
case ErrorCode::kUNSUPPORTED_NODE: return "UNSUPPORTED_NODE";
case ErrorCode::kUNSUPPORTED_NODE_ATTR: return "UNSUPPORTED_NODE_ATTR";
case ErrorCode::kUNSUPPORTED_NODE_INPUT: return "UNSUPPORTED_NODE_INPUT";
case ErrorCode::kUNSUPPORTED_NODE_DATATYPE: return "UNSUPPORTED_NODE_DATATYPE";
case ErrorCode::kUNSUPPORTED_NODE_DYNAMIC: return "UNSUPPORTED_NODE_DYNAMIC";
case ErrorCode::kUNSUPPORTED_NODE_SHAPE: return "UNSUPPORTED_NODE_SHAPE";
case ErrorCode::kREFIT_FAILED: return "REFIT_FAILED";
}
return "UNKNOWN";
}
inline std::string const parserErrorStr(nvonnxparser::IParserError const* error)
{
std::string const nodeInfo = "In node " + std::to_string(error->node()) + " with name: " + error->nodeName()
+ " and operator: " + error->nodeOperator() + " ";
std::string const errorInfo
= std::string("(") + error->func() + "): " + errorCodeStr(error->code()) + ": " + error->desc();
if (error->code() == ErrorCode::kMODEL_DESERIALIZE_FAILED || error->code() == ErrorCode::kREFIT_FAILED)
{
return errorInfo.c_str();
}
return (nodeInfo + errorInfo).c_str();
}
} // namespace pyonnx2trt
void bindOnnx(py::module& m)
{
py::bind_vector<std::vector<size_t>>(m, "NodeIndices");
py::class_<IParser>(m, "OnnxParser", OnnxParserDoc::descr, py::module_local())
// Use a lambda to force correct resolution. Pybind doesn't resolve noexcept factory methods correctly as
// constructors. https://github.com/pybind/pybind11/issues/2856
.def(py::init([](nvinfer1::INetworkDefinition& network, nvinfer1::ILogger& logger) {
return nvonnxparser::createParser(network, logger);
}),
"network"_a, "logger"_a, OnnxParserDoc::init, py::keep_alive<1, 3>{}, py::keep_alive<2, 1>{})
.def("parse", lambdas::parse, "model"_a, "path"_a = nullptr, OnnxParserDoc::parse)
.def("parse_from_file", lambdas::parseFromFile, "model"_a, OnnxParserDoc::parse_from_file,
py::call_guard<py::gil_scoped_release>{})
.def("supports_operator", &IParser::supportsOperator, "op_name"_a, OnnxParserDoc::supports_operator)
.def("supports_model_v2", lambdas::supportsModelV2, "model"_a, "path"_a = nullptr,
OnnxParserDoc::supports_model_v2)
.def_property_readonly("num_subgraphs", &IParser::getNbSubgraphs)
.def("is_subgraph_supported", lambdas::isSubgraphSupported, "index"_a, OnnxParserDoc::is_subgraph_supported)
.def("get_subgraph_nodes", lambdas::getSubgraphNodes, "index"_a, OnnxParserDoc::get_subgraph_nodes)
.def_property_readonly("num_errors", &IParser::getNbErrors)
.def("get_error", &IParser::getError, "index"_a, OnnxParserDoc::get_error)
.def("clear_errors", &IParser::clearErrors, OnnxParserDoc::clear_errors)
.def_property("flags", &IParser::getFlags, &IParser::setFlags)
.def("clear_flag", &IParser::clearFlag, "flag"_a, OnnxParserDoc::clear_flag)
.def("set_flag", &IParser::setFlag, "flag"_a, OnnxParserDoc::set_flag)
.def("get_flag", &IParser::getFlag, "flag"_a, OnnxParserDoc::get_flag)
.def("get_layer_output_tensor", &IParser::getLayerOutputTensor, "name"_a, "i"_a,
OnnxParserDoc::get_layer_output_tensor)
.def("get_used_vc_plugin_libraries", lambdas::get_used_vc_plugin_libraries,
OnnxParserDoc::get_used_vc_plugin_libraries)
.def("__del__", &utils::doNothingDel<IParser>)
.def("load_model_proto", lambdas::pLoadModelProto, "model"_a, "path"_a = nullptr,
OnnxParserDoc::load_model_proto, py::call_guard<py::gil_scoped_release>{})
.def("load_initializer", lambdas::pLoadInitializer, "name"_a, "data"_a, "size"_a,
OnnxParserDoc::load_initializer)
.def("parse_model_proto", &IParser::parseModelProto, OnnxParserDoc::parse_model_proto)
.def("set_builder_config", &IParser::setBuilderConfig, "builder_config"_a, OnnxParserDoc::set_builder_config,
py::keep_alive<1, 2>{});
py::enum_<OnnxParserFlag>(m, "OnnxParserFlag", OnnxParserFlagDoc::descr, py::module_local())
.value("NATIVE_INSTANCENORM", OnnxParserFlag::kNATIVE_INSTANCENORM, OnnxParserFlagDoc::NATIVE_INSTANCENORM)
.value("ENABLE_UINT8_AND_ASYMMETRIC_QUANTIZATION_DLA",
OnnxParserFlag::kENABLE_UINT8_AND_ASYMMETRIC_QUANTIZATION_DLA,
OnnxParserFlagDoc::ENABLE_UINT8_AND_ASYMMETRIC_QUANTIZATION_DLA)
.value(
"REPORT_CAPABILITY_DLA", OnnxParserFlag::kREPORT_CAPABILITY_DLA, OnnxParserFlagDoc::REPORT_CAPABILITY_DLA)
.value("ENABLE_PLUGIN_OVERRIDE", OnnxParserFlag::kENABLE_PLUGIN_OVERRIDE,
OnnxParserFlagDoc::ENABLE_PLUGIN_OVERRIDE)
.value("ADJUST_FOR_DLA", OnnxParserFlag::kADJUST_FOR_DLA, OnnxParserFlagDoc::ADJUST_FOR_DLA);
py::enum_<ErrorCode>(m, "ErrorCode", ErrorCodeDoc::descr, py::module_local())
.value("SUCCESS", ErrorCode::kSUCCESS)
.value("INTERNAL_ERROR", ErrorCode::kINTERNAL_ERROR)
.value("MEM_ALLOC_FAILED", ErrorCode::kMEM_ALLOC_FAILED)
.value("MODEL_DESERIALIZE_FAILED", ErrorCode::kMODEL_DESERIALIZE_FAILED)
.value("INVALID_VALUE", ErrorCode::kINVALID_VALUE)
.value("INVALID_GRAPH", ErrorCode::kINVALID_GRAPH)
.value("INVALID_NODE", ErrorCode::kINVALID_NODE)
.value("UNSUPPORTED_GRAPH", ErrorCode::kUNSUPPORTED_GRAPH)
.value("UNSUPPORTED_NODE", ErrorCode::kUNSUPPORTED_NODE)
.value("UNSUPPORTED_NODE_ATTR", ErrorCode::kUNSUPPORTED_NODE_ATTR)
.value("UNSUPPORTED_NODE_INPUT", ErrorCode::kUNSUPPORTED_NODE_INPUT)
.value("UNSUPPORTED_NODE_DATATYPE", ErrorCode::kUNSUPPORTED_NODE_DATATYPE)
.value("UNSUPPORTED_NODE_DYNAMIC", ErrorCode::kUNSUPPORTED_NODE_DYNAMIC)
.value("UNSUPPORTED_NODE_SHAPE", ErrorCode::kUNSUPPORTED_NODE_SHAPE)
.value("REFIT_FAILED", ErrorCode::kREFIT_FAILED)
.def("__str__", &pyonnx2trt::errorCodeStr)
.def("__repr__", &pyonnx2trt::errorCodeStr);
py::class_<IParserError, std::unique_ptr<IParserError, py::nodelete>>(m, "ParserError", py::module_local())
.def("code", &IParserError::code, ParserErrorDoc::code)
.def("desc", &IParserError::desc, ParserErrorDoc::desc)
.def("file", &IParserError::file, ParserErrorDoc::file)
.def("line", &IParserError::line, ParserErrorDoc::line)
.def("func", &IParserError::func, ParserErrorDoc::func)
.def("node", &IParserError::node, ParserErrorDoc::node)
.def("node_name", &IParserError::nodeName, ParserErrorDoc::node_name)
.def("node_operator", &IParserError::nodeOperator, ParserErrorDoc::node_operator)
.def("local_function_stack", lambdas::get_local_function_stack, ParserErrorDoc::local_function_stack)
.def("local_function_stack_size", &IParserError::localFunctionStackSize,
ParserErrorDoc::local_function_stack_size)
.def("__str__", &pyonnx2trt::parserErrorStr)
.def("__repr__", &pyonnx2trt::parserErrorStr);
py::class_<IParserRefitter>(m, "OnnxParserRefitter", OnnxParserRefitterDoc::descr, py::module_local())
// Use a lambda to force correct resolution. Pybind doesn't resolve noexcept factory methods correctly as
// constructors. https://github.com/pybind/pybind11/issues/2856
.def(py::init([](nvinfer1::IRefitter& refitter, nvinfer1::ILogger& logger) {
return nvonnxparser::createParserRefitter(refitter, logger);
}),
"refitter"_a, "logger"_a, OnnxParserRefitterDoc::init, py::keep_alive<1, 3>{}, py::keep_alive<2, 1>{})
.def("refit_from_bytes", lambdas::refitFromBytes, "model"_a, "path"_a = nullptr,
OnnxParserRefitterDoc::refit_from_bytes)
.def("refit_from_file", lambdas::refitFromFile, "model"_a, OnnxParserRefitterDoc::refit_from_file,
py::call_guard<py::gil_scoped_release>{})
.def_property_readonly("num_errors", &IParserRefitter::getNbErrors)
.def("get_error", &IParserRefitter::getError, "index"_a, OnnxParserRefitterDoc::get_error)
.def("clear_errors", &IParserRefitter::clearErrors, OnnxParserRefitterDoc::clear_errors)
.def("load_model_proto", lambdas::rLoadModelProto, "model"_a, "path"_a = nullptr,
OnnxParserRefitterDoc::load_model_proto, py::call_guard<py::gil_scoped_release>{})
.def("load_initializer", lambdas::rLoadInitializer, "name"_a, "data"_a, "size"_a,
OnnxParserRefitterDoc::load_initializer)
.def("refit_model_proto", &IParserRefitter::refitModelProto, OnnxParserRefitterDoc::refit_model_proto);
// Free functions.
m.def("get_nv_onnx_parser_version", &getNvOnnxParserVersion, get_nv_onnx_parser_version);
}
} // namespace tensorrt
+63
View File
@@ -0,0 +1,63 @@
/*
* 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.
*/
// This file contains top level bindings and defines the whole TRT Python package.
#include "ForwardDeclarations.h"
#include "NvInfer.h"
#include "pyTensorRTDoc.h"
#include <pybind11/stl_bind.h>
namespace tensorrt
{
PYBIND11_MODULE(TENSORRT_MODULE, m)
{
// Python strings can be automatically converted to FallbackStrings,
// whose lifetime is tied to TRT objects that reference, but do not own, a string.
// See ForwardDeclarations.h for more information about FallbackString.
// Note that we cannot allow Python to deallocate this string, hence the py::nodelete.
//
// Important: *All* Python enum and class interfaces exported by this module *must* be
// declared with py::module_local() scope, so that multiple TRT runtime modules
// (e.g. tensorrt_lean and tensorrt_dispatch) may be imported by the same Python script
// without conflicts.
//
// See https://pybind11.readthedocs.io/en/stable/advanced/classes.html#module-local-class-bindings
// for more information.
py::class_<FallbackString, std::unique_ptr<FallbackString, py::nodelete>>(m, "FallbackString", py::module_local())
.def(py::init<std::string>())
.def(py::init<py::str>());
py::implicitly_convertible<std::string, FallbackString>();
py::implicitly_convertible<py::str, FallbackString>();
// Make it so that we can use lists of PluginFields without creating unwanted copies.
// This is declared opaque in ForwardDeclarations.h
py::bind_vector<std::vector<nvinfer1::PluginField>>(m, "PluginFieldCollection");
// Order matters here - Dependencies must be resolved properly!
// TODO: Maybe use actual forward declarations and define functions later.
bindFoundationalTypes(m);
bindPlugin(m);
#if EXPORT_ALL_BINDINGS
bindGraph(m);
#endif
bindCore(m);
#if EXPORT_ALL_BINDINGS
// Parsers
bindOnnx(m);
#endif
}
} // namespace tensorrt
+167
View File
@@ -0,0 +1,167 @@
/*
* 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.
*/
#include "utils.h"
#if defined(_WIN32)
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif // defined(WIN32_LEAN_AND_MEAN)
#define NOMINMAX
#include <windows.h>
#else // defined(_WIN32)
#include <dlfcn.h>
#endif // defined(_WIN32)
namespace tensorrt
{
namespace utils
{
void issueDeprecationWarning(char const* useInstead)
{
std::string msg{"Use " + std::string{useInstead} + " instead."};
py::gil_scoped_acquire acquire{};
PyErr_WarnEx(PyExc_DeprecationWarning, msg.c_str(), 1);
}
void* nvdllOpen(char const* libName)
{
std::ostringstream fullLibName;
#if defined(_WIN32)
fullLibName << "nv" << libName << ".dll";
std::string strFullLibName = fullLibName.str();
return static_cast<void*>(LoadLibraryA(strFullLibName.c_str()));
#else // defined(_WIN32)
fullLibName << "lib" << libName << ".so.1";
std::string strFullLibName = fullLibName.str();
return dlopen(strFullLibName.c_str(), RTLD_LAZY);
#endif // defined(_WIN32)
}
void dllClose(void* handle)
{
if (handle)
{
#if defined(_WIN32)
FreeLibrary(static_cast<HMODULE>(handle));
#else // defined(_WIN32)
dlclose(handle);
#endif // defined(_WIN32)
}
}
void* dllGetSym(void* handle, char const* name)
{
#if defined(_WIN32)
return GetProcAddress(static_cast<HMODULE>(handle), name);
#else // defined(_WIN32)
return dlsym(handle, name);
#endif // defined(_WIN32)
}
// Returns the size in bytes of the specified data type.
size_t size(nvinfer1::DataType type)
{
switch (type)
{
case nvinfer1::DataType::kFLOAT: return 4;
case nvinfer1::DataType::kHALF: return 2;
case nvinfer1::DataType::kINT8: return 1;
case nvinfer1::DataType::kINT32: return 4;
case nvinfer1::DataType::kINT64: return 8;
case nvinfer1::DataType::kBOOL: return 1;
case nvinfer1::DataType::kUINT8: return 1;
case nvinfer1::DataType::kFP8: return 1;
case nvinfer1::DataType::kE8M0: return 1;
case nvinfer1::DataType::kBF16: return 2;
case nvinfer1::DataType::kINT4:
case nvinfer1::DataType::kFP4: break; // TRT-22011 - need to address sub-byte element size
}
return -1;
}
std::unique_ptr<py::dtype> nptype(nvinfer1::DataType type)
{
auto const makeDtype = [](char const* typeStr) { return std::make_unique<py::dtype>(typeStr); };
switch (type)
{
case nvinfer1::DataType::kFLOAT: return makeDtype("f4");
case nvinfer1::DataType::kHALF: return makeDtype("f2");
case nvinfer1::DataType::kINT8: return makeDtype("i1");
case nvinfer1::DataType::kINT32: return makeDtype("i4");
case nvinfer1::DataType::kINT64: return makeDtype("i8");
case nvinfer1::DataType::kBOOL: return makeDtype("b1");
case nvinfer1::DataType::kUINT8: return makeDtype("u1");
case nvinfer1::DataType::kFP8:
case nvinfer1::DataType::kBF16:
case nvinfer1::DataType::kINT4:
case nvinfer1::DataType::kFP4:
case nvinfer1::DataType::kE8M0: return nullptr;
}
return nullptr;
}
nvinfer1::DataType type(py::dtype const& type)
{
if (type.is(py::dtype("f4")))
{
return nvinfer1::DataType::kFLOAT;
}
else if (type.is(py::dtype("f2")))
{
return nvinfer1::DataType::kHALF;
}
else if (type.is(py::dtype("i8")))
{
return nvinfer1::DataType::kINT64;
}
else if (type.is(py::dtype("i4")))
{
return nvinfer1::DataType::kINT32;
}
else if (type.is(py::dtype("i1")))
{
return nvinfer1::DataType::kINT8;
}
else if (type.is(py::dtype("b1")))
{
return nvinfer1::DataType::kBOOL;
}
else if (type.is(py::dtype("u1")))
{
return nvinfer1::DataType::kUINT8;
}
int32_t constexpr kBITS_PER_BYTE{8};
std::stringstream ss{};
ss << "[TRT] [E] Could not implicitly convert NumPy data type: " << type.kind()
<< (type.itemsize() * kBITS_PER_BYTE) << " to TensorRT.";
std::cerr << ss.str() << std::endl;
PY_ASSERT_VALUE_ERROR(false, ss.str());
return nvinfer1::DataType::kFLOAT;
}
void throwPyError(PyObject* type, std::string const& message)
{
PyErr_SetString(type, message.data());
throw py::error_already_set();
}
} // namespace utils
} // namespace tensorrt