Skip to content

메모리 예산을 상징하는 이미지

radiance에는 "메모리 사용률 95%를 맞춰 주는" 마법이 없다. 설계 글에서 본 대로 모든 풀이 명시적 예산이고, 카드에서 KV 블록과 상주 가중치의 균형은 운영자가 워크로드를 보고 정하는 몫이다. GUIDE §4.3~4.4가 그 규칙과 계산법이다.

카드의 분할: 상주 가중치와 KV 풀 ​

카드는 상주 가중치와 페이징 KV 풀로 나뉜다. 분할은 카드와 모델에서 파생되고, 어느 쪽 풀이 몇 바이트인지를 직접 쓰는 플래그는 없다. 대신 그 입력을 직접 준다.

  • --gpu-headroom-mib — 카드 공간을 아예 안 잡고 비워 둔다(기본 96MiB). 힙에 커널 코드 오브젝트처럼 엔진이 안 잡는 할당을 위해 남기는 돈이다. 이 여유가 모자라면 첫 실행에서 커널 로드가 실패해 정당한 커널이 segfault를 낸다. 시작 로그가 "남은 방"을 계산해 정확한 값까지 알려준다.
  • --gpu-memory-mib N — 같은 노브를 "청구"로 쓴 것. headroom은 카드 빼기 N. 두 플래그는 함께 못 쓴다.
  • --max-model-len, --max-num-seqs — 캐시의 상한을 묶는다.
  • --host-pool-mib — 어떤 expert까지 카드에 남길지 정한다.

비 expert 가중치가 맨 위에서 빠지고, 나머지(수령증의 elastic 줄)를 expert 슬랩과 KV 캐시가 나눈다. 대여 캐시(lending cache; --placement auto 또는 expert_tiered, 가상 메모리 관리)가 켜진 상태에서는 호스트 풀에 못 들어가는 expert만 카드에 남기고, 캐시는 어느 라이브 요청도 안 잡는 블록을 전부 expert 슬랩에 대여한다. 그리고 KV 풀은 항상 탄력적 — 사용 블록 + 버퍼만 쥐고 나머지는 expert 평면이 삼킨다. 반면 --deterministic 등에서는 expert가 먼저고 캐시는 --max-model-len 시퀀스 하나를 지킨다. 카드를 하나도 못 본 호스트 백엔드에서는 RAM의 절반이 카드를 대신한다.

KV 풀 크기 계산하기 ​

시작 로그는 컨텍스트 1토큰이 모든 페이징 그룹에서 얼마인지를 인쇄한다. 곱하면 된다:

1토큰 비용 x 서빙할 컨텍스트 x 동시에 라이브로 둘 세션 수

Flash-Next의 실제 예 — 두 페이징 그룹이 토큰 축을 공유한다. kv_attn이 4토큰 블록당 26.00KiB, kv_qsa_bkey가 3.25KiB. 그러면 토큰당 7.32KiB이고, 200K 시퀀스는 1.43GiB다. 프리픽스 캐시가 있는 세션은 컨텍스트의 약 1.8배를 풀 토큰으로 점유하므로, 라이브 184K 세션 둘에는 약 662K 풀 토큰이 필요하다.

체감 곡선은 가파르다. Flash-Next로 200K 컨텍스트에 184K 세션 둘을 돌릴 때, 풀이 부족하면 두 번째 턴이 프리픽스 적중 0%에 173초(전체 재프리필), 충분히 크면 99% 적중에 3초였다. 풀이 한계에 가까워지면 kv_util이 보여준다. 캐시는 이미 expert가 낼 수 있는 것을 다 받고 있으므로, 더 주려면 --host-pool-mib(RAM 허락 시)를 늘리거나 --kv-cache-dtype fp8로 토큰 비용을 반으로 줄인다.

KV 캐시도 양자화한다: kv-cache-dtype ​

--kv-cache-dtype fp8은 (시퀀스, 헤드)별 descale를 둔 E4M3 캐시로, 토큰 컨텍스트 값을 절반으로 만든다. 실제 양자화라 출력이 조금 바뀌므로 명시적으로 켤 때만 쓴다. 더 좁힌 fp8_v4(V를 int4)와 k6_v4(K도 int6)는 Qwen3.8 계열의 geometry에서 fp8 대비 25/32, 22/32로 줄어든다 — R9700 둘에서 fp8 대비 풀이 +28%, +46% 늘어난 것을 GUIDE가 KL/top-1 표와 함께 실측해 둔다. 프리픽스 캐시·멀티턴 설계상 캐시는 대개 expert가 양보한 것을 다 가진 상태이므로, "풀이 작다"의 해법은 위 두 가지뿐이다.

롱 컨텍스트와 시퀀스 수의 교환 관계 ​

sh
radiance --model m.rad --max-model-len 200000 --kv-cache-dtype fp8 --max-num-seqs 8

--max-model-len은 요청별로 아무것도 예약하지 않는다 — 풀이 대비하는 최악의 상한일 뿐이다. 0이면 모델의 학습 컨텍스트를 쓴다. 시퀀스 수는 단순하지 않다. 각 시퀀스는 점유 블록만 쓰지만, 시퀀스당 고정 비용이 둘 있다.

  • 순환 상태 — 하이브리드 모델은 시퀀스마다 delta-net 상태를(초안 복호화 시 두 벌) 보유한다. Flash-Next는 카드마다 복사본 하나당 54MiB라 32시퀀스가 캐시 몫에서 3.4GiB를 가져간다. bf16 27B처럼 expert가 양보할 게 없으면 어텐션 캐시가 117K토큰쯤으로 줄어 200K 요청 하나도 안 담긴다.
  • 블록 테이블 — 스텝 배치의 테이블은 모든 시퀀스에 대해 전체 컨텍스트 기준으로 깎여 버짓에서 빠진다.

kv: the pool backs N% of the worst case ... M full-length sessions 라인이 컨텍스트 몫만으로 계산한 M을 알려주니, 실제로 띄울 세션 수와 비교한다.

참조 테이블의 배치: embedding, n-gram, 비전 타워 ​

Lookup 테이블은 스텝마다 몇 줄만 읽히므로 카드 아래 티어에서도 싸게 쓸 수 있다. 자기 배치를 받는 테이블이 셋 있다.

플래그값기본 동작
--embedding-placementvram/ram기본 ram — 토큰 임베딩(27B급에서 카드당 GiB 단위)을 호스트 메모리에 고정하고 링크로 줄 단위 읽기. VRAM 한 푼 안 쓴다
--ngram-placementvram/ram/disk/ram=DIR/disk=DIRFlash-Next의 n-gram 표(47.7GiB)를 카드/고정 RAM/컨테이너 직읽기 중 제일 빠른 곳에 둔다. ram=DIR은 tmpfs 파일로 만들어 엔진 두 개가 RAM 하나를 공유한다
--vision-tower-placementvram/ramram은 인코더 타워(예: Qwen3.8-27B 비전 타워 0.86GiB ≈ fp8 24K토큰)를 호스트에 두고 그 VRAM을 KV에 넘긴다. 이미지 한 장당 링크로 한 번 읽기(약 55ms)

카드보다 큰 모델: 디스크 티어 ​

--weights-disk-tier는 카드와 호스트 풀을 합쳐도 안 들어가는 모델을 드라이브가 스텝을 리듬타게 서빙한다. 어느 쪽에도 못 들어가는 라우팅 expert는 컨테이너에만 살고, 각 라우팅 계층의 router가 돈 뒤 그 스텝이 라우팅한 디스크 expert만 두 VRAM 버퍼 중 하나로 읽는다(아무 also도 라우팅하지 않는 expert는 드라이버에 남는다). bf16 Flash-Next(335GiB)가 R9700 둘에서 32K 스텝당 약 28초로 도는 참조 구성이다 — 원래 용도는 체크포인트를 있는 정밀도로 그대로 굴려 보정하거나 비교하는 것이지 프로덕션이 아니다.

컨텍스트가 카드를 넘는다면: KV 스트리밍 ​

--kv-resident N은 드문 그룹의 KV 캐시 전체를 고정 호스트 RAM에 두고, 카드에는 N토큰 링만 남긴다. 매 디코딩 스텝이 고른 블록을 resident화하고(빠진 것을 복사, 가장 차가운 것을 내림 — 내린 블록은 이미 호스트 사본에 있다) 프리필은 호스트 사본에서 계층별로 읽는다. 링은 컨텍스트 길이와 무관하게 고정이라 컨텍스트가 더 이상 VRAM에 묶이지 않는다. 실측: 262K 대화 둘을 16GB 카드 둘에서 띄우면 카드당 3.84GB였던 캐시가 VRAM 0.74GB + 호스트 RAM 3.22GB가 되고, 반납한 VRAM은 expert 슬랩으로 갔다.

sh
radiance --model flashnext.rad --tp 2 --max-model-len 262144 --max-num-seqs 2 --kv-resident 32768

링 권장은 32 768(이하로는 이 값으로 올려진다). 지원은 Qwen3.8-Flash-Next와 GLM-5.3-Flash의 bf16/fp8 캐시 — 밀집 어텐션 모델은 매 스텝 전체 이력을 읽으므로 스트리밍이 없다. /metrics의 kv_stream_*로 misses와 bytes를 본다(자세히는 docs/KV-STREAMING.md).

예산이 왜 이 모양인지 한 문장으로 요약하면 — 재현 가능한 벤치마크와 운영자의 판단을 위해, radiance는 자동 최적화 대신 계산 가능한 플래그를 준다. 다음 글에서는 속도 쪽 핵심인 초안 복호화와 멀티 카드 동작을 본다.

오픈소스를 한국어로 읽고 배웁니다.