Skip to content

Commit 1fa8c82

Browse files
committed
test: consolidate C++ runtime tests, add model-level coverage
Address PR review comments that asked the new C++ runtime tests be folded into existing feature-level files rather than shipped as parallel `*_cpp.py` files. What - Merge `test_000_runtime_cache_cpp.py` into the existing `test_000_runtime_cache.py`. The file already covered the Python runtime path; two new classes (`TestRuntimeCacheCppPersistence`, `TestCppSerializationIndices`) cover the C++ runtime path via `use_python_runtime=False`, and the serialization-index assertions. Skip on non-RTX builds. - Fold the C++ runtime cases for dynamic shapes kernel specialization strategy into `test_001_dynamic_shapes_kernel_ strategy.py` (introduced upstream in PR pytorch#4184). Two new classes (`TestDynamicShapesKernelStrategyCpp`, `TestDynamicShapesKernel StrategyCppInvalidValue`) exercise lazy/eager/none end-to-end and reject invalid strategy names. The pre-existing Python runtime tests remain untouched. - Rename `test_000_cuda_graph_strategy.py` to `test_001_cuda_graph_ strategy.py` to match the `test_001_*` convention used for L1 RTX-only features. When upstream lands the Python runtime counterpart (PR pytorch#4187), both sets fold into the same file. - Add model-level tests: `test_runtime_cache_models.py` gains a `TestRuntimeCacheCppModels` class exercising ResNet18 through the C++ runtime with warm-cache roundtrip. `test_dynamic_shapes_ kernel_strategy_models.py` gains `TestDynamicShapesKernelStrategy CppModels` covering lazy/eager/none on ResNet18 via the C++ runtime. Verified - 35 passed / 3 skipped in the runtime/ tests (merged file plus test_001 strategy files). - No regression in test_002_cudagraphs_cpp.py (8 passed) or test_005_dynamic_allocation.py (1 passed). Addresses PR pytorch#4202 review comments asking for test file merges and the addition of model-level runtime_cache_models.py / dynamic_shapes_kernel_strategy_models.py coverage.
1 parent 54f9ccd commit 1fa8c82

6 files changed

Lines changed: 390 additions & 279 deletions

tests/py/dynamo/models/test_dynamic_shapes_kernel_strategy_models.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,5 +129,69 @@ def test_dynamic_batch_none(self):
129129
self._test_dynamic_batch_with_strategy("none")
130130

131131

132+
@unittest.skipIf(
133+
not ENABLED_FEATURES.torch_tensorrt_runtime,
134+
"C++ runtime is not available",
135+
)
136+
@unittest.skipIf(
137+
not ENABLED_FEATURES.tensorrt_rtx,
138+
"Dynamic shapes kernel specialization strategy requires TensorRT-RTX",
139+
)
140+
@unittest.skipIf(
141+
not importlib.util.find_spec("torchvision"),
142+
"torchvision is not installed",
143+
)
144+
class TestDynamicShapesKernelStrategyCppModels(TestCase):
145+
"""End-to-end model tests with each strategy exercised through the C++ runtime."""
146+
147+
def tearDown(self):
148+
torch._dynamo.reset()
149+
150+
def _compile_and_verify_cpp(self, model, strategy):
151+
input_tensor = torch.randn(4, 3, 224, 224).cuda()
152+
compiled = torchtrt.compile(
153+
model,
154+
ir="dynamo",
155+
inputs=[
156+
torchtrt.Input(
157+
min_shape=(1, 3, 224, 224),
158+
opt_shape=(4, 3, 224, 224),
159+
max_shape=(8, 3, 224, 224),
160+
dtype=torch.float32,
161+
)
162+
],
163+
enabled_precisions={torch.float32},
164+
use_python_runtime=False,
165+
min_block_size=1,
166+
dynamic_shapes_kernel_specialization_strategy=strategy,
167+
)
168+
ref_output = model(input_tensor)
169+
trt_output = compiled(input_tensor)
170+
cos_sim = cosine_similarity(ref_output, trt_output)
171+
self.assertTrue(
172+
cos_sim > COSINE_THRESHOLD,
173+
f"C++ runtime cosine similarity {cos_sim} below threshold {COSINE_THRESHOLD} "
174+
f"with strategy={strategy}",
175+
)
176+
177+
def test_resnet18_lazy_strategy_cpp(self):
178+
import torchvision.models as models
179+
180+
model = models.resnet18(pretrained=True).eval().cuda()
181+
self._compile_and_verify_cpp(model, "lazy")
182+
183+
def test_resnet18_eager_strategy_cpp(self):
184+
import torchvision.models as models
185+
186+
model = models.resnet18(pretrained=True).eval().cuda()
187+
self._compile_and_verify_cpp(model, "eager")
188+
189+
def test_resnet18_none_strategy_cpp(self):
190+
import torchvision.models as models
191+
192+
model = models.resnet18(pretrained=True).eval().cuda()
193+
self._compile_and_verify_cpp(model, "none")
194+
195+
132196
if __name__ == "__main__":
133197
run_tests()

tests/py/dynamo/models/test_runtime_cache_models.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,5 +325,96 @@ def forward(self, x):
325325
self.assertTrue(True, "Timing test completed (informational)")
326326

327327

328+
@unittest.skipIf(
329+
not ENABLED_FEATURES.torch_tensorrt_runtime,
330+
"C++ runtime is not available",
331+
)
332+
@unittest.skipIf(
333+
not ENABLED_FEATURES.tensorrt_rtx,
334+
"Runtime cache is only available with TensorRT-RTX",
335+
)
336+
@unittest.skipIf(
337+
not importlib.util.find_spec("torchvision"),
338+
"torchvision is not installed",
339+
)
340+
class TestRuntimeCacheCppModels(TestCase):
341+
"""End-to-end model tests with runtime cache exercised through the C++ runtime."""
342+
343+
def setUp(self):
344+
self.cache_dir = tempfile.mkdtemp()
345+
self.cache_path = os.path.join(self.cache_dir, "runtime_cache.bin")
346+
347+
def tearDown(self):
348+
shutil.rmtree(self.cache_dir, ignore_errors=True)
349+
torch._dynamo.reset()
350+
351+
def test_resnet18_with_runtime_cache_cpp(self):
352+
import torchvision.models as models
353+
354+
model = models.resnet18(pretrained=True).eval().cuda()
355+
input_tensor = torch.randn(1, 3, 224, 224).cuda()
356+
357+
compiled = torchtrt.compile(
358+
model,
359+
ir="dynamo",
360+
inputs=[torchtrt.Input(input_tensor.shape, dtype=torch.float32)],
361+
enabled_precisions={torch.float32},
362+
use_python_runtime=False,
363+
min_block_size=1,
364+
runtime_cache_path=self.cache_path,
365+
)
366+
367+
ref_output = model(input_tensor)
368+
trt_output = compiled(input_tensor)
369+
370+
cos_sim = cosine_similarity(ref_output, trt_output)
371+
self.assertTrue(
372+
cos_sim > COSINE_THRESHOLD,
373+
f"ResNet18 C++ runtime cosine similarity {cos_sim} below threshold {COSINE_THRESHOLD}",
374+
)
375+
376+
# Verify the runtime cache is persisted on engine destruction.
377+
del compiled
378+
gc.collect()
379+
self.assertTrue(
380+
os.path.isfile(self.cache_path),
381+
"Runtime cache should be saved after ResNet18 C++-runtime inference",
382+
)
383+
384+
def test_resnet18_cache_reuse_cpp(self):
385+
"""Warm-cache second compile should match eager output."""
386+
import torchvision.models as models
387+
388+
model = models.resnet18(pretrained=True).eval().cuda()
389+
input_tensor = torch.randn(1, 3, 224, 224).cuda()
390+
ref_output = model(input_tensor)
391+
392+
compile_kwargs = {
393+
"ir": "dynamo",
394+
"inputs": [torchtrt.Input(input_tensor.shape, dtype=torch.float32)],
395+
"enabled_precisions": {torch.float32},
396+
"use_python_runtime": False,
397+
"min_block_size": 1,
398+
"runtime_cache_path": self.cache_path,
399+
}
400+
401+
compiled1 = torchtrt.compile(model, **compile_kwargs)
402+
out1 = compiled1(input_tensor)
403+
self.assertTrue(
404+
cosine_similarity(ref_output, out1) > COSINE_THRESHOLD,
405+
"First ResNet18 C++-runtime output should match eager",
406+
)
407+
del compiled1
408+
gc.collect()
409+
self.assertTrue(os.path.isfile(self.cache_path))
410+
411+
compiled2 = torchtrt.compile(model, **compile_kwargs)
412+
out2 = compiled2(input_tensor)
413+
self.assertTrue(
414+
cosine_similarity(ref_output, out2) > COSINE_THRESHOLD,
415+
"Second ResNet18 C++-runtime output (warm cache) should match eager",
416+
)
417+
418+
328419
if __name__ == "__main__":
329420
run_tests()

tests/py/dynamo/runtime/test_000_dynamic_shapes_kernel_strategy.py

Lines changed: 0 additions & 133 deletions
This file was deleted.

0 commit comments

Comments
 (0)