주요 콘텐츠로 건너뛰기
AI 튜토리얼

두 대의 NVIDIA DGX Spark 시스템에서 GLM-5.3 Flash EXL3 서비스 제공

두 대의 NVIDIA GB10 DGX Spark 시스템에 GLM-5.3 Flash EXL3를 설치하고 구성, 실행, 테스트 및 튜닝하는 방법을 알아보세요. 이 튜토리얼에서는 2노드 런타임, DFlash2 추측 디코딩, fp8 MLA KV 캐시, OpenAI 호환 요청, 프리픽스 캐싱, 벤치마킹, 선택적 절제 실험 및 주요 구성 제약 사항을 다룹니다.

두 대의 NVIDIA DGX Spark 시스템에서 GLM-5.3 Flash EXL3 서비스 제공

개요

2x DGX Spark용 GLM-5.3 Flash EXL3는 두 대의 NVIDIA GB10 시스템에서 GLM-5.3 Flash의 4 bpw EXL3/TR3 양자화를 제공하기 위한 배포 레시피이자 vLLM 오버레이입니다. 포트 8888에서 OpenAI 호환 API를 제공하며, 모델은 GLM-5.3-Flash-EXL3 식별자로 서비스됩니다.

이 레시피는 각 머신에 하나의 랭크를 배치하는 텐서 병렬화를 사용합니다. 패킹된 EXL3 라우팅 전문가, 네이티브 sm_121a 커널, fp8 sparse-MLA KV 캐시, CUDA 그래프, 7개의 초안 토큰을 사용하는 DFlash2 추측 디코딩을 결합합니다.

기본적으로 사용되는 체크포인트는 Mia-AiLab/GLM-5.3-Flash-EXL3-TR3-4bpw이며, 참조된 Brandon Music 스냅샷과 바이트 단위로 동일한 공개 미러입니다. 120개 샤드에 약 164GiB가 저장되어 있습니다. 모델 저장소에는 자체 라이선스가 적용되며, 서비스 스크립트와 오버레이는 MIT 라이선스가 적용됩니다.

오버레이가 필요한 이유

기본 ARM64 GLM-5.3 vLLM 이미지는 이 체크포인트를 로드할 수 있지만, GLM-5.3 Flash가 NoPE MLA를 사용하는 반면 사용 가능한 SM12x sparse-MLA 백엔드는 다른 패킹 형상을 요구하기 때문에 첫 번째 순전파에서 실패합니다. 오버레이는 QK 내적을 변경하지 않고 512차원 NoPE 잠재 표현을 FLASHINFER_MLA_SPARSE_SM120에 필요한 형상으로 패딩합니다.

또한 동작하는 EXL3 양자화 방식을 등록합니다. 이를 통해 라우팅 전문가는 BF16으로 확장되지 않고 패킹된 trellis, SUH, SVH, MCG 표현을 유지합니다. 융합 경로를 활성화하면 각 레이어에서 하나의 exllamav3_ext.exl3_moe 실행만 사용합니다.

이 오버레이는 EAGLE3 보조 은닉 상태 캡처, 대상 MLA KV 슬롯을 공유하는 초안 슬라이딩 윈도우 어텐션, 추측 초안 블록 내 비인과적 어텐션을 포함한 GLM 전용 DFlash2 통합 기능도 제공합니다.

주요 기능

  • OpenAI 호환 서비스: vLLM은 헤드 노드에서 /v1/chat/completions 및 관련 엔드포인트를 제공합니다.
  • 2노드 텐서 병렬화: 배포에는 --nnodes 2와 --tensor-parallel-size 2가 사용됩니다.
  • 컴팩트한 EXL3 가중치: 4 bpw 체크포인트의 다운로드 용량은 약 164GiB이며, 참조된 품질 패널에는 176GB로 표시됩니다.
  • DFlash2 추측 디코딩: 기본 초안 모델은 incoai/GLM-5.3-Flash-DFlash2이며 k=7이 적용됩니다.
  • 긴 컨텍스트: 기본 최대 모델 길이는 900,000토큰이며, 문서화된 메모리 구성에서 982,612토큰으로 보고된 fp8 MLA 풀을 기반으로 합니다.
  • 멀티모달 지원: 이미지 및 동영상 입력이 활성화되어 있으며, 프롬프트당 기본 제한은 이미지 4개와 동영상 1개입니다.
  • 도구 및 추론 파싱: 런처는 자동 도구 선택과 GLM 호환 도구 호출 및 추론 파서를 활성화합니다.
  • 프리픽스 캐싱: 관련 해시가 캐시에 남아 있으면 블록에 맞춰 정렬된 프리픽스를 재사용할 수 있습니다.
  • 선택적 거부 방향 제거: ABLIT=1은 로드 시 선택된 네이티브 BF16 출력 프로젝션 가중치를 메모리상에서 수정합니다.

하드웨어 및 소프트웨어 요구 사항

이 레시피는 문서화된 CX7 패브릭으로 연결된 두 대의 NVIDIA GB10 DGX Spark급 시스템을 위해 특별히 설계되었습니다. 일반적인 단일 GPU 배포용이 아닙니다.

  • 초기 설정을 위해 노드당 약 180GiB의 여유 저장 공간이 있는 NVIDIA GB10 시스템 2대.
  • 두 시스템에서 sudo 없이 사용할 수 있는 Docker.
  • 헤드 노드에서 워커로 비밀번호 없이 접속할 수 있는 SSH.
  • 헤드 노드에 설치된 hf 또는 huggingface-cli, curl, rsync.
  • 두 머신의 올바른 CX7 네트워크 인터페이스 및 RDMA 장치.
  • 120개 샤드 체크포인트와 약 2.3GiB 크기의 DFlash2 모델을 저장할 수 있는 Hugging Face 캐시 위치.

물리적 케이블 연결이 다른 경우가 아니라면 저장소의 CX7 인터페이스 및 HCA 설정을 유지하세요. README는 NCCL이 10.0.0.x 루프백 별칭을 사용할 수 없으며, 패브릭 핀이 잘못되면 ncclCommInitRank 중 멈출 수 있다고 경고합니다.

배포 설치 및 구성

1. 저장소 복제

git clone https://github.com/MiaAI-Lab/GLM-5.3-Flash-EXL3-2x-DGX-Sparks.git
cd GLM-5.3-Flash-EXL3-2x-DGX-Sparks

2. 환경 파일 생성

cp .env.example .env

머신에서 레시피의 기본 주소나 계정 이름을 사용하지 않는 경우 .env를 편집하세요. 주요 설정은 다음과 같습니다.

  • 헤드 노드 및 vLLM 마스터의 HEAD_IP=10.0.0.1.
  • 두 번째 Spark의 WORKER_IP=10.0.0.2.
  • 노드 간 SSH 계정이 다를 때 설정하는 WORKER_USER.
  • 워커의 홈 디렉터리 또는 Hugging Face 캐시 위치가 다를 때 설정하는 WORKER_HOME.
  • API 리스너의 PORT=8888.

런처는 .env가 없으면 .env.example에서 자동으로 생성합니다. 명령 실행 전에 직접 지정한 값이 파일의 값보다 우선합니다.

3. 선택적으로 가중치 준비

./download.sh

이 명령은 EXL3 체크포인트와 DFlash2 모델을 헤드 노드의 Hugging Face 캐시에 다운로드합니다. Docker를 실행하거나 워커에 연결하거나 파일을 동기화하지는 않습니다. 워커가 준비되기 전에 약 164GiB의 모델 다운로드를 완료하려는 경우 사용하세요.

캐시된 파일을 명시적으로 새로 받으려면 다음을 실행하세요.

REFRESH_WEIGHTS=1 ./download.sh

불필요하게 새로 고침하지 마세요. download.sh와 start.sh는 이미 완료된 저장소를 모두 건너뜁니다.

4. 두 rank와 API 시작

./start.sh

시작 스크립트는 다음 순서로 실행됩니다.

  1. 두 노드에서 Docker, SSH, 사용 가능한 디스크 공간을 확인합니다.
  2. 헤드에서 공개 ghcr.io/miaai-lab/glm-5.3-flash-2x-dgx-sparks:exl3 이미지를 가져옵니다.
  3. 이미지 다이제스트가 변경된 경우 컨테이너 이미지를 워커로 전송합니다.
  4. 누락된 모델 파일을 헤드의 Hugging Face 캐시에 다운로드합니다.
  5. rsync로 캐시를 워커에 동기화합니다.
  6. 워커에서 헤드리스 모드로 rank 1을 시작합니다.
  7. 헤드에서 rank 0과 OpenAI 호환 API를 시작합니다.
  8. 모델 로딩과 워밍업이 완료될 때까지 상태 엔드포인트를 폴링합니다.

가중치 로딩과 CUDA 그래프 캡처에 상당한 시간이 걸릴 수 있으므로 기본 준비 완료 시간 제한은 3,600초입니다.

5. 상태 및 로그 확인

./start.sh status
./start.sh logs
./start.sh logs worker

다음 명령으로 두 컨테이너를 중지합니다.

./start.sh stop

./stop.sh를 사용할 수도 있습니다.

기본 채팅 요청 보내기

헤드 노드에서 기본 API URL은 http://127.0.0.1:8888/v1입니다. 문서에 나오는 LAN 주소를 사용하면 다른 머신에서는 http://10.0.0.1:8888/v1을 사용할 수 있습니다.

curl -s http://127.0.0.1:8888/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "GLM-5.3-Flash-EXL3",
    "messages": [
      {"role": "user", "content": "Explain tensor parallelism briefly."}
    ],
    "chat_template_kwargs": {
      "enable_thinking": false
    }
  }'

요청의 model 값은 제공되는 모델 이름과 일치해야 하며, 기본값은 GLM-5.3-Flash-EXL3입니다. 사고 모드는 기본적으로 활성화됩니다. 비활성화하려면 위 예시처럼 JSON 요청의 최상위에 chat_template_kwargs를 배치하세요.

원시 HTTP를 통해 중첩된 리터럴 extra_body 객체를 보내지 마세요. OpenAI Python SDK에서 extra_body는 해당 내용을 최상위 요청에 병합하는 SDK 옵션입니다.

체크포인트의 생성 설정에 temperature=1.0 및 top_p=0.95가 지정되어 있을 수 있습니다. 다른 동작이 필요하면 각 요청에서 샘플링 값을 설정하세요.

기본 런타임 이해

이 배포의 기본값은 서로 맞물리도록 의도적으로 조정되어 있습니다. 한 구성 요소를 변경하면 커널 조합이 유효하지 않게 되거나 추측 수용률이 낮아질 수 있습니다.

  • 가중치: Mia-AiLab/GLM-5.3-Flash-EXL3-TR3-4bpw를 사용하며, 미러를 사용할 수 없거나 불완전하면 Brandon Music 저장소로 대체합니다.
  • 병렬화: 멀티프로세싱 실행기를 사용해 두 노드에서 텐서 병렬 크기 2로 실행합니다.
  • 양자화: exl3를 사용하며, 라우팅된 전문가 가중치는 패킹하고 dense, 공유 전문가, 어텐션, 임베딩 및 출력 헤드 가중치는 네이티브 형식으로 사용합니다.
  • 대상 KV 캐시: fp8이며 내부적으로 패킹된 fp8_ds_mla로 표현됩니다.
  • 추측 실행: DFlash2를 사용하고 추측 토큰 7개와 초안 텐서 병렬 크기 1을 적용합니다.
  • 초안 KV 캐시: 자동 선택되며, 대상 모델의 MLA 레이아웃 대신 dense 초안 모델에 BF16을 사용합니다.
  • 어텐션: 대상 모델에는 희소 MLA를 사용하고, DFlash2 초안 어텐션에는 자동 선택된 FLASH_ATTN을 사용합니다.
  • 컨텍스트: MAX_MODEL_LEN=900000.
  • 동시성: MAX_NUM_SEQS=4.
  • 프리필: MAX_NUM_BATCHED_TOKENS=1024.
  • 메모리 사용률: GPU_MEM_UTIL=0.87.

추측 디코딩 모드 전환

DFlash2가 기본값이며 incoai/GLM-5.3-Flash-DFlash2를 사용합니다. 추측 토큰 2개를 사용하는 체크포인트의 MTP 경로로 되돌리려면 다음과 같이 재시작하세요.

SPEC_METHOD=mtp ./start.sh restart

환경 변수는 SPEC_METHOD=none도 지원합니다. DFlash2의 기본 초안 텐서 병렬 크기는 1이므로 작은 초안 모델을 rank 0에 유지하고 각 초안 단계마다 CX7 통신이 발생하지 않도록 합니다.

DFlash2에 TRITON_ATTN을 강제로 사용하지 마세요. README의 측정 결과에 따르면 이 백엔드는 초안 블록 내 어텐션을 인과적으로 만들어 이후 추측 위치의 수용률을 급격히 떨어뜨렸습니다. 초안 어텐션을 설정하지 않아 SM121이 FLASH_ATTN을 선택하도록 하세요.

KV 캐시 및 긴 컨텍스트 구성

대상 KV 캐시는 fp8로 유지해야 합니다. 이 아키텍처에서는 희소 MLA 커널이 패킹된 fp8_ds_mla를 지원합니다. BF16에는 호환되는 희소 커널이 없으며, NVFP4 KV 커널은 희소 MLA가 아닌 dense MHA에 적용됩니다.

DFlash2, 비전 지원, 0.87의 메모리 사용률, 최대 모델 길이 900,000을 사용할 때 README는 약 15.67GiB를 사용하는 982,612토큰 풀을 보고합니다. 이는 900,000토큰 전체 요청 하나의 용량에 약 1.09배에 해당합니다. 문서에 설명된 설정에서는 네이티브 100만 토큰 구성에 여전히 할당할 수 없습니다.

의도적인 런타임 변경을 테스트하는 경우가 아니라면 다음 설정을 유지하세요.

KV_CACHE_DTYPE=fp8
GPU_MEM_UTIL=0.87
MAX_MODEL_LEN=900000
MAX_NUM_BATCHED_TOKENS=1024
SKIP_MM_PROFILING=1
LIMIT_MM={"image":4,"video":1}

SKIP_MM_PROFILING=1이 중요한 이유는 최대 크기의 이미지 및 비디오 더미 입력을 프로파일링하면 통합 메모리가 고갈될 수 있기 때문입니다. README는 배치 토큰 제한을 8,192로 높이면 긴 컨텍스트 작업 중 GB10 인덱서 top-k 경로가 오버서브스크라이브될 수 있다고도 경고합니다.

접두사 캐싱 동작 방식

프리픽스 캐싱이 활성화되어 있어도 OpenAI API는 상태 비저장 방식으로 작동합니다. 클라이언트는 매 턴마다 전체 대화 기록을 다시 전송해야 합니다. vLLM은 제출된 프리픽스를 해시하고, 캐시된 블록이 여전히 사용 가능한 경우 이를 재사용할 수 있습니다.

  • 문서화된 MLA 캐시 관리자에서는 블록 경계에 맞는 토큰만 적중으로 계산됩니다.
  • MAX_NUM_SEQS=4는 동시에 처리할 수 있는 생성 작업을 4개로 허용하지만, 영구적인 채팅 세션 4개를 예약하지는 않습니다.
  • 유휴 상태의 대화가 캐시에 계속 남아 있는 것은 보장되지 않습니다.
  • 한 대화의 활성값이 다른 대화의 활성값과 섞이지 않습니다.
  • 다른 작업 부하가 해당 프리픽스를 제거하면 이전 채팅에서 새 프리필이 필요할 수 있습니다.

README의 실제 테스트에서는 7,760토큰으로 구성된 후속 요청 중 3,584토큰을 재사용했으며, 이는 프롬프트의 약 46퍼센트입니다. 프리픽스 캐싱은 영구적인 세션 저장소가 아니라 상황에 따라 제공되는 가속 기능으로 간주해야 합니다.

디코드 성능 측정

저장소에는 스트리밍 디코드 및 일관성 검사를 위한 tests/bench_decode.py가 포함되어 있습니다. 구조화된 카운트 테스트를 다음과 같이 실행합니다.

python3 tests/bench_decode.py \
  --phase structured \
  --structured \
  --runs 5 \
  --max-tokens 400 \
  --skip-coherence \
  --out /tmp/glm53-structured.json

산문 형식의 해시 맵 설명 테스트는 다음과 같이 실행합니다.

python3 tests/bench_decode.py \
  --phase prose \
  --runs 5 \
  --max-tokens 400 \
  --skip-coherence \
  --out /tmp/glm53-prose.json

README에 문서화된 워밍 완료 및 빈 KV 프로토콜에서 구조화된 작업 부하는 동시성 1에서 초당 62.9토큰, 동시성 2에서 전체 초당 103.3토큰, 동시성 4에서 전체 초당 146.5토큰을 기록했습니다. 성능은 추측 수락률에 크게 좌우됩니다. 실험실 중앙값은 구조화된 출력에서 초당 61.7토큰이었지만 산문에서는 26.9토큰이었습니다. 약 60,000~100,000개의 캐시된 토큰을 사용하는 혼합 또는 긴 컨텍스트 테스트에서는 초당 24~27토큰이 보고되었습니다.

이 수치는 README의 특정 2-G​​B10 구성, 프롬프트 유형, 온도 0 설정, 비활성화된 thinking, DFlash2 k=7, 400토큰 생성 조건을 기준으로 합니다. 보편적으로 보장되는 처리량으로 해석해서는 안 됩니다.

선택적 거부 방향 제거 실험

저장소에서는 EXL3 체크포인트를 다시 작성하거나 재양자화하지 않고 가중치 로드 시 거부 방향 제거 실험을 적용할 수 있습니다. 다음과 같이 활성화합니다.

ABLIT=1 ./start.sh restart
./start.sh logs | grep ablit

기본 레시피는 15~45번 레이어의 각 네이티브 BF16 self_attn.o_proj를 수정합니다. 0~14번 레이어는 안전 앵커로서 변경되지 않습니다. 기본 스케일은 ABLIT_ALPHA=3.0이며, 이를 1.0으로 설정하면 제공된 방향을 따라 존재하는 성분을 제거하는 단순 투영을 적용합니다.

유용한 제어 옵션은 다음과 같습니다.

  • ABLIT=0 또는 값을 설정하지 않으면 기본 가중치를 변경하지 않습니다.
  • ABLIT_DIRECTION=dealign은 공개된 기본 방향을 사용합니다.
  • ABLIT_LAYERS=15-45는 수정할 레이어 범위를 양 끝 포함으로 지정합니다.
  • ABLIT_ALPHA=3.0은 투영 스케일을 지정합니다.
  • MTP를 사용하는 경우 ABLIT_INCLUDE_MTP=1로 체크포인트의 MTP 블록을 포함할 수 있습니다.

README의 KLD 품질 결과는 제거 실험 없이 측정되었습니다. 이를 활성화하면 거부 동작이 바뀌며, DFlash2 초안 생성기는 변경되지 않은 상태에서 대상 출력이 바뀌므로 일관성이나 추측 수락률에 영향을 줄 수 있습니다. 일관성이 저하되면 README에서는 먼저 ABLIT_ALPHA를 낮추도록 권장합니다.

고급 실행 워크플로

두 컴퓨터 모두에 이미지와 모델 캐시가 존재하면 반복적인 전송 작업을 건너뛸 수 있습니다.

SKIP_DOWNLOAD=1 SKIP_SYNC=1 ./start.sh

로컬 컨테이너 이미지를 유지하면서 모든 풀, 다운로드 및 동기화를 건너뛰려면 다음을 실행합니다.

SKIP_PULL=1 SKIP_DOWNLOAD=1 SKIP_SYNC=1 ./start.sh restart

공개 이미지를 사용하지 않고 현재 저장소에서 오버레이를 다시 빌드하려면 다음을 실행합니다.

BUILD=1 SKIP_DOWNLOAD=1 SKIP_SYNC=1 ./start.sh restart

Dockerfile을 직접 빌드할 수도 있습니다.

docker build -t glm53-flash-sm121:local .

시작 스크립트는 일반적으로 이미지를 워커로 전송하기 전에 GPU 오버레이 자체 검사를 실행합니다. 이 검사를 의도적으로 우회하려는 경우에만 SKIP_OVERLAY_VERIFY=1을 설정하십시오.

중요한 구성 경고

  • --moe-backend marlin을 전달하지 마십시오. 이 배포는 EXL3 가중치와 자체 패킹된 전문가 방식을 사용합니다.
  • 대상 KV 캐시를 NVFP4 또는 BF16으로 설정하지 마십시오. KV_CACHE_DTYPE=fp8을 유지하십시오.
  • 추측 초안 어텐션을 TRITON_ATTN으로 고정하지 마십시오.
  • 이미지를 이전의 glm53-flash-sm121:v8 NVFP4/Ray 배포로 교체하지 마십시오.
  • 텐서 병렬 처리, 노드 수, CX7 핀 또는 USE_HOST_NCCL을 신중한 검토 없이 변경하지 마십시오. 이러한 항목은 2노드 레시피에 필수적입니다.
  • 전체 모델을 다시 다운로드할 의도가 없다면 Hugging Face 체크포인트 캐시를 삭제하거나 재양자화하지 마십시오.
  • 통합 메모리 사용량을 고려하지 않은 채 멀티모달 프로파일링 보호 기능을 비활성화하지 마십시오.
  • 은닉 크기를 확인하지 않고 ABLIT_DIRECTION을 관련 없는 체크포인트의 벡터로 지정하지 마십시오.

문제 해결

서비스가 정상 상태가 되지 않음

./start.sh logs 및 ./start.sh logs worker로 두 로그를 확인하십시오. 비밀번호 없는 SSH, 사용 가능한 디스크 공간, Docker 권한, 캐시 완전성 및 CX7 인터페이스 이름을 점검하십시오. 초기 가중치 로드와 그래프 캡처에는 시간이 걸리므로 로그에서 진행 상황을 확인한 후에만 기본 준비 상태 제한 시간이 만료될 때까지 기다리십시오.

랭크 초기화 중 NCCL이 중단됨

HEAD_CX7_IF, WORKER_CX7_IF, HEAD_CX7_IB, WORKER_CX7_IB를 확인하세요. 문서에 명시된 기본값은 랩의 물리적 포트에 맞춰져 있으므로 케이블 연결이 다르면 조정해야 할 수 있습니다.

워커가 GHCR에 액세스할 수 없음

워커는 GHCR에 직접 액세스할 필요가 없습니다. 헤드가 공개 이미지를 가져온 다음 SSH를 통해 전송합니다. 헤드에서 익명 요청 제한이 발생하면 GHCR_USER와 GHCR_TOKEN을 구성하세요.

추측 디코딩이 예상보다 느림

SPEC_METHOD=dflash, DFLASH_TOKENS=7로 설정되어 있고 draft attention이 TRITON_ATTN으로 강제되지 않았는지 확인하세요. 또한 추측 디코딩 성능은 출력 유형에 따라 달라집니다. 구조가 매우 잘 정의된 시퀀스는 제약이 없는 산문보다 수용률이 훨씬 높을 수 있습니다.

결론

이 프로젝트는 한 쌍의 NVIDIA GB10 시스템을 컴팩트한 EXL3 가중치, fp8 sparse-MLA 캐싱, DFlash2 추측 디코딩을 사용하는 2-랭크 OpenAI 호환 GLM-5.3 Flash 서버로 전환합니다. 가장 빠른 방법은 제공된 네트워크, KV, attention, 양자화 기본값을 유지하고 ./start.sh로 시작한 다음 상태 확인 엔드포인트, 채팅 API, 로그 및 포함된 디코드 벤치마크를 통해 배포를 검증하는 것입니다.