[ultralytics] Ultralytics 8.3.229: COCO Segmentation 평가 300% 가속화 분석
PR 링크: ultralytics/ultralytics#22651 상태: Merged | 변경: +101 / -79
들어가며
최근 릴리즈된 ultralytics 8.3.229 버전에서는 COCO Segmentation 평가 과정에서 획기적인 성능 개선이 이루어졌습니다. 기존에는 외부 라이브러리인 faster_coco_eval에 의존하여 마스크를 인코딩하고, NumPy와 OpenCV를 사용하여 마스크 스케일링을 수행했습니다. 이 과정에서 발생하는 CPU-GPU 간 데이터 이동, 멀티스레딩 오버헤드, 그리고 비효율적인 이미지 처리 방식이 병목 구간이었습니다. 본 글에서는 이 PR이 어떻게 이러한 문제를 해결하고 300%의 성능 향상을 이끌어냈는지 분석합니다.
코드 분석
1. RLE(Run-Length Encoding) 인코딩의 내재화
기존에는 faster_coco_eval의 encode 함수를 호출하기 위해 데이터를 NumPy로 변환하고 ThreadPool을 사용하여 병렬 처리를 수행했습니다. 이번 변경에서는 이를 순수 PyTorch 연산으로 대체했습니다.
Before (기존 방식):
from faster_coco_eval.core.mask import encode
# ...
pred_masks = np.transpose(predn["masks"], (2, 0, 1))
with ThreadPool(NUM_THREADS) as pool:
rles = pool.map(single_encode, pred_masks)
After (개선된 방식):
# PyTorch 텐서 연산을 통한 RLE 직접 구현
def multi_encode(pixels: torch.Tensor) -> list[int]:
transitions = pixels[:, 1:] != pixels[:, :-1]
row_idx, col_idx = torch.where(transitions)
# ... (생략) ...
return counts
이 방식은 데이터가 GPU 메모리에 있는 상태에서 최대한 연산을 수행하여 CPU로의 복사 비용을 최소화합니다.
2. scale_masks를 통한 일관된 스케일링
기존의 scale_image 함수는 OpenCV에 의존적이었으며, 512 채널 제한 등 기술적 제약이 있었습니다. 이를 ops.scale_masks로 통합하여 PyTorch의 F.interpolate를 활용하도록 변경했습니다.
Before (기존 방식):
"masks": ops.scale_image(
torch.as_tensor(predn["masks"], dtype=torch.uint8).permute(1, 2, 0).contiguous().cpu().numpy(),
pbatch["ori_shape"],
ratio_pad=pbatch["ratio_pad"],
),
After (개선된 방식):
"masks": ops.scale_masks(predn["masks"][None], pbatch["ori_shape"], ratio_pad=pbatch["ratio_pad"])[0].byte(),
ops.scale_masks는 이제 ratio_pad를 직접 지원하며, 텐서 기반으로 동작하여 파이프라인의 일관성을 높였습니다.
왜 이게 좋은가
- 데이터 이동 최소화: NumPy/OpenCV로의 변환 없이 PyTorch 텐서 내에서 모든 연산이 완료되므로, 호스트-디바이스 간 데이터 전송 오버헤드가 제거되었습니다.
- 의존성 감소:
faster_coco_eval과 같은 외부 라이브러리 의존성을 제거하여 설치 환경을 단순화하고 유지보수성을 높였습니다. - 일관된 API:
scale_masks를 통해 박스 스케일링과 마스크 스케일링 로직을 통일함으로써, 향후 유지보수 시 발생할 수 있는 휴먼 에러를 줄였습니다.
리뷰어 피드백 반영
코드 리뷰 과정에서 RLE의 델타 인코딩 로직에 대한 중요한 지적이 있었습니다. i > 2로 구현되었던 조건문을 i > 1로 수정함으로써 COCO 표준 규격과의 호환성을 확보했습니다. 이는 최적화 과정에서 발생할 수 있는 정밀도 오류를 방지하는 중요한 수정이었습니다.
결론
이번 최적화는 단순히 코드를 줄이는 것을 넘어, 프레임워크의 핵심 철학인 'PyTorch Native'를 준수함으로써 성능과 안정성을 동시에 확보한 사례입니다. 복잡한 외부 의존성을 제거하고 내재화하는 전략은 대규모 데이터셋을 다루는 컴퓨터 비전 프로젝트에서 매우 권장되는 접근 방식입니다.
References
- torch.nn.functional.interpolate — 마스크 스케일링에 사용된 PyTorch 보간 함수
참고 자료
⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.
관련 포스트
PR Analysis 의 다른글
- 이전글 [Triton] AMD CI에 pip 캐시 디렉토리 도입 — 네트워크 장애 대응
- 현재글 : [ultralytics] Ultralytics 8.3.229: COCO Segmentation 평가 300% 가속화 분석
- 다음글 [triton] tl.cat 연산을 permute+reshape+join으로 재구현하여 결정적(deterministic) 동작 보장
댓글