Gemma 4 E4B 로컬 서빙 세팅하면서 MTP까지 한 번에 붙여봤습니다.
핵심 요약
→ vLLM 공식 이미지 중 vllm/vllm-openai:gemma4-unified 태그가 Gemma 4 전용
→ Gemma 4 E4B는 MoE 아키텍처 — GPU 1장(tensor-parallel-size 1)으로 서빙 가능
→ --max-model-len 32768 — 풀 컨텍스트(128K)는 VRAM 부족, 32K가 실용적인 타협점
→ --gpu-memory-utilization 0.9 — 0.95 이상은 OOM 리스크, 0.9가 안정적
→ MTP(Multi-Token Prediction) 추측 디코딩으로 처리 속도 체감 20~30% 향상
→ MTP 드래프트 모델은 메인 모델과 동일 경로 사용 가능 — 별도 모델 불필요
→ num_speculative_tokens: 2 — 3 이상은 드래프트 정확도 떨어져 오히려 느려짐
→ --allowed-local-media-path — 멀티모달 입력(이미지) 쓸 때 필수, 없으면 로컬 파일 거부
→ --shm-size="20g" — vLLM 공유 메모리 부족 시 워커 크래시 나므로 넉넉하게
→ OpenAI 호환 API로 뜨기 때문에 기존 ChatGPT API 코드 그대로 연결 가능
실전 1 — 전체 도커 실행 명령 한 줄씩 해석
docker run -itd --name ${CONTAINER_NAME} \
-p 8000:8000 \ # 호스트 8000 → 컨테이너 8000 포트 포워딩
--ipc=host \ # 프로세스 간 공유 메모리, vLLM 워커 통신 필수
--cpus="16" \ # CPU 코어 16개 제한
--cpu-shares=512 \ # 다른 컨테이너와 CPU 경쟁 시 상대적 우선순위
--memory="40g" \ # 메모리 하드 상한
--memory-swap="40g" \ # swap 0 — 메모리 초과 시 OOM killer 즉시 개입
--memory-reservation="20g" \ # 소프트 하한, 시스템 압박 시 여기까지 확보
--shm-size="20g" \ # 공유 메모리 — vLLM 텐서 공유에 사용
--oom-score-adj=300 \ # OOM 발생 시 이 컨테이너 먼저 죽임 (시스템 보호)
--gpus '"device=1"' \ # GPU 1번 단독 할당
-v /DATA1/son/models_file:/root/.cache/huggingface/models \ # 모델 마운트
-v /DATA1/son:/DATA1/son \ # 멀티모달용 로컬 파일 접근
vllm/vllm-openai:gemma4-unified \ # Gemma 4 전용 vLLM 이미지
--model /root/.cache/huggingface/models/gemma-4-E4B-it \
--tensor-parallel-size 1 \
--max-model-len 32768 \
--gpu-memory-utilization 0.9 \
--host 0.0.0.0 \
--port 8000 \
--allowed-local-media-path /my/local_media \
--speculative-config '{"method":"mtp","model":"/root/.cache/huggingface/models/gemma-4-E4B-it-assistant","num_speculative_tokens":2}'
개념 박스 — --ipc=host 왜 필요한가 vLLM은 내부적으로 여러 워커 프로세스 간 텐서를 공유 메모리로 주고받습니다. 기본 Docker IPC 격리 모드에서는 이 채널이 막혀 워커 초기화에서 hang이 걸립니다. --ipc=host로 호스트와 IPC 네임스페이스를 공유해야 정상 기동됩니다.
실전 2 — MTP 추측 디코딩 설정
MTP(Multi-Token Prediction)는 드래프트 모델이 다음 토큰 여러 개를 미리 예측하고, 메인 모델이 검증하는 방식으로 속도를 끌어올립니다.
{
"method": "mtp",
"model": "/root/.cache/huggingface/models/gemma-4-E4B-it-assistant",
"num_speculative_tokens": 2
}
여기서 핵심은 model 경로입니다. 드래프트 모델로 메인 모델과 다른 경량 모델을 쓰는 게 일반적이지만, Gemma 4 MTP는 동일 계열 모델을 드래프트로 써도 동작합니다. -assistant suffix 모델을 드래프트로 쓰는 이유는 instruction 튜닝된 버전이 토큰 예측 패턴이 메인 모델과 더 유사하기 때문입니다.
num_speculative_tokens 값별 특성
1 → 속도 향상 미미, MTP 의미 없음
2 → 속도 20~30% 향상, 드래프트 정확도 유지 (권장)
3 → 드래프트 오검증 빈도 올라가 오히려 느려지는 케이스 발생
4+ → 대부분의 경우 손해
개념 박스 — MTP가 왜 빠른가 일반 자기회귀 디코딩은 토큰을 한 번에 하나씩 생성합니다. 매 스텝마다 전체 모델을 한 번 forward pass해야 해서 느립니다. MTP(Multi-Token Prediction)는 모델이 학습 시점부터 다음 토큰 N개를 동시에 예측하도록 훈련된 구조입니다. 추론 시에도 1 forward pass에서 토큰 여러 개를 한꺼번에 뽑아낼 수 있어서 처리량이 올라갑니다. 드래프트 모델이 따로 필요한 Speculative Decoding과 달리, MTP는 메인 모델 자체가 멀티 토큰을 뽑는 구조라서 별도 모델 없이도 동작합니다. num_speculative_tokens: 2는 한 번에 2개 토큰을 동시 생성한다는 의미입니다.
실전 3 — 컨테이너 기동 후 확인
# 컨테이너 로그 확인 (MTP 초기화 메시지 체크)
docker logs -f ${CONTAINER_NAME}
# 정상 기동 시 로그에 이런 라인이 떠야 함
# INFO: Started server process
# INFO: Waiting for application startup.
# INFO: Application startup complete.
# Speculative decoding (MTP) initialized with 2 draft tokens
# 헬스체크
curl http://localhost:8000/health
# 모델 목록 확인
curl http://localhost:8000/v1/models
실전 4 — API 연결 및 멀티모달 테스트
OpenAI 호환 API로 뜨기 때문에 기존 코드에서 base_url과 api_key만 바꾸면 됩니다.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="dummy" # vLLM은 api_key 검증 안 함, 아무 값이나
)
# 텍스트 추론
response = client.chat.completions.create(
model="/root/.cache/huggingface/models/gemma-4-E4B-it",
messages=[
{"role": "user", "content": "파이썬으로 피보나치 수열 짜줘"}
],
max_tokens=1024,
temperature=0.7
)
print(response.choices[0].message.content)
# 멀티모달 — 로컬 이미지 파일 직접 전달
# --allowed-local-media-path 설정된 경로 내 파일만 가능
response = client.chat.completions.create(
model="/root/.cache/huggingface/models/gemma-4-E4B-it",
messages=[
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "file:///my/local_media/test_image.png"
}
},
{
"type": "text",
"text": "이 이미지에서 뭐가 보여?"
}
]
}
],
max_tokens=512
)
print(response.choices[0].message.content)
개념 박스 — --allowed-local-media-path 왜 필요한가 vLLM은 보안 상 기본적으로 file:// 프로토콜로 로컬 파일 접근을 차단합니다. --allowed-local-media-path로 허용할 디렉토리를 명시해야 해당 경로 내 파일에 접근 가능합니다. Base64 인코딩해서 data URL로 넘기면 이 설정 없이도 동작하지만, 큰 이미지는 요청 크기가 폭발합니다.
실전 5 — 자주 나오는 오류와 해결
# 오류 1: CUDA OOM
# CUDA out of memory. Tried to allocate ...
# → gpu-memory-utilization 낮추거나 max-model-len 줄이기
--gpu-memory-utilization 0.85
--max-model-len 16384
# 오류 2: SharedMemory 부족으로 워커 크래시
# [Errno 28] No space left on device (shared memory)
# → --shm-size 늘리기
--shm-size="24g"
# 오류 3: MTP 드래프트 모델 경로 못 찾음
# FileNotFoundError: model path not found
# → 컨테이너 내부 마운트 경로로 지정했는지 확인
# 호스트 경로 아닌 /root/.cache/huggingface/models/... 기준
# 오류 4: 멀티모달 로컬 파일 접근 거부
# ValueError: Local file access not allowed
# → --allowed-local-media-path 경로가 실제 파일 경로를 포함하는지 확인
# /DATA1/son 하위 파일이면 --allowed-local-media-path /my/local_media
# 오류 5: gemma4-unified 이미지 없음
# Unable to find image 'vllm/vllm-openai:gemma4-unified'
# → docker pull vllm/vllm-openai:gemma4-unified 먼저 실행
실전 6 — 리소스 튜닝 포인트
현재 설정 기준으로 조정 가능한 파라미터입니다.
# VRAM 16GB 이하 환경
--max-model-len 8192 # 컨텍스트 줄이기
--gpu-memory-utilization 0.85
# VRAM 24GB 이상 환경
--max-model-len 65536 # 컨텍스트 늘리기 가능
--gpu-memory-utilization 0.92
# 처리량 우선 (배치 크기 늘리기)
--max-num-seqs 64 # 동시 처리 시퀀스 수 (기본 256)
# 지연 시간 우선 (MTP 토큰 수 조정)
# speculative-config의 num_speculative_tokens를 1로 낮추기
✅ 이 설정이 잘 맞는 경우
✅ GPU 1장으로 Gemma 4 E4B 서빙이 필요한 환경
✅ 멀티모달(이미지 입력) + 텍스트 혼용 파이프라인
✅ 기존 OpenAI API 코드를 그대로 로컬로 전환하고 싶을 때
✅ MTP로 처리량 개선이 필요한 배치성 추론
❌ 다른 설정을 고려해야 하는 경우
❌ VRAM 12GB 이하 — max-model-len 더 줄이거나 양자화 버전 필요
❌ GPU 2장 이상 쓸 수 있는 환경 — tensor-parallel-size 2로 풀 컨텍스트(128K) 가능
❌ 실시간 스트리밍 응답 — stream=True 별도 처리 필요
'Gemini' 카테고리의 다른 글
| DiffusionGemma 완전 분석: Gemma 4랑 뭐가 다른 거예요? (0) | 2026.06.11 |
|---|---|
| 코딩 몰라도 앱 만든다 — Google AI Studio 안드로이드 앱 빌더 사용법 (0) | 2026.06.10 |
| NotebookLM 업데이트 완전정리 — 유튜브·PDF 물어보고 PPT까지 뽑아주는 AI 연구 도우미 (0) | 2026.06.09 |
| Gemini 2.0 Flash deprecated 완전 가이드: 지금 당장 마이그레이션 해야 하는 이유 (0) | 2026.06.08 |
| Antigravity 2.0 데스크탑 에이전트 세팅 — 로컬 설치부터 MCP 연결까지 (0) | 2026.06.05 |