Skip to content

Speed up per-class NMS for segment, pose and obb with a SIMD suppression loop - #470

Closed
onuralpszr wants to merge 2 commits into
mainfrom
refactor/detect-decode-reuse
Closed

Speed up per-class NMS for segment, pose and obb with a SIMD suppression loop#470
onuralpszr wants to merge 2 commits into
mainfrom
refactor/detect-decode-reuse

Conversation

@onuralpszr

@onuralpszr onuralpszr commented Sep 1, 2026

Copy link
Copy Markdown
Member

🛠️ PR Summary

Made with ❤️ by Ultralytics Actions

🌟 Summary

Added an eight-lane SIMD suppression loop for capped per-class NMS to speed up axis-aligned box filtering used by segment, pose, and OBB inference paths.

📊 Key Changes

  • Introduced nms_per_class_simd, which processes candidate boxes in groups of eight using wide::f32x8.
  • Preserved score ordering, same-class suppression, NaN ordering, and early termination after max_det detections.
  • Added a scalar fallback for fewer than eight remaining candidates.
  • Updated nms_per_class_capped to use the SIMD implementation.

🎯 Purpose & Impact

  • Capped per-class NMS now uses SIMD for the main suppression loop while retaining the existing capped behavior, reducing the amount of scalar IoU-processing work for large prediction sets.

Signed-off-by: Onuralp SEZER <onuralp@ultralytics.com>
@UltralyticsAssistant UltralyticsAssistant added the enhancement New feature or request label Sep 1, 2026
@UltralyticsAssistant

Copy link
Copy Markdown
Member

👋 Hello @onuralpszr, thank you for submitting a ultralytics/inference 🚀 PR! This automated message confirms your contribution was received, and an Ultralytics engineer will assist with the review. To ensure a seamless integration of your work, please review the following checklist:

  • Define a Purpose: Clearly explain the purpose of your fix or feature in your PR description, and link to any relevant issues. Ensure your commit messages are clear, concise, and adhere to the project's conventions.
  • Synchronize with Source: Confirm your PR is synchronized with the ultralytics/inference main branch. If it's behind, update it by clicking the 'Update branch' button or by running git pull and git merge main locally.
  • Ensure CI Checks Pass: Verify all Ultralytics Continuous Integration (CI) checks are passing. If any checks fail, please address the issues.
  • Update Documentation: Update the relevant documentation for any new or modified features.
  • Add Tests: If applicable, include or update tests to cover your changes, and confirm that all tests are passing.
  • Sign the CLA: Please ensure you have signed our Contributor License Agreement if this is your first Ultralytics PR by writing "I have read the CLA Document and I sign the CLA" in a new message.
  • Minimize Changes: Limit your changes to the minimum necessary for your bug fix or feature addition. "It is not daily increase but daily decrease, hack away the unessential. The closer to the source, the less wastage there is." — Bruce Lee

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 UltralyticsAssistant left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 PR Review

Made with ❤️ by Ultralytics Actions

Reviewed both changed files and the NMS callers. The SIMD suppression control flow matches the scalar implementation for normal finite boxes, but detect now incurs additional per-image allocation and copying without gaining a faster suppression algorithm. This is a bounded performance regression in the detect hot path.

💬 Posted 1 inline comment
  • 📝 LOW src/postprocessing.rs:567 This adds avoidable hot-path overhead for detect: the previous implementation sorted candidates in place and built the SIMD SoA directly, whereas this now copies every retained candidate into nms_input; nms_per_class_simd then allocates an index vector, performs an indirect sort, and copies the coordinates again. With the default max_det and the existing 10x pre-cap, this affects up to 3,000 candidates per image even though detect already had the same SIMD suppression loop. Please prese…

Comment thread src/postprocessing.rs Outdated
}
}
}
let nms_input: Vec<([f32; 4], f32, usize)> = candidates

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 LOW: This adds avoidable hot-path overhead for detect: the previous implementation sorted candidates in place and built the SIMD SoA directly, whereas this now copies every retained candidate into nms_input; nms_per_class_simd then allocates an index vector, performs an indirect sort, and copies the coordinates again. With the default max_det and the existing 10x pre-cap, this affects up to 3,000 candidates per image even though detect already had the same SIMD suppression loop. Please preserve the detect-side representation or provide a shared sorted-input/SoA entry point so detect can reuse its existing setup without the extra tuple materialization.

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.03896% with 30 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/utils.rs 61.03% 30 Missing ⚠️

📢 Thoughts on this report? Let us know!

Signed-off-by: Onuralp SEZER <onuralp@ultralytics.com>
@onuralpszr onuralpszr changed the title Share the SIMD NMS between detect and the other detection heads Speed up per-class NMS for segment, pose and obb with a SIMD suppression loop Sep 1, 2026
@onuralpszr onuralpszr closed this Sep 1, 2026
@onuralpszr
onuralpszr deleted the refactor/detect-decode-reuse branch September 1, 2026 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants