DGX Spark급 박스 두 대, 하나의 모델: 각 대에 사본을 두고 분할을 중단

운영

7주 동안 로컬 언어 모델은 텐서 병렬 처리를 통해 NVIDIA GB10 머신 두 대에 분할되어 실행되었습니다. 10월 22일, 이를 각 머신에 모델의 전체 사본을 두고 그 앞에 최소 연결 수 기준 프록시를 배치하는 방식으로 교체했습니다. 처리량은 초당 약 180에서 210 토큰으로 증가했으며, 이제 어느 한 머신을 재시작해도 모델이 중단되지 않습니다.

분할했던 이유

각 머신은 CPU와 GPU가 공유하는 128 GB 메모리를 갖추고 있습니다. 9월에는 모델이 한 대의 머신에 탑재되었지만, 캐시는 간신히 들어갔습니다. 사용했던 vLLM 빌드가 이 모델의 KV 캐시를 FP8으로 유지하지 못해 캐시가 BF16으로 저장되었고, 한 대의 머신에는 499,110개 토큰의 캐시를 위한 공간만 있었습니다. 이는 모델의 전체 컨텍스트인 262,144개 토큰 기준 요청 두 개보다도 적은 양입니다. 두 머신 간 직접 네트워크 링크를 통해 텐서 병렬 처리로 분할하면 캐시는 300만 개 토큰 이상으로 늘어났습니다. 우리는 속도가 아닌 공간을 위해 모델을 분할했습니다.

변경 사항

동일 모델의 최신 4비트 빌드(NVFP4, 양자화 인식 증류로 생성)는 약 71 GiB의 메모리를 사용하며, GB10용 커뮤니티 vLLM 빌드(eugr/spark-vllm-b12x)는 캐시를 FP8로 실행합니다. 이제 한 머신에 전체 모델과 0.76에서 1.08백만 토큰의 캐시를 저장할 수 있으며, 머신에 할당된 메모리 양에 따라 전체 컨텍스트 기준 2.9에서 4.1개의 요청을 처리할 수 있는 공간이 확보됩니다. 두 사본 모두 모델 자체의 추측 디코딩(MTP, 4개의 드래프트 토큰)을 사용합니다. 전환 전에 새로운 빌드로 도구 호출 테스트를 실행한 결과 86점을 기록했으며, 교체된 이전 빌드는 75점이었습니다.

측정 결과

두 머신에 분할각 머신에 사본
KV 캐시300만 개 토큰 이상76만 개 및 108만 개 토큰
전체 컨텍스트 기준 요청 수약 12개2.9 및 4.1개
부하 하의 처리량초당 약 180 토큰초당 210 토큰 (111 + 99)
시작 시간약 20분사본당 5에서 13분
한 머신 재시작모델 중단다른 사본이 서비스

복제본 한 개만 사용할 때, 동시에 처리하는 요청 수에 따른 결과입니다. 짧은 프롬프트에서는 요청 1개가 초당 36개 토큰, 4개가 82개, 8개가 109개, 16개가 150개를 생성했습니다. 이메일 에이전트의 긴 프롬프트에서는 4개가 81개, 8개가 113개를 생성했지만 16개는 87개에 그쳤습니다. 8개 이상의 요청이 동시에 들어오면 오히려 속도가 느려졌습니다.

오후 동안 한 복제본은 최대 12개, 다른 복제본은 8개의 요청을 동시에 처리했습니다. 첫 번째 복제본은 초당 91~93개 토큰을 생성하며 분당 26~27개 요청을 완료했고, 두 번째 복제본은 초당 81~83개 토큰을 생성하며 분당 22개 요청을 완료했습니다. 현재 두 복제본 모두 12개를 처리합니다.

포기한 것

공간. 분할된 모델은 300만 개 토큰 이상의 캐시 하나를 가졌지만, 복제본은 더 작은 캐시 두 개를 가지며 요청은 이를 처리하는 복제본의 캐시만 사용할 수 있습니다. 우리의 에이전트는 짧고 중간 길이의 요청을 많이 보내므로, 이들에게는 처리량이 더 중요했습니다. 매우 긴 컨텍스트를 몇 개만 동시에 처리한다면 분할이 여전히 더 나은 선택일 수 있습니다. 우리는 분할 설정을 유지했으며, 되돌리는 작업은 스크립트 하나면 됩니다.

전환 중 발생한 문제

  1. 모델 없이 11분, 그 후 502 오류 30초. 분할된 모델은 같은 머신에서 복제본이 로드되기 전에 중단되어야 했으므로, 에이전트는 약 11분간 대기해야 했습니다. 첫 번째 복제본이 올라왔을 때 프록시는 약 30초 동안 "502 no live upstreams" 응답을 계속 반환했습니다. 백엔드가 다운된 동안 이를 실패로 표시(max_fails=3, fail_timeout=30s)했고, 해당 시간이 지나기 전까지는 재시도하지 않았기 때문입니다.
  2. 프록시를 거치지 않은 클라이언트. 배치 작업 중 하나가 첫 번째 머신의 주소를 설정에 포함하고 있어, 모든 부하가 한 복제본으로만 전달되고 다른 복제본은 여유 용량이 남아 있었습니다. 이제 모든 클라이언트는 프록시를 거치며, 머신의 자체 주소는 헬스 체크에만 사용합니다.
  3. 급변한 지표. 처리량 모니터링 도구는 프록시를 통해 vLLM의 /metrics를 읽었습니다. 두 개의 백엔드가 있을 때 연속된 읽기 작업이 서로 다른 복제본에서 발생하여 카운터가 앞뒤로 급변했고, 모니터링 도구는 모델이 고갈된 것으로 보고했습니다. 이제 각 복제본에서 직접 읽어 합산합니다.
  4. 새 복제본을 중단시켰을 오래된 워치독. 분할 설정에는 모델이 응답을 멈추면 서비스를 재시작하는 워치독이 있었습니다. 새 서비스는 이전 서비스와 Conflicts=를 선언하므로, 이 재시작은 새 복제본을 중단시켰을 것입니다. 이는 단순히 중지하는 것이 아니라 systemctl disable --now로 꺼야 했습니다. 우리의 운영 계층은 활성화되었으나 실행 중이지 않은 유닛을 재시작하기 때문입니다.
  5. 다른 작업을 수행하는 머신에 메모리를 할당합니다. 한 머신에서 데이터베이스와 사이트 빌드도 함께 실행됩니다. vLLM의 gpu-memory-utilization을 0.78로 설정하면 나머지 작업을 위해 5 GiB만 남았으므로, 이를 0.74로 낮추고 다른 인스턴스가 부하를 담당하는 동안 해당 인스턴스만 재시작했습니다. 이러한 머신에서는 vLLM에 할당하는 메모리 용량이 다른 모든 작업과 동일한 메모리에서 차감됩니다.

이러한 머신이 두 대 있는 경우

Factory Floor는 한 대 또는 두 대의 머신용 프록시 및 실행 설정, 모델 전환 전에 실행하는 상태 확인 및 도구 사용 테스트, 그리고 머신의 나머지 부분을 위한 워치독과 메모리 가드를 제공합니다.

업데이트됨: