[ultralytics] RT-DETR FLOPs 프로파일링 성능 최적화 및 안정화
PR 링크: ultralytics/ultralytics#25652 상태: Merged | 변경: +6 / -3
들어가며
최신 객체 탐지 모델인 RT-DETR은 강력한 성능을 자랑하지만, 모델의 연산 복잡도(FLOPs)를 측정하는 과정에서 기술적인 병목이 존재했습니다. 기존의 ultralytics 라이브러리는 효율적인 프로파일링을 위해 thop 라이브러리의 stride-based proxy 방식을 사용해 왔습니다. 하지만 RT-DETR의 디코더 구조는 고정된 32x32 입력 샘플로는 정확한 연산량을 추정할 수 없으며, 특히 Attention 연산이 포함된 경우 FLOPs 곡선이 선형(affine)이 아닌 이차(quadratic) 함수 형태를 띠게 되어 기존 방식으로는 심각한 오차가 발생했습니다. 본 PR은 이러한 문제를 해결하고 프로파일링 속도와 정확도를 동시에 개선합니다.
코드 분석
ultralytics/utils/torch_utils.py 변경 사항
핵심 변경 사항은 get_flops 함수 내에서 RT-DETR 모델을 명시적으로 감지하고, 해당 모델에 최적화된 프로파일링 경로를 타도록 수정하는 것입니다.
Before:
attn = tuple(m for m in model.modules() if isinstance(m, (Attention, AAttn)))
stride = None if attn else max(int(model.stride.max()), 32) if hasattr(model, "stride") else 32
return thop.profile(model, inputs=[im], stride=stride, custom_ops=custom_ops, verbose=False)[0] / 1e9 * 2
After:
from ultralytics.nn.modules.head import RTDETRDecoder
# ...
rtdetr = any(isinstance(m, RTDETRDecoder) for m in model.modules())
# ...
if rtdetr: # RT-DETR cannot run the stride-sized proxy input
return thop.profile(model, inputs=[im], custom_ops=custom_ops, verbose=False)[0] / 1e9 * 2
return thop.profile(model, inputs=[im], stride=stride, custom_ops=custom_ops, verbose=False)[0] / 1e9 * 2
기존에는 stride 파라미터를 통해 입력 이미지를 축소하여 프로파일링했으나, RT-DETR의 디코더는 num_queries=300과 같은 고정된 쿼리 수를 요구하므로 작은 입력 샘플에서는 연산이 불가능하거나 부정확했습니다. RTDETRDecoder를 감지하여 이를 우회하고, 전체 크기(full-size) 프로파일링을 직접 수행함으로써 정확도를 확보했습니다.
왜 이게 좋은가
- 성능 향상: 로컬 CPU 벤치마크 결과,
rtdetr-l모델 기준으로 640 해상도에서 약 1.47배, 1280 해상도에서 약 5.47배 빠른 프로파일링 속도를 달성했습니다. - 정확도 보장: Attention 연산이 포함된 모델에서 발생하는 이차 함수적 복잡도를 정확히 반영합니다. 기존의 stride 기반 근사치는 실제 연산량보다 약 97% 낮게 측정되는 문제가 있었으나, 이번 변경으로 실제
thop결과값과 일치하게 되었습니다. - 안정성:
pytest를 통해 640 및 1280 해상도에 대한 회귀 테스트를 추가하여, 향후 코드 변경 시에도 프로파일링 결과가 일관되게 유지되도록 보장합니다.
이번 최적화의 교훈은 '범용적인 최적화 기법(stride-based proxy)이 특정 아키텍처(RT-DETR)의 특수성을 고려하지 못할 때 발생하는 오차를 어떻게 식별하고 해결할 것인가'에 대한 좋은 사례를 보여줍니다. 모델의 구조적 특성을 파악하여 프로파일링 전략을 동적으로 변경하는 것이 성능과 정확도 사이의 균형을 맞추는 핵심입니다.
참고 자료
⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.
관련 포스트
- [vllm] vLLM의 성능 병목 해결: Host-to-Device 복사 최적화로 비동기 실행 보장하기
- [vllm] [vLLM 분석] Speculative Decoding 성능 최적화: DSpark Markov Head 복제 전략
- [sglang] SGLang 성능 최적화: 과도한 Prefill CUDA Graph Padding 방지로 TTFT 개선
- [triton] Triton Reduce 커널 성능 최적화: Subtiling과 RowIdxs 도입
- [sglang] SGLang NPU 최적화: MoE 모델을 위한 Dual Stream 병렬 처리 도입
PR Analysis 의 다른글
- 이전글 [sglang] [Kimi K3] CPU 전송 이미지의 지연 전처리(Deferred Preprocessing)를 통한 VLM 성능 최적화
- 현재글 : [ultralytics] RT-DETR FLOPs 프로파일링 성능 최적화 및 안정화
- 다음글 [sglang] SGLang, Sol-Attn 도입으로 비디오 생성 속도 1.23배 향상
댓글