
概述
适用于 2 台 DGX Spark 的 GLM-5.3 Flash EXL3 是一套部署方案和 vLLM 覆盖层,用于跨两台 NVIDIA GB10 系统提供 GLM-5.3 Flash 的 4 bpw EXL3/TR3 量化版本。它在端口 8888 上公开 OpenAI 兼容 API,并以标识符 GLM-5.3-Flash-EXL3 提供模型服务。
该方案使用张量并行,每台机器运行一个 rank。它结合了打包的 EXL3 路由专家、原生 sm_121a 内核、fp8 稀疏 MLA KV 缓存、CUDA 图,以及使用 7 个草稿 token 的 DFlash2 推测解码。
默认使用的检查点是 Mia-AiLab/GLM-5.3-Flash-EXL3-TR3-4bpw,它是所引用 Brandon Music 快照的公开逐字节一致镜像。该检查点包含 120 个分片,总大小约为 164 GiB。模型仓库采用其自身许可证,而服务脚本和覆盖层采用 MIT 许可证。
为什么需要覆盖层
标准 ARM64 GLM-5.3 vLLM 镜像能够加载此检查点,但会在第一次前向传播时失败,因为 GLM-5.3 Flash 使用 NoPE MLA,而现有 SM12x 稀疏 MLA 后端要求不同的打包几何结构。该覆盖层会将 512 维 NoPE 潜在表示填充为 FLASHINFER_MLA_SPARSE_SM120 所需的几何结构,同时不改变 QK 点积。
它还注册了一种可正常运行的 EXL3 量化方法。这使路由专家能够保持其打包的 trellis、SUH、SVH 和 MCG 表示,而不是展开为 BF16。启用融合路径后,每层只需调用一次 exllamav3_ext.exl3_moe。
此外,该覆盖层还为 DFlash2 提供 GLM 专用集成,包括 EAGLE3 辅助隐藏状态捕获、共享目标 MLA KV 槽位的草稿滑动窗口注意力,以及推测草稿块内部的非因果注意力。
主要功能
- OpenAI 兼容服务:vLLM 在头节点上公开
/v1/chat/completions及相关端点。 - 双节点张量并行:部署使用
--nnodes 2和--tensor-parallel-size 2。 - 紧凑的 EXL3 权重:4 bpw 检查点下载大小约为 164 GiB,在所引用的质量面板中报告为 176 GB。
- DFlash2 推测解码:默认草稿模型为
incoai/GLM-5.3-Flash-DFlash2,并设置k=7。 - 长上下文:默认最大模型长度为 900,000 个 token;在文档所述内存配置下,fp8 MLA 池报告可容纳 982,612 个 token。
- 多模态支持:已启用图像和视频输入,默认每个提示最多包含 4 张图像和 1 个视频。
- 工具与推理解析:启动器启用自动工具选择,以及兼容 GLM 的工具调用和推理解析器。
- 前缀缓存:当相关哈希仍保留在缓存中时,可以复用按块对齐的前缀。
- 可选拒答方向消融:
ABLIT=1会在加载时对选定的原生 BF16 输出投影权重执行内存内编辑。
硬件和软件要求
此方案专门面向通过文档所述 CX7 网络互连的两台 NVIDIA GB10 DGX Spark 级系统,并非通用的单 GPU 部署方案。
- 两台 NVIDIA GB10 系统;首次设置时每个节点约需 180 GiB 可用存储空间。
- 两台系统上均可在不使用
sudo的情况下运行 Docker。 - 头节点能够通过免密码 SSH 连接工作节点。
- 头节点上已安装
hf或huggingface-cli、curl和rsync。 - 两台机器上均配置了正确的 CX7 网络接口和 RDMA 设备。
- Hugging Face 缓存位置必须能够容纳包含 120 个分片的检查点和约 2.3 GiB 的 DFlash2 模型。
除非物理布线不同,否则请保留仓库中的 CX7 接口和 HCA 设置。README 警告称,NCCL 无法使用
10.0.0.x回环别名;如果 fabric 固定设置不正确,可能会在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-Sparks2. 创建环境文件
cp .env.example .env如果机器未使用方案中的默认地址或账户名,请编辑 .env。最重要的设置包括:
HEAD_IP=10.0.0.1:头节点和 vLLM 主节点。WORKER_IP=10.0.0.2:第二台 Spark。WORKER_USER:当节点之间的 SSH 账户不同时进行设置。WORKER_HOME:当工作节点的主目录或 Hugging Face 缓存位置不同时进行设置。PORT=8888:API 监听端口。
如果缺少 .env,启动器会自动根据 .env.example 创建该文件。直接放在命令前提供的值优先于文件中的值。
3. 可选:预先下载权重
./download.sh此命令会将 EXL3 检查点和 DFlash2 模型下载到头节点的 Hugging Face 缓存中。它不会运行 Docker、连接工作节点或同步文件。如果希望在工作节点准备就绪前完成约 164 GiB 的模型下载,请使用此命令。
要明确刷新缓存文件,请运行:
REFRESH_WEIGHTS=1 ./download.sh请避免不必要的刷新。download.sh 和 start.sh 都会跳过已经完整的仓库。
4. 启动两个 rank 和 API
./start.sh启动脚本会依次执行以下操作:
- 检查两个节点上的 Docker、SSH 和可用磁盘空间。
- 在头节点上拉取公开镜像
ghcr.io/miaai-lab/glm-5.3-flash-2x-dgx-sparks:exl3。 - 当容器镜像摘要发生变化时,将镜像传输到工作节点。
- 将缺失的模型文件下载到头节点的 Hugging Face 缓存。
- 使用
rsync将缓存同步到工作节点。 - 在工作节点上以无头模式启动 rank 1。
- 在头节点上启动 rank 0 和 OpenAI 兼容 API。
- 轮询健康检查端点,直到模型加载和预热完成。
默认就绪超时时间为 3,600 秒,因为加载权重和捕获 CUDA 图可能需要较长时间。
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。使用文档所述局域网地址时,其他机器可使用 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": "请简要解释张量并行。"}
],
"chat_template_kwargs": {
"enable_thinking": false
}
}'请求中的 model 值必须与服务名称一致,默认值为 GLM-5.3-Flash-EXL3。思考模式默认启用。要将其禁用,请像上例一样,将 chat_template_kwargs 放在 JSON 请求的顶层。
请勿通过原始 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,使用打包的路由专家,以及原生稠密层、共享专家、注意力、嵌入和输出头权重。 - 目标 KV 缓存:
fp8,内部表示为打包的fp8_ds_mla。 - 推测:DFlash2 使用 7 个推测 token,草稿张量并行大小设为 1。
- 草稿 KV 缓存:自动选择,因此稠密草稿模型使用 BF16,而不是目标模型的 MLA 布局。
- 注意力:目标模型使用稀疏 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。要回退到检查点的 MTP 路径并使用 2 个推测 token,请通过以下命令重启:
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 内核适用于稠密 MHA,不适用于稀疏 MLA。
启用 DFlash2 和视觉支持、显存利用率设为 0.87、最大模型长度设为 900,000 时,README 报告的池容量为 982,612 个 token,fp8 MLA 约占用 15.67 GiB。这大约相当于一个完整 900,000-token 请求所需容量的 1.09 倍。在文档所述配置下,原生一百万 token 配置仍无法完成分配。
除非正在测试有意设计的运行时变更,否则请保留以下设置:
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 还警告,将批处理 token 上限提高到 8,192,会使 GB10 indexer top-k 路径在长上下文运行期间超额使用资源。
前缀缓存的工作方式
前缀缓存已启用,但 OpenAI API 仍然是无状态的。客户端必须在每轮对话中重新发送完整的对话历史。vLLM 会对提交的前缀进行哈希,并可能在相关块仍然可用时复用缓存块。
- 根据文档所述的 MLA 缓存管理器,只有按块对齐的 token 才计为命中。
MAX_NUM_SEQS=4允许 4 个并行生成任务;它不会预留 4 个持久聊天会话。- 无法保证空闲对话会一直保留在缓存中。
- 一个对话的激活值不会与另一个对话混合。
- 当其他工作负载逐出较早聊天的前缀后,该聊天可能需要重新执行预填充。
README 中的实际测试在一个包含 7,760 个 token 的后续请求中复用了 3,584 个 token,约占提示的 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 个 token,在并发数为 2 时达到每秒 103.3 个聚合 token,在并发数为 4 时达到每秒 146.5 个聚合 token。性能高度依赖推测接受率:实验室测得的中位数在结构化输出下为每秒 61.7 个 token,而散文输出为每秒 26.9 个 token。据报告,包含约 60,000 至 100,000 个缓存 token 的混合或长上下文测试速度为每秒 24 至 27 个 token。
这些数据描述的是 README 中特定的双 GB10 配置、提示类型、温度为零的配置、已禁用的思考模式、DFlash2 k=7 和 400-token 生成,不应将其解释为通用吞吐量保证。
可选的拒答方向消融
该仓库可以在加载权重时应用拒答方向消融,无需重写或重新量化 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:设置投影缩放值。ABLIT_INCLUDE_MTP=1:使用 MTP 时包含检查点的 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:v8NVFP4/Ray 部署。 - 不要随意更改张量并行、节点数量、CX7 固定设置或
USE_HOST_NCCL。它们是双节点方案不可分割的一部分。 - 除非打算重新下载完整模型,否则不要删除或重新量化 Hugging Face 检查点缓存。
- 在未考虑统一内存用量的情况下,不要禁用多模态分析保护措施。
- 在未验证隐藏层大小的情况下,不要让
ABLIT_DIRECTION指向无关检查点的向量。
故障排除
服务始终未进入健康状态
使用 ./start.sh logs 和 ./start.sh logs worker 检查两端日志。检查免密码 SSH、可用磁盘空间、Docker 权限、缓存完整性和 CX7 接口名称。首次加载权重和捕获图会比较慢,因此只有在查看日志中的进度后,才应等待默认就绪超时结束。
NCCL 在 rank 初始化期间挂起
检查 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,并确保草稿注意力未被强制设为 TRITON_ATTN。还应注意,推测性能会随输出类型而变化:高度结构化的序列可能比不受约束的散文具有高得多的接受率。
总结
该项目使用紧凑的 EXL3 权重、fp8 稀疏 MLA 缓存和 DFlash2 推测解码,将一对 NVIDIA GB10 系统转变为采用两个 rank 的 OpenAI 兼容 GLM-5.3 Flash 服务器。获得最佳性能的最直接方式是保留所提供的网络、KV、注意力和量化默认值,使用 ./start.sh 启动,并通过健康检查端点、聊天 API、日志和附带的解码基准测试验证部署。
