MakeAI 딥러닝

GPU 한 장으로 하루에 몇 장이나 처리할 수 있을까 — 배치 처리량 설계

온프레미스에선 GPU가 보통 한두 장이에요. 그 안에서 처리량을 최대로 뽑으려고 저희가 한 것들 — 파이프라인 분리, 동적 배치, CPU 선행 처리 — 을 정리했어요.

3분 읽기

설치형으로 들어가면 GPU는 보통 한 장, 많아야 두 장이에요. "하루에 문서 몇 장 처리돼요?"라는 질문에 답하려면 이 한 장을 얼마나 잘 쓰느냐가 전부예요. 오늘은 처리량을 올리려고 저희가 한 것들을 적어 볼게요. 숫자는 저희 환경 기준이라 참고만 하세요.

처음엔 GPU가 놀고 있었어요

처음 버전은 문서 한 장을 받으면 순서대로 처리했어요. PDF 렌더링 → 레이아웃 검출(GPU) → 표 구조 인식(GPU) → 글자 인식(GPU) → 후처리 → JSON. 프로파일링해 보니 GPU 사용률이 30%도 안 됐어요. 나머지 시간엔 CPU가 PDF를 그리거나 후처리를 하는 동안 GPU가 기다리고 있었어요.

1. 단계를 분리하고 큐로 이었어요

파이프라인을 단계별 워커로 쪼개고 사이에 큐를 뒀어요.

[렌더링 워커 ×4, CPU] → 큐 → [레이아웃 워커 ×1, GPU] → 큐 → [OCR 워커 ×1, GPU] → 큐 → [후처리 워커 ×4, CPU]

CPU 단계는 여러 프로세스로, GPU 단계는 하나로요. 이렇게 하면 GPU 워커가 항상 할 일이 있어요. 단순한 변경인데 처리량이 두 배 넘게 올랐어요.

2. 동적 배치

GPU 워커는 한 번에 한 장이 아니라 큐에 쌓인 만큼 묶어서 추론해요. 최대 배치 크기와 최대 대기 시간을 두고, 둘 중 먼저 차는 쪽에서 실행해요. 저희 기본값은 배치 16, 대기 50ms예요.

주의할 점이 있어요. 문서 이미지는 크기가 제각각이라 그냥 묶으면 패딩이 엄청 커져요. 비슷한 크기끼리 묶도록 큐를 몇 개 버킷으로 나눴어요(세로 긴 것, 가로 긴 것, 큰 것, 작은 것). 패딩 낭비가 줄면서 같은 배치 크기에서 실제 처리량이 더 올라갔어요.

3. 모델 세 개를 한 GPU에 같이 올려요

레이아웃, 표 인식, OCR 모델을 각각 다른 프로세스에서 돌리면 GPU 메모리를 따로따로 잡고 컨텍스트 전환도 생겨요. 저희는 한 프로세스에서 세 모델을 모두 올리고 순서대로 호출해요. 메모리도 아끼고 전환 비용도 없어요. 대신 이 프로세스가 죽으면 전부 죽어서, 감시 프로세스가 재시작하게 해 뒀어요.

4. 정밀도 낮추기

FP16으로 바꾸면 거의 공짜로 빨라져요. 저희 모델들은 FP16에서 정확도 차이가 측정 오차 안이었어요. INT8 양자화는 OCR 인식 모델에서 작은 글자 정확도가 떨어져서 안 썼어요. 레이아웃 검출은 INT8도 괜찮았는데, 전체 시간에서 차지하는 비중이 작아서 굳이 안 했어요. 이건 모델마다 다르니 꼭 직접 재 보세요.

5. CPU 단계가 병목이 되는 순간

GPU를 잘 쓰기 시작하니까 이번엔 CPU가 병목이 됐어요. 특히 PDF 렌더링이요. 벡터가 복잡한 CAD PDF는 한 장 그리는 데 몇 초 걸려요. 해결한 방법은 이래요.

  • 렌더링 해상도를 단계별로 다르게. 레이아웃 검출엔 낮은 해상도, OCR엔 해당 영역만 높은 해상도로 다시 그려요. 전체를 고해상도로 그리는 것보다 훨씬 빨라요.
  • 텍스트 레이어가 있는 PDF는 OCR 자체를 건너뛰어요. 글자를 PDF에서 바로 뽑고, 위치도 PDF 좌표로 받아요. CAD에서 나온 도면 PDF는 대부분 텍스트 레이어가 있어요. 스캔본만 OCR을 해요.

6. 한 장이 느린 것과 전체가 느린 것은 달라요

처리량(throughput)과 지연(latency)은 다른 목표예요. 배치를 키우면 처리량은 오르는데 한 장의 대기 시간은 늘어요. 저희는 두 가지 큐를 둬요.

  • 대화형 큐: 사용자가 콘솔에서 한 장 올리고 기다리는 경우. 배치 작게, 우선순위 높게.
  • 배치 큐: 밤에 수천 장 돌리는 경우. 배치 크게, 우선순위 낮게.

GPU 워커는 대화형 큐를 먼저 보고, 비어 있으면 배치 큐를 가져가요.

저희 환경에서 나온 숫자

조건을 쓸 수 없는 숫자는 안 쓴다고 했으니 조건을 써요. 24GB 메모리 GPU 한 장, CPU 8코어, A4 스캔 문서(300dpi, 표 2~3개 포함) 기준이에요. 처음 순차 버전에서 분당 수십 장이었던 게 위 작업을 다 하고 나서 분당 수백 장 단위가 됐어요. 정확한 숫자는 문서 종류에 따라 몇 배씩 차이가 나서 범위로만 말씀드릴게요. 도면은 해상도가 높고 글자가 작아서 문서보다 훨씬 느려요.

정리

  • GPU 사용률부터 재 보세요. 놀고 있을 가능성이 높아요.
  • CPU 단계와 GPU 단계를 분리하고 큐로 이으세요.
  • 동적 배치는 크기 버킷이랑 같이 쓰세요.
  • 텍스트 레이어가 있으면 OCR을 건너뛰세요.
  • 대화형과 배치 큐를 나누세요.

다음 주부터는 에이전트 운영 이야기로 넘어가요. 첫 글은 LLM 호출을 OpenTelemetry로 기록하는 방법이에요.