연속 배치는 질문을 바꾼다. “요청을 몇 개 모을까”가 아니라 “이번 스텝에 누가 참여할까”를 매 스텝마다 다시 정한다.
스텝 단위로 다시 짜기
토큰 하나를 생성하는 스텝이 끝나면 스케줄러가 개입한다. 끝난 요청은 자리를 비우고, 큐에서 기다리던 요청이 그 자리에 들어온다. 배치의 구성원이 매 스텝 달라진다.
낙오자 문제가 여기서 사라진다. 20토큰에서 끝난 요청은 21번째 스텝에 이미 자리를 비웠고, 그 자리는 새 요청이 쓴다.
두 종류의 스텝
다만 새 요청이 합류할 때 성격이 다른 계산이 필요하다.
- 프리필: 새 요청의 프롬프트 전체를 한 번에 계산한다. 무겁고 길이에 비례한다.
- 디코드: 기존 요청들이 토큰 하나씩 나아간다. 가볍고 균일하다.
이 둘을 같은 스텝에 섞으면 프리필이 디코드를 붙잡는다. 진행 중인 요청들의 토큰 간격이 갑자기 튀는 현상이 대개 여기서 온다.
프리필과 디코드를 다루는 선택지
몇 가지 접근이 있고, 각각 다른 것을 포기한다.
- 프리필 우선: 새 요청의 첫 토큰이 빠르다. 대신 기존 요청의 토큰 간격이 흔들린다.
- 디코드 우선: 진행 중인 응답이 매끄럽다. 대신 새 요청의 대기가 길어진다.
- 청크 프리필: 긴 프롬프트를 쪼개 여러 스텝에 나눠 넣는다. 양쪽을 완화하지만 구현이 복잡하다.
세 번째가 현재 실무의 기본값에 가깝다. 다만 어느 선택이든 자리 수의 상한은 메모리가 정한다. 그 상한이 어디서 오는지가 다음 부의 주제다.