TT Lab
요금제

한국어

시작하기
블로그

블로그

33ms 의 예산: 끝단 지연과 처리량은 다른 숫자다

상태: 초안 (2026-10-16), 일부 실측. 단계별 시간은 집 랩의 8GB급 노트북용 GPU 한 장이 달린 서버에서 1회용 파드(CPU 4코어 한도)로 쟀습니다(예열 30회 뒤 300회의 중앙값). 폰에서의 잡기·인코딩 시간과 인터넷 구간은 미실측입니다. 큐 흉내는 노트북 CPU 예제(code/01_latency_queue.py, 1초 안팎)입니다. 시리즈 「비전 모델 읽기 3: 실시간으로 돌리기」 1편. 이 시리즈는 비전 모델 읽기 1·2에서 본 모델들을 정해진 시간 안에 돌리는 방법을 다룹니다.

목차

1. 「실시간」 의 두 숫자

탁구 점수판 앱이 「실시간」 이려면 두 가지가 동시에 맞아야 합니다.

둘은 자주 섞여 쓰이지만 다른 숫자입니다. 처리량은 「가장 느린 한 단계」 가 정하고, 지연은 「모든 단계의 합 + 줄에서 기다린 시간」 입니다. 30fps 의 프레임 간격 1000 ÷ 30 = 33.3ms 는 처리량의 예산이지, 지연의 상한이 아닙니다. 단계를 겹치면 지연이 33ms 를 넘어도 30fps 를 낼 수 있고, 반대로 지연이 10ms 여도 줄이 쌓이면 1초 뒤의 결과를 보게 됩니다.

한 프레임의 일생: 지연과 처리량 ① 끝단 지연 = 찍힌 순간부터 화면에 나올 때까지의 합 카메라 잡기 전처리 줄이기 추론 모델 후처리 공 찾기 화면 그리기 단계 시간의 합 + 줄에서 기다린 시간 ② 단계를 겹치면 처리량이 는다 — 한 프레임의 지연은 그대로 전처리 추론 후처리 1 2 3 1 2 3 1 2 3 시간 → 추론이 쉬지 않고 돌면 처리량 = 1 ÷ 추론 시간 ③ 추론이 예산보다 느릴 때 1 2 3 4 5 6 줄 세우기: 1부터 차례로 → 지연이 계속 는다 1 2 3 4 5 6 최신만: 2–5 를 버리고 6 → 지연이 묶인다
그림: 카메라에서 화면까지 다섯 단계와 끝단 지연, 단계를 겹치면 처리량이 늘지만 한 프레임의 지연은 그대로인 파이프라인, 추론이 밀릴 때 줄 세우기와 최신만 처리의 차이

2. 단계를 겹치면: 처리량은 늘고 지연은 그대로

전처리 8ms, 추론 25ms 를 차례로 하면 한 프레임에 33ms, 1초에 30.3장입니다. 전처리를 다른 스레드에서 미리 해 두면(파이프라인) GPU 는 쉬지 않고 추론만 하므로 1초에 40장까지 됩니다. 그런데 한 프레임이 겪는 시간은 여전히 8 + 25 = 33ms 입니다.

처리량  = 1 ÷ (가장 느린 단계의 시간)
지연    = 단계 시간의 합 + 줄에서 기다린 시간
리틀의 법칙: 처리 중인 프레임 수 = 처리량 × 지연   (40장/초 × 0.033초 = 1.32장)

리틀의 법칙(대기열 이론의 기본 공식)은 거꾸로도 씁니다. 처리량이 정해져 있는데 「지금 처리 중이거나 기다리는 프레임」 이 늘었다면, 그만큼 지연이 늘었다는 뜻입니다.

3. 밀릴 때: 줄을 세울까, 버릴까

추론 시간은 매번 조금씩 다릅니다. 평균 25ms 면 대개 예산 안이지만, 평균이 36ms 로 예산을 넘으면 어떻게 될까요. 30fps 카메라 60초를 흉내 냈습니다(code/01_latency_queue.out.txt, 추론 시간은 로그정규 분포, 숫자는 설명용 가정).

추론 평균 규칙 처리 fps 버린 프레임 지연 중앙 · p99 60초 뒤 마지막 프레임 지연
25ms 줄 세우기 30.0 0% 24.6 · 44.1ms 21.3ms
25ms 최신만 30.0 0% 24.6 · 44.1ms 21.3ms
36ms 줄 세우기 27.9 0% 2,068.7 · 4,465.7ms 4,500.7ms
36ms 최신만 27.4 8.6% 48.0 · 82.3ms 75.9ms

예산 안에서는 두 규칙이 같습니다. 예산을 넘으면 줄 세우기는 처리량을 거의 유지하면서 지연이 끝없이 쌓입니다(1분 뒤 4.5초 늦은 화면). 「최신만」 은 처리기가 비는 순간 가장 새 프레임만 집고 밀린 것을 버립니다. 8.6% 를 버리는 대신 지연이 묶입니다. 실시간 영상에서 몇 초 전 프레임의 결과는 쓸모가 없으니, 버리는 쪽이 맞습니다. TT Score 의 실시간 작업자와 브라우저도 이렇게 합니다(8편).

4. 늦은 정답은 틀린 답: Streaming Perception

Li·Wang·Ramanan 의 「Towards Streaming Perception」(ECCV 2020)은 이 생각을 평가 방법으로 만들었습니다. 보통의 검출 정확도(AP)는 세상이 모델을 기다려 준다고 가정합니다. 이 논문의 streaming AP 는 시각 t 의 정답을 「t 이전에 계산이 끝난 가장 최근 출력」 과 비교합니다. 늦게 나온 출력은 이미 움직인 세상과 비교되므로 점수가 자연히 깎입니다.

검출기(자율주행 영상 30fps, 1920×1200) 한 프레임 AP
HTC(정확하지만 느림), 보통 평가 700.5ms 38.0
같은 모델, streaming 평가 700.5ms 6.2
RetinaNet(가장 빠름), 0.2배 입력 31–36ms 5.5–6.0
Mask R-CNN, 0.5배 입력, 전처리 GPU 56.7ms 12.0
+ 일정 조정(가끔 쉬기) 56.7ms 13.0
+ 칼만 예측, 0.75배 입력으로 다시 고름 92.7ms 17.8

(논문 표 1·2, 2017년 소비자용 상위 GPU 한 장.) 세 가지가 보입니다.

「일정 조정」 이 흥미롭습니다. 다음 프레임이 곧 올 것 같으면 지금 프레임을 시작하지 않고 기다립니다. 낡은 프레임을 붙잡고 있느라 새 프레임을 놓치는 것보다 낫기 때문입니다. 3절의 「최신만」 과 같은 정신입니다.

5. 우리 실측: 공 찾기 한 프레임의 일생

TT Score 의 실시간 경로를 서버 쪽에서 단계별로 쟀습니다. 실제 경기 화면 한 장(1920×1080 을 카메라 크기 1280×720 으로 줄인 것)을 300번 돌렸습니다. 폰이 하는 일(줄이기·인코딩)도 같은 서버 CPU 에서 흉내만 냈습니다.

단계 어디서 중앙값 p90
1280×720 → 512×288 줄이기 폰(서버 CPU 로 흉내) 0.27ms 0.30ms
JPEG 인코딩(품질 70) 폰(서버 CPU 로 흉내) 0.30ms 0.31ms
(전송: JPEG 중앙 12,252바이트) 인터넷 미실측 미실측
JPEG 디코딩 서버 CPU 0.31ms 0.32ms
BGR → RGB, 0–1 정규화, 평균·표준편차 빼기 서버 CPU 1.35ms 1.38ms
3프레임 창 쌓기 + GPU 로 옮기기 CPU → GPU 1.76ms 1.86ms
공 모델 추론(FP32, 운영 방식) GPU 15.17ms 15.19ms
(같은 추론을 FP16 으로) GPU 9.98ms 10.03ms
sigmoid + 히트맵을 CPU 로 GPU → CPU 0.18ms 0.20ms
공 덩어리 찾기 서버 CPU 0.07ms 0.07ms

서버에서 한 프레임에 드는 시간은 약 19ms(FP32)이고 그중 추론이 80% 입니다. 남은 몫에서 큰 것은 디코딩이 아니라 정규화(1.35ms)와 GPU 로 옮기기(1.76ms) 였습니다. 512×288×3 을 float32 로 바꾸면 한 장에 1.77MB, 창 세 장이면 5.3MB 를 매번 만들어 옮깁니다. uint8 그대로 GPU 에 보내 GPU 에서 정규화하면 옮길 양이 4분의 1 이 되고 정규화도 GPU 가 합니다. 아직 바꾸지 않았고 효과는 미실측입니다.

이 표에는 폰의 카메라 잡기·실제 인코딩, 인터넷 왕복, 웹 서버 중계, 화면 그리기가 빠져 있습니다. 그 부분은 8편에서 실제 브라우저 시험으로 잰 끝단 값과 함께 정리합니다.

6. 숫자를 읽는 습관

7. 한계

8. 우리 프로젝트와의 연결

티티 한마디. 공이 튄 지 4초 뒤에 「바운드!」 라고 외치면, 아무리 정확해도 저는 이미 다음 공을 치고 있어요. 늦은 정답은 틀린 답이에요!

참고 문헌

로그인하면 좋아요를 누를 수 있습니다

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다