在单个节点上部署 Llama 3.3 70B。
从五分钟前刚交付的服务器,到能响应请求的 OpenAI 兼容端点——包含悄悄让吞吐量减半的两个参数,以及会让您系统被攻破的那一个。
简短的答案
- 所需显存
- 4-bit 为 43 GB,FP8 为 82 GB,BF16 为 164 GB — 均为 8k 上下文
- 最简单的机型
- 一张 80 GB 显卡。无需拆分、无需互联、无需同步
- 首个 token 延迟
- 从交付到可用不到十五分钟,大部分时间用于下载权重
- 唯一的错误
- 把 8000 端口发布到公网地址。它没有身份验证
您需要什么
700 亿参数。采用 4-bit 精度时,权重为 35 GB;在 8k 上下文、单个请求下,KV 缓存额外增加 2.5 GB,运行时开销约 15%。其余部分都由这三个数字决定——具体来源见显存估算指南。
| 精度 | 权重 | 8k 时的总量 | 32k 时的总量 | 128k 时的总量 |
|---|---|---|---|---|
| BF16 / FP16 | 140 GB | 164 GB | 173 GB | 207 GB |
| FP8 | 70 GB | 82 GB | 86 GB | 103 GB |
| 4-bit (AWQ, GPTQ) | 35 GB | 43 GB | 52 GB | 86 GB |
请注意 128k 那一行的 4-bit 数据:权重缩小到 35 GB,但缓存完全不会缩小,因为 AWQ 和 GPTQ 只量化权重。仅这一点,就决定了下面大部分的机型选择。
选择节点
产品目录中,能在单张显卡上放下该模型的最便宜机型——如果可以选择,这正是您想要的配置:不拆分意味着不用同步,也少一件需要排查的事。
| 节点 | 放得下的精度 | 显卡显存 | 预计 tok/s | 每月 |
|---|---|---|---|---|
| NVIDIA RTX A6000 | 4-bit (AWQ, GPTQ) | 48 GB | ~10 | $286/月 |
| 2 × NVIDIA RTX A6000 | 4-bit (AWQ, GPTQ) | 48 GB | ~10 | $597/月 |
| NVIDIA L40S | 4-bit (AWQ, GPTQ) | 48 GB | ~11 | $714/月 |
| NVIDIA A100 PCIe | 4-bit (AWQ, GPTQ) | 80 GB | ~25 | $1,091/月 |
吞吐量指的是受显存带宽限制的单流生成速度,且刻意取保守值。在连续批处理下,多个并发请求的总和要高出好几倍——这正是 vLLM 的意义所在。
十分钟搭建完成
除了地址之外,这里没有任何东西是我们特有的。Docker、NVIDIA 容器工具包和可用的驱动程序栈,服务器上都已经装好。
$ ssh root@203.0.113.42
$ nvidia-smi --query-gpu=name,memory.total --format=csv
# Weights on the fast local NVMe, not the system volume.
$ mkdir -p /scratch/models
$ df -h /scratch
# A gated model needs a token. Skip if yours is open.
$ export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxx
启动服务
一个容器。首次运行会下载大约 40 GB 的量化权重,在 1 Gbit/s 端口上需要几分钟;之后每次重启只需几秒。
$ docker run -d --name vllm --restart unless-stopped \
--gpus all --ipc=host \
-v /scratch/models:/root/.cache/huggingface \
-e HF_TOKEN="$HF_TOKEN" \
-p 127.0.0.1:8000:8000 \
vllm/vllm-openai:latest \
--model casperhansen/llama-3.3-70b-instruct-awq \
--quantization awq_marlin \
--max-model-len 8192 \
--gpu-memory-utilization 0.92
# Watch it load. "Application startup complete" is the signal.
$ docker logs -f vllm
$ curl -s http://127.0.0.1:8000/v1/models | head
$ curl -s http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"casperhansen/llama-3.3-70b-instruct-awq",
"messages":[{"role":"user","content":"In one sentence: what is a KV cache?"}],
"max_tokens":80}'
真正重要的参数
不对外公开
0.0.0.0,就成了一个开放的推理服务器,扫描器几小时内就能找到它。请注意上面命令中的 -p 127.0.0.1:8000:8000——开头那个地址正是让它不暴露在公网上的关键,也是从别处复制命令时最容易被漏掉的一个字符。
通过 SSH 隧道从您自己的机器访问它——无需开放端口,无需管理证书,也没有什么能配置错:
$ ssh -N -L 8000:127.0.0.1:8000 root@203.0.113.42
# Now http://127.0.0.1:8000 on your laptop is the server.
如果确实必须公开,请在前面加一个带 TLS 和 API 密钥的反向代理,同时在防火墙中限制来源地址。文档中有一套最小规则集。对于会回应任何请求的端点,多重防护才是正确的姿态。
提升吞吐量
按值得尝试的顺序排列。前两项免费,通常也带来最大的收益。
- 把
--max-model-len降到您实际使用的上下文长度。这几乎总是单项收益最大的调整,而且不会牺牲您原本在用的任何东西。 - 把
--gpu-memory-utilization提高到 0.95。这是一台独享服务器,显卡上没有别的东西需要留出空间。 - 如果显卡支持,开启 FP8 KV 缓存。能让您可容纳的内容翻倍。
- 在客户端做批处理。连续批处理只有在请求并发到达时才有效。逐个发送的请求无论怎么配置,都会让显卡大部分时间处于空闲。
- 到这一步之后,才该考虑更快的显卡。生成速度受限于显存带宽,因此同一模型下,带宽为 4,800 GB/s 的 H200,大约是带宽为 2,000 的 H100 PCIe 的 2.4×——这是实实在在的提升,也是这份清单里最贵的一项。
$ docker exec vllm python -m vllm.entrypoints.openai.api_server --help | head -1
$ docker exec vllm vllm bench serve \
--model casperhansen/llama-3.3-70b-instruct-awq \
--num-prompts 200 --request-rate 8
# And watch the card while it runs: if utilisation sits below 90%,
# the bottleneck is your client, not the GPU.
$ nvidia-smi dmon -s um
让它持续运行
有三件事值得在第一天就做好,因为这三件事如果拖到第十四天才发现,会很麻烦。
重启策略
上面的命令中包含 --restart unless-stopped。重启后容器会自动恢复,权重已经在 /scratch 上,因此不到一分钟就能重新就绪。
关注显卡,而不是进程
掉出总线的 GPU 仍会让容器看起来健康。健康检查中加入 nvidia-smi -q -d PERFORMANCE 才能发现这一点;仅检查端口发现不了。
权重不会被备份
它们只存放在您本地的 NVMe 上,别无他处。这没关系——它们可以重新下载。但您微调过的适配器不行,请把它们存放在服务器之外的地方。
租期结束后,硬盘会在一小时内被清除,没有宽限期。/scratch 上的一切都会随之消失。这是刻意如此——正是同一份承诺,保证了您拿到的服务器上没有别人的数据——但也意味着,租期的最后一天不是开始搬移数据的时候。