TT Lab
博客

한국어 English 日本語 中文

开始
博客

博客

并行化、多模态与池化:单张 GPU 能测与不能测的内容

状态:草稿(2026-10-27),已完成池化与多模态实测,并行化未实测。 池化测量于 2026-10-27 使用单张 8GB 级笔记本 GPU(Ada 架构)、vLLM 0.31.0 进行。并行化与多模态未实测,仅记录了从官方文档(0.32.0)和论文中确认的内容。LoRA 多实例服务的实测请参考《Toss ML/AI Infra 准备》第 15 篇。 2026-10-27 新增。 获得批准后,我们下载了 vLLM 0.32.0 镜像以及 Qwen3-VL-2B-Instruct(Apache-2.0,safetensors 4.26GB),并补充了 2-1 节的多模态实测。这是初版中标记为“未实测”的内容。 编写规则:以实测数据为基础,无法测量的标注为“未实测”,未能确认的标注为“未确认”。

目录

1. 四种并行化:拆分什么

方式 选项 拆分内容 通信 适用场景
张量并行 (TP) --tensor-parallel-size 将单层矩阵切片分摊到各 GPU 每层进行 all-reduce 模型无法放入单张 GPU 时,在单台服务器内部
流水线并行 (PP) --pipeline-parallel-size 按前后层拆分,每张 GPU 承载若干层 仅在阶段间传输激活值 跨多台服务器、且没有 NVLink 时
数据并行 (DP) --data-parallel-size 不拆分,完整复制多份模型 几乎没有(MoE 除外) 提升吞吐量时
专家并行 (EP) --enable-expert-parallel 将 MoE 的专家分摊到各 GPU 将 Token 向专家侧进行 all-to-all 大型 MoE 模型

查看模型能否装下时,可以看启动日志中的两行: GPU KV cache size: N tokens 和 Maximum concurrency for M tokens per request: Kx 。本系列实验服务器的数据为“基于 40,208 个 Token、4,096 个 Token 请求时达到 9.82 倍”。文档指出,如果该并发度低于目标,则应增加 GPU。

由于只有一张 GPU,这四种方式均未实测。将两张同系列 GPU 通过 1GbE 互联并迁移 KV 的实测(分离服务的速度慢了 20 倍以上)记录在《Toss ML/AI Infra 准备》第 24 篇中,因此低速连接下连接 GPU 所付出的代价可以用该篇文章来代替说明。

2. 多模态输入

vLLM 使用相同的 OpenAI 兼容 API 来服务接收图像、视频和音频的模型。如果在聊天消息的 content 中放入 image_url, video_url, input_audio 片段,API 服务器的处理程序会下载并预处理媒体,然后发送给模型的编码器。一张图像在提示词中会被替换为多个占位符 Token,前缀缓存会将图像的哈希值混入该占位符块的哈希中,使得相同的图像之间可以共享缓存(参考第 2 篇的前缀缓存设计文档)。

在实际运维中,比起性能,更应该优先关注这一点。

初版中因为需要重新下载视觉语言模型而未作实测,获得批准后我们在下文的 2-1 节进行了测量。

2-1. 2026-10-27 实测:在 8GB 上部署 2B 视觉语言模型

首先,让它成功启动

配置 KV 剩余内存 KV 空间 结果
默认(--gpu-memory-utilization 0.85) -0.07GiB 启动失败“No available memory for the cache blocks”
--limit-mm-per-prompt '{"image":1,"video":0}' 仅增加 -0.07GiB 同样的失败
内存比例 0.92 0.47GiB 4,352 个 Token(4,096 Token 请求 1.06 个) 成功启动
0.92 + 尺寸提示 {"image":{"count":1,"width":896,"height":896},"video":0} 2.13GiB 19,904 个 Token(4.86 个) 成功启动

vLLM 在启动时会使用“模型能够接收的最大图像”运行一次编码器来测量内存。日志记录显示编码器缓存预算被设为了 16,384 个 Token。加上 4GB 的权重和该预算后,在 8GB 上就没有剩余的 KV 空间了。仅减少图像数量并没有用,而当告知实际要接收的图像大小时,KV 空间变为了原来的 4.5 倍。这是在小 GPU 上部署视觉语言模型时最先需要调整的参数。

结果(带大小提示的服务)

项目 448×448 896×896
提示词 Token(图像 + 问题) 220 808
新图像的 TTFT 中位数 67.9ms 238.0ms
相同图像,再次询问相同问题 31.8ms(缓存 208 个 Token) 32.7ms(缓存 800 个 Token)
相同图像,不同问题 32.1ms(缓存 192 个 Token) 33.4ms(缓存 784 个 Token)

SSRF:服务器是否会代为下载

请求的图像地址 默认服务器 --allowed-media-domains example.com
http://127.0.0.1:8000/health(服务器自身) 400 “Failed to load image: cannot identify image file”(5.5ms) 400 “The URL must be from one of the allowed domains”(2.6ms)
http://127.0.0.1:8000/metrics 400,相同消息 400,相同拒绝
file:///etc/passwd 500 “Cannot load local files without --allowed-local-media-path」 同左

默认服务器返回的消息是“这不是图像”。这说明 服务器确实向该内部地址发送了请求并获取了响应。虽然响应内容没有被返回,但请求者可以通过该服务器探测内网,并根据响应时间和错误类型来探知开放了什么端口。指定域名后,系统在下载前就进行了拒绝。本地文件默认处于禁止状态。对于接收图像 URL 的服务来说, --allowed-media-domains 绝非可选配置,而是必需项。

3. 池化:嵌入与重排也使用相同的引擎

不进行生成、而是提取并使用最后隐藏状态的模型,在 vLLM 中被称为 池化模型。 --runner pooling 以 /v1/embeddings, /score, /rerank, /classify, /pooling 启动时,提供的是

方法

结果

任务 发起的请求 延迟中位数(5次) 吞吐量 备注
Embedding 64 个句子 × 约 127 个 token 371.8ms 每秒 172 个(约 21,900 个 token) 维度 1,024
重排 1 个问题 + 32 个文档 33.9ms 每秒 944 个 匹配的文档得分为 0.993,排在第 1 位

4. LoRA 多路服务

这是指在单个基础模型上加载多个 LoRA 适配器,并在每次请求时使用不同适配器的功能(--enable-lora --max-loras --max-lora-rank)。在同款 8GB 级别 GPU 上使用 1.7B 模型测得的数据可以在 LoRA 适配器服务部分找到。使用适配器会使速度变慢 8.5% 至 17.9%,并且当适配器数量超过槽位数量时,吞吐量会急剧下降。本节将补充两点内容。

在 0.32.0 文档的功能兼容性表中,LoRA 和投机解码的交叉处标记为 ❌(第 3 篇)。

Embedding 吞吐量随批次大小(Batch Size)的变化、长文档重排以及准确率评估均未进行实际测量。

登录后即可点赞

评论

还没有评论。

登录后即可发表评论