Articlehuggingface.co·2026년 5월 14일·0

Unlocking asynchronicity in continuous batching

Quick Summary

연속 배치의 동기식 유휴 시간을 없애기 위해 중앙처리장치의 배치 준비와 그래픽처리장치의 계산을 분리하고, 비기본 CUDA 스트림과 이벤트로 병렬 실행과 작업 순서를 함께 보장하는 방법을 설명한다.

Unlocking asynchronicity in continuous batching 관련 대표 이미지

🖼️ 인포그래픽

Unlocking asynchronicity in continuous batching 내용을 설명하는 본문 이미지

🖼️ 4컷 인포그래픽

Unlocking asynchronicity in continuous batching 내용을 설명하는 본문 이미지

💡 한 줄 요약

연속 배치의 동기식 유휴 시간을 없애기 위해 중앙처리장치의 배치 준비와 그래픽처리장치의 계산을 분리하고, 비기본 CUDA 스트림과 이벤트로 병렬 실행과 작업 순서를 함께 보장하는 방법을 설명한다.

📌 핵심 요약

  • 연속 배치는 패딩으로 낭비되는 연산을 줄이지만, 기본적인 동기식 구조에서는 중앙처리장치와 그래픽처리장치가 번갈아 작동해 추가적인 유휴 시간이 발생한다.
  • 8B 모델로 배치 크기 32에서 8천 개의 토큰을 생성한 측정에서는 총 300.6초 가운데 24.0% 동안 그래픽처리장치가 중앙처리장치의 작업을 기다렸다.
  • 비기본 CUDA 스트림을 사용하면 그래픽처리장치 작업을 실행한 직후 중앙처리장치가 제어권을 되찾아 다음 작업을 준비할 수 있다.
  • 연속 배치에는 호스트에서 장치로의 입력 전송, 그래픽처리장치 계산, 장치에서 호스트로의 출력 전송을 담당하는 세 개의 독립적인 스트림이 필요하다.
  • 독립 스트림만 사용하면 작업 순서가 깨지므로 CUDA 이벤트를 기록하고 대기하게 만들어 입력 전송, 계산, 출력 전송의 의존성을 그래픽처리장치 내부에서 명시적으로 보장해야 한다.

🧩 주요 포인트

  1. 연속 배치는 패딩으로 낭비되는 연산을 줄이지만, 기본적인 동기식 구조에서는 중앙처리장치와 그래픽처리장치가 번갈아 작동해 추가적인 유휴 시간이 발생한다.
  2. 8B 모델로 배치 크기 32에서 8천 개의 토큰을 생성한 측정에서는 총 300.6초 가운데 24.0% 동안 그래픽처리장치가 중앙처리장치의 작업을 기다렸다.
  3. 비기본 CUDA 스트림을 사용하면 그래픽처리장치 작업을 실행한 직후 중앙처리장치가 제어권을 되찾아 다음 작업을 준비할 수 있다.
  4. 연속 배치에는 호스트에서 장치로의 입력 전송, 그래픽처리장치 계산, 장치에서 호스트로의 출력 전송을 담당하는 세 개의 독립적인 스트림이 필요하다.
  5. 독립 스트림만 사용하면 작업 순서가 깨지므로 CUDA 이벤트를 기록하고 대기하게 만들어 입력 전송, 계산, 출력 전송의 의존성을 그래픽처리장치 내부에서 명시적으로 보장해야 한다.

🧠 상세 정리

1. 연속 배치 이후에도 남는 유휴 시간

이 글은 효율적인 대규모 언어 모델 추론 연재의 두 번째 글로, 연속 배치가 제거하지 못한 동기식 실행의 낭비를 다룬다. 연속 배치는 요청을 빈틈없이 묶어 패딩에 쓰이는 연산을 줄이지만, 기본 방식에서는 중앙처리장치와 그래픽처리장치가 번갈아 일하므로 한쪽이 작업하는 동안 다른 쪽이 기다린다. 시간당 약 5달러인 H200을 하루 사용하면 약 120달러가 드는 만큼, 저자들은 그래픽처리장치를 최대한 쉬지 않게 만드는 것이 중요하다고 설명한다. 해결 방향은 다음 배치 준비와 현재 배치 계산을 분리해 중앙처리장치와 그래픽처리장치를 병렬로 움직이는 비동기 배치이며, 목표는 계산 장치의 유휴 간격을 없애는 것이다.

2. 동기식 배치 루프의 작동 방식

동기식 루프에서 중앙처리장치는 먼저 새 배치에 포함할 요청을 선택하고, 키·값 캐시 표를 갱신하며, 이전 실행에서 완료된 요청을 제거한 뒤 빈자리에 새 요청을 넣는다. 준비된 입력이 그래픽처리장치로 전달되면 모델의 순전파가 실행되고, 각 요청에서 다음에 생성할 토큰을 선택하는 샘플링이 진행된다. 그 결과는 다시 중앙처리장치로 돌아와 각 요청이 방금 생성한 토큰과 상태를 반영하고, 이후 재스케줄링을 거쳐 다음 주기가 시작된다. 문제는 그래픽처리장치가 계산을 마친 뒤 중앙처리장치의 샘플링 결과 처리, 요청 상태 갱신, 배치 재구성이 끝날 때까지 다음 계산을 시작하지 못한다는 점이다.

3. 측정으로 확인된 24%의 손실

저자들은 8B 모델과 배치 크기 32를 사용해 8천 개의 토큰을 생성하면서 중앙처리장치와 그래픽처리장치의 활동 시간을 측정했다. 실행 시간선에서는 그래픽처리장치가 활성화된 구간과 중앙처리장치가 활성화된 구간이 교대로 나타났으며, 두 장치가 유용한 작업을 동시에 수행하는 구간은 없었다. 총 생성 시간은 300.6초였고, 그중 24.0%는 그래픽처리장치가 중앙처리장치의 작업 완료를 기다리며 쉬는 시간이었다. 저자들은 이 중앙처리장치 오버헤드를 없앨 수 있다면 새 커널이나 모델 변경 없이도 생성 시간이 약 300초에서 228초로 줄어드는 효과를 기대할 수 있다고 설명한다.

4. 비동기화를 위해 풀어야 할 세 가지 문제

핵심 발상은 배치 N을 그래픽처리장치에서 계산하는 동안 중앙처리장치가 배치 N+1을 준비하도록 두 작업을 겹치는 것이다. 그러나 이를 구현하려면 그래픽처리장치 작업을 실행한 뒤 완료될 때까지 기다리지 않고 중앙처리장치가 즉시 제어권을 되찾는 방법이 필요하다. 또한 중앙처리장치나 그래픽처리장치가 각 작업을 시작하는 시점에 필요한 데이터가 이미 준비되어 있음을 보장해야 한다. 마지막으로 다음 배치의 구성이 현재 배치의 예측 결과에 의존한다는 점을 처리해야 하며, 글은 이 문제들을 CUDA 스트림과 이벤트를 이용해 단계적으로 해결한다.

5. CUDA 스트림과 동시 실행의 기반

CUDA 스트림은 커널 실행, 메모리 복사, 동기화 장벽과 같은 그래픽처리장치 작업이 제출 순서대로 들어가는 대기열이다. 같은 스트림 안의 작업은 앞 작업이 끝난 뒤 다음 작업이 시작되므로 순차적으로 실행되지만, 서로 다른 스트림에 들어간 작업들은 독립적이어서 동시에 실행될 수 있다. 다만 모든 그래픽처리장치 작업은 중앙처리장치가 적절한 커널을 찾고 호출을 발행하며 명령을 전달하는 과정을 통해 시작되므로, 실제 시작 시점에는 작은 간격이 생긴다. 글은 이 중앙처리장치 실행 오버헤드도 실제 시간을 차지한다고 강조하고, 비동기 작업 흐름에서 무엇이 언제 실행되는지 추적하기 위해 이후 설명에서도 이를 명시적으로 다룬다.

6. 기본 스트림을 피해야 하는 이유

일반적인 파이토치 연산은 별도의 스트림을 지정하지 않으면 기본 CUDA 스트림에 배치되며, 이 기본 스트림은 다른 스트림과 동기화되는 특별한 성질을 가진다. 기본 스트림의 작업은 다른 모든 스트림의 작업이 끝날 때까지 기다리고, 반대로 다른 스트림의 작업도 기본 스트림이 비워질 때까지 시작하지 못한다. 따라서 기본 스트림에서 생성된 결과를 중앙처리장치로 옮기면 전송 자체를 비차단 방식으로 지정하더라도 모든 그래픽처리장치 작업이 끝날 때까지 중앙처리장치가 막힐 수 있다. 비기본 스트림에 커널 실행이나 비차단 메모리 복사를 넣으면 호출 직후 중앙처리장치가 제어권을 되찾고 그래픽처리장치는 백그라운드에서 작업하므로, 동시 실행을 만들기 위한 첫 번째 조건이 충족된다.

7. 연속 배치를 위한 세 개의 스트림

연속 배치 한 주기에서 그래픽처리장치와 관련된 작업은 입력을 호스트에서 장치로 옮기는 전송, 장치에서 수행하는 모델 계산, 출력을 장치에서 호스트로 되돌리는 전송으로 나뉜다. 글은 이 세 작업을 각각 호스트-장치 전송 스트림, 계산 스트림, 장치-호스트 전송 스트림에 배치한다. 두 방향의 전송은 서로 독립적이므로 하나의 스트림에 직렬화할 이유가 없으며, 계산 역시 별도의 스트림에서 실행한다. 중앙처리장치는 배치 입력을 준비한 뒤 세 스트림에 입력 전송, 순전파, 출력 전송을 차례로 등록하고 마지막에 결과를 확인하지만, 비차단 실행을 사용하므로 작업 간 의존성은 별도로 표현해야 한다.

8. 스트림만 사용했을 때 발생하는 오류

세 개의 독립 스트림에 작업을 등록하기만 하면 결과가 거의 즉시 반환되지만, 그 결과는 올바르지 않다. 각 스트림이 다른 스트림을 기다리지 않기 때문에 계산 스트림은 호스트-장치 입력 전송이 끝나기 전에 순전파를 시작하고, 기존 그래픽처리장치 메모리에 있던 값을 사용할 수 있다. 장치-호스트 전송 스트림도 계산 완료를 기다리지 않으므로 아직 만들어지지 않은 출력을 중앙처리장치로 복사하게 된다. 기본 스트림이 없어서 중앙처리장치를 막는 요소도 없으므로 결과 확인 단계까지 즉시 진행되며, 이는 개별 작업의 문제가 아니라 스트림 사이의 필수 실행 순서를 알려주지 않은 데서 발생한 오류다.

9. CUDA 이벤트로 의존성 보장하기

CUDA 이벤트는 특정 스트림의 한 지점에 기록되는 표식으로, 그래픽처리장치가 그 지점에 도달하면 완료 상태가 된다. 다른 스트림은 해당 이벤트가 완료될 때까지 다음 작업을 진행하지 않도록 대기할 수 있는데, 이 대기는 중앙처리장치나 다른 스트림 전체가 아니라 지정된 스트림만 멈춘다. 연속 배치에서는 입력 전송 뒤 호스트-장치 스트림에 전송 완료 이벤트를 기록하고, 계산 스트림이 그 이벤트를 기다린 다음 순전파를 시작하게 한다. 이어 계산 스트림에 계산 완료 이벤트를 기록하고 장치-호스트 스트림이 이를 기다린 뒤 출력을 복사하도록 구성하면, 중앙처리장치를 차단하지 않으면서도 입력 전송, 계산, 출력 전송의 필수 순서가 그래픽처리장치 내부에서 명시적으로 보장된다.

🧾 핵심 주장 / 시사점

  • 패딩 제거로 배치 밀도를 높이는 것만으로는 그래픽처리장치 활용률을 극대화할 수 없으며, 배치 사이의 중앙처리장치 처리 시간까지 계산과 겹쳐야 동기식 유휴 시간을 줄일 수 있다.
  • 비기본 CUDA 스트림은 중앙처리장치에 빠르게 제어권을 돌려주는 수단이고, CUDA 이벤트는 독립 스트림 사이에서 데이터 의존성과 실행 순서를 보장하는 수단이다.
  • 측정된 병목은 모델이나 커널 자체가 아니라 중앙처리장치와 그래픽처리장치의 교대 실행에서 발생했으므로, 하드웨어 작업을 재조정하는 것만으로도 상당한 처리 시간 감소 여지가 드러난다.

✅ 액션 아이템

  • 연속 배치에서 CPU·GPU가 번갈아 유휴를 만드는 구간을 비기본 CUDA 스트림 기반의 입력·연산·출력 3단계 흐름으로 분리한다.
  • 독립 스트림 간 입력 전송, 계산, 출력 전송의 순서를 깨지 않도록 CUDA 이벤트를 기록·대기 방식으로 의존성을 명시한다.
  • 8B 모델 배치32, 토큰 8천 건 실험의 300.6초 중 24.0% GPU 대기 수치를 기준선으로 두고 비동기화 전후 성능을 비교한다.

❓ 열린 질문

  • 연속 배치에서 CPU와 GPU 유휴 제거를 위해 비기본 스트림 전환만으로 실제 대기율은 어느 수준까지 낮아지는가?
  • 세 개 독립 스트림을 사용할 때 이벤트 의존성을 어떤 위치에 두면 입력·계산·출력 순서가 가장 안정적으로 유지되는가?
  • 배치 크기나 모델 규모가 달라질수록 GPU 대기 24.0% 개선 효과는 어떻게 달라질 것으로 판단할 것인가?

관련 문서

공통 태그와 주제 흐름을 기준으로 같이 보면 좋은 문서를 이어서 제안합니다.