1 、VLLM效率基础
一、VLLM 的推理流程🧀
VLLM 通常由三部分组成:
flowchart LR
V[视频帧] --> E[Vision Encoder]
E --> P[Projector]
P --> T[Visual Tokens]
Q[问题] --> X[Tokenizer]
X --> L[Text Tokens]
T --> M[LLM]
L --> M
M --> A[答案] - 视觉编码:把每一帧划分为 patch,再编码成视觉 token。
- 模态对齐:Projector 把视觉特征映射到 LLM 的词向量空间。
- Prefill:LLM 同时处理视觉 token 与问题 token,并建立 KV Cache。
- Decode:利用 KV Cache 自回归生成答案。
设视频包含 \(F\) 帧,每帧产生 \(N_v\) 个 token,则原始视觉 token 数为:
视频越长、分辨率越高,\(n_v\) 越大。实际输入长度还包括系统提示与问题:
视觉 token 往往占据绝大部分,因此 VLLM 的主要瓶颈不是答案生成,而是长视觉序列的 Prefill。
二、为什么要压缩视觉 Token🧀
设 LLM 有 \(L\) 层,隐藏维度为 \(d\),FFN 中间维度为 \(m\)。处理长度为 \(n\) 的序列时,计算量近似为:
其中:
- \(4nd^2\) 来自注意力中的线性投影。
- \(2n^2d\) 来自注意力矩阵计算,随序列长度平方增长。
- \(2ndm\) 来自 FFN。
减少视觉 token 会同时带来三种收益:
| 收益 | 原因 |
|---|---|
| Prefill 更快 | 每层处理的 token 更少 |
| 显存更低 | KV Cache 中保存的视觉键和值更少 |
| 可读取更多帧 | 相同 token 预算下可以覆盖更长的视频 |
视频中存在大量冗余:同一背景会连续出现,相邻 patch 可能表达相同物体,大面积区域也可能与问题无关。压缩的关键不是简单地“少看几帧”,而是:
用更少的 token 保留时间顺序、关键细节和问题所需的信息。
三、压缩发生在哪里🧀
| 范式 | 压缩位置 | 优点 | 缺点 |
|---|---|---|---|
| Before-LLM | 进入 LLM 前 | 所有 LLM 层都享受加速,容易与 KV Cache、FlashAttention 配合 | 压缩时还不知道 LLM 的深层语义判断 |
| Inner-LLM | LLM 的中间层 | 可以利用问题与视觉 token 的注意力 | 前几层仍需处理完整序列 |
| Hybrid | LLM 前与中间层 | 兼顾前期降本和问题相关性 | 实现与缓存管理更复杂 |
三种方法处理 6272 个视觉 Token
假设 32 帧视频每帧产生 196 个 token,共有:
- Before-LLM 保留 20%,则每一层只处理约 1254 个视觉 token。
- Inner-LLM 在第 3 层后保留 20%,前 3 层仍要处理全部 6272 个 token。
- Hybrid 可以先保留 40%,再在中间层压到 20%。
所以相同的最终保留率,不代表相同的真实计算量。
四、选择、剪枝与合并🧀
1、Token Selection🧀
为每个 token 计算重要性分数,只保留 Top-K:
分数可以来自 CLS Attention、问题到视觉的 Attention、事件相关性或特征密度。
选择的优点是快,缺点是被删除 token 中的信息完全丢失。
2、Token Merging🧀
先为 token 找到语义相近的目标,再聚合到目标 token:
合并能保留被压缩 token 的部分信息,但需要计算相似度和分配关系。如果聚类本身很慢,压缩节省的时间可能被前处理抵消。
3、时间与空间冗余🧀
- 空间冗余:同一帧中相邻或语义相似的 patch。
- 时间冗余:连续帧中重复出现的背景与物体。
- 时空耦合冗余:物体移动后空间位置发生变化,但语义仍然相同。
只按固定空间坐标比较相邻帧,无法处理移动物体;只做全局聚类,又可能打乱原始时间顺序。
五、常用评价指标🧀
| 指标 | 含义 |
|---|---|
| Retention Ratio | 压缩后保留的视觉 token 比例 |
| FLOPs | 理论浮点运算量 |
| TTFT | 从请求开始到生成第一个 token 的时间 |
| Prefill Latency | 处理输入序列并建立 KV Cache 的时间 |
| Decode Throughput | 每秒生成的 token 数 |
| Peak Memory | 推理过程中的峰值显存 |
压缩率越高不一定越好。一个有效的方法必须同时观察:
- 压缩本身是否足够快。
- 时间顺序是否仍然正确。
- 小目标与瞬时事件是否被保留。
- 多轮对话时能否复用压缩后的视觉 token。
六、常见评价数据集🧀
| 数据集 | 规模 | 主要内容 | 注意点 |
|---|---|---|---|
| MVBench | 20 类视频任务 | 动作顺序、运动方向、物体交互与状态变化 | 重点观察细粒度时间信息是否丢失 |
| Video-MME | 900 个视频、2700 组问答 | 覆盖 11 秒到 1 小时的短、中、长视频 | 比较时要统一是否使用字幕 |
| LongVideoBench | 3763 个视频、6678 道选择题 | 长视频中的信息定位与推理 | 重点观察稀疏证据是否被压缩掉 |
| MLVU | 多类型长视频、多种任务 | 电影、监控、第一人称视频、动画与游戏 | 适合观察不同场景下的稳定性 |
| EgoSchema | 5000 多道五选一问题 | 第一人称长视频中的行为理解 | 重点观察长程因果与行为线索 |
比较不同方法时,Backbone、输入帧数、Token Budget、字幕设置和评测数据划分必须一致。
七、LMMs-Eval🧀
LMMs-Eval 是统一的多模态评测框架,不是一个评价数据集。它把模型实现与数据集评测逻辑分开,使同一个模型可以运行多个任务,同一个任务也可以测试多个模型。
flowchart LR
C[CLI 参数] --> R[Model Registry]
C --> T[Task YAML]
R --> M[模型适配器]
T --> D[Dataset]
T --> P[Prompt 与媒体预处理]
M --> I[模型推理]
D --> I
P --> I
I --> O[答案后处理]
O --> E[Metric 聚合]
E --> J[JSON / JSONL 日志] 1、核心组成🧀
| 组成 | 作用 |
|---|---|
| Model Adapter | 加载模型,把统一请求转换成模型需要的输入格式 |
| Task YAML | 声明数据集、数据划分、输出类型与评价指标 |
doc_to_messages | 把一条样本转换为文本、图像、视频或音频消息 |
process_results | 从模型输出中解析答案并生成指标所需结果 |
| Metric Aggregation | 汇总准确率等指标,并处理多进程结果 |
| Sample Log | 保存每条样本的输入、输出与评分,便于检查错误 |
现代多模态模型优先使用 Chat 接口。任务样本会被转换为带角色和媒体类型的结构化消息,再由模型自己的 Chat Template 编码。
2、最小运行命令🧀
常用参数:
| 参数 | 含义 |
|---|---|
--model | 模型适配器名称 |
--model_args | 权重路径、设备映射等模型参数 |
--tasks | 一个或多个任务名称 |
--batch_size | 推理批大小 |
--limit | 只运行部分样本,适合 Smoke Test |
--log_samples | 保存逐样本输出 |
--output_path | 指定结果与日志目录 |
评测一个 Token 压缩方法
假设为 LLaVA-OneVision 接入一个压缩比例参数 retention_ratio,应保持下面设置完全一致:
两次实验只改变压缩比例。模型权重、视频解码后端、采样帧数、Prompt、任务版本和随机种子都要保持一致。
3、接入新方法🧀
将 FlashVID 等压缩方法接入 LMMs-Eval 时,通常修改模型适配器中的视觉特征路径:
除了任务分数,还应在同一份日志中记录:
- 原始与压缩后的视觉 token 数。
- 压缩算子耗时。
- Vision Encoder、Prefill、Decode 的分段耗时。
- 峰值显存与生成 token 数。
- 每条样本的帧数、视频时长与保留率。
这样才能区分“理论 FLOPs 下降”和“端到端推理真的变快”。
Warning
--limit 只适合检查代码能否运行,不能作为正式结论。部分样本可能改变任务分布,正式对比应运行相同的完整数据划分,并保留逐样本日志。