跳到主要内容
AI教程

在单张 24 GB RTX 3090 上通过主机内存卸载运行 GLM-5.3-Flash

本教程介绍 glm53-flash-offload 如何结合锁页主机内存、弹性 GPU 专家缓存、零拷贝 PCIe 访问以及可选的 AVX2 CPU 计算,在一张 24 GB NVIDIA GPU 上运行 GLM-5.3-Flash。你将安装 Docker 镜像、选择快速或精确模式、调用 API、验证性能并调整部署。

在单张 24 GB RTX 3090 上通过主机内存卸载运行 GLM-5.3-Flash

概览

glm53-flash-offload 可在单张 24 GB NVIDIA GPU 加主机 DDR4 内存上运行 125.3 GB、EXL3 3.05-bpw 版本的 GLM-5.3-Flash。它提供兼容 OpenAI 的 HTTP API,同时将模型路由混合专家权重主要保存在固定系统内存中。

该项目是在原版 exllamav3 1.5.1 基础上的一组轻量 monkey patch,并辅以几个小型自定义内核。无需修改 exllamav3 源码。文档中的配置是在通过 PCIe 4.0 x16 连接到 AMD EPYC 7443P 系统的 RTX 3090 上测得的。

其核心思路是将常用专家保存在弹性 GPU 缓存中。未命中缓存的专家可以通过 PCIe 直接从固定主机内存读取。在快速模式下,最冷的解码缓存未命中也可以改由 AVX2 CPU 工作线程计算。

主要特性

  • 单 GPU 部署:使用一张 24 GB 的 RTX 3090 级别 GPU 运行 GLM-5.3-Flash。
  • 兼容 OpenAI 的 API:支持聊天补全、文本补全、模型发现、流式传输、推理内容以及 OpenAI 风格的工具调用。
  • 固定内存零拷贝存储:所有路由专家都保存在固定主机 RAM 中,并可通过 CUDA 统一虚拟寻址访问。
  • 弹性 GPU 专家缓存:高频专家占用可用显存,同时缓存空间可暂时让给长前缀填充激活值和暂存缓冲区。
  • 前缀填充暂存:非缓存专家会提前一层复制,从而使 PCIe 传输能够与计算重叠。
  • 可选 CPU 层:快速模式会将选定的冷解码缓存未命中任务分配给 AVX2 CPU 内核。
  • 批量解码:使用文档中的 -ambs 4 配置时,最多可同时解码四个流。
  • 可复现配置:模型版本、容器摘要、exllamav3 版本、Triton 选项、基准测试和参考质量面板均已固定。

在快速模式和精确模式之间选择

服务器通过 GLM53_MODE 环境变量提供两种运行模式。

快速模式

fast 是默认模式。它结合了 GPU 专家缓存、零拷贝缓存未命中处理、针对选定冷解码缓存未命中的 AVX2 CPU 处理、批量解码和融合解码内核。在测试主机上,它使用了约 218 GiB,即 234 GB 的主机 RAM。

已发布的测试活动测得单个解码流约为每秒 28.15 个 token,两个流的聚合速率为每秒 31.57 个 token,四个流的聚合速率为每秒 33.98 个 token。对当前摘要执行的图像冒烟测试分别测得每秒 28.88、31.27 和 35.00 个聚合 token。

质量警告:前缀填充是精确的,但快速模式的解码与原版 exllamav3 并非逐位一致。配对解码检查报告的平均 KL 为 0.0053,top-1 一致率为 0.977。需要输出等价性时,请使用精确模式。

精确模式

exact 会禁用 CPU 层和仅限快速模式的解码内核,但保留 GPU 专家缓存和零拷贝主机内存缓存未命中处理。参考面板测得 top-1 一致率为 1.0000,KL 为 0,主机内存使用量约为 111 GiB,即 119 GB。

精确模式速度较慢,但使用的 RAM 少得多。在较短的测试上下文中,测得的单流解码速率为每秒 12.57 个 token;相比之下,当原版 exllamav3 将无法容纳的专家放入其 CPU 工作线程时,速率约为每秒 7.5 到 8.4 个 token。

硬件和软件要求

GPU 和驱动程序

  • 一张具有 24 GB 显存的 NVIDIA GPU。
  • 测量目标是 sm_86 GPU,例如 RTX 3090 或 A5000。
  • 随附的 sm_86 二进制文件也可在包括 RTX 4090 在内的 sm_89 上运行,但该配置未经测量。
  • 由于镜像使用 CUDA 13.0.3,因此需要支持 CUDA 13.0 的 NVIDIA 驱动程序。
  • 建议使用 PCIe 4.0 x16。缓存未命中在测量链路上会占用约 25 GB/s。

主机内存

  • 快速模式:在几乎没有其他程序运行时,256 GiB 总内存是最低要求;建议使用 320 GB 或更多。如果使用 Docker 内存限制,请至少允许 230g。
  • 精确模式:最低要求为 128 GiB,建议使用 160 GB 或更多。

CPU 和存储

  • 快速模式需要支持 AVX2、FMA 和 F16C 的 x86-64 CPU。
  • 对于测得的快速模式表现,建议使用约 24 个物理核心以及八通道 DDR4 或更高规格的内存。
  • 检查点在磁盘上占用约 117 GiB,即 125.3 GB。
  • 建议使用 NVMe 存储,以缩短模型加载时间。
  • 文档所述设置需要 Docker、NVIDIA Container Toolkit 和 Hugging Face CLI。

使用 Docker 安装并启动服务器

第 1 步:下载检查点

将固定的 3.05-bpw 检查点下载到本地目录:

hf download turboderp/GLM-5.3-Flash-exl3 \
  --revision 3.05bpw \
  --local-dir /data/GLM-5.3-Flash-exl3-3.05bpw

也可以将一个空目录挂载到 /models。如果缺少 config.json,容器会将配置的检查点下载到该目录。

第 2 步:启动快速模式

以下命令会在 GPU 0 上启动服务器,并通过端口 30000 发布服务。它使用包含流式传输交付修复的镜像摘要。

docker run -d \
  --name glm53 \
  --gpus '"device=0"' \
  --ulimit memlock=-1 \
  --shm-size 16g \
  -p 30000:30000 \
  -v /data/GLM-5.3-Flash-exl3-3.05bpw:/models \
  ghcr.io/0xsero/glm53-flash-offload@sha256:bb633b0bcb85573ad40b6c408af5e1036ae062c593e42479f4e4d2ab521e551d

建议使用 --ulimit memlock=-1 设置,因为服务器会锁定大量主机内存。在实测驱动上,即使不设置该参数,发布的镜像也能正常加载,但不应假设所有主机都具备相同行为。

步骤 3:观察启动过程

docker logs -f glm53

等待出现包含 loaded in ... s 的消息。在文档所述系统上,启动大约需要两到三分钟,具体取决于缓存和主机状况。

步骤 4:确认运行状态

curl -s http://localhost:30000/health

运行精确模式

如需优先保证输出一致性并减少主机内存消耗,请添加 -e GLM53_MODE=exact:

docker run -d \
  --name glm53-exact \
  --gpus '"device=0"' \
  --ulimit memlock=-1 \
  --shm-size 16g \
  -p 30000:30000 \
  -e GLM53_MODE=exact \
  -v /data/GLM-5.3-Flash-exl3-3.05bpw:/models \
  ghcr.io/0xsero/glm53-flash-offload@sha256:bb633b0bcb85573ad40b6c408af5e1036ae062c593e42479f4e4d2ab521e551d

不要同时在同一端口运行快速模式和精确模式示例。切换模式前,请停止并删除第一个容器:

docker rm -f glm53

基本 API 用法

发送聊天补全请求

curl -s http://localhost:30000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"Explain zero-copy model offloading."}],"max_tokens":512}'

默认提供的模型名称是 glm-5.3-flash。除非显式配置,否则 max_tokens 默认为剩余上下文长度,而不是限制为较小的固定值。

禁用思考

GLM 的推理内容会返回在 reasoning_content 中。要为某个请求禁用思考,请传入聊天模板选项:

curl -s http://localhost:30000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"Reply with one sentence."}],"chat_template_kwargs":{"enable_thinking":false},"max_tokens":128}'

流式传输响应

curl -N http://localhost:30000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"Write a short explanation of mixture-of-experts models."}],"stream":true,"max_tokens":512}'

请使用上面显示的固定 bb633b0b... 摘要。较旧的 1159044a... 镜像能够以全速生成内容,但在最后刷新积压数据之前,其流式事件传输速度约为全速的一半。

列出可用模型

curl -s http://localhost:30000/v1/models

查看运行时统计信息

curl -s http://localhost:30000/stats

统计信息端点包含专家缓存命中信息和 CPU 层级计数器。其他端点还包括 /v1/completions、/server_info,以及采用 SGLang 形式的 /generate 和 /tokenize 路由。

此部署仅支持文本。未加载检查点中的视觉塔。

使用 OpenAI 风格的工具

聊天端点接受 tools 字段。GLM 以内部 <tool_call> 格式生成的工具表达式,会在响应中转换为兼容 OpenAI 的 tool_calls。因此,客户端应用可以使用标准的工具调用循环:提交工具定义,检查助手的工具调用,执行函数,然后将工具结果作为另一条消息发回。

调整上下文和服务器参数

放置在镜像名称之后的参数会附加到服务器命令中,并且最后一个值会生效。例如,使用 65,536 个 token 的 KV 缓存:

docker run -d \
  --name glm53-64k \
  --gpus '"device=0"' \
  --ulimit memlock=-1 \
  --shm-size 16g \
  -p 30000:30000 \
  -v /data/GLM-5.3-Flash-exl3-3.05bpw:/models \
  ghcr.io/0xsero/glm53-flash-offload@sha256:bb633b0bcb85573ad40b6c408af5e1036ae062c593e42479f4e4d2ab521e551d \
  -cs 65536

较小的 KV 缓存可以为更多专家缓存槽位留出空间。发布的基准测试配置使用了 131,072 个 token 的 KV 缓存、8 的最大批量大小,以及 8,192 个 token 的块大小。

不使用 Docker 安装

原生安装需要为目标 GPU 构建的 exllamav3 1.5.1。在项目克隆目录中,运行扩展安装程序,然后设置仓库和模型路径并启动提供的入口点:

scripts/install.sh
GLM53_ROOT=$PWD \
GLM53_MODEL_DIR=/path/to/model \
docker/entrypoint.sh

安装程序会构建项目的自定义扩展。Docker 仍是可复现性最高的方式,因为它固定了 CUDA、PyTorch、Triton、SGLang、exllamav3、项目提交版本以及经过测试的服务器配置。

验证质量和性能

评估参考面板

在仓库克隆目录中,使用随附的仅依赖标准库的基准测试客户端:

python3 bench/score_ref_panel.py \
  --url http://127.0.0.1:30000 \
  --panel reference/glm-5.3-flash-exl3-ref-panel.json \
  --out score.json

在快速模式和精确模式下,教师强制面板都应报告 top-1 一致率为 1.0000,KL 为 0。该面板评估预填充或教师强制路径,不能证明快速模式的自回归解码是精确的。

运行速度测试

python3 bench/sweep.py \
  --url http://127.0.0.1:30000 \
  --card rtx-3090-24gb/glm-5.3-flash-offload \
  --template glm \
  --config "bb633b0b fast" \
  --prefill 8192 32768 \
  --conc 1 2 4 \
  --reps 3 \
  --dec-reps 2 \
  --no-early-exit \
  --out sweep.json

检查流式传输

python3 bench/stream_rate.py --url http://127.0.0.1:30000

通过的结果应显示文本均匀到达,而不是大约一半的响应最后以突发形式出现。

高级调优

配置 CPU 层级

默认情况下,GLM53_CT_CPUS=auto 会为每个物理核心选择一个逻辑 CPU,并保留前两个物理核心供操作系统和驱动 GPU 的 Python 线程使用。在实测的 24 核主机上,这会使用 CPU 2 到 23,以及 22 个工作线程。

如需显式指定,可以设置:

-e GLM53_CT_CPUS=2-23 \
-e GLM53_CT_THREADS=22

CPU 成本模型使用 GLM53_CT_B,在 22 个线程下测得每个专家为 0.104 毫秒。对于 N 个工作线程,README 建议按 0.104 x 22 / N 进行估算。例如,保留两个核心的 16 核主机应使用 14 个工作线程,并将该值设为约 0.16。

如果物理核心少于约 12 个,大多数未命中预计会回到 PCIe 路径,使性能接近精确模式。在这种情况下,精确模式可能是更好的选择。

控制 CPU 层级的内存布局

GLM53_CT_SWZ=1 会让 CPU 层级使用专家的独立、块连续副本。这是实测的快速配置,会额外占用约 114.2 GB RAM。将其设为 0 后,CPU 层级会直接读取固定的主副本,从而显著降低内存使用,但项目报告称 CPU 专家内核基准性能约慢 40%。该设置的端到端性能尚未测量。

调节缓存预留

GLM53_EC_RESERVE_GB 会在分配专家缓存后保留空闲显存。快速模式默认值为 1.5 GB,精确模式默认值为 1.0 GB。除非长序列预填充出现内存不足,否则请将快速模式的预留保持为 1.5 GB。

GLM53_EC_ELASTIC_GB 默认值为 10 GB。这部分缓存内存可以释放给预填充激活值和暂存使用,然后在解码时回收。GLM53_EC_STAGE_GB 默认每个暂存缓冲区为 2.6 GB,并使用两个缓冲区实现重叠。

使用更大的 GPU

专家缓存会根据模型加载完成后以及应用配置预留之后的可用显存自动确定大小。因此,32 GB 或 48 GB 显卡会获得更多专家槽位,这应能提高命中率并改善解码性能。README 未提供这些大显存显卡的结果。

RTX 4090 可以运行随附的 sm_86 构建版本,但尚未进行测量。Blackwell 需要使用以下配置重新构建:

TORCH_CUDA_ARCH_LIST="8.6;12.0"

在其他架构上可能还需要新的 Triton 固定版本。如果创建新的固定版本,请确认参考面板仍保持 top-1 1.0000 和 KL 0。

保护 Triton 的精确选择

该镜像通过 data/triton_pin_exact.json 固定 KDA 线性注意力预填充内核的选择。允许 Triton 选择不同配置可能会改变浮点舍入结果。当参考等效的预填充行为很重要时,请保持 GLM53_TRITON_PIN 为默认值。

卸载流水线的工作原理

  1. 将路由的专家加载到固定主机内存。 每一层都会获得一个精确大小的固定内存区域,exllamav3 的专家指针则指向 CUDA UVA 别名。
  2. 在显存中填充弹性 CLOCK 缓存。 路由选择会去重,缓存命中会被标记,并为获准的未命中选择待替换项。
  3. 通过 PCIe 读取未缓存的专家。 exllamav3 的内核可以访问固定的主机表示,无需主机端同步复制。
  4. 暂存长序列预填充。 当每层选择数量足够大时,缺失的专家会提前一层复制到暂存缓冲区,同时上一层进行计算。
  5. 在快速模式下拆分选定的解码未命中。 成本模型会将较热的未命中通过零拷贝 GPU 执行,并将选定的较冷未命中发送到 CPU 层级。
  6. 合并 CPU 和 GPU 结果。 CPU 通过固定映射内存发布其工作结果,GPU 在等待设备端标志后加入所得的 FP32 部分结果,而不是执行主机同步。

运行注意事项

  • 当解码输出必须匹配原版 exllamav3 时,请使用 GLM53_MODE=exact。
  • 如果流式延迟很重要,请避免使用旧的 sha256:1159044a... 镜像,改用文档中记录的 sha256:bb633b0b... 摘要。
  • 快速模式当前会在主机 RAM 中保留两份专家副本。启动容器前请确保内存充足。
  • 不要假设较慢 PCIe 链路也能达到实测的 RTX 3090 吞吐量。解码速度对缓存未命中流量非常敏感。
  • 更改上下文大小、缓存预留、并发数或暂存设置时,请监控 /stats、系统内存和 GPU 内存。
  • 服务器仅处理文本;此部署不支持图像输入。

结论

glm53-flash-offload 通过结合固定主机存储、零拷贝 PCIe 读取、弹性显存缓存、分阶段的预填充传输以及可选的 AVX2 CPU 层级,使异常庞大的混合专家检查点能够在单张 24 GB GPU 上实用运行。请从固定版本的 Docker 镜像开始,根据输出保真度选择精确模式,或根据吞吐量选择快速模式,然后使用随附的质量、速度和流式检查验证安装,最后再调节缓存或 CPU 设置。