LabHub

한국어

시작하기
블로그

블로그

LoRA 어댑터 서빙을 직접 재 보기: 처리량 비용, 어댑터 슬롯, 실행 중 적재

상태: 초안 (2026-10-07), 실측 글입니다. 어댑터는 성능 시험용으로 만든 무작위 가중치라서 출력 품질은 의미가 없고, 속도와 자원 거동만 측정했습니다. 계산한 것은 「계산」, 못 잰 것은 「미실측」으로 표시했습니다. 작성 규칙: 실측 데이터가 기본이고, 못 잰 것은 「미실측」으로 표시합니다.

1. 왜 LoRA 를 서빙하는가

모델을 용도마다 미세 조정하면 그만큼 모델 전체를 메모리에 올려야 합니다. LoRA 는 기본 가중치 W 를 그대로 두고 저차원 행렬 두 개(B, A)를 학습해 W + (α/r)·B·A 로 바꾸는 방식이라, 기본 모델 하나에 작은 어댑터 여러 개를 붙여 요청마다 다른 어댑터를 쓸 수 있습니다. 고객별·업무별 모델을 GPU 한 장에서 서비스하려는 이유입니다. vLLM 문서는 어댑터를 요청 단위로 적은 오버헤드로 서빙할 수 있다고 설명합니다. 이 글은 그 「적은」이 이 환경에서 몇 퍼센트인지를 재 봅니다.

2. 환경과 방법

항목 값
GPU 8GB급 노트북 GPU 한 장, 다른 작업 없음
서버 vLLM 0.31.0, Qwen3-1.7B(bf16), --max-model-len 4096, --max-num-seqs 64, --max-lora-rank 16
어댑터 PEFT 로 만든 LoRA 3개(a, b, c). 랭크 8, 대상은 어텐션의 q, k, v, o 투영, lora_B 를 시드가 다른 무작위 값(표준편차 0.02)으로 초기화
어댑터 크기 학습 가능 파라미터 3,211,264개로 기본 모델 1,720,574,976개의 0.19%(측정). bf16 이면 약 6.4MB(계산)
요청 입력 Write a long story about a robot., 출력 128토큰, 온도 0, ignore_eos, 요청마다 서버의 모델 이름으로 어댑터를 선택
반복 같은 요청 묶음을 한꺼번에 보내고 총 처리량(출력 토큰 수 ÷ 걸린 시간)을 계산

동시 요청 수에 주의하십시오. 이 글의 표는 「한꺼번에 보낸 요청 수」를 적습니다(3개, 18개, 48개). 시험 도구의 인자 이름 때문에 처음에는 「동시 1, 16」이라고 부르다가 실제로는 3배의 요청을 보내고 있음을 확인해 바로잡았습니다.

어댑터가 무작위라서 출력은 의미가 없습니다. 어댑터 행렬의 크기와 연산량은 학습 여부와 무관하므로 속도와 메모리 거동은 학습된 어댑터와 같다고 보지만, 학습된 어댑터에서 확인하지는 않았습니다(미실측).

3. 처리량의 비용

기본 서버(LoRA 끔)와 LoRA 를 켠 서버에서 같은 요청을 보냈습니다.

한꺼번에 보낸 요청 수 서버 요청이 쓰는 모델 총 처리량 기본 대비 ITL 중앙
3 LoRA 끔 기본 199 tok/s 기준 15ms
3 LoRA 켬 기본(어댑터 없음) 200 tok/s +0.5% 15ms
3 LoRA 켬 어댑터 a 182 tok/s −8.5% 16ms
48 LoRA 끔 기본 2,667 tok/s 기준 17ms
48 LoRA 켬 기본(어댑터 없음) 2,664 tok/s −0.1% 17ms
48 LoRA 켬 어댑터 a 2,190 tok/s −17.9% 19ms
48 LoRA 켬 a 와 b 를 번갈아 2,323 tok/s −12.9% 20ms
48 LoRA 켬 a, b, 어댑터 없음을 번갈아 2,346 tok/s −12.0% 20ms

반복 시험(5회씩, 같은 서버). 요청 48개(동시 16 의 3배)를 어댑터 없음, 어댑터 a, 어댑터 a 와 b 번갈아의 세 조건으로 순서를 섞어 5번씩 보냈습니다(--max-loras 2).

조건 처리량(tok/s), 5회 중앙값 기본 대비
어댑터 없음 2,647, 2,658, 2,669, 2,663, 2,667 2,663 기준
어댑터 a 2,183, 2,398, 2,390, 2,391, 2,390 2,390 -10.3%
어댑터 a 와 b 번갈아 2,329, 2,330, 2,332, 2,329, 2,332 2,330 -12.5%

4. 어댑터 슬롯: 어댑터 수가 --max-loras 를 넘으면

--max-loras 는 한 배치 안에 들 수 있는 서로 다른 LoRA 의 수입니다(기본 1). 처음에는 「GPU 에 동시에 올려 둘 수 있는 어댑터 수」로 적었지만, 이 글이 쓴 vLLM 0.31.0 이미지의 소스(vllm/config/lora.py)를 직접 읽어 보니 설명이 「Max number of LoRAs in a single batch」이고, CPU 쪽에 둘 어댑터 수는 별도의 --max-cpu-loras(기본은 max_loras 와 같은 값)였습니다. 어댑터 3개로 요청 18개를 한꺼번에 보냈습니다(각 설정 2회 반복. 두 회의 값이 거의 같은 경우가 많았지만 슬롯 2개의 어댑터 a, b 는 886과 984 로 달랐습니다).

서버 설정 어댑터 없음 어댑터 a, b 어댑터 a, b, c
--max-loras 2 1,120 tok/s 886~984 tok/s 529 tok/s
--max-loras 4 1,131 tok/s 986~987 tok/s 950 tok/s

4-1. 같은 시험을 SGLang 에서 하면

같은 모델과 같은 무작위 어댑터 3개(rank 16, 파라미터의 0.19%)로 SGLang 0.5.21 의 LoRA(--enable-lora --max-loras-per-batch N)를 재었습니다.

시험 SGLang vLLM(위 3절, 4절)
동시 16(요청 48개), 어댑터 없음 2,539 tok/s 2,664(LoRA 켠 서버의 어댑터 없는 요청)
같은 부하, 어댑터 a 2,516 tok/s(-0.9%, 한 번) 2,390 tok/s(-10.3%, 5회 중앙)
요청 18개, 어댑터 2개를 섞음, 슬롯 2 1,045 tok/s(어댑터 없음 1,027) 886~984 tok/s(어댑터 없음 1,120)
요청 18개, 어댑터 3개를 섞음, 슬롯 2 558 tok/s 529 tok/s
같은 시험, 슬롯 4 1,045 tok/s 950 tok/s

5. 실행 중에 어댑터를 올리는 데 걸리는 시간

VLLM_ALLOW_RUNTIME_LORA_UPDATING=True 로 서버를 띄운 뒤 /v1/load_lora_adapter 로 어댑터 c 를 추가했습니다.

항목 결과
적재 요청의 응답 LoRA adapter 'c' added successfully, 호출 전체 0.18초(원격 명령 실행 오버헤드 포함)
적재 직후 첫 요청들 3개 요청 182 tok/s, 어댑터 a 와 같은 속도

6. 운영에서 가져갈 것

  1. 어댑터를 쓰는 요청의 처리량 비용을 미리 잽니다. 이 환경에서 8~18% 였고 모델과 동시성에 따라 달라집니다.
  2. --max-loras 를 동시에 등장하는 어댑터 수에 맞춥니다. 슬롯이 모자라면 절반 수준으로 떨어집니다.
  3. 어댑터 배포는 가볍지만 무통제 적재는 위험합니다. 파이프라인으로 통제하고 검증된 어댑터만 올립니다.
  4. LoRA 를 켜 두는 비용은 없었습니다. 어댑터를 쓰지 않는 요청은 영향이 없었습니다.
  5. 큰 모델과 학습된 어댑터에서는 다시 재야 합니다. 이 글의 수치는 작은 모델과 무작위 어댑터에서 얻었습니다.

7. 면접에서 나올 만한 질문

외부 근거: 논문과 공식 자료로 확인한 것

외부 수치는 모델, GPU, 어댑터 구성이 달라 직접 비교하지 않고 방향과 자릿수의 일치만 판정했습니다.

주제 자료와 확인한 위치 확인한 내용과 조건 이 글과의 관계
LoRA 의 크기 Hu 외, 「LoRA: Low-Rank Adaptation of Large Language Models」, arXiv 2106.09685(ICLR 2022), 초록과 4.2절 GPT-3 175B 에서 학습 파라미터를 최대 10,000배, 체크포인트 350GB 를 35MB 로 줄임(랭크 4, 쿼리와 값 투영만 적용). 추론 지연이 늘지 않는다는 말은 W0 + BA 로 합친 단일 어댑터에만 성립하고, 서로 다른 어댑터를 한 배치에 섞는 것은 합친 상태에서는 어렵다고 논문이 한계에 적음 지지. 우리 어댑터는 기본 모델의 0.19%(3,211,264개, 모델 설정에서 계산해 일치). 3절의 8.5~17.9% 감소는 합치지 않고 요청마다 고르는 방식의 비용
다중 어댑터 서빙의 처리량 Chen 외, Punica, MLSys 2024, arXiv 2310.18547, 7절 그림 11. Sheng 외, S-LoRA, MLSys 2024, arXiv 2311.03285, 7.2절 표 3 Punica: A100 80GB 한 장, Llama-2 7B·13B, 랭크 16. 같은 어댑터만 쓸 때 백본 전용 vLLM 보다 7B 약 8.4%, 13B 약 12.2% 낮음(논문 수치로 계산)이고 토큰당 약 2ms 추가 지연. S-LoRA: 어댑터를 호스트 메모리에 두고 실행 중인 요청의 것만 GPU 로 가져와 어댑터 5개에서 100개로 늘어도 처리량 유지, 약간의 감소 제한적으로 지지. 어댑터를 쓰는 요청의 처리량 감소와 자릿수가 같음. 「슬롯 초과 시 절반」에 대응하는 외부 수치는 없고, S-LoRA 는 활성 어댑터 수가 비용을 정한다고 설명해 이 현상이 vLLM 의 max_loras 구성에 특유할 수 있음을 시사
--max-loras 의미 vLLM 0.31.0 소스 config/lora.py, v1/core/sched/scheduler.py(이 글이 쓴 이미지에서 직접 읽음) 한 배치 안의 서로 다른 LoRA 수(기본 1). 한도에 도달하면 다른 어댑터의 요청을 건너뜀. max_cpu_loras 는 별도(기본 max_loras와 같음) 처음 서술을 정정. 위 4절
오버헤드와 런타임 적재 vLLM 문서 「LoRA Adapters」(2026-09-28 표기) 어댑터를 요청 단위로 적은 오버헤드로 서빙한다고 적고 정량 수치는 없음. VLLM_ALLOW_RUNTIME_LORA_UPDATING 은 격리된 신뢰 환경이 아니면 운영에서 쓰지 말라는 경고가 있고 구체적 이유는 적혀 있지 않음 제한적으로 지지. 「적은 오버헤드」는 이 환경에서 8.5~17.9% 로 작지 않았음

확인하지 못한 것

참고 자료

확인한 버전과 날짜

2026-10-07 기준. vLLM 0.31.0, PEFT 0.21.2, accelerate 1.15.0, Qwen3-1.7B(bf16).

로그인하면 좋아요를 누를 수 있습니다

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다