Environment
- Ryzen AI Software 1.7.1 (Windows), VitisAI ONNX Runtime EP
- Target: Phoenix (XDNA1), X1 backend, XINT8 quantization (via Quark,
enable_npu_cnn), static batch export (no dynamic_axes), opset 17
Problem
Exporting and quantizing a standard CNN (ResNet50, ImageNet) at a genuinely static batch size of 2 instead of 1 does not fail or throw when run through the VitisAI EP. Instead it silently produces a fragment of correct output and a fragment of stale, unwritten output, with nothing in the logs, the returned tensors, or the operator assignment report indicating which is which:
- The EP accepts only a fragment of the graph at batch 2: 80 of 395 nodes go to the NPU (vs. 393/395 at batch 1);
Conv itself falls entirely to CPU.
- The session builds and runs to completion, reporting a plausible-looking latency (71.6 ms/image — 12.6x the batch-1 per-image latency, not an obviously broken number in isolation).
- Batch slot 0's output is correct: 72.00% top-1, matching the batch-1 accuracy within noise.
- Every subsequent batch slot (slot 1 of 2 tested) is wrong in a specific way — not merely inaccurate, but numerically identical across every input image tested, regardless of what's actually in that slot. This is the signature of an unwritten or stale output buffer, not a miscomputation.
- A single pooled accuracy number across both slots (36.0%) looks like ordinary quantization degradation on its own and gives no indication that a slot is unwritten — this only becomes visible when accuracy is checked per batch-index rather than as an aggregate.
- Running the identical exported batch-2 model on
CPUExecutionProvider (same weights) produces correct results in both slots (76.0% top-1), confirming the model/export itself is fine and the failure is specific to the VitisAI EP's batch>1 handling on this backend.
Reproduction
- Export a standard CNN (e.g. torchvision/timm ResNet50) to ONNX with a genuinely static batch dimension of 2 (not
dynamic_axes), opset 17.
- Quantize XINT8 via Quark with
enable_npu_cnn enabled.
- Build a VitisAI EP session targeting PHX/HPT (X1 backend / XINT8) and run inference with a real batch of 2 different images.
- Compare per-slot outputs against a
CPUExecutionProvider run on the same weights and the same batch, split by batch index rather than pooled into a single accuracy number.
Impact
This is a silent correctness bug, not a silent fallback. It's a step worse than the already-known silent-CPU-fallback behavior on unsupported quantization configs (A8W8 falls back to CPU, which is at least numerically correct) — here the EP claims to run on-device, returns a tensor of the expected shape, and reports a plausible latency, while quietly leaving part of that tensor stale. A pooled accuracy metric can look like ordinary degradation rather than a hard failure, which is exactly the shape of bug that ships unnoticed.
Ask
Is static batch > 1 expected to be supported at all on the X1 (PHX/HPT INT8) backend? If not, the EP should refuse to build the session or throw at inference time rather than silently returning an unwritten buffer for batch slots beyond the first — an explicit error is a much safer failure mode than a plausible-looking wrong answer.
Environment
enable_npu_cnn), static batch export (nodynamic_axes), opset 17Problem
Exporting and quantizing a standard CNN (ResNet50, ImageNet) at a genuinely static batch size of 2 instead of 1 does not fail or throw when run through the VitisAI EP. Instead it silently produces a fragment of correct output and a fragment of stale, unwritten output, with nothing in the logs, the returned tensors, or the operator assignment report indicating which is which:
Convitself falls entirely to CPU.CPUExecutionProvider(same weights) produces correct results in both slots (76.0% top-1), confirming the model/export itself is fine and the failure is specific to the VitisAI EP's batch>1 handling on this backend.Reproduction
dynamic_axes), opset 17.enable_npu_cnnenabled.CPUExecutionProviderrun on the same weights and the same batch, split by batch index rather than pooled into a single accuracy number.Impact
This is a silent correctness bug, not a silent fallback. It's a step worse than the already-known silent-CPU-fallback behavior on unsupported quantization configs (A8W8 falls back to CPU, which is at least numerically correct) — here the EP claims to run on-device, returns a tensor of the expected shape, and reports a plausible latency, while quietly leaving part of that tensor stale. A pooled accuracy metric can look like ordinary degradation rather than a hard failure, which is exactly the shape of bug that ships unnoticed.
Ask
Is static batch > 1 expected to be supported at all on the X1 (PHX/HPT INT8) backend? If not, the EP should refuse to build the session or throw at inference time rather than silently returning an unwritten buffer for batch slots beyond the first — an explicit error is a much safer failure mode than a plausible-looking wrong answer.