(monkeypatch)
| 270 | |
| 271 | |
| 272 | def test_tensorrt_int8_calibration(monkeypatch): |
| 273 | # INT8 calibration path: the first N runs feed calibration batches, then the INT8 engine is |
| 274 | # built and run. Validates that the calibrator copies a full batch (batch_size * per-sample |
| 275 | # elements) without over-reading the input or over-writing the device buffers, which previously |
| 276 | # crashed for batch > 1. |
| 277 | @tvm.script.ir_module |
| 278 | class Conv2dInt8: |
| 279 | @R.function |
| 280 | def main( |
| 281 | data: R.Tensor((2, 8, 16, 16), "float32"), weight: R.Tensor((4, 8, 3, 3), "float32") |
| 282 | ): |
| 283 | with R.dataflow(): |
| 284 | out = relax.op.nn.conv2d(data, weight, padding=1) |
| 285 | R.output(out) |
| 286 | return out |
| 287 | |
| 288 | data = np.random.randn(2, 8, 16, 16).astype("float32") |
| 289 | weight = np.random.randn(4, 8, 3, 3).astype("float32") |
| 290 | ref = build_and_run(Conv2dInt8, [data, weight], "llvm", legalize=True) |
| 291 | |
| 292 | patterns = [("tensorrt.nn.conv2d", is_op("relax.nn.conv2d")(wildcard(), wildcard()))] |
| 293 | offloaded = tvm.transform.Sequential( |
| 294 | [ |
| 295 | relax.transform.BindParams("main", {"weight": weight}), |
| 296 | relax.transform.FuseOpsByPattern(patterns), |
| 297 | relax.transform.MergeCompositeFunctions(), |
| 298 | relax.transform.RunCodegen(), |
| 299 | ] |
| 300 | )(Conv2dInt8) |
| 301 | |
| 302 | num_calibration_batches = 2 |
| 303 | monkeypatch.setenv("TVM_TENSORRT_USE_INT8", "1") |
| 304 | monkeypatch.setenv("TENSORRT_NUM_CALI_INT8", str(num_calibration_batches)) |
| 305 | |
| 306 | dev = tvm.device("cuda", 0) |
| 307 | vm = relax.VirtualMachine(tvm.compile(offloaded, "cuda"), dev) |
| 308 | data_trt = tvm.runtime.tensor(data, dev) |
| 309 | out = None |
| 310 | for _ in range(num_calibration_batches + 1): |
| 311 | out = vm["main"](data_trt).numpy() |
| 312 | |
| 313 | assert np.isfinite(out).all() |
| 314 | # INT8 is lossy, so use a generous tolerance; the key assertion is that calibration completed |
| 315 | # without a CUDA error. |
| 316 | tvm.testing.assert_allclose(out, ref, rtol=0.2, atol=0.1 * float(np.abs(ref).max())) |
| 317 | |
| 318 | |
| 319 | if __name__ == "__main__": |
nothing calls this directly
no test coverage detected
searching dependent graphs…