Use separable SPPF pooling in PyTorch, preserving square pooling for export - #26082
Use separable SPPF pooling in PyTorch, preserving square pooling for export#26082glenn-jocher wants to merge 1 commit into
Conversation
|
👋 Hello @glenn-jocher, 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
LGTM. Reviewed the complete 14-line change in ultralytics/engine/exporter.py and ultralytics/nn/modules/block.py; the separable eager-PyTorch path and export-only square-pooling override are consistent with existing model and exporter behavior. No concrete correctness, compatibility, security, or performance issue was found.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Replace SPPF's
5×5max pooling with sequential1×5and5×1pooling during PyTorch training, validation, and prediction. Width-first pooling preserves gradient tie-breaking. Exports retain the original square pooling.Performance
Faster on CPU; slower for the SPPF block on CUDA, with little change to full-model CUDA inference.
Ranges cover the measured configurations on
ultra5: AMD EPYC 9655 (FP32, 1/8 threads) and RTX PRO 6000 Blackwell (CUDA 7, FP32/FP16), using PyTorch 2.7.0 / CUDA 12.8. Full-model inference uses 640×640 inputs and batches 1/8, excluding preprocessing and postprocessing. Results are medians of three trials on a shared server. Full-model training throughput was not measured.Validation
Full benchmark data and reproduction scripts
Setup
ultra5, dual AMD EPYC 9655 96-Core processors; CPU FP32 with 1 and 8 intra-op threads.forwardfrom baseb5f6c7024against this implementation, using identical weights/inputs. Pool-only rows compare three sequential square pools against three pairs of separable pools. Complete SPPF rows useSPPF(256,256,k=5,n=3)(128 hidden pooling channels); pooling-only rows have 256 channels.torch.utils.benchmark.Timer.blocked_autorange(min_run_time=0.3)trials per variant. Timer synchronizes accelerator work. Report the median of the three trial medians. All timings are milliseconds per batch; speedup = old/new (>1 is faster). Include every trial median below to expose variation.Full results
CPU float32, 1 CPU thread(s)
CPU float32, 8 CPU thread(s)
CUDA float32, 8 CPU thread(s)
CUDA float16, 8 CPU thread(s)
Reproduce
Run from this PR checkout in an environment with its dependencies, using the selected physical GPU:
Complete benchmark script
Focused validation script