재현성
재현성 (Reproducibility)
같은 입력을 넣어도 매번 같은 결과가 나오길 기대하지만, vLLM은 기본적으로 성능을 우선해서 재현성을 보장하지 않아요. 이 문서는 재현 가능한 결과를 얻으려면 어떻게 설정해야 하는지 설명해요.
vLLM이 재현성을 보장하지 않는 이유
vLLM은 성능을 위해 기본적으로 결과의 재현성을 보장하지 않아요. 샘플링이 배치 스케줄링에 따라 달라질 수 있기 때문인데, 같은 요청이라도 다른 동시 요청, 배치 크기의 변화, 추측 디코딩의 배치 확장 같은 요인 때문에 배치가 매번 다르게 묶일 수 있어요. 이런 배치 변화는 Torch 연산의 수치적 불안정성과 결합해 매 단계의 logit/logprob 값을 조금씩 다르게 만들고, 그 차이가 누적되면 결국 다른 토큰이 샘플링될 수도 있습니다.
재현 가능한 결과 얻기
재현 가능한 결과를 얻으려면 다음을 할 수 있어요.
- 오프라인 모드:
VLLM_ENABLE_V1_MULTIPROCESSING=0을 설정하면 스케줄링을 결정적으로 만들어요. 또는 batch invariance를 활성화해 출력이 스케줄링에 둔감하게 만들 수 있습니다.
예시: examples/features/batch_invariance/reproducibility_offline.py
경고: VLLM_ENABLE_V1_MULTIPROCESSING=0을 설정하면 사용자 코드(즉 LLM 클래스를 구성하는 코드)의 난수 상태가 바뀌어요.
전역 시드 설정 (Setting the global seed)
vLLM의 seed 파라미터는 다양한 난수 생성기의 난수 상태를 제어하는 데 사용돼요. 특정 시드 값이 주어지면 random, np.random, torch.manual_seed의 난수 상태가 그에 맞게 설정됩니다.
기본 동작 (Default Behavior)
V1에서 seed 파라미터는 기본값이 0이며 각 워커의 난수 상태를 설정해요. 그래서 temperature > 0이어도 매 vLLM 실행마다 결과가 일관되게 유지됩니다.
추측 디코딩 같은 워크플로는 서로 다른 워커가 같은 출력을 샘플링해야 하므로, V1에서 시드를 "미지정"하는 것은 불가능해요. 자세한 내용은 Pull Request #17929를 참고하세요.
참고: 사용자 코드(즉 LLM 클래스를 구성하는 코드)의 난수 상태는 워커가 사용자 코드와 같은 프로세스에서 실행될 때, 즉 VLLM_ENABLE_V1_MULTIPROCESSING=0일 때만 vLLM이 갱신해요.
기본적으로 VLLM_ENABLE_V1_MULTIPROCESSING=1이라서, 난수 상태에 의존하는 후속 연산을 실수로 결정적으로 만들 걱정 없이 vLLM을 쓸 수 있어요.
로그 확률 안정성 (FAQ에서)
질문: vLLM이 출력 토큰에 대해 안정적인 로그 확률(logprobs)을 보장하나요?
답: 아니요, 보장하지 않아요. 배치가 바뀌면 Torch 연산의 수치적 불안정성이나 비결정적 동작 때문에 logprobs에 변동이 생길 수 있어요.
완화 전략:
- 안정성 향상과 분산 감소를 위해
float32를 사용하세요. 다만 메모리를 더 요구합니다. bfloat16을 쓰고 있다면float16으로 전환하는 것도 도움이 될 수 있어요.