[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를 기반으로 작성했습니다.
관련 포스트
- [sglang] Apple Silicon MLX 환경에서 SwitchGLU MoE 블록의 SwiGLU 활성화를 Gate Gather-QMV로 융합하여 성능 최적화
- [ultralytics] Ultralytics 코드베이스 경량화: SciPy 의존성 감소 및 NumPy 기반 최적화
- [Ultralytics] MPS 디바이스에서 메모리 누수 방지를 위한 적극적 메모리 정리
- [ultralytics] Ultralytics 8.3.229: COCO Segmentation 평가 300% 가속화 분석
- [uv] uv의 휠 태그 호환성 검사 최적화: 불필요한 메모리 할당 제거하기
PR Analysis 의 다른글
- 이전글 [triton] Triton 커널 최적화: 불필요한 텐서 메모리 할당 제거하기
- 현재글 : [ultralytics] RT-DETR의 CoreML 추론 성능 최적화: ComputeUnit.ALL 전략 도입
- 다음글 [sglang] Intel XPU를 위한 고성능 그래프 캡처 및 리플레이 지원 구현
댓글