실행 프로그램과 확장
SGLang으로 로컬 모델 서빙하기: 캐시와 가속을 나눠 봅니다
같은 문서를 두고 질문을 이어갈 때, 처음에는 오래 기다렸는데 다음 답변은 금방 시작되기도 합니다. 모델이 갑자기 빨라진 것이 아니라 앞에서 읽은 내용을 재사용했을 수 있습니다. SGLang을 고를 때 도움이 되는 것은 이 차이를 이해하고 내 작업에 맞게 남기는 일입니다.
1. 반복 질문과 새 문서는 다른 작업입니다
프로젝트 설명을 길게 붙이고 코드 수정을 여러 번 요청하는 상황을 생각해보세요. 매번 앞부분이 같다면 이미 계산한 입력을 재사용할 여지가 있습니다. SGLang의 Radix 캐시는 이런 공통 접두부를 활용하는 데 쓰입니다. 반면 새로운 문서를 계속 넣는 작업은 같은 이득을 기대하기 어렵습니다. 두 경우를 한 줄의 프리필 속도로 합치면 내가 기다릴 시간을 잘못 짐작하게 됩니다.
캐시는 답변의 정확도를 대신하지 않습니다. 이전 대화와 새 문서가 앱에서 어떻게 전달되는지도 확인해야 합니다. 비교할 때는 새 입력과 반복 입력을 분리하고, 답변 생성 중 tok/s도 별도로 봅니다. 여러 요청을 동시에 받아 표시하는 서버 총처리량은 한 사람이 읽는 출력 속도와 같지 않습니다. 문서 묶음 처리와 대화용 설정을 같은 순위로 평가하지 않는 이유입니다.
2. Spark의 명령을 PC나 Mac에 그대로 붙이지 않습니다
일반 NVIDIA 경로에서는 Linux, CUDA, PyTorch와 SGLang의 GPU 커널 패키지가 맞아야 합니다. 별도 환경에서 설치하고 정상 동작한 버전 조합을 남기세요. DGX Spark는 ARM64와 Blackwell을 함께 지원하는 빌드가 필요합니다. 특정 모델용 컨테이너나 패치에서 나온 성능을 일반 설치의 결과로 받아들이면 재현하기 어렵습니다.
Mac에도 공식 문서가 설명하는 MLX 기반 Metal 서빙 경로가 있습니다. 이를 켜는 SGLANG_USE_MLX=1과 CUDA 경로는 같은 설치가 아닙니다. MLX 변환 모델과 지원 기능을 따로 확인해야 합니다. 이미지·영상용 SGLang Diffusion의 PyTorch MPS 경로와도 구별하세요. 이 글 아래의 시작 명령은 NVIDIA CUDA 환경용이며 Mac용 명령으로 제공하는 것이 아닙니다.
3. 가속 없이 서버와 질문을 먼저 연결합니다
설치 후에는 작은 Qwen2.5-0.5B-Instruct로 서버가 질문을 받는지 확인합니다. 문맥 상한 4,096과 동시 요청 1은 연결 확인을 위한 값이지 장비별 최고속 설정이 아닙니다. 아직 파일이 없으면 첫 실행 때 다운로드가 필요합니다. 모델을 읽고 서버가 준비될 때까지 기다린 다음, 별도 터미널에서 두 번째 명령을 실행하세요.
질문이 정상적으로 돌아오면 앱에 http://127.0.0.1:30000/v1을 연결합니다. 연결이 안 될 때 주소를 0.0.0.0으로 바꾸기보다 서버 준비 여부와 포트, 모델 이름부터 맞추세요. 작은 모델의 답변 품질은 주사용 모델을 선택하는 기준이 아닙니다. 여기서 확인하는 것은 엔진과 클라이언트 사이의 연결입니다.
SGLang CUDA 서버 시작
python3 -m sglang.launch_server \
--model-path Qwen/Qwen2.5-0.5B-Instruct \
--host 127.0.0.1 --port 30000 \
--context-length 4096 --max-running-requests 1해당 NVIDIA 장비에 맞는 SGLang 설치를 마친 뒤 실행하는 연결 확인 예제입니다.
로컬 서버에 짧은 질문 보내기
curl --fail-with-body http://127.0.0.1:30000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"Qwen/Qwen2.5-0.5B-Instruct","messages":[{"role":"user","content":"Explain what a local AI server does in two sentences."}],"max_tokens":64,"temperature":0}'서버와 요청에서 같은 모델 이름을 사용합니다. 공개 예문이므로 개인 문서를 넣을 필요가 없습니다.
4. 문서를 읽다가 멈추는지, 쓰다가 멈추는지
주사용 모델로 바꾸면 같은 양자화 이름이어도 로더와 GPU 연산 지원을 확인해야 합니다. 모델 가중치와 KV 캐시가 차지하는 몫은 --mem-fraction-static으로 조절하지만, 나머지 계산 공간도 필요합니다. 높은 값을 복사해 빈 메모리를 모두 채우면 오히려 실행 중 실패할 수 있습니다. 작은 모델에서 됐던 설정이 큰 모델에서도 된다는 보장은 없습니다.
긴 문서를 읽는 프리필에서 메모리가 부족하면 --chunked-prefill-size를 줄여 한 번에 처리할 입력을 나눠봅니다. 이 변경은 대기 시간도 바꿀 수 있습니다. 답변을 쓰는 동안만 부족하다면 --max-running-requests부터 낮춥니다. 모델 자체가 들어가지 않는 문제와 작업 중 공간이 부족한 문제를 나눠야, 작은 양자화 파일이 필요한지 설정 조정으로 충분한지 알 수 있습니다.
5. MTP와 NGRAM은 이름만 보고 묶지 않습니다
SGLang의 MTP는 모델에 맞는 투기 디코딩 경로를 사용합니다. --speculative-algorithm과 후보 깊이·폭 설정이 등장하지만, 별도 초안 모델이 필요한 방식과 내장 MTP는 다릅니다. 현재 문서에서 NEXTN은 EAGLE의 별칭으로 설명됩니다. 이 이름이 있다고 모든 Qwen·Gemma·GLM 파일에 같은 명령을 붙일 수 있는 것은 아닙니다.
NGRAM 투기 디코딩은 이전 토큰에서 후보를 찾는 기능입니다. 큰 n-gram 임베딩 테이블을 RAM이나 SSD에 놓는 PLE 오프로드와는 다른 이야기입니다. 가속을 더할 때는 후보 검증용 메모리와 현재 백엔드의 제약도 함께 확인합니다. 먼저 가속 없이 같은 조건의 기록을 남기고, 켠 뒤 새 문서와 반복 문서에서 각각 나아졌는지 판단하세요.
6. 동작한 설정을 남긴 뒤 다음을 시험합니다
커널이나 라이브러리 오류라면 기존 가상환경에 패키지를 계속 덧씌우기보다 마지막으로 동작한 환경으로 돌아갑니다. MTP 추가 후 메모리 오류가 생겼다면 가속을 먼저 빼세요. 지원되지 않는 옵션이라는 메시지는 모델 성능 문제가 아니라 설치 버전과 명령이 어긋났다는 신호일 수 있습니다. 다른 엔진의 --gpu-memory-utilization을 SGLang의 메모리 옵션 대신 넣지 않습니다.
마지막에는 모델 revision, 런타임·커널 버전, 가속 여부와 실제 입력 길이를 함께 남깁니다. 같은 조건에서 준비 실행 뒤 세 번 이상 확인하고 첫 토큰과 디코드 시간을 나눠보세요. Spark 두 대를 쓸 때도 용량을 늘리기 위한 분할과 요청을 나눠 받는 처리는 다른 목적입니다. 내가 자주 하는 작업이 개선됐다는 기록이 생긴 다음에 장비를 늘려도 늦지 않습니다.
수정 내역
사이트의 안내가 바뀐 기록입니다. 설치된 엔진·모델 버전을 자동으로 확인한 결과는 아닙니다.
SGLang 캐시·모델별 옵션 안내 추가
로컬 서버 연결 예제와 프리필·디코드 단계별 메모리 조정 순서를 추가했습니다. 반복 입력의 캐시 효과를 분리하고, NGRAM 후보 검색과 PLE 테이블의 RAM·SSD 배치를 다른 기능으로 설명했습니다.