Galahad가 LLM의 반복 읽기를 한 번만 지불하게 만든다

Working Around the Compute Ceiling: Byte-Exact Memory in Galahad Makes LLM Reading a One-Time Cost LLM Reading a One-Time Cost

HF Daily2609.39358

Sietse Schelpe2026-09-30

무엇인가

이 논문이 다루는 문제는 트랜스포머 서빙이 요청 간 무상태라는 점이다. 모델은 토큰당 유한한 연산만 수행하는데, 같은 문서에 두 번째 질문을 하면 첫 토큰부터 문서의 어텐션 상태를 다시 계산한다. 저자들은 7개 실제 데이터셋에서 프롬프트 토큰의 98.7%가 모델이 이미 읽은 텍스트였다고 보고한다. vLLM과 SGLang의 prefix cache는 GPU 메모리 안에서만 동작하고 메모리 압박에 밀리거나 프로세스가 재시작되면 사라진다. 논문은 연산 상한 자체를 높이려 하지 않고, 그 아래 예산이 이미 한 일을 반복하는 데 얼마나 쓰이는지를 묻는다. 결론은 "추론 비용의 단위는 전체 텍스트가 아니라 새 텍스트여야 한다"는 것이다.

어떻게 동작하나

해법은 Galahad라는 단일 공유 라이브러리(libgalahad.so, Linux x86-64, OpenSSL libcrypto와 zstd 의존)다. vLLM에는 KV 커넥터로, SGLang에는 HiCache 스토리지 백엔드로, llama.cpp에는 슬롯 저장·복원으로 붙으며 모델 가중치나 런타임 소스 코드는 수정하지 않는다. 테넌트 ID와 모델 지문이 없으면 시작을 거부해 다른 모델·테넌트의 상태를 로드할 수 없게 한다. 구성 요소는 둘이다. Taliesin은 입력 바이트·모델·테넌트 지문 아래 KV 상태를 저장하고, 같은 바이트가 다시 나타나면 재계산 대신 로드한다. 회전 위치 인코딩 때문에 개별 KV 행은 위치에 의존하므로(직접 테스트에서 344,064개 행 중 0개가 일치) 재사용은 토큰 위치가 정확히 맞는 블록 단위로만 일어난다. Blaise는 문서를 바이트 그대로 섹션으로 나눠 보관하고, CPU에서 질문에 필요한 한 섹션을 골라 그 텍스트만 모델에 넘긴다. 선택 기법은 공개되지 않았고, 모델이 Blaise 색인을 한 번 읽고 Taliesin이 그 읽기를 보관하는 두 번째 모드는 설계에만 있고 이 논문에서는 평가하지 않았다.

무엇과 다른가

정확성은 fail-closed 원칙으로 다룬다. 확인 해시, 라이선스 서명, 테넌트 분리, 로드 시 바이트 비교라는 네 가지 방어 각각에 대해 방어를 켠 경우·끈 경우·복구한 경우로 공격을 3회씩 수행했고 네 가지 모두 기준을 통과했다. 주소 새니타이저를 포함한 10개 분석 도구 점검에서는 out-of-bounds 읽기 1건이 발견돼 릴리스 전에 수정됐다. 검사를 통과하지 못한 로드는 재계산되고 요청은 정상 완료되며, 재시작·재수화·핫로드 후 복원된 상태는 262,144개 출력 로짓이 모두 일치했다.

어떻게 쓰나

핵심 실험은 13개 위키백과 문서(434KB, 96,726토큰, 11블록)에 100개 사실을 심고 코퍼스 깊이 1~99% 지점에서 패러프레이즈로 질문한 회수 테스트다. Gemma 4 31B(4비트)를 RTX A6000에서 돌렸고, 매 질문 전에 런타임 자체 캐시를 비워 재사용이 반드시 Galahad에서 오게 했다. Galahad 없는 베이스라인은 12,000토큰 창이라 코퍼스의 마지막 12%만 본다. Taliesin 단독으로 모델이 전체 코퍼스를 보게 했을 때 3개 런타임에서 100문항 중 98~100개를 맞혔고 베이스라인은 10개였다. llama.cpp에서 질문당 평균 53,219개 프롬프트 토큰 중 99.5%가 Taliesin에서 로드됐으며, 잘린 베이스라인(질문당 9,700토큰)보다 5.5배 많은 토큰을 처리하고도 3.1배 빨랐고(3.01초 대 9.25초) GPU 에너지는 79% 적었다(572J 대 2,754J). vLLM 자체 캐시를 질문 사이에 유지하면 99/100, 1.09초, 329J였다. Blaise를 더하면 질문당 약 668토큰만 읽고 모든 런타임에서 100/100을 맞혔으며, vLLM 기준 0.59초·200J로 베이스라인의 8.11초·2,402J 대비 시간 13.7배, 에너지 92%를 줄였다. llama.cpp에서 Taliesin 단독의 3.1배가 Blaise로 14.5배가 됐다. 코퍼스 저장은 96,726토큰 prefill 한 번으로 llama.cpp 96초·27.8kJ, vLLM 108초·28.4kJ가 들었고, 이후 질문마다 2,182J·6.2초를 아껴 에너지는 13문항, 시간은 16문항 뒤 회수된다. Blaise 인덱싱은 0.1초였고 GPU 토큰을 쓰지 않았다. 튜닝된 RAGFlow 파이프라인은 77/100을 맞혔다.

전제와 한계

튜닝하지 않은 데이터로는 헬프데스크 티켓, 고객지원 로그, 추출 오류가 있는 PDF, SWE-bench Lite, The Stack, AgentBench, WebArena에서 뽑은 349문항을 3개 런타임에서 평가했다. 프롬프트 토큰의 98.69%가 Taliesin에서 로드됐고(llama.cpp 99.49%, vLLM 99.37%, SGLang 97.21%), Taliesin 단독은 329~333개(94~95%), Blaise를 더하면 319~321개(91~92%)를 맞히면서 질문당 3~10배 빨랐다. 서빙 지표로는 Gemma 4 12B·약 5,200토큰 프롬프트에서 첫 토큰 시간이 7개 GPU 모두 개선됐고(RTX PRO 4500 1,138.8ms→391.2ms, H100 SXM 251.2ms→191.0ms), H100의 Qwen3-30B-A3B(16세션, 동시성 8) 처리량은 초당 2.643→3.424턴(+29.6%)이었다. 로드 3건 중 1건을 일부러 실패시켜도 2.716턴으로 베이스라인보다 높았다. 24,018토큰 블록 복원은 81ms, 96,726토큰 코퍼스는 Gemma 4 31B에서 17.1~17.2GB(llama.cpp·vLLM), SGLang에서 39.0GB를 차지했고 DeepSeek-V4-Flash(284B)의 93,157토큰은 27.6GB였다. A40에서 5.97M 토큰(30,000토큰 블록 200개)도 5/5 정답에 GPU 메모리 24.4~24.7GB였고, 1M~50M 사다리는 24/25(1건은 하네스 파싱 오류)에 피크 33.8~34.1GB였다. GKE L4에서는 파드 재시작을 넘겨 63.9%가 히트했고 SIGKILL 후 손상 레코드는 0이었다. vLLM에서 30/30 모델이 저장·로드·히트에 성공했고, 284B 모델은 2×H200에서 100문항 중 98개를 0.133초·143J에 답했다.

개발자 관점에서 이 시스템은 같은 문서에 반복 질의하는 지원, 코드, 법률, 에이전트 워크로드에 직접 해당한다. 도입 전에 확인할 것은 블록 경계가 토큰 위치 기준으로 정확히 맞는지, 저장소가 감당할 디스크 예산과 최소 여유 공간 설정, 로드 실패 시 재계산으로 정상 완료되는 fail-closed 동작, 테넌트·모델 지문 분리가 실제로 걸려 있는지다. 또 하나 중요한 전제는 메모리가 주어진 텍스트에서 시작한다는 점이다. 50개 messy-PDF 질문 중 9개는 PDF 텍스트 추출기가 답을 잃어버려 추론 전에 이미 정보가 사라졌고, 어떤 메모리 계층도 상류 파서가 버린 텍스트를 되살릴 수 없다. 논문은 이 구조가 작은 모델로도 긴 컨텍스트 모델이 필요한 질문을 처리하게 만들 수 있다고 주장한다.

저자가 명시한 한계도 분명하다. 이 논문은 시스템 기술이며 저장 포맷, Blaise의 내부 구조, 보안 설계의 구현 세부는 특허 출원 중이라 공개하지 않았고 Blaise의 선택 기법도 밝히지 않는다. Blaise의 두 번째 모드, 잘 추출되지 않은 PDF로의 섹션 선택 확장, 더 많은 모델과 독립 운영자 결과는 향후 과제로 남겨졌다. 7개 데이터셋 평가는 런타임당 1회 실행이고 모든 실험은 저자가 임대한 클라우드 GPU에서 수행됐다. 또한 이 논문은 Sikka와 Sikka가 제시한 토큰당 연산 상한을 반박하지 않는다. 모델이 답하는 방식과 토큰당 연산은 그대로 두고, 반복 작업과 검색과 검증을 모델 밖으로 옮겨 상한 아래에서 낭비를 줄이는 접근이라고 스스로 위치를 규정한다.