Problem – TensorRT Batch Inference Times Out Under High Concurrency
In a production GPU inference service the following symptoms appear when the request rate spikes:
- Requests that submit a batched input to
IExecutionContext::enqueueV2return false after ~10 s. - Server logs contain messages such as:
[ERROR] Failed to enqueue inference: Timeout while waiting for GPU
[TensorRT] Execution context timed out after 10000 ms
CUDA driver error: CUDA_ERROR_LAUNCH_TIMEOUT
- GPU utilization plateaus at ~90 % and
nvidia-smishowsGPU-Utilstuck at 99 % while the driver resets the device. - On Windows the Event Viewer records “CUDA driver timeout: kernel execution took too long”.
The issue only manifests when the number of simultaneous inference streams exceeds ~30 or when the per‑batch size is increased beyond the previously stable value (e.g., from 64 to 256).
Root Cause – Interaction of Watchdog Timers, Stream Saturation, and Asynchronous Execution
TensorRT’s asynchronous execution model (see the Developer Guide – Asynchronous Execution) relies on CUDA streams to overlap kernel launches and data transfers. Two independent mechanisms can abort a kernel:
- CUDA watchdog timer – On Windows the WDDM driver enforces a 2 s execution limit per kernel launch (CUDA_ERROR_LAUNCH_TIMEOUT). When a single batch or a collection of concurrent kernels exceeds this window the driver aborts the launch, resets the GPU, and returns the error observed.
- TensorRT internal timeout – The execution context tracks the elapsed time from the moment
enqueueV2is called until the completion callback fires. If the elapsed time exceeds the value configured bysetTimingCacheor the default 10 s, TensorRT logs “Execution context timed out after X ms” and returnsfalse.
High concurrency amplifies both effects:
- Each request creates its own CUDA stream. When >30 streams are active the driver’s scheduler cannot guarantee that every kernel finishes within the watchdog window, especially for large batch sizes that increase kernel runtime (see the Performance Guide – Batch Size).
- TensorRT’s default stream priority is
0. Without explicit stream management, kernels compete for the same hardware resources, causing longer queuing delays that push execution past the watchdog limit.
Therefore the timeout is not a “configuration mistake” per se; it is the result of exceeding the runtime guarantees of the underlying driver under a workload that scales both batch size and concurrency.
Debug – Systematic Investigation Steps
1. Capture Immediate Symptoms
$ journalctl -u inference-service -f
[2026-07-11 14:32:07] INFO Enqueue batch id=1024 size=256
[2026-07-11 14:32:07] ERROR Failed to enqueue inference: Timeout while waiting for GPU
[2026-07-11 14:32:07] TensorRT: Execution context timed out after 10000 ms
2. Verify Driver‑Level Timeout
On Windows, check the Event Viewer for CUDA driver timeout. On Linux, inspect dmesg for “GPU reset” entries.
$ dmesg | grep -i reset
[ 12345.678901] NVRM: GPU at PCI:0000:65:00.0: Resetting GPU due to timeout
3. Profile Kernel Execution Time
Use nvprof or Nsight Systems to measure the longest kernel in a batch.
$ nvprof --profile-from-start off -f -o profile.nvvp ./inference_server
# After reproducing the failure:
$ nsys stats profile.nvvp | grep kernel
kernel_name avg(ms) min(ms) max(ms)
__launch_bounds__... 1850 1800 2100
If the max exceeds 2000 ms, the watchdog on WDDM will definitely trigger.
4. Inspect Stream Usage
$ cat /proc/$(pidof inference_server)/fdinfo/* | grep -i stream
Alternatively, instrument the code to log the number of active streams at enqueue time.
5. Review TensorRT Context Settings
IExecutionContext* ctx = engine->createExecutionContext();
bool ok = ctx->setTimingCache(timingCache, false);
if (!ok) { LOG_ERROR("Failed to set timing cache"); }
If setTimingCache is never called, the default 10 s timeout applies.
Solution – Architectural and Configuration Adjustments
1. Move to TCC Driver (Linux) or Use Dedicated Compute Mode (Windows)
On Windows, switch from the default WDDM driver to the TCC (Tesla Compute Cluster) driver, which disables the 2 s watchdog. This requires a GPU that supports TCC (e.g., Tesla, RTX A-series).
# Check current mode
nvidia-smi -q | grep "Compute Mode"
# Set to TCC
nvidia-smi -dm 1
2. Limit Concurrency per GPU
Introduce a semaphore that caps the number of simultaneous streams to a safe threshold (e.g., 24).
// Before enqueue
static std::counting_semaphore<24> gpu_sem;
gpu_sem.acquire();
std::thread([&, request]{
// ...prepare input...
bool ok = context->enqueueV2(buffers, stream, nullptr);
if (!ok) { LOG_ERROR("Enqueue failed"); }
// ...post‑process...
gpu_sem.release();
}).detach();
3. Reduce Per‑Batch Size or Split Large Batches
Empirically determine the batch size that keeps the longest kernel < 1.8 s. For a model that scales linearly, a size of 128 may be safe.
4. Prioritize Streams and Use Explicit Synchronization
Assign higher priority to latency‑critical streams.
cudaStream_t high_pri_stream;
cudaStreamCreateWithPriority(&high_pri_stream, cudaStreamNonBlocking, -1); // -1 = highest priority
bool ok = context->enqueueV2(buffers, high_pri_stream, nullptr);
Ensure callbacks are cleared to avoid dead‑locks (see the “dead‑locks when async callbacks were not cleared” incident).
5. Extend TensorRT Timeout (if driver timeout is already mitigated)
If the GPU driver no longer aborts kernels, increase the internal timeout:
context->setTimingCache(timingCache, false); // reuse cache
context->setProfiler(&myProfiler); // optional
// No direct API to change timeout, but you can wrap enqueue in a larger host‑side timeout.
Before / After Comparison
| Aspect | Before | After |
|---|---|---|
| Driver mode | WDDM (2 s watchdog) | TCC (no watchdog) |
| Max concurrent streams | Unlimited (≈40) | 24 (semaphore‑limited) |
| Batch size | 256 | 128 (or dynamic split) |
| Stream priority | Default (0) | High‑priority for latency paths |
| Timeout observed | CUDA_ERROR_LAUNCH_TIMEOUT | Successful completion, latency ~1.5 s |
Verification – Confirming the Fix
- Re‑run a load test with
wrkor a custom client that opens 40 parallel connections. - Monitor
nvidia-smifor GPU reset events; there should be none. - Check server logs for the absence of “Failed to enqueue inference” messages.
- Collect a new
nvprofrun; the longest kernel should stay < 1900 ms. - Validate end‑to‑end latency meets SLA (e.g., 95th percentile < 2 s).
Prevention – Operational Guardrails
- Capacity planning: Use the TensorRT Performance Guide to benchmark kernel runtime versus batch size on the target GPU.
- Watchdog awareness: On Windows, enforce TCC mode for any production inference workload.
- Dynamic throttling: Implement a back‑pressure mechanism that reduces batch size or stalls new requests when
gpu_semcannot be acquired. - Metrics & alerts: Emit a Prometheus metric
inference_enqueue_timeout_totaland alert if it spikes. - Stream hygiene: Always destroy streams and clear callbacks after each request to avoid resource leaks.
Related Topic Hub: Model Serving Troubleshooting Hub
FAQ
Q1: Why does the timeout only appear after increasing the batch size?
A1: Larger batches increase the compute workload per kernel, lengthening execution time. When the kernel runtime exceeds the driver’s watchdog limit (2 s on WDDM) the GPU is reset, producing
CUDA_ERROR_LAUNCH_TIMEOUT.
Q2: Can I keep using WDDM and still avoid timeouts?
A2: Only if you guarantee that every kernel finishes < 2 s. This usually requires aggressive batch‑size limits and strict concurrency caps, which may hurt throughput. Switching to TCC is the recommended production approach.
Q3: Does setting
IExecutionContext::setTimingCachechange the watchdog behavior?A3: No. The timing cache only affects TensorRT’s internal profiling. The watchdog is enforced by the CUDA driver, independent of TensorRT settings.
Q4: How can I detect that the GPU watchdog is the culprit without looking at driver logs?
A4: When
enqueueV2returns false and the log contains “CUDA_ERROR_LAUNCH_TIMEOUT”, the error originates from the driver. A concurrentdmesgor Windows Event Viewer entry confirming a GPU reset further corroborates this.
Q5: Is there a way to increase the watchdog timeout on Windows?
A5: The WDDM watchdog timeout is fixed (≈2 s) and cannot be configured. The only supported method to bypass it is to switch the GPU to TCC mode, which removes the watchdog entirely.