8월 21일, 앤트그룹의 Ling 인프라 팀이 알리바바, SGLang 팀과 함께 LMSYS 블로그에 Weight Cache Daemon이라는 컴포넌트를 공개했다. GPU 메모리에 상주하는 프로세스가 양자화되고 분할된 가중치를 계속 유지하고 있다가, 새로 뜨는 추론 엔진이 CUDA IPC를 통해 제로카피로 매핑해 가져가는 방식이다. 팀이 제시한 수치에 따르면 Ling-2.6-1T FP8의 가중치 로딩 시간은 약 495초에서 0.63초로, 전체 시작 시간은 8.8분에서 0.528분으로 줄었다.
8분 30초 중 8분이 디스크 읽기였다
팀은 전체 시작 과정을 단계별로 나눠 측정했다. H20-3e 8장에서 Ling-2.6-1T FP8을 구동하고 가중치를 3.5T NVMe SSD에 둔 상태에서, 기동부터 요청을 처리할 수 있게 되기까지 약 527초가 걸렸다. 이 중 가중치 로딩이 495초, 비율로는 93.9%를 차지했다. tokenizer 초기화는 13초, torch 분산 초기화는 5초, CUDA graph 캡처는 7.7초였고, 나머지를 다 합쳐도 6초가 되지 않았다.
각 GPU는 디스크에서 약 120GB의 safetensors를 읽어 역직렬화하고, 텐서 병렬 방식에 맞춰 분할한 뒤 FP8 양자화와 가중치 재배열을 수행한다. 분할 조각은 총 161개다. 이 파이프라인은 재시작할 때마다 처음부터 다시 돌려야 하지만, 결과물 자체는 결정적이다. 같은 모델, 같은 설정이라면 최종적으로 GPU 메모리에 올라가는 텐서는 매번 동일하며, 대개는 직전 프로세스가 막 종료된 시점에도 그 자리에 그대로 남아 있다.
프로덕션 환경에서 이 몇 분은 재시작 동안 P99 테일 지연이 크게 튀고, 처리 중이던 요청이 전부 실패하거나 무한 대기에 빠진다는 뜻이다. 롤링 업그레이드와 장애 복구 모두 이 주기에 발목이 잡힌다.
가중치를 GPU 메모리에 남겨둔다
GPU마다 daemon 프로세스가 하나씩 돌며, TP rank 하나에 대응한다. daemon은 전체 파이프라인을 거쳐 디스크에서 한 번 로드한 뒤, model.state_dict()에 담긴 모든 파라미터와 버퍼를 CUDA IPC 핸들로 내보내 Unix 소켓을 통해 접속해오는 엔진 프로세스에 전달한다. 엔진 쪽에서는 먼저 meta device 위에 모델 구조만 세우고 메모리는 전혀 할당하지 않은 상태에서, 각 파라미터의 data 포인터를 매핑된 텐서로 향하게 한다. 두 프로세스는 동일한 물리 GPU 메모리를 공유하며 그 과정에서 복사는 전혀 일어나지 않는다. FP8 양자화 과정에서 생성되는 weight_scale 같은 후처리 파라미터도 함께 캐시되어 재양자화를 생략한다.
안전장치는 두 단계로 걸려 있다. 하나는 설정 지문으로, 모델 경로, TP/PP/DP 분할, 양자화 방식과 설정 해시, dtype이 모두 일치해야 하며, 여기에 GPU 컴퓨트 능력과 torch 버전도 환경 정보로 함께 기록된다. 아키텍처나 torch 버전이 다르면 후처리 분기가 달라져 가중치는 깔끔하게 매핑되더라도 값이 엉뚱하게 나올 수 있다. 환경 정보를 지문에 포함시키면 이런 눈에 띄지 않는 오류를 명확한 불일치로 바꿔 디스크 로딩으로 되돌아가게 만든다.
다른 하나는 양자화 방식 화이트리스트다. 현재 검증된 것은 비양자화와 block-wise FP8뿐이며, per-tensor FP8, Marlin, AWQ/GPTQ는 곧바로 오류를 낸다. 이유는 IPC가 원시 텐서 데이터만 내보내는 반면, 이 방식들은 효과 일부를 파이썬 쪽 메타데이터에 담거나 가중치를 재배열·전치하기 때문이다. 그대로 매핑하면 값이 틀리게 나온다. 팀은 잘못된 결과를 조용히 내놓는 대신 명확하게 오류를 내는 쪽을 택했다.
daemon이 다운돼도 이미 돌고 있는 엔진에는 영향이 없다. CUDA의 참조 카운트가 살아 있는 한 메모리는 유지되며, 양쪽 프로세스가 모두 종료돼야 해제된다. daemon이 재시작되면 다시 디스크에서 읽어 핸들을 재발급하고, 그제야 새 엔진이 다시 접속할 수 있다.
덤으로 해결된 핫스탠바이 비용 문제
이 컴포넌트에는 세 가지 모드가 있다. daemon(엔진이 직접 daemon을 띄우며, 최초 기동은 기존과 마찬가지로 느리다), client(이미 돌고 있는 daemon에 접속해 1초 미만으로 재시작), off(기본값, 디스크에서 읽으며 Ling-2.6-1T 기준 405~411초가 걸린다).
시작 속도 향상보다 더 실용적인 것은 몇 가지 배포 형태다. 같은 GPU 위에서 여러 엔진 인스턴스가 같은 가중치를 매핑하면 디스크 읽기와 양자화가 각각 한 번씩만 일어난다. 우선순위가 높은 온라인 서비스와 낮은 오프라인 배치 작업이 같은 GPU를 공유하다가, 후자가 선점당해도 1초 미만으로 다시 뜬다. 주-예비 전환에서는 예비 엔진이 같은 가중치를 제로카피로 붙잡고 웜 상태를 유지하다가, 주 인스턴스가 다운되면 1초 안에 넘겨받는다.
마지막 항목은 그대로 비용 항목이다. 대략 계산하면, Ling-2.6-1T 인스턴스 하나가 H20-3e 8장을 차지한다. 전통적인 핫스탠바이 방식이라면 그 옆에 8장을 더 놀리며 대기시켜야 한다. 가중치를 공유하는 예비기로 바꾸면 이 통째로 놀고 있던 GPU 그룹이 사라진다. 롤링 업그레이드도 마찬가지다. 8.8분에 한 번꼴로 잡으면 인스턴스 하나가 재시작 한 번마다 약 1.2GPU시간을 공회전으로 태우는 셈이고, 인스턴스 수가 수백 대인 클러스터에서는 업그레이드 한 번에 세 자릿수 GPU시간이 쌓인다.
아직 끝이 아니다
Weight Cache Daemon은 Fast Engine Recovery Framework의 1단계일 뿐이다. 로드맵에는 콜드 스타트 10초 이내, 핫스탠바이 전환 1초 이내라는 목표가 적혀 있다. 다음 단계로는 CUDA graph 직렬화, kernel 캐시, 분산 초기화 최적화가 계획돼 있다. 위의 분해 결과로 보면 이 항목들을 합치면 약 26초로, 가중치 로딩 이후 남은 가장 큰 부분에 해당한다.
Qwen3-235B FP8급 수치도 함께 공개됐다. 가중치는 약 235GB, 디스크 로딩은 306~327초, IPC 매핑은 1초 미만으로 약 500배 빠르다. Ling-2.6-1T급은 약 780배에 이른다.
블로그는 막 공개된 2.8T 규모의 Kimi K3도 슬쩍 언급했다. 파라미터 수가 늘어날수록 디스크 로딩 시간은 거의 선형으로 늘어나지만, IPC 매핑은 거의 상수 수준을 유지하며, 이 격차는 갈수록 벌어질 수밖에 없다. 이미 조 단위 파라미터 모델을 운영 중인 팀에게 재시작 비용은 "몇 분 기다리는 일"에서 "거의 기다리지 않는 일"로 바뀌고 있다. 이 변화가 영향을 미치는 것은 가용성 수치만이 아니라, 설정을 자주 바꿀 용기, 같은 GPU에 서비스 두 개를 욱여넣을 용기이기도 하다.
참고 출처: LMSYS Org 기술 블로그, CocoLoop, SGLang 프로젝트 문서. 기동 시간 분해, 가중치 로딩과 IPC 매핑 비교 수치는 모두 팀이 공개한 단일 노드 벤치마크 표에서 가져왔다.