[ultralytics] RT-DETR의 CoreML 추론 성능 최적화: ComputeUnit.ALL 전략 도입
PR 링크: ultralytics/ultralytics#24999 상태: Merged | 변경: +5 / -1
들어가며
Apple Silicon 환경에서 CoreML을 사용하여 모델을 배포할 때, 일반적으로 ComputeUnit.CPU_AND_NE(Neural Engine)를 사용하는 것이 가장 효율적입니다. 하지만 RT-DETR 모델의 경우, Neural Engine 단독 실행 시 FP16 정밀도에서 심각한 정확도 저하가 발생하고 오히려 추론 속도가 느려지는 현상이 발견되었습니다. 본 PR은 모델의 구조적 특성을 메타데이터로 식별하여, RT-DETR 모델에 한해 ComputeUnit.ALL을 사용하도록 동적으로 라우팅하는 최적화 기법을 다룹니다.
코드 분석
1. 모델 메타데이터 확장 (ultralytics/engine/exporter.py)
모델을 CoreML 형식으로 내보낼 때, 모델의 마지막 레이어(Head) 정보를 메타데이터에 추가하여 추론 시점에 모델의 종류를 식별할 수 있도록 했습니다.
# Before
"task": model.task,
"batch": self.args.batch,
# After
"task": model.task,
"head": type(model.model[-1]).__name__, # 모델의 마지막 레이어 클래스 이름을 저장
"batch": self.args.batch,
2. 동적 ComputeUnit 선택 (ultralytics/nn/backends/coreml.py)
추론 시점에 저장된 head 메타데이터를 읽어와, RTDETRDecoder인 경우 ComputeUnit.ALL을 사용하고, 그 외의 모델은 기존의 안정적인 ComputeUnit.CPU_AND_NE를 사용하도록 로직을 개선했습니다.
# After
meta = dict(ct.utils.load_spec(str(weight)).description.metadata.userDefined)
default_unit = ct.ComputeUnit.ALL if meta.get("head") == "RTDETRDecoder" else ct.ComputeUnit.CPU_AND_NE
try:
self.model = ct.models.MLModel(weight, compute_units=default_unit)
왜 이게 좋은가
이번 최적화의 핵심은 '범용적 설정'과 '모델 특화 설정'의 균형입니다. 기존 CPU_AND_NE 설정은 대부분의 YOLO 모델에서 최상의 성능을 보장하지만, RT-DETR과 같은 특정 아키텍처에서는 오히려 독이 되었습니다.
성능 비교 (RT-DETR-L)
| Precision | mAP50-95 (Before) | mAP50-95 (After) | Inference (Before) | Inference (After) |
|---|---|---|---|---|
| FP16 | 0.485 | 0.714 | 85.3 ms/im | 37.0 ms/im |
FP16 환경에서 mAP는 약 47% 향상되었으며, 추론 속도는 2배 이상 빨라졌습니다. 이는 하드웨어 가속기를 무조건 사용하는 것이 능사가 아니라, 모델의 연산 특성에 맞는 실행 유닛을 선택하는 것이 중요함을 시사합니다.
리뷰어 피드백 및 교훈
리뷰 과정에서 모든 모델에 ComputeUnit.ALL을 적용하자는 논의가 있었으나, YOLO 모델들에 대한 벤치마크 결과 성능 차이가 미미하고 CPU_AND_NE가 이미 최적화되어 있다는 점을 확인했습니다. 또한, macOS 환경에서의 컴파일러 버그 이슈를 고려하여 기존 모델들의 기본값은 유지하는 보수적인 접근을 취했습니다. 이처럼 '데이터에 기반한 의사결정'이 기술 부채를 줄이면서도 확실한 성능 개선을 이끌어내는 핵심임을 다시 한번 확인했습니다.
참고 자료
- https://apple.github.io/coremltools/docs-guides/source/compute-units.html
- https://docs.ultralytics.com/modes/export/
⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.
관련 포스트
- [ultralytics] Ultralytics 추론 성능 극대화: CPU 전처리 병목 해소하기
- [ultralytics] Ultralytics 체크포인트 로딩 최적화 및 스레드 안전성 강화
- [ultralytics] Ultralytics FLOPs 프로파일링 최적화: deepcopy 제거를 통한 성능 향상
- [ultralytics] [Ultralytics] NDJSON 변환 최적화: 보안과 성능을 동시에 잡는 설계 전략
- [sglang] Apple Silicon MLX 환경에서 SwitchGLU MoE 블록의 SwiGLU 활성화를 Gate Gather-QMV로 융합하여 성능 최적화
PR Analysis 의 다른글
- 이전글 [triton] Triton 커널 최적화: 불필요한 텐서 메모리 할당 제거하기
- 현재글 : [ultralytics] RT-DETR의 CoreML 추론 성능 최적화: ComputeUnit.ALL 전략 도입
- 다음글 [sglang] Intel XPU를 위한 고성능 그래프 캡처 및 리플레이 지원 구현
댓글