본문으로 건너뛰기

[Ray Serve] SGLang 서버의 순차 배치 처리를 동시 실행으로 전환

PR 링크: ray-project/ray#61189 상태: Merged | 변경: +44 / -8

들어가며

Ray Serve의 SGLang 통합에서 completions() 엔드포인트는 여러 프롬프트를 받을 수 있다. 그러나 기존 구현에서는 프롬프트 리스트를 for 루프로 순회하며 하나씩 순차적으로 생성 요청을 보냈다. SGLang 엔진은 자체적으로 async_generate를 통한 동시 처리를 지원하므로, 리스트를 통째로 전달하면 엔진의 스케줄러가 최적으로 처리할 수 있다.

핵심 코드 분석

Before: 프롬프트별 순차 처리

all_choices = []
total_prompt_tokens = 0
total_completion_tokens = 0

for index, prompt_string in enumerate(prompts_to_process):
    metadata = await self._generate_and_extract_metadata(request, prompt_string)
    total_prompt_tokens += metadata["prompt_tokens"]
    total_completion_tokens += metadata["completion_tokens"]
    # ... choice 생성

After: 배치 전달로 동시 처리

async def _generate_and_extract_metadata(
    self,
    request: Any,
    prompt: Union[str, List[str]],
) -> Union[dict[str, Any], List[dict[str, Any]]]:
    raw = await self._generate_raw(request, prompt)
    # 배치인 경우 리스트 반환
    if isinstance(prompt, list):
        return [self._extract_generation_metadata(r) for r in raw]
    return self._extract_generation_metadata(raw)

# 호출부
results = await self._generate_and_extract_metadata(request, prompts_to_process)

for index, metadata in enumerate(results):
    total_prompt_tokens += metadata["prompt_tokens"]
    total_completion_tokens += metadata["completion_tokens"]
    # ... choice 생성

왜 이게 좋은가

  1. SGLang 스케줄러 활용: 프롬프트 리스트를 한 번에 전달하면 SGLang의 continuous batching 스케줄러가 GPU 활용률을 최적화하여 처리한다. 순차 호출에서는 이전 요청이 끝날 때까지 다음 요청이 대기해야 했다.
  2. 네트워크 왕복 최소화: N개의 개별 async_generate 호출이 1번의 배치 호출로 줄어든다.
  3. 하위 호환성 유지: _generate_and_extract_metadata가 단일 문자열과 리스트를 모두 처리하도록 Union 타입으로 확장하여, 스트리밍 등 기존 단일 프롬프트 경로는 그대로 동작한다.

참고 자료

댓글

관련 포스트

PR Analysis 의 다른글