XPU
XPU
이 문서는 SGLang 환경을 Intel GPU에서 설정하고 LLM 추론을 실행하는 방법을 다루어요 (PyTorch 생태계 내 Intel GPU 지원에 대한 자세한 맥락은 이 문서를 참고하세요).
출처: 문서
본문
구체적으로 SGLang은 Intel® Arc™ Pro B-Series Graphics와 Intel® Arc™ B-Series Graphics에 최적화되어 있어요.
Llama 시리즈, Qwen 시리즈 같은 널리 알려진 오픈소스 모델과 FLUX, Z-Image 같은 Diffusion 모델 시리즈를 포함해 많은 인기 LLM이 XPU에서 최적화되어 효율적으로 실행돼요. 지원 상태와 예시 명령은 SGLang Cookbook 페이지에서 확인할 수 있어요.
양자화된 MoE 모델은 아래의 MXFP4 MoE 양자화에서 별도로 다루어요.
설치 (Installation)
소스에서 설치 (Install From Source)
현재 SGLang XPU는 소스에서만 설치를 지원해요. XPU 의존성 설치는 "Getting Started on Intel GPU"를 참고하세요.
# 아래 명령은 Ubuntu/Debian OS를 예시로 보여줌. 다른 OS는 유사하게 명령을 바꿔야 함
# 패키지 설치 시 필요하면 sudo 추가
# curl과 protobuf 컴파일러 설치
apt-get update && apt-get install -y curl protobuf-compiler
# Rust 설치 (비대화형)
curl --proto '=https' --tlsv1.2 --retry 3 --retry-delay 2 -sSf https://sh.rustup.rs | sh -s -- -y
# 현재 셸에서 cargo 사용 가능하게
source "$HOME/.cargo/env"
# conda 환경 생성 및 활성화
conda create -n sgl-xpu python=3.12 -y
conda activate sgl-xpu
# PyTorch XPU를 기본 pip 설치 채널로 설정해 더 큰 CUDA 지원 버전 설치를 피하고 잠재적 런타임 문제 방지
pip3 install torch==2.13.0+xpu torchvision==0.28.0+xpu torchaudio==2.11.0+xpu --index-url https://download.pytorch.org/whl/xpu
pip3 install xgrammar==0.1.33 --no-deps # xgrammar는 XPU와 충돌할 수 있는 CUDA 지원 triton을 도입함
# SGLang 코드 클론
git clone https://github.com/sgl-project/sglang.git
cd sglang
git checkout <YOUR-DESIRED-VERSION>
# 전용 toml 파일 사용
cd python
cp pyproject_xpu.toml pyproject.toml
# SGLang 의존 라이브러리 설치 및 SGLang 메인 패키지 빌드
pip install --upgrade pip setuptools
pip install -v . --extra-index-url https://download.pytorch.org/whl/xpu
Docker 사용 설치 (Install Using Docker)
SGLang 환경을 구성할 때는 Docker를 사용하는 것을 권장해요.
Docker Hub에서 받아오기 (Pull from Docker Hub)
lmsysorg/sglang 저장소에서 미리 빌드된 SGLang 패키지 릴리스 Docker 이미지를 받아오세요. XPU 이미지 태그는 xpu 접미사로 끝나요. 이미지 받아오기 명령은 다음과 같아요:
docker pull lmsysorg/sglang:v0.5.20-xpu
Dockerfile에서 빌드하기 (Build from Dockerfile)
The SGLang XPU Dockerfile이 설치를 돕기 위해 제공돼요. 아래의 <secret>을 여러분의 HuggingFace access token으로 바꾸세요.
# SGLang 저장소 클론
git clone https://github.com/sgl-project/sglang.git
cd sglang/docker
# 도커 이미지 빌드
docker build -t sglang-xpu:latest -f xpu.Dockerfile .
# 도커 컨테이너 시작
docker run \
-it \
--privileged \
--ipc=host \
--network=host \
--user root \
--group-add $(getent group video | cut -d: -f3) \
--device /dev/dri \
-v /dev/dri/by-path:/dev/dri/by-path \
-v /dev/shm:/dev/shm \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 30000:30000 \
-e "HF_TOKEN=<secret>" \
sglang-xpu:latest /bin/bash
서빙 엔진 실행 (Launch of the Serving Engine)
SGLang 서빙을 실행하는 예시 명령:
sglang serve \
--model-path <MODEL_ID_OR_PATH> \
--trust-remote-code \
--device xpu \
--host 0.0.0.0 \
--tp 2 \
--attention-backend intel_xpu \
--page-size
MXFP4 MoE 양자화 (MXFP4 MoE Quantization)
네이티브 MXFP4 MoE 체크포인트(OCP microscaling FP4: packed e2m1 가중치 + 32개 요소당 ue8m0 블록 스케일)는 sgl-kernel-xpu W4A16 grouped GEMM을 통해 Intel GPU에서 실행돼요. 전문가 가중치는 체크포인트의 packed 레이아웃으로 처음부터 끝까지 유지돼요 — BF16으로의 역양자화가 없어요 — 그래서 GPT-OSS-20B는 BF16 업캐스트가 필요한 ~42 GB 대신 약 13 GB로 로드돼요. 이것이 단일 24 GB 카드에 맞을 수 있는 이유예요.
mxfp4 메서드는 --device xpu에서 자동으로 등록돼요. 이는 이미 sgl-kernel-xpu를 요구하므로 추가 플래그가 필요 없어요:
sglang serve \
--model-path openai/gpt-oss-20b \
--device xpu \
--attention-backend intel_xpu
테스트된 모델:
| 모델 | 참고 |
|---|---|
| openai/gpt-oss-20b | 32 전문가, top-k 4, hidden 2880, intermediate 2880; 전문가 바이어스를 가진 clamped-swiglu 활성화(gemm1_alpha 1.702, limit 7.0) |
요구 사항과 제한:
| 항목 | 상태 |
|---|---|
| GPU 아키텍처 | Xe2 / BMG만 (Intel® Arc™ B-Series 및 Arc™ Pro B-Series) |
| 양자화 레이어 | Fused MoE 전문가만; 어텐션, 라우터, 임베딩, LM head는 BF16 유지(체크포인트의 modules_to_not_convert 기준) |
| 활성화 | BF16 (W4A16). Clamped swiglu (GPT-OSS)와 일반 SiLU 지원 |
| 전문가 병렬 처리 | 이 경로에서 아직 검증되지 않음 |
요청으로 벤치마킹 (Benchmarking with Requests)
bench_serving 스크립트로 성능을 벤치마킹할 수 있어요. 다른 터미널에서 명령을 실행하세요.
python -m sglang.bench_serving \
--dataset-name random \
--random-input-len 1024 \
--random-output-len 1024 \
--num-prompts 1 \
--request-rate inf \
--random-range-ratio 1.0
파라미터의 자세한 설명은 다음 명령으로 확인할 수 있어요:
python -m sglang.bench_serving -h
또한 요청은 OpenAI Completions API로 형식을 만들 수 있고, 커맨드라인(예: curl)이나 여러분만의 스크립트로 보낼 수 있어요.
XPU Graph [실험적]
SGLang은 스텝당 커널 실행 오버헤드를 줄이기 위해 XPU graph 캡처를 활성화해요.
| 단계 | 백엔드 | 메커니즘 | 기본 |
|---|---|---|---|
| Decode | full |
배치 크기마다 torch.xpu.XPUGraph 하나, 시작 시 캡처 |
꺼짐 (opt-in) |
| Prefill | tc_piecewise |
torch.compile + XPU graph, 토큰 길이 버킷마다 그래프 세그먼트 하나 |
꺼짐 (opt-in) |
| Prefill | breakable |
분할된 torch.xpu.XPUGraph 캡처/재생 (torch.compile 없음); 어텐션/MoE 경계에서 eager 중단점 |
꺼짐 (opt-in) |
Decode Graph 활성화
Decode graph 캡처는 XPU에서 opt-in이에요. 명시적으로 활성화하세요:
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-backend-decode full
Prefill Graph 활성화
Prefill graph 캡처는 XPU에서 opt-in이며 명시적으로 활성화해야 해요. 두 백엔드를 사용할 수 있어요: tc_piecewise와 breakable.
tc_piecewise
torch.compile과 XPU graph를 함께 사용해 토큰 길이 버킷마다 그래프 세그먼트 하나를 만듭니다:
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-backend-prefill tc_piecewise
기본적으로 prefill 서브그래프는 eager 모드로 컴파일돼요. 더 긴 시작 시간을 대가로 더 높은 품질의 생성 코드를 위해 inductor로 전환:
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-backend-prefill tc_piecewise \
--cuda-graph-tc-compiler inductor
breakable
torch.compile 없이 어텐션/MoE 경계에서 eager 중단점을 가진 분할된 XPUGraph로 트랜스포머 스택을 캡처합니다:
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-backend-prefill breakable
단일 --cuda-graph-config JSON 인자로 두 단계를 함께 구성할 수도 있어요:
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-config '{"decode":{"backend":"full"},"prefill":{"backend":"tc_piecewise","tc_compiler":"eager"}}'
Decode용 torch.compile 활성화
--enable-torch-compile은 decode XPU graph 위에 torch.compile 패스를 추가해요: 모델 포워드가 먼저 컴파일되고, 컴파일된 포워드가 XPUGraph로 캡처돼요. 이는 커널당 오버헤드를 더 줄이지만 시작 시간은 늘려요.
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--enable-torch-compile
주의:
--enable-torch-compile은 prefilltc_piecewisegraph와 상호 배타적이에요(호환성 규칙이 자동으로 비활성화함). 둘 다 필요하면 별도로 사용하거나--cuda-graph-config로 prefill 백엔드를 명시적으로 고정하세요.
XPU Graph 비활성화
두 단계 모두 기본적으로 비활성화되어 있어요. 그래도 명시적으로 비활성화하려면:
# Decode graph 비활성화 (기본적으로 꺼져 있음; 명시적 형태)
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-backend-decode=disabled
# Prefill graph 비활성화 (기본적으로 꺼져 있음; 명시적 형태)
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-backend-prefill=disabled
# 두 단계 모두 비활성화
python -m sglang.launch_server --model-path <MODEL> --device xpu \
--cuda-graph-backend-decode=disabled \
--cuda-graph-backend-prefill=disabled
캡처 버킷 커스터마이즈 (Customize Capture Buckets)
기본적으로 prefill 캡처 크기는 --chunked-prefill-size에서 파생돼요. 명시적 토큰 길이 버킷을 지정하려면:
python -m sglang.launch_server \
--model-path <MODEL> --device xpu \
--cuda-graph-backend-prefill tc_piecewise \
--cuda-graph-bs-prefill 64 128 256 512
명시적 decode graph 배치 크기를 지정하려면:
python -m sglang.launch_server \
--model-path <MODEL> --device xpu \
--cuda-graph-bs-decode 1 2 4 8
서버 인자 (Server Args)
| 인자 | XPU 허용 값 | 기본 | 설명 |
|---|---|---|---|
--cuda-graph-backend-decode |
full, disabled |
disabled |
decode 단계용 백엔드. XPU에서는 full만 지원. 활성화하려면 full로 설정. |
--cuda-graph-backend-prefill |
tc_piecewise, breakable, disabled |
disabled* |
prefill 단계용 백엔드. 활성화하려면 tc_piecewise 또는 breakable로 명시적으로 설정. |
--cuda-graph-tc-compiler |
eager, inductor |
eager |
tc_piecewise prefill 서브그래프용 컴파일러. inductor는 더 최적화된 코드를 생성하지만 시작 시간이 더 길어요. |
--cuda-graph-bs-prefill |
정수 리스트 | auto | prefill 캡처용 명시적 토큰 길이 버킷. |
--cuda-graph-bs-decode |
정수 리스트 | auto | decode 캡처용 명시적 배치 크기. |
--cuda-graph-config |
JSON 문자열 | — | 두 단계 모두를 위한 원샷 JSON 구성, 예: '{"decode":{"backend":"full"},"prefill":{"backend":"tc_piecewise","tc_compiler":"eager"}}'. 모든 단계별 플래그를 덮어씀. |
--disable-decode-cuda-graph |
— | False |
--cuda-graph-backend-decode=disabled의 약칭. |
--disable-prefill-cuda-graph |
— | False |
--cuda-graph-backend-prefill=disabled의 약칭. |
--enable-torch-compile |
— | False |
추가 커널 최적화를 위해 decode XPU graph 위에 torch.compile 적용. |
--torch-compile-max-bs |
정수 | 32 |
--enable-torch-compile 설정 시 torch.compile이 컴파일할 최대 배치 크기. |
* Prefill graph는 --cuda-graph-backend-prefill 또는 --cuda-graph-config로 백엔드를 명시적으로 고정하지 않으면 XPU에서 자동 비활성화돼요.
제한 (Limitations)
| 기능 | 상태 |
|---|---|
Two-batch overlap (--enable-two-batch-overlap) |
아직 지원되지 않음 |
| 투기적 디코딩 | 아직 구현되지 않음 |
Intel XPU의 메모리 세이버 [실험적] (Memory Saver)
SGLang은 보유한 GPU 메모리 대부분(모델 가중치 및/또는 KV 캐시)을 일시적으로 해제하고 프로세스를 재시작하지 않고 나중에 회수할 수 있어요. 이는 CUDA에서 사용 가능한 것과 같은 release_memory_occupation / resume_memory_occupation 기능으로, RL 롤아웃/훈련 핸드오프와 추론 버스트 사이의 디바이스 해제에 사용돼요.
이 기능은 CUDA에서 사용하는 것과 같은 torch_memory_saver 패키지로 구현돼요. 이 패키지는 Level Zero 위에 네이티브로 구축된 Intel XPU 백엔드를 얻었어요(가상 주소를 고정 유지하면서 zeVirtualMemUnmap / zeVirtualMemMap으로 물리 페이지를 해제/재커밋).
torch_memory_saver 설치. CUDA(사전 빌드 휠)와 달리 XPU 백엔드는 여러분의 로컬 oneAPI + torch+xpu 런타임에 맞춰 소스에서 빌드돼요(.so가 libsycl.so.<N>을 링크하며, 이는 설치된 intel-sycl-rt와 일치해야 함). TMS_PLATFORM=xpu는 XPU 백엔드를 강제하고, --no-build-isolation은 빌드가 설치된 torch를 임포트해 libsycl 메이저를 일치시킬 수 있게 해요:
게시된 휠은 CUDA 전용이므로 git에서 설치하고 빌드를 진행하세요. 아래 ref는 v0.0.10b2 릴리스로, 재현 가능한 빌드를 위해 고정됐어요.
source /opt/intel/oneapi/setvars.sh
TMS_PLATFORM=xpu pip install --no-build-isolation \
git+https://github.com/fzyzcjy/torch_memory_saver.git@a5c99f11b18ebb8e9fda71a68812e476ae49e417
사용은 --enable-memory-saver로 실행해서(XPU 백엔드가 자동 선택됨); 선택적으로 --enable-weights-cpu-backup을 추가해 해제하는 동안 가중치를 호스트 RAM에 유지할 수 있어요:
python -m sglang.launch_server --model-path Qwen/Qwen3-0.6B \
--trust-remote-code --device xpu --enable-memory-saver
# 유휴 동안 GPU 메모리 해제 후 회수 (서버는 유휴 상태여야 함)
curl -X POST http://127.0.0.1:30000/release_memory_occupation
curl -X POST http://127.0.0.1:30000/resume_memory_occupation
Python 엔진 API(engine.release_memory_occupation(tags=...) / engine.resume_memory_occupation(tags=...))와 weights / kv_cache 태그는 CUDA에서와 동일하게 동작해요. XPU에서는 일시정지 가능한 CUDA-graph 캡처가 사용되지 않으므로 cuda_graph 태그는 여기서 no-op이에요.
메모리 해제 확인: 물리 페이지가 해제되어도
torch.xpu.memory_allocated()나torch.xpu.mem_get_info()는 내려가지 않아요 — 전자는 할당기 회계이고, 후자는 torch가 해제된 블록을 캐시해 두기 때문에 평평하게 유지돼요. 실제 디바이스 메모리는 sysman(ZES_ENABLE_SYSMAN=1)으로 조회하세요.
Intel XPU의 Prefill-Decode (P/D) 분리 [실험적]
SGLang은 NIXL KV 전송 백엔드를 사용해 Intel XPU에서 prefill-decode 분리를 지원해요.
테스트된 모델:
| 모델 | 참고 |
|---|---|
| Qwen/Qwen3-0.6B | 통합 테스트에 사용; 동종 P/D(XPU prefill + XPU decode)로 Intel XPU에서 검증됨 |
| Qwen/Qwen2.5-7B-Instruct | 동종 P/D(XPU prefill + XPU decode)로 Intel XPU에서 검증됨 |
사전 요구 사항: pip install nixl sglang-router
Prefill 서버 시작 (GPU 0):
ZE_AFFINITY_MASK=0 UCX_POSIX_USE_PROC_LINK=n python -m sglang.launch_server \
--model-path Qwen/Qwen3-0.6B --trust-remote-code --device xpu \
--disaggregation-mode prefill --disaggregation-transfer-backend nixl \
--disaggregation-bootstrap-port 12335 --host 0.0.0.0 --port 30000
Decode 서버 시작 (GPU 1):
ZE_AFFINITY_MASK=1 UCX_POSIX_USE_PROC_LINK=n python -m sglang.launch_server \
--model-path Qwen/Qwen3-0.6B --trust-remote-code --device xpu \
--disaggregation-mode decode --disaggregation-transfer-backend nixl \
--disaggregation-bootstrap-port 12335 --host 0.0.0.0 --port 30001
라우터 시작:
python -m sglang_router.launch_router \
--pd-disaggregation \
--prefill http://127.0.0.1:30000 \
--decode http://127.0.0.1:30001 \
--host 0.0.0.0 --port 8000
요청 보내기:
curl http://127.0.0.1:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "Qwen/Qwen3-0.6B", "prompt": "The capital of France is", "max_tokens": 32}'
주의: UCX 공유 메모리 전송 문제를 피하려면 Intel XPU에서
UCX_POSIX_USE_PROC_LINK=n이 필요해요.