Runway 发布 Characters 实时视频推理研究:57B 模型在 4 张 H100 上跑实时
Real-Time Video at Batch Size One
Runway 发布研究论文,介绍 Runway Characters 如何把 57B 参数自回归视频扩散 Transformer 的推理优化到实时对话水平。优化后单次扩散步从 240.9ms 降到 159.3ms,可在 4 张 H100 上维持 24.5 fps,融合通信内核进一步降到 147.4ms。
Runway 公开了 57B 视频扩散模型实时对话服务的推理优化细节,包含每步耗时拆解与生产事故复盘。
每段对话都有节奏。一个人停止说话,另一个人开始,这种来回的节奏定下了基调。我们互相打断、抢话、从一个话题跳到另一个话题,同时始终保持不偏离主题。要让人信服——要跨越恐怖谷——虚拟角色必须保持同样的节奏。
Runway Characters 能将单张图像变成可以与之对话的实时角色,其背后是一个约 57B 参数的自回归视频扩散 transformer。在每秒 24 帧(fps)下,该模型必须每 166.7ms 生成一个新的四帧 704x1088 视频块,一次服务一个用户,持续整个对话期间。
今年 5 月,我们首次分享了 Characters 的构建方式。在我们新发表的研究Runway Characters: Serving a 57B Video Diffusion Transformer for Real-Time Conversation中,我们介绍了推理以及让这一节奏在生产环境中成为可能的系统。下面我们将对每一项做高层次概述。论文对它们进行了深入探讨。
关键发现:
- Characters 上线时每个会话使用八块 H100。在四块 H100 上,上线时的软件每个扩散步骤耗时 240.9ms,远超我们所需的 166.7ms。我们的优化将其降至 159.3ms(提速 1.51 倍,持续 24.5 fps),因此现在每个会话可在四块 H100 上实时运行。融合通信内核进一步将其降至 147.4ms(1.63 倍)。
- 在最初的步骤中,29% 的 GPU 时间用于在 240 次注意力调用中每次重新处理基本未变的缓存,而注意力本身仅占 6%。在每帧写入时只做一次这项工作,将缓存维护从每步 69.7ms 降至 6.2ms。
- 将张量并行 all-reduce 融合进 FP8 矩阵乘法,可隐藏其 54-68% 的时间。在我们的生产形态下,融合调用耗时 153.8µs,而非融合为 208.2µs,且优势随 GPU 数量增加而扩大。
- Characters 运行在自回归模型上,这使得像素比较相对没有意义。我们将每项改动与重复运行之间的差异进行对比衡量。在 51 个评分片段中,平均唇同步差异至多为 0.03,与运行间差异处于同一量级,四个 10 分钟会话也显示出相同结果。
- 在七周的遥测中,对于流式传输至少一秒的会话,worker 在 99.5% 的会话中平均高于 23.5 fps。在一次回滚和修复之后,融合内核运行时仅有 0.08% 的会话处于 23.5 fps 或以下。
永不停歇的时钟
传统生成视频按模型的时间表工作。你写一个提示词,等待,然后得到一个完成的片段。但角色必须像对话另一端的人一样快速倾听、回应和反应,没有自然的停止点,也没有机会事后追赶。
这使得速度成为硬性要求:对话中的视频角色绝不能落后。在 24 fps 下,Runway Characters 必须每 166.7ms 生成一个新的四帧视频块,持续整个对话期间。播放器仅保留少量块作为储备,且由于每帧都携带其音频切片,一个迟到的块会同时冻结面部并卡住声音。视频模型还与语音智能体共享循环,因此生成所增加的任何时间都是用户等待回复的时间。
大多数服务系统通过批处理、在众多用户请求间共享 GPU 来获得效率。Character 做不到这一点。每个会话都是私密的一对一流,在 24 fps 下需要 2.24 PFLOP/s 的有效算力,超过单块 H100 的稠密 FP8 峰值。矩阵乘法已经运行在接近该峰值三分之二的水平,因此向批次中加入第二个会话几乎会让单步耗时翻倍。我们节省的每一毫秒都必须来自单步内部。
时间都去哪了
每一步通过 60 块 transformer 的四次遍历对一帧 latent 去噪,合计 240 次注意力调用。每次调用读取自己 5,788 个槽位的缓存,其中只有 757 个是新的。在原始实现中,每次调用都会对整个缓存重做工作:对每个缓存的 key 重新应用旋转位置编码(RoPE)、将缓存重新量化为 FP8,并通过复制来移动窗口。这项维护在 239.2ms 的单步中占了 69.7ms。
只在写入时做一次
为解决这个问题,我们在每个新帧进入缓存时就对其应用 RoPE 和 FP8 量化,使用每个会话校准一次的按头缩放系数。我们将缓存存储为环形结构,因此窗口无需复制即可前进。缓存维护降至每步 6.2ms
我们模型中的位置每 42 步重置一次,因此缓存的 key 不能永远保持其旋转。每次重置时,我们对缓存窗口应用一次增量旋转,而不是在每次读取时重新旋转所有内容。这表现为 42 步中出现一次较慢的步骤,耗时 263ms,由播放缓冲区吸收。
环形结构只有在写入时应用 RoPE 才有效。每个新帧会覆盖最旧的槽位,因此一旦环形回绕,槽位顺序就不再与时间顺序匹配。原始代码按槽位顺序分配位置,因此与环形结构结合时,会悄无声息地给缓存帧分配错误的位置。现在有测试将这种组合标记为无效。

每步扩散时间的累积瀑布图。每项优化及其效果,单位为毫秒;越低越好。
将通信折叠进计算
缓存工作消除后,矩阵乘法之后最大的开销是每个块之后跟随的张量并行 all-reduce,每步 240 次。换用更快的集合通信只节省了 0.4ms,因为归约仍需等待整个矩阵乘法完成后才能开始。
于是我们将两者融合。我们将 ParallelKittens 的融合 GEMM 与 all-reduce 内核扩展到 FP8 和奇数 GPU 数量。每个输出 tile 的部分结果一到达,就在 NVLink 交换机中进行归约,而后续 tile 仍在计算中。在我们的生产形态下,融合调用耗时 153.8µs,而非融合为 208.2µs,隐藏了 54-68% 的 all-reduce。
没有融合内核时,我们的优化将扩散步骤降至 159.3ms,在四块 H100 上维持 24.5 fps。有了它,步骤达到 147.4ms。
给解码器一块独立 GPU
将 latent 转换为视频帧的解码器每步耗时 114ms。如果放在扩散 GPU 上,这段时间会加到每一步上,因为张量并行组要等待最慢的成员。在独立 GPU 上,它可以在下一块去噪的同时解码上一块,步骤周期仅比扩散时间多 1.6ms。
我们在 B200 上测试了替代方案。一块在解码和扩散之间共享的 GPU 停留在其 1,000 W 功耗上限,使其扩散内核慢了 18-26%。

在四块 H100 上运行一个会话,第 i−1 步的解码和第 i−2 步的回放与第 i 步的去噪重叠进行。
当像素无法判断时的质量评估
这些优化中有三项会改变模型的数值行为:FP8 缓存、融合的 pre-attention 内核以及融合的 all-reduce。通常的检查方法是将输出像素与参考结果进行比较。在自回归模型中,这种比较在几秒内就失去意义,因为任何数值差异——哪怕是 GPU 的非确定性——都会让视频走上不同的轨迹。大约 10 秒后,同一生产配置的两次运行在 PSNR 上的差异,与任意两个不同配置之间的差异一样大。
因此我们改为按任务来评判每项改动。我们用所有配置生成了 53 段视频的评估集,该评估集基于 50 张合成参考图像构建,涵盖写实、卡通、黏土动画、奇幻和非人类风格。我们还运行了四次生产配置,以测量相同运行之间唇同步分数的波动幅度。
在全部 51 段视频中,每次运行的 SyncNet 分数平均差异最多为 0.03,所有 95% 区间都落在 ±0.08 以内。仅四次生产运行之间,LSE-D 的跨度就达 0.024,LSE-C 达 0.018。四次 10 分钟的会话交替进行说话和倾听,显示出相同的模式,会话期间没有出现超出重跑所能产生的差异的增长。
这些结果只是界定了改动的范围,而非证明等价。SyncNet 在风格化角色上表现较弱,区间宽出两到五倍,而且四次长会话也无法排除缓慢的趋势。
生产环境中出现的问题
融合内核于 2026 年 8 月进入生产环境,平稳运行了数周。随后,在一次 PyTorch 和 NCCL 升级之后,由于我们的基准测试中输入多样性不足,worker 开始出现内存耗尽。
一个会话的首次前向传播长度取决于其提示词,而该内核会为它见到的每种 token 数量保留一个缓冲区,因此 worker 会为每个新的提示词长度绑定新的多播缓冲区。使用固定提示词的基准测试从未触发这一问题。系统中的每项优化都位于一个开关之后,该开关会保留普通代码路径,因此回退到 NCCL 只需更改配置。
我们现在只融合稳态形状,让首次前向传播使用 NCCL。经过 15 小时的灰度验证——其中每个被测会话平均达到 24.0 fps 或更高——我们于 2026 年 10 月 8 日重新启用了该内核。在随后的 15 天里,时长至少一秒的会话中有 0.7% 平均帧率在 24 fps 或以下,而此前五周中这一比例每周为 7-23%。
另外两个 bug 通过了所有 eager 模式测试,只在编译模式下失败。其中一个 bug 中,编译器合法地将一次调用的读取移到了下一次调用对共享缓冲区写入之后,导致 96% 的元素出错。现在每个内核测试都会在 torch.compile 配合 CUDA graphs 的情况下串联调用。
我们最严重的 bug 是每步添加一次 .item() 调用,用于监控 FP8 缩放因子。它使单步耗时从 168.5ms 增加到 278ms,原因是阻止了 CPU 跑到 GPU 前面,增加的时间比我们所有缓存工作节省的时间加起来还多。
一轮对话的流程
对话有其自身的节奏。在一项涵盖 10 种语言的研究中,一位说话者结束到下一位开始之间的间隔平均为 208ms。一个商用语音代理在相同指标上平均为 1.30s。
我们追踪了 12 个实时会话中的 51 轮对话。中位轮次延迟,从用户语音结束到客户端角色发声,为 2.13 秒。其中语音代理占 1.42 秒。我们的流水线,从代理的首个音频到首个说话帧,耗时 0.49 秒,而传输到浏览器增加了约 190 毫秒。

各阶段中位轮次延迟。时间从用户语音结束到客户端虚拟形象音频的流向。
Blackwell 及超越四块 GPU
生产环境在四块 H100 上实时运行,每步 159.3 毫秒,在三块 B200 上为 154.3 毫秒。但并非所有 H100 优化都能延续。FP8 缓存在 H100 上节省 17.0 毫秒,但在 B200 上却增加 2.4 至 6.7 毫秒,因为我们的构建没有支持逐头缩放(per-head scales)的 FP8 注意力内核。融合内核在解码不在关键路径上时最为重要,在更高 GPU 数量下端到端最高提升 1.20 倍。
更多 GPU 加速模型,但不加速解码器。在八块 H100 上,扩散降至每步 118.2 毫秒,但将结果转为视频帧的单块 GPU 跟不上,因此每步仍需 128.7 毫秒(31 fps)。
与我们共建实时系统
我们相信实时视频是生成式媒体的未来方向,而提供此类服务本身就是一个研究问题。完整论文涵盖了内核设计、质量评估和生产测量。如果你想从事低延迟系统和 GPU 内核方面的工作,我们正在招聘。
来源:Runway · runway.com