Repository navigation
Exclude Sigmoid from TensorRT INT8 quantization - #25020
glenn-jocher merged 8 commits into
Conversation
|
All Contributors have signed the CLA. ✅ |
|
👋 Hello @davidnichols-ops, thank you for submitting a
For more guidance, please refer to our Contributing Guide. Don't hesitate to leave a comment if you have any questions. Thank you for contributing to Ultralytics! 🚀 |
UltralyticsAssistant
left a comment
There was a problem hiding this comment.
🔍 PR Review
Made with ❤️ by Ultralytics Actions
Found two actionable issues: a misleading exporter warning when end2end is left as the default None, and a likely failure path for fused end-to-end models with end2end=False due to the one-to-one-head selection guard.
💬 Posted 2 inline comments
Y-T-G
left a comment
There was a problem hiding this comment.
Thanks for the PR.
Can this be resolved with Fix 2 and Fix 3 alone?
Fix 1 and Fix 4 are regressive. Fix 4 defeats the point of end2end=False.
The PR is also too large and verbose for a fix. Please scope it and reduce verbosity.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
@Y-T-G Yes — the PR now contains only Fix 2 and Fix 3. Fix 1 (exporter warning for The squashed commit (
No changes to |
Latest changes — what I found and fixedWhile testing the Softmax generalization, I ran into a few issues with the TRT 10 path and the test suite. Here's what happened and how I dealt with each: 1. Softmax wasn't actually being preserved on TRT 10 (real bug) In TensorRT, Softmax is a separate Fixed by adding an explicit softmax_type = getattr(trt.LayerType, "SOFTMAX", None)
...
if layer.type == trt.LayerType.ACTIVATION and _is_precision_sensitive_activation(layer, trt):
# constrain Sigmoid activations
elif softmax_type is not None and layer.type == softmax_type:
# constrain Softmax layersThe execution test now includes a Softmax layer with 2. The call-site test wasn't actually testing the call site The old
3. Comment said FP32, but it's actually FP16 The comment on the ModelOpt path said excluded nonlinearities "run in FP32 on dequantized logits," but ModelOpt defaults to 4. Test could trigger a network install The ModelOpt test was calling 5. Removed a test that's no longer relevant Dropped 6. OpenVINO parity test — kept as-is The OpenVINO test uses source inspection (searching the wrapped function's source for Verification: |
|
Thanks, this rescope addresses the original concern and the TRT 10 Softmax branch/test coverage makes sense. One remaining cleanup to keep the PR minimal: please drop the standalone |
YOLO26's one-to-one detection head produces moderate logits (0-3) in the sigmoid's steep region, making confidence scores sensitive to INT8 quantization error. Exclude precision-sensitive nonlinearities (Sigmoid, Softmax) from INT8 quantization to preserve score calibration, mirroring the OpenVINO INT8 exporter's IgnoredScope(types=["Sigmoid"]). TRT 11+ (ModelOpt Q/DQ path): Pass op_types_to_exclude=["Sigmoid", "Softmax"] to modelopt.quantize() so the nonlinearities run in FP32 on dequantized inputs. TRT 10 (implicit quantization path): Force Sigmoid/Softmax activation layers to FP32 via setPrecision / setOutputType + OBEY_PRECISION_CONSTRAINTS. Detection uses a typed IActivationLayer cast first (TRT 10.3-), falling back to layer name matching (TRT 10.7+ bindings don't expose activation_type on ILayer. T4 GPU validation (TensorRT 10.7, full COCO val, 500 cal images): YOLO26s INT8 retains 92.9% mAP50 / 91.5% mAP50-95 vs FP16 YOLO11s INT8 retains 98.0% mAP50 / 97.2% mAP50-95 vs FP16 (no regression) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> EOF )
|
Done — dropped
Benchmark/reproduction details remain in the PR description (collapsed sections) and the Kaggle kernel link. |
|
Thanks, that cleanup is exactly what I was looking for. With the benchmark script removed, the PR is now focused on the TensorRT INT8 precision handling plus tests/docs; we can proceed with the normal CI/review path from here. |
|
Thanks, Glenn. I appreciate the feedback. I’ll leave it as-is and wait for CI approval and the normal review process! |
Sigmoid/Softmax from TensorRT INT8 quantization
…ns_fp32` docstring Fixes failing Publish Docs CI check on PR #25020, which requires every parameter to have a type in the signature or `(type)` in the docstring Args section. `network`, `config`, `trt`, and `prefix` were untyped. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I have updated the PR to include the requested type annotations in _constrain_sensitive_activations_fp32 to resolve the documentation CI gap. |
|
Thanks, the type annotations on |
Fold the TRT 10 FP32 constraint loop into the existing INT8 calibrator branch, drop the speculative IActivationLayer cast (not constructible in TRT 10 Python bindings; name matching is what ran in the T4 validation), and inline the op list at both call sites. Deleted: _FP32_PRESERVED_ACTIVATIONS, _FP32_PRESERVED_OPS, _is_precision_sensitive_activation, _is_sensitive_by_name, _constrain_sensitive_activations_fp32, four mock-heavy tests (call-site, execution, binding-branches, OpenVINO source inspection), and the YOLO26 docs subsection referencing private constants.
|
Thanks @davidnichols-ops, the diagnosis and T4 validation here are excellent and the approach (mirroring OpenVINO's I've pushed a simplification to your branch that preserves the validated behavior while reducing the diff to +35/−4:
|
|
Should this be |
|
Good question — I looked into this, and I don’t think w8a32 applies directly to this particular path. From what I found, ModelOpt’s ONNX quantization flow does not currently expose a weight-only mode. The available modes are INT8 static, INT4, and FP8. For the INT8 path this PR is using, excluded ops are kept in The TRT 10 path also seems limited here since it uses activation + weight INT8 through I also ran a quick T4 comparison using ONNX Runtime Since ModelOpt doesn’t currently expose a weight-only mode, would it be worth considering whether an ONNX Runtime-based weight-only path is something worth exploring, or would the added complexity outweigh the accuracy benefit compared with the current ModelOpt/TensorRT approach? I can share the benchmark details if useful. Conclusion for this PR: I would keep the existing |
|
Agreed — let’s keep this PR on the current TensorRT |
glenn-jocher
left a comment
There was a problem hiding this comment.
LGTM. The final patch is scoped to the validated Sigmoid issue, removes the speculative Softmax policy and silent compatibility guard, covers TensorRT 7–11 through the correct APIs, includes the 8.4.91 patch bump, and is green across the full final-head CI matrix.
Sigmoid/Softmax from TensorRT INT8 quantizationSigmoid from TensorRT INT8 quantization
|
Thank you Glenn for the help in getting this to the finish line. Nothing like green CI's in realtime. |
|
Thanks @davidnichols-ops — your careful diagnosis, T4 validation, and responsive cleanup made this a strong community contribution. Glad we got it merged with green CI! |
|
Thanks Glenn — appreciate the kind words. It was a great review process,
and it was rewarding digging into the issue, validating the behavior on T4,
and getting the fix into a clean state. Looking forward to contributing
more.
… Message ID: ***@***.***>
|
|
Thanks again @davidnichols-ops—the careful validation and focused iteration benefited the whole YOLO community. We appreciate the contribution and look forward to your future PRs. |
…ics#25020) Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Ultralytics Assistant <[email protected]> Co-authored-by: Glenn Jocher <[email protected]>
Softmax was intentionally left quantized in #25020 (its docs describe Sigmoid-only exclusion); restore that behavior. This reverts commit 2aab46546b0b1a93e40a81f828e7b72b34d45fc1.
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Ultralytics Assistant <[email protected]> Co-authored-by: Glenn Jocher <[email protected]>
- Restore region-shape ObjectCounter polygon direction so one lane never splits IN/OUT (#25104) - Plot per-frame counts in Analytics line charts, not 30-frame sums (#25567) - Read gray-palette semantic masks as gray-level class ids (#26426) - Use args.conf for confusion matrices again (#25677, reverting #25320's fix) - Stop deleting classify splits on every run, which wiped cache=disk files (#26423) - Keep segment and semantic label caches from invalidating each other (#26207) - Ignore *.yml files so they never shadow data.yaml (#26323) - Skip the OS font rescan that costs 8s on macOS (#26256) - Stop the false slow-access warning on tiny-file datasets (#25025) - Scope TensorRT INT8 FP32 layers to the head for nms=True exports (#25020) - Follow kpt_shape in RKNN and LiteRT pose keypoint scaling, skip RT-DETR in RKNN INT8 normalization (#25524) - Document the shared dataset cache version - Delete mock tests (#25106, #25720, #25875)
Summary
YOLO26's one-to-one detection head produces moderate logits in Sigmoid's steep region, where INT8 quantization error compresses confidence scores and degrades F1 calibration.
This keeps Sigmoid at higher precision in both TensorRT export paths:
SigmoidONNX op from INT8 quantization.OBEY_PRECISION_CONSTRAINTS.STRICT_TYPES.The patch also bumps Ultralytics from
8.4.90to8.4.91and adds a real static INT8 detect export to the existing GPU matrix.Deletion/relocation cannot combine the two implementation sites because TensorRT 7–10 configures parsed builder layers while TensorRT 11+ quantizes the ONNX graph through ModelOpt.
Deleted: the speculative Softmax exclusion, its standalone documentation block, and the silent
OBEY_PRECISION_CONSTRAINTS-availability guard from prior PR revisions; the guidance now lives in the existing INT8 drawbacks section and legacy builders selectSTRICT_TYPESinstead of skipping the fix.Fixes #24668
T4 validation
INT8 inference remained comparable to FP16 (3.9 ms vs 4.0 ms), with 27–31% smaller engines and no YOLO11s regression.
Environment: Kaggle Tesla T4 (SM 7.5), TensorRT 10.7.0, PyTorch 2.10.0+cu128, 500 COCO validation calibration images, full 5,000-image COCO validation, batch 1, 640 px.
Test plan