ELORA: Multi-LoRA serving 에서 adapter weight 와 KV cache 를 한 pool 에서, usage dependency 를 지키며 관리하기
papers/elora-hpca26.pdf (14쪽) · §III-D p.4 = 논문이 그렇게 쓴 절·쪽 · 해석 = 논문 내용에서 요약자가 끌어낸 설명 · 논문에 없음 = 배경지식·예시 · 용어는 1 절 용어표의 뜻으로만 쓴다 · 그림은 누르면 크게 열린다0한눈에 보기
한 base 모델에 LoRA adapter 여러 개를 붙여 서비스하면, KV cache 는 그것을 계산한 adapter 마다 따로 생기고 그 adapter 의 adapter weight 가 GPU HBM 에 있어야 쓸 수 있다 §I p.1 §III-A p.3.
vLLM 은 adapter weight 와 KV cache 를 고정 분할한 두 영역에서 따로 swap 하며, 이때 invalid KV 가 평균 42.4% 관측됐다. ELORA 는 둘을 한 dependency tree 와 한 cost model 로 관리해 vLLM 대비 TTFT 를 평균 45.7% 줄였다 §VIII-B p.9.
| 그림 요소 | 뜻 | 근거 |
|---|---|---|
| 0.4.10.2.1virtual root | adapter 별 subtree 를 한 tree 로 묶으려고 둔 가상 node. 데이터는 없다 | §V-A p.6 |
| 0.4.20.2.2LoRA node | adapter 하나(label = LoRA ID). query 는 여기서 자기 adapter 를 먼저 match 한다 | §V-A p.6 |
| 0.4.30.2.3KV node | token 열의 KV cache(label = token 열의 hash). 부모 node 가 있어야 쓸 수 있다 | §V-A p.6 |
| 0.4.40.2.4굵은 선 | query 는 LoRA-1 을 match 한 뒤 DFS 로 "To" → "be" → "or" 순서로 가장 긴 prefix 를 찾는다 | §V-B p.6–7 |
| 0.4.50.2.5out | swap-out 은 GPU HBM 의 leaf 에서 시작한다. "or" 는 GPU HBM 쪽 가지의 끝이라 후보다 | §V-B p.7 · 후보 판정은 해석 |
| 0.4.60.2.6in | swap-in 은 host main memory 쪽 subtree 의 맨 위 node 에서 시작한다. "the" 와 LoRA-2 가 후보다. "Hi" 는 LoRA-2 가 올라오기 전에는 올라올 수 없다 | §V-B p.7 · 예시는 해석 |
그림을 보면 GPU HBM 에 있는 node 가 항상 가지의 위쪽에 모여 있다. 아래에서만 빼고 위에서부터만 넣으니, GPU HBM 의 KV node 는 부모 node(LoRA node 포함)도 GPU HBM 에 있다. 논문은 이 규칙으로 GPU HBM 의 KV cache 가 모두 valid 하다고 쓴다 §V-B p.7.
1배경: LoRA adapter 와 KV cache 의 관계
LoRA 는 base weight $W$ 는 고정하고 작은 행렬 한 쌍 $A_t$, $B_t$ 만 학습하는 fine-tuning 기법이다. 이 한 쌍(adapter $t$)이 $W_K$·$W_V$ 에 더해지면 Key·Value 계산식이 바뀐다 §III-A p.3.
그래서 같은 token 이라도 adapter 마다 KV cache 가 다르고, 그 KV cache 로 query 를 실행하려면 같은 adapter 의 adapter weight 가 GPU HBM 에 있어야 한다 §I p.1.
1.1용어표
| 용어 | 정확한 뜻 (이 요약에서) | 기호 | 논문 원문 표기 |
|---|---|---|---|
| 1.1.1.1LoRA | base weight 는 고정하고 low-rank 행렬 한 쌍만 학습하는 fine-tuning 기법. 이 요약은 기법 이름으로만 쓴다 | – | "LoRA [20] is a popular method" (§III-A p.3). 원문은 "LoRA" 를 adapter 한 벌("LoRA for short", §I p.1)과 adapter weight("caching hot LoRAs")에도 쓴다 |
| 1.1.1.2adapter $t$ | 작업 $t$ 용으로 학습된 행렬 한 쌍 $A_t$, $B_t$ 한 벌. LoRA adapter 라고도 쓴다 | $A_t$, $B_t$ | "a unique pair of low-rank matrices $A_t$ and $B_t$" (§III-A p.3), "LoRA adapters" |
| 1.1.1.3LoRA-$i$ · KV$i$-$j$ | 논문 그림의 label. LoRA-$i$ = adapter $i$, KV$i$-$j$ = adapter $i$ branch 의 $j$ 번째 KV node | – | Fig.1·3·6·8 |
| 1.1.1.4adapter weight | adapter $t$ 의 $A_t$, $B_t$ 가 GPU HBM 또는 host main memory 에 차지하는 data. swap·cache 의 대상 | – | "LoRAs" ("swap in LoRAs", "LoRA cold-start") |
| 1.1.1.5base weight | 모든 adapter 가 공유하는 원래 weight. GPU HBM 에 한 벌 상주한다 | $W$, $W_K$, $W_V$ | "original weight matrix", "Resident Base Model" (Fig.1) |
| 1.1.1.6KV cache | hidden state $h$ 에 adapter $t$ 를 적용해 계산한 Key·Value. 계산한 adapter 가 정해져 있다 | $K_t$, $V_t$ | "KV caches", "KVs" |
| 1.1.1.7history KV | 이전 query 가 남긴 KV cache. prefix 가 맞으면 재사용한다 | – | "history KV caches" |
| 1.1.1.8running KV | 지금 실행 중인 query 의 KV cache | – | "running KV caches" (§II p.2, Fig.14) |
| 1.1.1.9invalid KV | GPU HBM 에 있지만 그것을 계산한 adapter 의 adapter weight 가 GPU HBM 에 없어 query 가 쓸 수 없는 KV cache | – | "invalid KV caches" (§I p.1). 비율의 분모(전체 KV 인지 history KV 인지)는 원문에 명시 없음 |
| 1.1.1.10usage dependency | KV cache 는 자기 adapter weight 가, 뒤 token 의 KV cache 는 앞 token 의 KV cache 가 먼저 있어야 쓸 수 있다는 관계 | – | "usage dependencies" (§I p.1, §V-A p.6) |
| 1.1.1.11GPU HBM / host main memory | GPU 메모리(H800 한 장 80 GB) / CPU 쪽 DRAM(256 GB) | – | "GPU memory" / "main memory", "host memory". "HBM" 은 요약의 표기 |
| 1.1.1.12adapter 영역 / KV 영역 | vLLM 이 GPU HBM 을 고정 비율로 나눈 두 구역. 실험 설정은 0.2 / 0.8 | – | "GPU memory space for LoRAs / KVs" (§III-C p.4) |
| 1.1.1.13unified caching pool · block | adapter weight 와 KV cache 를 같은 고정 크기 block 에 담는 하나의 pool. block 예시 크기 16 MB | – | "unified caching pool", "memory block" (§VII p.8, §VIII-L p.12) |
| 1.1.1.14node | dependency tree 의 원소. LoRA node 와 KV node 가 있다 | $i$ | §V-A p.6 은 "block 1 개 = node 1 개" 라 쓰고, Fig.7 은 adapter 하나를 LoRA node 하나로 그린다 |
| 1.1.1.15virtual root · 2nd layer · leaf · branch | virtual root = LoRA node 별 subtree 들을 잇는 가상 node, 2nd layer = LoRA node 층, leaf = 자식 없는 node, branch = LoRA node 하나 아래 subtree | – | "virtual root node", "second layer", "leaves", "LoRA branch". 원문은 swap-in 후보도 "root nodes of each subtree in the main memory" 라 불러 virtual root 와 이름이 겹친다 (§V-B p.7) |
| 1.1.1.16swap-in / swap-out | host main memory → GPU HBM 으로 올리기 / 그 반대 | – | "swap in/out", "load", "offload", "evict" 혼용 |
| 1.1.1.17cold-start | 필요한 adapter weight 나 KV cache 를 GPU HBM 으로 다시 올리는 동안의 지연. LoRA cold-start / KV cold-start 로 나눈다 | – | "cold starts" (§III-A p.3), Fig.12 |
| 1.1.1.18TTFT · TPOT | query 의 첫 output token 까지 시간 · 그 뒤 token 하나당 시간. 논문 수치는 query 평균 | – | "Time-To-First-Token", "Time-Per-Output-Token" (§I p.2, §VIII-A p.9) |
| 1.1.1.19peak load | TTFT < 500 ms 를 지키는 최대 QPS | – | "supported peak load" (§VIII-A p.9) |
| 1.1.1.20Eval | node $i$ 를 GPU HBM 에 남겼을 때의 TTFT 이득 점수 (Eq.6) | $\mathrm{Eval}_i$ | "benefits to TTFT" (§VI-B p.7). 원문의 "access benefits" 는 assess 의 오기로 보인다 |
1.2LoRA adapter 는 어디에 붙나
크기 예시: $d = 4096$, $r = 32$ 이면 $W$ 하나는 $4096^2 \approx 1{,}680$ 만 개 값이고, $A_t$ 와 $B_t$ 는 합쳐 $2 \times 4096 \times 32 \approx 26$ 만 개 값으로 약 1.6% 다. 그래서 작업마다 adapter 를 따로 두어도 GPU HBM 을 적게 쓴다. ELORA 가 adapter weight 를 "rank 방향으로 자른다" 는 말은 그림의 검은 줄처럼 $A_t$ 를 길이 $d$ 의 열 $r$ 개, $B_t$ 를 길이 $d$ 의 행 $r$ 개로 나눈다는 뜻이다 §VII p.8. tensor parallel 의 rank(GPU 번호)와는 관계가 없다.
adapter 는 작업별로 따로 학습한 $A_t$, $B_t$ 한 쌍이고, $r$ 은 학습을 시작할 때 정하는 크기다. 학습이 끝나면 $A_t$, $B_t$ 의 값과 $r$ 이 함께 파일로 저장된다. 서버는 이 파일들을 등록해 두고, 요청은 그중 하나를 지정한다 §III-A p.3. 그래서 같은 서버에서 $r$ 이 다른 adapter 가 함께 쓰일 수 있다. 논문 실험의 adapter 는 $r$ 이 32 또는 64 였고 §III-B p.3, ELORA 는 $r$ 이 다른 adapter 를 쓰는 요청을 한 batch 로 묶으려고 SGMV 를 쓴다 §VII p.8.
1.3한 projection 을 확대하면
1.4같은 문장인데 adapter 마다 KV cache 가 다르다
| $A$ ($2\times1$) | $B$ ($1\times2$) | $W_K + AB$ | $K = (W_K + AB)\,h$ | |
|---|---|---|---|---|
| 1.4.2.1base weight 만 | – | – | $\begin{bmatrix}1&0\\0&1\end{bmatrix}$ | $[1,\ 2]$ |
| 1.4.2.2LoRA-1 | $[1,\ 0]^\top$ | $[0,\ 1]$ | $\begin{bmatrix}1&1\\0&1\end{bmatrix}$ | $[3,\ 2]$ |
| 1.4.2.3LoRA-2 | $[0,\ 1]^\top$ | $[1,\ 0]$ | $\begin{bmatrix}1&0\\1&1\end{bmatrix}$ | $[1,\ 3]$ |
앞 layer 에서 adapter 가 출력을 바꾸면 다음 layer 에 들어가는 $h$ 부터 달라지므로, LoRA-1 로 계산한 KV cache 를 LoRA-2 query 에 그대로 쓸 수 없다 해석. 또 history KV 를 재사용해도 새 token 을 계산하려면 그 adapter 의 adapter weight 가 GPU HBM 에 있어야 한다 §III-A p.3. 논문은 이 관계를 usage dependency 라 부르고, adapter weight 가 GPU HBM 에 없는 KV cache 를 invalid KV 라 부른다 §I p.1.
1.5query 마다 adapter 는 누가 정하나
논문은 query 의 task 에 따라 해당 adapter 의 $A_t$, $B_t$ 를 GPU HBM 에 load 한다고 쓴다 §III-A p.3. 실험에서는 dataset 의 속성(model 이름·언어 쌍·task scene)으로 query 마다 adapter 를 정했다 §III-B p.3. 모델이 adapter 를 자동으로 고르는 routing 은 논문이 다루지 않는다 해석. vLLM 에서는 --lora-modules name=path 로 adapter 를 등록하고 요청의 "model": "name" 으로 고른다 논문에 없음.
| 실험 시나리오 | query 내용 → adapter 대응 | 도착 시각 |
|---|---|---|
| 1.5.1.1chatbot | LMSYS-33k 대화. trace 의 model 이름으로 adapter 를 정한다 §III-B p.3 | LMSYS timestamp 를 비율대로 scale |
| 1.5.1.2번역 | OPUS-100 문장 쌍. 언어 쌍 하나당 adapter 하나 (예: French→English) §III-B p.3 | MAFT 호출 빈도 상위 $n$ 개 함수의 도착 패턴을 adapter $n$ 개에 대응 |
| 1.5.1.3personal agent | Taskmaster 대화. task scene 하나당 adapter 하나 §III-B p.3 | 번역과 같은 MAFT 방식 |
1.6나머지 용어
swap · cold-start
GPU HBM(H800 80 GB)이 모자라면 adapter weight 나 KV cache 를 host main memory(256 GB)로 내리고(swap-out), 필요할 때 PCIe 로 다시 올린다(swap-in). 다시 올릴 때의 지연을 cold-start 라 하고, 논문은 LoRA cold-start 와 KV cold-start 로 나눠 잰다 §III-A p.3 §VIII-C p.10.TTFT · TPOT · peak load
TTFT 는 query 의 첫 output token 까지 시간, TPOT 는 그 뒤 token 하나당 시간이고, 논문 수치는 query 평균이다. peak load 는 TTFT < 500 ms 를 지키는 최대 QPS 다 §VIII-A p.9. 논문은 queue 대기·LoRA cold-start·KV cold-start 가 TTFT 와 TPOT 모두에 영향을 준다고 쓴다 §III-A p.3.LRU (Least Recently Used)
가장 오래 안 쓴 것부터 내보내는 교체 규칙이다 논문에 없음. vLLM 은 adapter 영역과 KV 영역에서 LRU 를 따로 쓴다 §III-C p.4. 논문은 LRU 순위와 방문 빈도·swap 비용 순위 사이에 뚜렷한 상관이 없음을 보인다 (Fig.5) §III-D2 p.5.tree · root · leaf
root 에서 가지가 갈라지는 자료구조이고, 자식이 없는 node 를 leaf 라 한다 논문에 없음. ELORA 는 virtual root → LoRA node(2nd layer) → 앞 token KV node → 뒤 token KV node 순서를 tree 로 적는다 §V-A p.6.2문제: vLLM 에서 TTFT 가 높아지는 이유
① intra-LoRA: adapter weight 가 swap-out 돼도 그 adapter 의 KV cache 는 GPU HBM 에 남아 invalid KV 가 된다 (vLLM 평균 42.4%) §I p.1.
② inter-LoRA: adapter 영역과 KV 영역이 고정 분할이라 부하가 바뀌면 한 영역만 가득 차고, LRU 순위는 방문 빈도·swap 비용과 뚜렷한 상관이 없다 §III-D2 p.5.
2.1① invalid KV: adapter weight 없이 남은 KV cache
"In this case, the cached KVs are actually 'invalid', because the query cannot run without the required LoRA, showing their inherent usage dependencies."§I p.1 · invalid KV 평균 42.4% 는 §I p.1, §III-D1 p.5 (§VIII 평가에서 측정)
2.2② 고정 분할과 LRU
Fig.5 — LRU 만으로 부족한 이유
3기법: ELORA 의 두 부품
① Cache manager: adapter weight 와 KV cache 를 같은 크기 block 의 unified caching pool 에 담고, virtual root → LoRA node → KV node tree 로 usage dependency 를 유지해 GPU HBM 에 invalid KV 가 남지 않게 한다 §V-B p.7.
② Cache swapper: 100 ms 마다 모든 node 의 Eval 을 갱신하고, GPU HBM 이 가득 차면 Eval 이 낮은 leaf 부터 swap-out, 사용률이 낮으면(원문 예: 70% 미만) Eval 이 높은 subtree 맨 위 node 부터 swap-in 한다 §VI-C p.8.
ELORA 는 일을 두 부품에 나눈다. cache swapper 는 tree 의 node 마다 "GPU HBM 에 남길 가치" 점수 $\mathrm{Eval}_i$ 를 계산하고 swap 순서를 정한다. cache manager 는 GPU HBM 이 얼마나 찼는지 보고 swap 을 요청하고, 정해진 순서대로 실제 memory 이동을 한다 §IV p.5–6. swap 하는 대상은 node 하나, 즉 adapter weight 또는 KV cache 의 고정 크기 block 하나다 §V-A p.6.
| swap-out | swap-in | |
|---|---|---|
| 3.0.5.13.0.3.1언제 | GPU HBM 이 가득 찼을 때 | GPU HBM 이 비었을 때 (원문 예: 사용률 70% 미만) |
| 3.0.5.23.0.3.2후보 | GPU HBM 에 있는 leaf node | host main memory 쪽 subtree 의 맨 위 node |
| 3.0.5.33.0.3.3순서 | $\mathrm{Eval}_i$ 낮은 것부터 | $\mathrm{Eval}_i$ 높은 것부터 |
| 3.0.5.43.0.3.4Fig.6 예 | ② KV2-1 (가장 cold 한 leaf) | Fig.6 에는 없음 |
출처: §VI-C p.8 · §V-B p.7
tree 규칙은 "어떤 node 를 내보내도 되는가" 만 정한다. swap-out 은 GPU HBM 의 leaf 만 할 수 있다 §V-B p.7. 그런데 GPU HBM 에는 leaf 가 여러 개 있으므로, 그중 무엇을 먼저 내보낼지는 tree 규칙이 정하지 못한다. cache swapper 는 이 순서를 정하려고 후보 leaf 들을 $\mathrm{Eval}_i$ 오름차순으로 정렬하고, cache manager 는 $\mathrm{Eval}_i$ 가 가장 낮은 leaf 부터 swap-out 한다 §VI-C p.8.
$\mathrm{Eval}_i$ 를 LRU 순서 하나로 대신하지 않는 이유는 Fig.5 의 관측 때문이다. node 의 마지막 사용 시각 순위는 node 의 방문 빈도 순위·swap 비용 순위와 뚜렷한 상관이 없었다 §III-D2 p.5. 그래서 논문은 마지막 사용 시각·방문 빈도·swap 비용·GPU HBM 의 adapter 수를 Eq.4~6 으로 한 점수에 합치고, 그 점수로 후보 순서를 정한다 §VI-B p.7–8. swap-in 도 같은 방식이고, 후보가 host main memory 쪽 subtree 의 맨 위 node 이며 $\mathrm{Eval}_i$ 가 높은 것부터 올린다는 점만 다르다 §VI-C p.8.
3.1① Cache manager: dependency tree
Fig.7 · Fig.8 — tree 를 만들고 유지하는 법
- 3.1.4
- 3.1.4.1node 1 개는 고정 크기 memory block 1 개다 §V-A p.6. adapter weight 는 rank 방향으로 잘라 KV cache 와 같은 크기 block 에 담는다 §VII p.8. Fig.7 은 adapter 하나를 LoRA node 하나로 그려, adapter weight 가 여러 block 일 때 node 구성은 원문에 명시가 없다 해석.
- 3.1.4.2KV node label 은 token 열의 hash, LoRA node label 은 LoRA ID 다. node 마다 방문 빈도·마지막 사용 시각·크기를 기록한다 §V-A p.6.
- 3.1.4.3SGLang 의 RadixAttention tree 와 비슷하지만 RadixAttention 은 adapter 를 고려하지 않는다 §V-B p.7.
3.2② Cache swapper: GPU HBM 에 남길 node 를 점수로
전제. $\mathrm{Eval}_i$ 는 tree 의 node $i$ 하나에 붙는 점수다. cache swapper 는 swap 후보 node 들의 순서를 정할 때만 이 점수를 쓴다. swap-out 은 점수가 낮은 node 부터, swap-in 은 점수가 높은 node 부터 한다 §VI-C p.8. 점수의 절댓값에는 뜻이 없고 node 사이의 크기 비교만 쓴다 §VI-B p.8.
1 단계: 전체 식 (Eq.6). $\mathrm{Eval}_i = ① \times ②$ 다. ① adapter 개수 충족률은 node $i$ 를 swap 한 뒤 GPU HBM 에 남는 adapter 개수가 최근 batch 에 필요한 adapter 개수에 얼마나 미치는지를 나타내는 비율이며, 최대 1 이다. ② 지연 감소 기대값은 node $i$ 를 GPU HBM 에 남겨 두었을 때 이후 query 의 cold-start 지연이 얼마나 줄어들지를 나타내는 값이다. ① 은 adapter 가 선택될 확률이 아니다. GPU HBM 의 adapter 수가 충분하면 ① 이 1 이라 순서는 ② 로만 정해진다. adapter 수가 모자랄 때만 ① 이 1 보다 작아져 점수에 끼어든다 해석.
2 단계: ① adapter 개수 충족률 (Eq.4, 안에서 Eq.3 을 씀). ① 을 계산하려면 먼저 Eq.3 으로 "최근 batch 에 필요한 adapter 수" $\mathrm{Low}_{lora}$ 를 구한다. adapter $i$ 가 batch 의 query $BS$ 개 중 한 번이라도 쓰일 확률 $1-(1-prob_i)^{BS}$ 를 모든 adapter 에 대해 더한 값이다 §VI-A p.7.
예시 논문에 없음: adapter 세 개의 $prob$ 가 0.5, 0.3, 0.2 이고 $BS=4$ 이면 다음과 같다.
그다음 Eq.4 로 node $i$ 를 swap 한 뒤 GPU HBM 에 남는 adapter 수 $\mathrm{NowLoRA}_i$ 를 $\mathrm{Low}_{lora}$ 로 나누고, 1 을 넘으면 1 로 자른다 §VI-B p.7. 예를 들어 swap 뒤에도 adapter 가 3 개 있으면 $\min(1, 3/2.29) = 1$ 이라 ① 은 점수를 바꾸지 않는다. adapter 가 2 개로 줄면 $2/2.29 \approx 0.87$ 이라 점수가 13% 깎인다.
3 단계: ② 지연 감소 기대값 (Eq.5). 세 값을 곱한다. 세 값 모두 node $i$ 하나에 대해 잰다 §VI-B p.8.
| 값 | node $i$ 에 대해 재는 것 | 클수록 남기는 이유 |
|---|---|---|
| 3.2.3.13.2.1.1$cost_i$ | node $i$ 를 PCIe 로 GPU HBM 에 다시 올리는 시간 (node 크기와 PCIe 대역폭으로 계산) | 내보냈다가 다시 필요해지면 그만큼 query 가 기다린다 |
| 3.2.3.23.2.1.2$visit_i$ | query 가 node $i$ 를 사용한 빈도 확률 (tree 기록으로 계산) | 다음 query 도 node $i$ 를 쓸 가능성이 높다 |
| 3.2.3.33.2.1.3$1-\mathrm{sigmoid}(t_i)$ | $t_i$ = 지금 − query 가 node $i$ 를 마지막으로 사용한 시각. $t_i=0$ 이면 0.5, $t_i$ 가 커질수록 0 으로 줄어든다 | 최근에 쓰인 node 일수록 또 쓰인다고 본다 (LRU 성분) |
예시 논문에 없음: KV node X 와 Y 는 크기가 같은 block 이라 $cost$ 를 둘 다 1 로 둔다. X 는 $visit=0.3$, 방금 사용($t=0$)이고, Y 는 $visit=0.05$, 사용한 지 2 단위 시간이 지났다($t=2$).
X 의 점수가 Y 보다 크므로, 둘 다 swap-out 후보이면 Y 를 먼저 내보낸다.
원문만으로 확정하지 못한 점: swap-out 때 ① 의 방향
원문 식을 글자 그대로 적용하면, swap-out 후보가 adapter node 일 때 그 node 를 내보낸 뒤의 adapter 수 $\mathrm{NowLoRA}_i$ 가 1 줄어 ① 이 작아지고 $\mathrm{Eval}_i$ 도 작아진다. 점수가 낮을수록 먼저 내보내므로, adapter 가 모자랄 때 adapter node 가 오히려 먼저 내보내지는 방향이 된다. 논문이 밝힌 의도(adapter 수를 $\mathrm{Low}_{lora}$ 근처로 유지)와 반대로 읽힌다 해석. swap-in 에서는 adapter node 를 올리면 $\mathrm{NowLoRA}_i$ 가 늘어 ① 이 커지므로 의도와 맞다. 원문은 swap-out 때 ① 을 어떻게 적용하는지 따로 설명하지 않으며, 이 차이의 원인은 미규명이다.
Eval 은 두 항의 곱이다. 하나는 "GPU HBM 에 adapter weight 가 충분한 수만큼 있나"(Eq.3–4), 다른 하나는 "이 node 를 GPU HBM 에 남기면 이후 query 의 cold-start 지연을 얼마나 줄이나"(Eq.5) 이다. 두 값을 곱한 Eq.6 이 클수록 GPU HBM 에 남긴다 §VI-B p.7–8.
왜 곱셈인가, 왜 1 − sigmoid 는 0.5 에서 시작하나
곱셈이면 한 항이라도 0 에 가까울 때 전체 점수가 0 에 가까워진다. 예를 들어 다시 쓰일 확률이 0 인 node 는 swap 비용이 커도 남길 이유가 없다. 또 단위가 다른 항끼리 가중치를 맞출 필요가 없다 해석. 논문은 곱셈을 고른 이유를 따로 적지 않았다.
$t_i \ge 0$ 이고 $\mathrm{sigmoid}(0) = 0.5$ 이므로, 방금 쓴 node 도 이 항은 1 이 아니라 0.5 다. $1 - \mathrm{sigmoid}(t) = 1/(1+e^{t})$ 라서 0.5 에서 0 으로 줄어든다. 최대값이 모든 node 에 같으므로 순서 비교에는 영향이 없다 해석. 논문은 $t_i$ 의 단위(초·ms)를 밝히지 않았다.
| $t_i$ | $\mathrm{sigmoid}(t_i)$ | $1 - \mathrm{sigmoid}(t_i)$ |
|---|---|---|
| 3.2.8.10 | 0.500 | 0.500 |
| 3.2.8.21 | 0.731 | 0.269 |
| 3.2.8.32 | 0.881 | 0.119 |
| 3.2.8.43 | 0.953 | 0.047 |
| 3.2.8.55 | 0.993 | 0.007 |
Fig.9 · Fig.10 — adapter 수가 왜 중요한가, swapper 가 도는 순서
4구현
vLLM 위에 Python 7,856 줄 + C++ 1,766 줄로 구현했다. vLLM 의 BlockManager 를 확장해 GPU HBM 과 host main memory 를 같은 크기 block 으로 나누고, S-LoRA 식 pool 에 history KV 까지 담는다 §VII p.8.
tree 는 block 주소만 기록하는 trie 로 host main memory 에 두고(최대 676.5 KB, match·갱신 1 ms 미만), swap 은 torch stream 으로 비동기라 다른 query 의 inference 를 막지 않는다 §VII p.8.
구현 세부와 오버헤드
| 항목 | 값 | 근거 |
|---|---|---|
| 4.1.1Eval 갱신 비용 | 최대 3.1 μs | §VI-C p.8 |
| 4.1.2비동기 swap 오버헤드 | 최대 0.47 ms | §VI-C p.8 |
| 4.1.3query 1 개 inference 중 swap 오버헤드 | 5 ms 이내 | §VIII-L p.12 |
| 4.1.4tree match·갱신 (query 당 평균, tree 최대 크기일 때) | < 0.5 ms | §VIII-L p.12 |
| 4.1.5block 당 메타데이터 | 232 B / 16 MB (0.0014%) | §VIII-L p.12 |
| 4.1.6Eval 저장 | 24 B / block (0.0001%) | §VIII-L p.12 |
- 4.2
- 4.2.1rank 가 다른 adapter 를 쓰는 query 들을 한 batch 로 묶기 위해 SGMV 를 쓰고, tensor parallelism 으로 여러 GPU 에 나눈다 §VII p.8.
- 4.2.2GPU HBM 과 host main memory 가 모두 차면 cold KV block 을 버리고 tree 에서도 지운다 §VII p.8.
5평가
H800 ×8 (Llama3-8B 는 1 장, Llama2-34B 는 4 장, Llama3-70B 는 8 장), adapter 20·50·100 개, chatbot·번역·agent 세 시나리오로 실험했다. baseline 은 vLLM(adapter 영역 0.2 고정, LRU)과 S-LoRA(unified pool, history KV 재사용 없음)다 §VIII-A p.9.
27 조합 모두에서 ELORA 의 평균 TTFT·TPOT 가 가장 낮고 peak load 가 가장 높으며 §VIII-B p.9, 시나리오별 TTFT 의 queue·LoRA cold-start·KV cold-start 지연도 가장 짧다 §VIII-C p.10.
27 조합 평균으로 vLLM 대비 TTFT −45.7%, TPOT −37.8%, peak load +78.9%, S-LoRA 대비 −43.3%, −31.4%, +49.9% 다. P99 TTFT 는 vLLM 대비 −73.8% 이고, 조합마다 20 회 반복한 표준오차는 평균 1.7% 다. 논문은 개선이 usage dependency 유지와, 이득이 큰 adapter weight·KV cache 를 GPU HBM 에 남겨 cold-start 를 줄인 데서 온다고 쓴다. vLLM 대비 TTFT 감소가 번역에서 평균 49.4% 로 다른 시나리오(43.8%)보다 큰 것은 adapter 분포 변화가 가장 커서이고, S-LoRA 대비 agent 에서 53.2%(다른 시나리오 38.4%)인 것은 대화가 가장 길어 history KV 를 남기지 않는 S-LoRA 의 약점이 커져서라고 설명한다 §VIII-B p.9–10.
Fig.13 · Fig.14 — GPU HBM 을 실제로 어떻게 쓰나
Fig.15 · Fig.16 · Fig.17 — 부품을 하나씩 빼 보기 (ablation)
Fig.18 · Fig.19 · Fig.20 — 확장성과 oracle 비율의 vLLM
6결론과 한계
논문의 결론은 cache manager 가 tree 로 usage dependency 를 유지해 invalid KV 를 없애 GPU HBM 사용률을 올리고, cache swapper 가 query 성능 이득을 반영한 cost model 로 swap 을 정해, 기존 시스템 대비 평균 TTFT −45.7%, TPOT −37.8% 를 얻었다는 것이다 §IX p.12–13.
논문에 limitation 절은 없다. 아래는 요약자가 정리한 한계다 논문에 없음.
| 한계 | 근거 |
|---|---|
| 6.1.1메모리 계층이 GPU HBM ↔ host main memory 두 단계뿐이다. SSD·원격 KV store 나 여러 노드 사이 공유는 다루지 않는다 | 둘 다 차면 cold KV block 을 버림 (§VII p.8) |
| 6.1.2cost model 은 곱셈 형태의 수작업 식이고, 100 ms 주기 · 70% 기준 · 5 초 $BS$ 창의 민감도 분석이 없다 | §VI-A·C p.7–8 에 값만 제시 |
| 6.1.3KV cache 를 adapter 사이에 공유할 수 없다는 전제다. 같은 문서를 adapter 여러 개로 처리하면 KV cache 를 adapter 수만큼 저장한다 (1 절 숫자 예시 참고) | Eq.2 (§III-A p.3) |
| 6.1.4workload 는 공개 dataset 을 adapter 에 대응시켜 만들었고 adapter 는 HuggingFace 에서 무작위로 골랐다. 실제 Multi-LoRA 서비스 trace 는 아니다 | §III-B p.3 |
| 6.1.5baseline 이 vLLM · S-LoRA 둘이다. SGLang 은 Multi-LoRA 사용 시 history KV 를 재사용하지 못하고 평균 TTFT 가 9,568.9 ms 여서, TensorRT-LLM 은 adapter 를 미리 compile 해야 해서 제외했다 | §III-C p.4, §VIII-A p.9 |
| 6.1.6TPOT 개선은 논문 설명상 prefill 재계산 감소의 간접 효과다. decode 연산 자체를 바꾸는 기법은 제시되지 않았다 | §VIII-B p.9 |
7관련 연구
Table I 은 비교한 네 시스템 중 "Multi-LoRA serving + online adapter (un)loading + history KV 재사용 + KV cache·adapter weight 동적 관리" 넷을 모두 하는 것은 ELORA 뿐이라고 보인다.
vLLM 은 앞의 세 개, S-LoRA 는 앞의 두 개를 한다. TensorRT-LLM 은 Multi-LoRA serving 과 history KV 재사용은 하지만 adapter 를 base 모델과 미리 compile 해야 해 online loading 이 안 된다 §II p.2–3.
관련 연구 한 줄씩
| 연구 | 한 일 | ELORA 와 차이 |
|---|---|---|
| 7.2.1SGLang RadixAttention | global prefix tree + LRU 로 KV cache 재사용 | adapter 를 고려하지 않는다. ELORA tree 구현의 바탕 operator (§II p.2) |
| 7.2.2AttentionStore · Pensieve | 다단 KV caching 으로 다회 대화의 재계산 제거 | adapter weight 와 통합 관리 없음 (§II p.2) |
| 7.2.3Punica · S-LoRA | base 모델과 adapter 연산 분리(Punica), adapter weight·running KV 의 unified pool(S-LoRA) | history KV 재사용 없음. S-LoRA pool 은 ELORA 의 바탕 operator (§II p.2) |
| 7.2.4dLoRA | adapter 를 base 모델에 merge·unmerge, replica 간 query·adapter 이동 | 논문은 직교한다고 쓴다 (§II p.2) |
8세미나 발표 대본 (약 18 분)
Fig.1~20 을 슬라이드 순서대로 놓고, 슬라이드마다 말할 내용을 2~4 문장으로 적었다. 세부 수식과 구현 수치는 빼고, 문제 → 설계 → 실험 환경 → 평가 흐름만 남겼다.
발화문은 요약자가 쓴 것이고 논문에 없음, 수치와 주장은 원문에서 확인한 것만 넣었다. 각 슬라이드 옆 시간은 권장 분량이다.