Skip to content

Commit 2c9bed5

Browse files
authored
fix: make the packaged ExecuTorch reference runner run TensorRT delegated models (#4573)
1 parent 58c59a2 commit 2c9bed5

5 files changed

Lines changed: 114 additions & 2 deletions

File tree

.github/scripts/verify-executorch-reference-runner.sh

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,24 @@ if [[ -n "${extra_defs}" ]]; then
441441
exit 1
442442
fi
443443

444+
# ET_CHECK_MSG and ET_LOG hand their text to the core archive's vlogf, so an
445+
# archive compiled with logging off turns every runtime failure in the packaged
446+
# runner into a bare exit code with no output at all. Prove the runner can still
447+
# say why it failed, on a path that needs neither a GPU nor a valid model.
448+
diagnostic_log="${verify_root}/packaged_runner_diagnostic.log"
449+
if "${packaged_runner}" \
450+
--model_path="${verify_root}/no-such-model.pte" >"${diagnostic_log}" 2>&1; then
451+
echo "Packaged runner exited 0 on a missing model file" >&2
452+
exit 1
453+
fi
454+
if ! grep -q "FileDataLoader::from" "${diagnostic_log}"; then
455+
echo "Packaged runner gave no diagnostic for a missing model file." >&2
456+
echo "ET_LOG_ENABLED likely disagrees between libexecutorch_core.a and the" >&2
457+
echo "Bazel targets that call into it. Output was:" >&2
458+
cat "${diagnostic_log}" >&2
459+
exit 1
460+
fi
461+
444462
"${runner_path}" \
445463
--model_path="${model_path}" \
446464
--num_runs=1 2>&1 | tee "${runner_log}"
@@ -454,9 +472,19 @@ packaged_runner_log="${verify_root}/packaged_runner.log"
454472
# Assert both precisely. Matching only "shape=" accepts any shape, and matching one
455473
# 2.0000 anywhere on the values line accepts a line of wrong numbers that happens to
456474
# contain one right one, so neither catches a stream-ordering regression returning
457-
# stale or partial output. ET_LOG output is not part of the packaged runner contract
458-
# and may be compiled out, so nothing here depends on it.
475+
# stale or partial output. Both lines come from fprintf in the runner, so these
476+
# assertions hold whatever ET_LOG_ENABLED is set to.
459477
for _log in "${runner_log}" "${packaged_runner_log}"; do
478+
# A right answer produced entirely on the host would not prove much here: the
479+
# program is delegated to TensorRT, so at least one planned buffer has to be
480+
# served by a registered CUDA DeviceAllocator. Pin that, otherwise a model or
481+
# a planning change could quietly turn this into a CPU-only test.
482+
if ! grep -q 'planned buffer\[[0-9]*\] = [0-9]* bytes on device_type 1' "${_log}"; then
483+
echo "No CUDA planned buffer was allocated in ${_log}:" >&2
484+
grep 'planned buffer' "${_log}" >&2 || echo " no planned buffer line at all" >&2
485+
exit 1
486+
fi
487+
460488
if ! grep -q 'output\[0\] shape=\[2,3,4,4\]' "${_log}"; then
461489
echo "Unexpected output shape in ${_log}:" >&2
462490
grep 'output\[0\] shape=' "${_log}" >&2 || echo " no shape line at all" >&2

cpp/BUILD

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,37 @@ cc_library(
141141
],
142142
)
143143

144+
# Registration only, kept out of :tensorrt_executorch_backend so that linking
145+
# the backend into both a shared library and an executable cannot register the
146+
# allocator twice. Executables that run a TensorRT delegated program depend on
147+
# this directly.
148+
#
149+
# Not part of :executorch_backend_source_files. The CMake build of the reference
150+
# runner enables the CUDA/AOTI delegate, which already registers this allocator.
151+
cc_library(
152+
name = "tensorrt_executorch_cuda_device_allocator",
153+
srcs = [
154+
"src/torch_tensorrt/executorch/RegisterCudaDeviceAllocator.cpp",
155+
],
156+
alwayslink = True,
157+
target_compatible_with = select({
158+
":linux_x86_64": [],
159+
":sbsa": [],
160+
"//conditions:default": ["@platforms//:incompatible"],
161+
}),
162+
deps = select({
163+
":linux_x86_64": [
164+
"@executorch//:executorch_cuda_allocator",
165+
"@executorch//:executorch_headers",
166+
],
167+
":sbsa": [
168+
"@executorch//:executorch_cuda_allocator",
169+
"@executorch//:executorch_headers",
170+
],
171+
"//conditions:default": [],
172+
}),
173+
)
174+
144175
cc_library(
145176
name = "tensorrt_executorch_backend",
146177
srcs = [
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <executorch/backends/cuda/runtime/cuda_allocator.h>
2+
#include <executorch/runtime/core/device_allocator.h>
3+
4+
namespace {
5+
6+
// A program delegated to TensorRT still asks the ExecuTorch runtime for its
7+
// device planned buffers, and the runtime can only serve those once something
8+
// has registered a CUDA DeviceAllocator. The pinned ExecuTorch release does
9+
// that from inside the CUDA/AOTI delegate, which an application that delegates
10+
// to TensorRT alone has no reason to link. Register it here instead.
11+
//
12+
// Deliberately unguarded. If the CUDA/AOTI delegate is ever linked into the
13+
// same binary it registers the same singleton a second time, and the registry
14+
// is meant to abort on that rather than silently pick one.
15+
[[maybe_unused]] const bool cuda_device_allocator_registered = [] {
16+
executorch::runtime::register_device_allocator(&executorch::backends::cuda::CudaAllocator::instance());
17+
return true;
18+
}();
19+
20+
} // namespace

examples/executorch_reference_runner/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ cc_binary(
2525
],
2626
deps = [
2727
"//cpp:tensorrt_executorch_backend",
28+
"//cpp:tensorrt_executorch_cuda_device_allocator",
2829
"@executorch//:executorch_core",
2930
"@executorch//:executorch_file_data_loader",
3031
"@executorch//:extension_cuda",
@@ -36,6 +37,7 @@ cc_binary(
3637
srcs = ["kv_cache_decode_check.cpp"],
3738
deps = [
3839
"//cpp:tensorrt_executorch_backend",
40+
"//cpp:tensorrt_executorch_cuda_device_allocator",
3941
"@cuda//:cudart",
4042
"@executorch//:executorch_core",
4143
"@executorch//:executorch_file_data_loader",

third_party/executorch/BUILD

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ filegroup(
1919
),
2020
)
2121

22+
# EXECUTORCH_ENABLE_LOGGING is pinned rather than left to follow
23+
# CMAKE_BUILD_TYPE. Its default is off in Release, which compiles the archive
24+
# with ET_LOG_ENABLED=0, but that is a CMake compile definition and
25+
# rules_foreign_cc harvests only the .a, so the Bazel targets that call into it
26+
# keep runtime/platform/log.h's default of 1. logf is an inline function whose
27+
# body is guarded by that macro, so the two halves disagree on its definition
28+
# and every ET_LOG and ET_CHECK_MSG message reaches an empty vlogf. A runner
29+
# built that way dies without saying why.
2230
cmake(
2331
name = "executorch_core",
2432
cache_entries = {
@@ -31,6 +39,7 @@ cmake(
3139
"EXECUTORCH_BUILD_EXTENSION_MODULE": "ON",
3240
"EXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP": "ON",
3341
"EXECUTORCH_BUILD_PYBIND": "OFF",
42+
"EXECUTORCH_ENABLE_LOGGING": "ON",
3443
},
3544
install = False,
3645
lib_source = ":executorch_sources",
@@ -116,6 +125,28 @@ cc_library(
116125
],
117126
)
118127

128+
# The CUDA DeviceAllocator that serves device planned buffers. In the pinned
129+
# ExecuTorch release this source is compiled only into the CUDA/AOTI delegate,
130+
# so a binary that delegates to TensorRT alone cannot get one without linking a
131+
# delegate it never calls. Compile it on its own instead. It has no delegate
132+
# dependencies: cuda_runtime.h, the caller-stream header already in
133+
# libextension_cuda.so, and the ExecuTorch runtime headers.
134+
#
135+
# This target names a path that goes away when the allocator stops living under
136+
# backends/cuda upstream, so the pin cannot move forward while it is still here.
137+
cc_library(
138+
name = "executorch_cuda_allocator",
139+
srcs = ["executorch/backends/cuda/runtime/cuda_allocator.cpp"],
140+
hdrs = ["executorch/backends/cuda/runtime/cuda_allocator.h"],
141+
include_prefix = "executorch",
142+
strip_include_prefix = "executorch",
143+
deps = [
144+
":executorch_headers",
145+
":extension_cuda",
146+
"@cuda//:cudart",
147+
],
148+
)
149+
119150
cc_library(
120151
name = "executorch_headers",
121152
hdrs = glob(

0 commit comments

Comments
 (0)