Skip to content

Commit ccea431

Browse files
cehongwangtp5uiuc
andauthored
Cherrypick ws fix (#4389)
Co-authored-by: Tejaswin Parthasarathy <56932502+tp5uiuc@users.noreply.github.com>
1 parent 86f2052 commit ccea431

31 files changed

Lines changed: 4058 additions & 894 deletions

core/runtime/BUILD

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,39 @@ cc_library(
8686
"DeviceList.cpp",
8787
"Platform.cpp",
8888
"RTDevice.cpp",
89+
"RuntimeSettings.cpp",
8990
"TRTEngine.cpp",
9091
"TRTEngineProfiler.cpp",
92+
"TRTRuntimeConfig.cpp",
9193
"execute_engine.cpp",
9294
"runtime.cpp",
9395
"runtime_utils.cpp",
9496
],
9597
hdrs = [
9698
"Platform.h",
9799
"RTDevice.h",
98-
"TensorRTBindingNames.h",
100+
"RuntimeSettings.h",
99101
"TRTEngine.h",
100102
"TRTEngineProfiler.h",
103+
"TRTRuntimeConfig.h",
104+
"TensorRTBindingNames.h",
101105
"runtime.h",
102106
],
103107
copts = if_torch_nccl(["-DUSE_C10D_NCCL"]),
108+
defines = select({
109+
# nvinfer1::IRuntimeConfig (and the matching ICudaEngine::createRuntimeConfig
110+
# / createExecutionContext(IRuntimeConfig*) overloads) was introduced in
111+
# TensorRT 10.11. The TensorRT shipped with the Jetpack l4t-r36.4 toolchain
112+
# (@tensorrt_l4t) predates 10.11 and does not export this type. Every other
113+
# configuration here (RTX, SBSA, Windows, default x86_64 Linux) is on a
114+
# TensorRT >= 10.11 bundle, so it gets the macro.
115+
#
116+
# Gate every IRuntimeConfig-using site in core/runtime with
117+
# `#ifdef TRT_HAS_IRUNTIME_CONFIG`; the Jetpack path falls back to the
118+
# legacy createExecutionContext() no-arg overload.
119+
":jetpack": [],
120+
"//conditions:default": ["TRT_HAS_IRUNTIME_CONFIG"],
121+
}),
104122
linkopts = [
105123
"-lstdc++fs",
106124
],
@@ -135,9 +153,11 @@ cc_library(
135153
hdrs = [
136154
"Platform.h",
137155
"RTDevice.h",
138-
"TensorRTBindingNames.h",
156+
"RuntimeSettings.h",
139157
"TRTEngine.h",
140158
"TRTEngineProfiler.h",
159+
"TRTRuntimeConfig.h",
160+
"TensorRTBindingNames.h",
141161
"runtime.h",
142162
],
143163
deps = [
@@ -151,9 +171,11 @@ filegroup(
151171
srcs = [
152172
"Platform.h",
153173
"RTDevice.h",
154-
"TensorRTBindingNames.h",
174+
"RuntimeSettings.h",
155175
"TRTEngine.h",
156176
"TRTEngineProfiler.h",
177+
"TRTRuntimeConfig.h",
178+
"TensorRTBindingNames.h",
157179
"runtime.h",
158180
],
159181
visibility = ["//visibility:public"],

core/runtime/RuntimeSettings.cpp

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
#include "core/runtime/RuntimeSettings.h"
2+
3+
#include <array>
4+
#include <cstring>
5+
#include <iterator>
6+
#include <sstream>
7+
#include <tuple>
8+
#include <type_traits>
9+
10+
// ``at::empty`` (factory function) lives in ``ATen/Functions.h``. Some bundled
11+
// torch builds (e.g. torch_l4t on Jetpack) only ship the minimal
12+
// ``ATen/core/Tensor.h`` transitively, so include the full ATen surface here.
13+
#include "ATen/ATen.h"
14+
#include "core/util/prelude.h"
15+
16+
namespace torch_tensorrt {
17+
namespace core {
18+
namespace runtime {
19+
20+
namespace {
21+
22+
// Reverse-lookup tables. Indices match the enum integer values (which mirror
23+
// the nvinfer1 enums). Out-of-range -> "<unknown>".
24+
constexpr std::array<std::string_view, 3> kDsStrategyNames = {"lazy", "eager", "none"};
25+
constexpr std::array<std::string_view, 2> kCgStrategyNames = {"disabled", "whole_graph_capture"};
26+
27+
// "a|b|c" from {"a", "b", "c"}. Used to render the accepted-names tail of the
28+
// validator error messages.
29+
template <size_t N>
30+
std::string join_string_views(std::string_view sep, std::array<std::string_view, N> const& parts) {
31+
if (N == 0) {
32+
return {};
33+
}
34+
std::ostringstream os;
35+
os << parts.front();
36+
for (auto it = std::next(std::cbegin(parts)); it != std::cend(parts); ++it) {
37+
os << sep << *it;
38+
}
39+
return os.str();
40+
}
41+
42+
// "(expected 0..N-1 mapping to a|b|c)" -- the common error-message tail.
43+
template <size_t N>
44+
std::string format_expected_strategy(std::array<std::string_view, N> const& names) {
45+
std::ostringstream os;
46+
os << "(expected 0.." << (N - 1) << " mapping to " << join_string_views("|", names) << ')';
47+
return os.str();
48+
}
49+
50+
// "(expected a|b|c)" -- name-only variant for ``from_string`` errors.
51+
template <size_t N>
52+
std::string format_expected_name(std::array<std::string_view, N> const& names) {
53+
std::ostringstream os;
54+
os << "(expected " << join_string_views("|", names) << ')';
55+
return os.str();
56+
}
57+
58+
} // namespace
59+
60+
// ---- DynamicShapesKernelSpecializationStrategy -----------------------------
61+
62+
std::string_view DynamicShapesKernelSpecializationStrategy::to_string() const noexcept {
63+
// Negative underlying values wrap to a huge ``size_t``, so a single bounds
64+
// check from the top covers both ends without needing ``std::clamp``.
65+
auto const i = static_cast<size_t>(v_);
66+
return i < std::size(kDsStrategyNames) ? kDsStrategyNames[i] : std::string_view{"<unknown>"};
67+
}
68+
69+
DynamicShapesKernelSpecializationStrategy DynamicShapesKernelSpecializationStrategy::from_underlying(int64_t v) {
70+
TORCHTRT_CHECK(
71+
v >= 0 && static_cast<size_t>(v) < std::size(kDsStrategyNames),
72+
"Invalid dynamic_shapes_kernel_specialization_strategy int: " << v << " "
73+
<< format_expected_strategy(kDsStrategyNames));
74+
return DynamicShapesKernelSpecializationStrategy(static_cast<Value>(v));
75+
}
76+
77+
DynamicShapesKernelSpecializationStrategy DynamicShapesKernelSpecializationStrategy::from_string(
78+
std::string_view name) {
79+
for (size_t i = 0; i < std::size(kDsStrategyNames); ++i) {
80+
if (kDsStrategyNames[i] == name) {
81+
return DynamicShapesKernelSpecializationStrategy(static_cast<Value>(i));
82+
}
83+
}
84+
TORCHTRT_CHECK(
85+
false,
86+
"Invalid dynamic_shapes_kernel_specialization_strategy name: " << name << " "
87+
<< format_expected_name(kDsStrategyNames));
88+
}
89+
90+
// ---- CudaGraphStrategy -----------------------------------------------------
91+
92+
std::string_view CudaGraphStrategy::to_string() const noexcept {
93+
auto const i = static_cast<size_t>(v_);
94+
return i < std::size(kCgStrategyNames) ? kCgStrategyNames[i] : std::string_view{"<unknown>"};
95+
}
96+
97+
CudaGraphStrategy CudaGraphStrategy::from_underlying(int64_t v) {
98+
TORCHTRT_CHECK(
99+
v >= 0 && static_cast<size_t>(v) < std::size(kCgStrategyNames),
100+
"Invalid cuda_graph_strategy int: " << v << " " << format_expected_strategy(kCgStrategyNames));
101+
return CudaGraphStrategy(static_cast<Value>(v));
102+
}
103+
104+
CudaGraphStrategy CudaGraphStrategy::from_string(std::string_view name) {
105+
for (size_t i = 0; i < std::size(kCgStrategyNames); ++i) {
106+
if (kCgStrategyNames[i] == name) {
107+
return CudaGraphStrategy(static_cast<Value>(i));
108+
}
109+
}
110+
TORCHTRT_CHECK(false, "Invalid cuda_graph_strategy name: " << name << " " << format_expected_name(kCgStrategyNames));
111+
}
112+
113+
// ---- RuntimeCacheHandle methods ---------------------------------------------
114+
//
115+
// The ``#ifdef TRT_MAJOR_RTX`` is intentionally confined to this translation
116+
// unit: the public header advertises a uniform interface (always-callable
117+
// methods that simply degrade to no-ops on non-RTX builds), and the JIT-binding
118+
// registration file (``register_jit_hooks.cpp``) calls these as plain member
119+
// references with zero conditional compilation.
120+
121+
at::Tensor RuntimeCacheHandle::serialize() const {
122+
auto const opts = at::TensorOptions().dtype(at::kByte);
123+
auto const empty = [&]() { return at::empty({0}, opts); };
124+
#ifdef TRT_MAJOR_RTX
125+
std::lock_guard<std::mutex> lock(state_mu_);
126+
if (!trt_handle_) {
127+
LOG_WARNING(
128+
"RuntimeCacheHandle::serialize() called before the IRuntimeCache was materialized; returning empty bytes.");
129+
return empty();
130+
}
131+
auto host_mem = make_trt(trt_handle_->serialize());
132+
TORCHTRT_CHECK(host_mem, "IRuntimeCache::serialize() returned null host memory; cannot serialize cache bytes.");
133+
auto tensor = at::empty({static_cast<int64_t>(host_mem->size())}, opts);
134+
std::memcpy(tensor.data_ptr(), host_mem->data(), host_mem->size());
135+
return tensor;
136+
#else
137+
LOG_WARNING("RuntimeCacheHandle::serialize() invoked on a non-RTX build; returning empty bytes.");
138+
return empty();
139+
#endif
140+
}
141+
142+
void RuntimeCacheHandle::deserialize(TORCHTRT_UNUSED at::Tensor data) {
143+
#ifdef TRT_MAJOR_RTX
144+
if (data.numel() == 0) {
145+
LOG_WARNING("RuntimeCacheHandle::deserialize() called with an empty tensor; nothing to load.");
146+
return;
147+
}
148+
auto contig = data.contiguous().to(at::kCPU);
149+
std::lock_guard<std::mutex> lock(state_mu_);
150+
if (trt_handle_) {
151+
// Live cache -- write through directly.
152+
trt_handle_->deserialize(contig.data_ptr(), static_cast<size_t>(contig.numel()));
153+
} else {
154+
// No live cache yet -- stash bytes for the next ``ensure_materialized``
155+
// call to drain. Fixes the cpp-rt warm-start path where ``wrapper.load()``
156+
// fires before any engine has materialized ``trt_handle_``.
157+
auto const* p = static_cast<uint8_t const*>(contig.data_ptr());
158+
pending_warm_bytes_.assign(p, p + contig.numel());
159+
}
160+
#else
161+
LOG_WARNING("RuntimeCacheHandle::deserialize() invoked on a non-RTX build; bytes ignored.");
162+
#endif
163+
}
164+
165+
bool RuntimeCacheHandle::has_cache() const {
166+
#ifdef TRT_MAJOR_RTX
167+
std::lock_guard<std::mutex> lock(state_mu_);
168+
return trt_handle_ != nullptr;
169+
#else
170+
return false;
171+
#endif
172+
}
173+
174+
#ifdef TRT_MAJOR_RTX
175+
std::shared_ptr<nvinfer1::IRuntimeCache> RuntimeCacheHandle::ensure_materialized(nvinfer1::IRuntimeConfig* config) {
176+
std::lock_guard<std::mutex> lock(state_mu_);
177+
if (!trt_handle_) {
178+
trt_handle_ = make_trt(config->createRuntimeCache());
179+
if (!trt_handle_) {
180+
return nullptr;
181+
}
182+
// Drain any bytes that ``deserialize`` stashed pre-materialization.
183+
// This is the cpp-rt warm-start path: ``load()`` fired before the first
184+
// ``ensure_materialized``, bytes parked in ``pending_warm_bytes_``,
185+
// first engine to ``ensure_materialized`` creates the cache and drains.
186+
if (!std::empty(pending_warm_bytes_)) {
187+
trt_handle_->deserialize(pending_warm_bytes_.data(), std::size(pending_warm_bytes_));
188+
pending_warm_bytes_.clear();
189+
pending_warm_bytes_.shrink_to_fit();
190+
LOG_DEBUG("Drained pending warm-start bytes into IRuntimeCache.");
191+
}
192+
}
193+
return trt_handle_;
194+
}
195+
#endif
196+
197+
// ---- RuntimeSettings methods ------------------------------------------------
198+
199+
bool RuntimeSettings::operator==(RuntimeSettings const& other) const noexcept {
200+
// ``runtime_cache`` compares by pointer identity: passing the same handle
201+
// twice through the settings setter is a no-op. Hoisted into locals because
202+
// ``std::tie`` requires lvalues.
203+
auto* this_cache = runtime_cache.get();
204+
auto* other_cache = other.runtime_cache.get();
205+
return std::tie(dynamic_shapes_kernel_specialization_strategy, cuda_graph_strategy, this_cache) ==
206+
std::tie(other.dynamic_shapes_kernel_specialization_strategy, other.cuda_graph_strategy, other_cache);
207+
}
208+
209+
std::string RuntimeSettings::to_str() const {
210+
std::ostringstream os;
211+
os << "RuntimeSettings{" << std::endl;
212+
os << " Dynamic Shapes Kernel Strategy: " << dynamic_shapes_kernel_specialization_strategy << std::endl;
213+
os << " CUDA Graph Strategy: " << cuda_graph_strategy << std::endl;
214+
if (runtime_cache) {
215+
auto const& p = runtime_cache->path;
216+
os << " Runtime Cache: " << (p.empty() ? "<in-memory shared>" : p) << std::endl;
217+
} else {
218+
os << " Runtime Cache: <engine-local, in-memory>" << std::endl;
219+
}
220+
os << "}";
221+
return os.str();
222+
}
223+
224+
std::ostream& operator<<(std::ostream& os, RuntimeSettings const& rs) {
225+
os << rs.to_str();
226+
return os;
227+
}
228+
229+
} // namespace runtime
230+
} // namespace core
231+
} // namespace torch_tensorrt

0 commit comments

Comments
 (0)