Llama-Server가 멀쩡한 KV 캐시를 날려버리는 문제와 해결 방법
Llama-Server is Throwing Away Your Perfectly Good KV Caches, and How to Fix It
핵심 요약
llama-server의 KV 캐시 복구 시 발생하는 재연산 문제를 체크포인트 메타데이터를 담은 '사이드카' 파일로 해결했습니다.
- KV 캐시 복구 문제 — 서버 재시작 후 복구된 캐시가 첫 요청 시 무시되고 재연산되는 현상 발생
- 근본 원인 — 프로세스 메모리에만 존재하는 체크포인트 메타데이터가 디스크 저장 시 누락됨
- 사이드카 해결책 — 체크포인트 정보를 별도 파일로 저장하여 복구 시 재연산 없이 즉시 로드
- 성능 개선 — 복구 후 쿼리 응답 속도가 약 720배 향상됨
2026년 7월 6일 수정: markole이 정확히 지적했듯이, 버그를 어떻게 발견하고 테스트하고 고쳤는지 굳이 알고 싶은 사람이 아니라면, LLM이 생성한 빽빽한 요약본을 읽을 필요 없게 그냥 핵심만 딱 적어주는 게 커뮤니티에 더 도움이 됨. 이 친구가 핵심을 잘 짚었음: "그냥 '야, llama.cpp에서 kv 캐시 슬롯 제대로 저장하고 싶으면 여기 diff 파일 써라'라고 했으면 좋았을 텐데." 그래서 여기 올림: https://github.com/TheTom/llama-cpp-turboquant/pull/206/changes.
왜 이걸 업스트림에 PR 안 보냈냐고? 솔직히 말하면 AI 도움을 좀 받았는데, 난 그게 아무 문제 없다고 보거든. 근데 GGML 쪽은 아님. 자기들 규칙 안 지키는 사람한테 엄청나게 적대적이더라고. 그래서 굳이 귀찮게 안 하려고.
서론
디스크에서 2.49GB짜리 상태를 1.23초 만에 복구하는 걸 지켜봤는데, 바로 날려버리더라. llama-server의 슬롯 저장/복구 기능은 저사양 하드웨어에서 긴 컨텍스트를 다룰 때 딱 필요한 기능임. 세션을 디스크에 파킹해뒀다가 나중에 다시 불러와서 프리필(prefill) 비용을 또 낼 필요가 없게 만드는 거니까. 복구 자체는 완벽하게 작동함. 근데 프로세스를 재시작하면 이 기능이 사실상 무용지물임. 복구 후 첫 번째 쿼리가 재구성된 상태를 전부 폐기하고 처음부터 다시 프리필을 돌려버리거든. 원인은 프로세스 메모리에만 존재하는 메타데이터 한 조각 때문이었음.
테스트 환경: Qwopus3.6-27B Q6_K (하이브리드 아키텍처), 2× Tesla P100 레이어 분할, turbo4 KV 양자화.
발견 과정
고컨텍스트 벤치마크를 돌릴 때 복구는 기계적으로 완벽해 보였음. 2.49GB가 1.23초 만에 VRAM으로 돌아왔으니까. 근데 바로 다음 /completion 요청에서 forcing full prompt re-processing due to lack of cache data라는 로그가 찍히면서 전체 재프리필이 돌아감 (100K 컨텍스트 기준 약 17.5분 소요). 저장 빠르고, 복구 빠른데, 결국 다 갖다 버리는 꼴임.
(이 발견 당시에는 검증 때와는 약간 다른 설정을 썼음. 아래의 모든 수치는 패치된 빌드에서 제어된 검증을 거친 결과임.)
근본 원인
llama_state_seq_save_file은 토큰과 물리적 KV 셀은 직렬화하는데, 프로세스 메모리에만 존재하는 체크포인트 메타데이터 리스트인 slot.prompt.checkpoints는 저장하지 않음. 콜드 재시작 후 첫 요청은 항상 약간의 롤백이 필요함. 프롬프트 끝부분을 다시 토큰화하면 BPE 경계가 바뀔 수 있어서, 로짓을 생성하려면 최소한 토큰 하나는 다시 처리해야 하거든. 재사용 경로는 커버링 체크포인트(covering checkpoint), 즉 롤백 대상 지점과 같거나 그 이전 지점에 있는 체크포인트를 통해서만 롤백이 가능함. 체크포인트 리스트가 비어 있으니 서버는 아무것도 못 찾고 포기한 뒤 전부 다시 계산하는 거임.
실패한 수정안 (v1)
뻔한 해결책은 복구 시점에 복구된 상태로부터 체크포인트를 합성하는 거였음. 근데 실패했고, 그 실패가 교훈을 줌. 합성된 체크포인트는 끝부분(tip), 즉 100K 실행 기준 100,042 위치에 놓이는데, 롤백 대상은 그보다 앞인 100,034 위치거든. 체크포인트는 자기 위치와 같거나 그 이후의 롤백만 처리할 수 있어서, 끝부분 체크포인트는 항상 발생하는 롤백에 아무런 도움이 안 됨. 불변의 법칙: 끝부분 의 체크포인트가 필요한데, 그건 저장 시점에만 존재함.
