GPT-OSS 的第 0 天支持

通过采用 FP8、汇聚注意力和 MoE 优化来调整 ROSE,实现 H200 上 GPT-OSS 的第 0 天支持

作者Perplexity Engineering

Perplexity 致力于为追求准确、可靠答案及智能体操作的求知者提供最优的 AI 模型。OpenAI 最近发布了其开放权重模型(gpt-oss-20b 和 gpt-oss-120b)。与众多领先模型一样,Perplexity 是首批评估 gpt-oss-20b 和 gpt-oss-120b 的组织之一。

在本文中,我们将分享我们内部推理堆栈的基础设施决策,正是这些决策使得“第 0 天”(Day-0)支持成为可能。我们将重点介绍在 NVIDIA H200 GPU 上服务这些模型的细节,包括内核变更、部署方案以及速度与成本之间的权衡。

Hopper 架构上的 GPT-OSS

这些开放权重模型使用 MXFP4 量化技术发布,这有助于它们适应消费级硬件的内存,或在 NVIDIA Blackwell 上实现峰值吞吐量。然而,为了进行初步评估,我们希望在现有的 H200 Hopper 集群上运行它们,同时将推理引擎的更改降至最低。Hopper 架构没有 Blackwell 引入的专用 FP4 张量核心。因此,我们决定使用 FP8 精度来服务这些模型,以尽量减少对自定义内核的需求,并充分利用现有硬件资源。

从宏观层面来看,Transformer 大语言模型(LLM)的结构非常简单:

输入嵌入(Input embedding)

一系列 Transformer 层。每一层包含一个注意力模块,以及一个稠密 MLP 或稀疏 MoE 模块。

输出 Logit 投影

当部署一个新的 Transformer 模型时,我们主要关心它们与现有模型的匹配程度,从而确定所需的变更。OpenAI 提前分享了其模型概览,使我们能够相应地调整推理设置。我们发现该模型确实需要进行多次细微的调整。

注意力机制:具有注意力汇聚(Attention Sinks)的 GQA

每个注意力头都有一个预训练的汇聚参数,该参数会被纳入 Softmax 计算中

YaRN 位置编码,类似于 DeepSeek-V3

QKV 投影包含偏置,类似于 Qwen 2

输出投影包含偏置

MLP:稀疏混合专家(MoE)

SwiGLU 激活函数,与大多数开放权重模型不同

专家权重在 Top-K 之后进行 Softmax

专家模块包含偏置

考虑到参数数量预计在 100B 到 200B 左右,我们决定:

扩展 FlashInfer 以支持注意力汇聚

重用已为 DeepSeek-V3 系列模型构建的 MoE 实现

选择 FP8 128x128 块缩放作为量化方案,并扩展 DeepGEMM 内核以支持偏置项。

内部推理引擎

我们的推理工作由内部推理引擎 ROSE 提供支持。我们正将 ROSE 打造成一个灵活的框架,以便快速部署新模型。此外,一旦我们决定大规模服务某个模型,它就能提供一个优化并提升性能以达到行业领先水平的平台。

ROSE 提供了一个 LLM 引擎,该引擎能够加载模型,并通过多种解码器(包括推测解码和 MTP 解码器)为模型生成解码 Token。这些模型本身由一组自定义层组成,支持各种用于量化和并行的配置。在层级之下,它捆绑了 Triton 和 CUDA 内核,以高效地实现并融合各个层执行的计算。

ROSE 主要使用 Python 构建,并依赖 PyTorch 进行模型定义。虽然 Python 使我们能够保持灵活性并适应新模型,但我们正在将大部分对性能敏感的组件(如服务和批处理调度)迁移到 Rust。

为了部署新模型,我们首先定义模型层次结构并构建权重转换器。在处理完所有权重后,我们为最简单的 TP=1 用例定义前向传递,并确保其端到端运行正常。最后,在发布新容器并在集群上部署模型进行评估之前,我们实现并测试了各种形式的并行支持。随后,我们根据仪表盘和细粒度基准测试的反馈来迭代优化性能。

ROSE 对数值 Token 进行操作,除了集成测试外,对聊天格式几乎没有了解。与此同时,我们不得不研究调整周围的基础设施,以支持 Harmony 分词器并正确地将请求映射到输入 Token 序列。

对于 GPT OSS 模型,我们发现无需对解码器、CUDA 图框架或周围的基础设施进行任何更改,这使我们能够集中精力调整支持该模型的内核。

GPT-OSS 内核

汇聚注意力(Sink Attention)

汇聚注意力在 Softmax 之前引入了一个额外的偏置因子,该因子与 Q 和 K 的乘积进行累加:

plaintext
attn = softmax(q @ k^T * sm_scale + sink) * V

虽然简单的实现相当直观,但高效的注意力实现(例如 FlashInfer)会在独立的注意力头和 KV 序列长度上并行计算注意力。此外,为了数值稳定性,Softmax 是在线计算的,同时减去最大元素以保持数值稳定:

plaintext
softmax(x) = e^x / sum(e^x) = e ^ (x - max(x)) / sum(e ^ (x - max(x))

在线实现追踪一个运行中的最大值 m(初始化为 -inf)和一个缩放因子 d(初始化为 1)。通过将最大值初始化为当前头的汇聚值,我们确保它能被正确累加到 Softmax 中。如果注意力沿着序列长度被拆分为多个块,我们需要确保该最大值仅包含在第一个块中。

我们调整了 FlashInfer FA2 内核模板(用于预填充和解码),以包含汇聚参数。

MoE

不同模型的 MoE 层之间的主要区别通常在于路由方案。由于预计存在巨大的可变性,ROSE 在 Triton 中实现了此内核,使我们能够轻松地将其调整为适应新模型。在 GPT-OSS 的情况下,我们不得不调整权重评分,仅在 Top-K 所选专家之间进行 Softmax 计算,这与某些在所有专家之间计算 Softmax 的 DeepSeek 风格模型不同。我们发现,以 bfloat16 精度计算专家权重对于准确性至关重要。

MoE 层面临的挑战源于我们决定重用现有的 DeepGEMM 内核,而这些内核缺乏对偏置项的支持。幸运的是,随着时间的推移,我们与它们进行了深度集成,并做出了更改以更好地将它们与我们的自定义全对全(all-to-all)调度内核连接起来。我们通过将 WGMMA 累加器寄存器初始化为从内存加载的偏置值,为 DeepGEMM 添加了偏置支持。这是在处理 MN 块期间的一次性操作,因此其成本几乎可以忽略不计,且 L2 缓存确保了对这些值的高效访问。

由于这些模型无法从数据并行中直接获益,我们重用了仅限 TP 的调度和合并内核。输入到调度器的内容会在所有 Rank 之间复制,因此调度器会为本地可用的专家选择 Token。合并操作会通过 NVLink 执行加权累加。

性能调优

尽管我们的目标是快速部署模型,但我们仍希望确保性能合理。在对照 OpenAI 提供的参考实现验证了正确性后,我们使用默认的 PyTorch 分析器对实现进行了性能分析,重点关注内核间的块和线程分配。我们重用的功能是为隐藏维度较大(7168)的模型构建的,远大于 GPT-OSS 模型的 2880。我们专门定制了内核启动器以选择更好的网格维度,从而显著提高了吞吐量。

标记化与通道

Harmony 的聊天格式在构建对话、推理内容和函数调用方面有几个重要的概念。在此格式中,每条消息都由头部和内容组成:

plaintext
<|start|>{header}<|message|>{content}<|end|>

头部包含元数据——最重要的是角色(系统、开发者、用户、助手、工具)、通道以及接收者(例如在调用函数时使用 to=functions.<function-name>)。

通道(例如分析、评论和最终答案)使模型的输出更加透明和分段。由于该格式强制执行这种分离,模型可以透明地进行推理(并可被检查以进行调试),而不会将思维链泄露到生产环境中。接收者标签(to= 头部)会准确告知运行时哪个参与者应该接收下一个有效载荷——无论是函数、模型本身还是最终用户。

我们的推理引擎 ROSE 与格式无关。它接收一批输入 Token 并流式传回输出 Token。在我们的推理堆栈中,将输入格式化为 Token 化提示并将 LLM 结果解析回结构化消息的任务由专门的 JSON API 前端服务处理。我们通过向该前端添加一个新的可插拔格式化器/解析器来集成 Harmony,从而允许后端保持不变,同时前端整洁地管理聊天格式规则、函数调用和流式传输。这种关注点分离保持了架构的模块化,使得在极少修改后端的情况下就能快速采用新格式和响应功能。

成本与性能

鉴于 GPT-OSS 模型相对较小,我们将副本的部署限制在单节点内,以避免节点间通信开销。我们的实现支持专家并行(EP)、数据并行(DP)和张量并行(TP)的灵活组合。为了确定最佳部署设置,我们对各种批处理大小(从 1 到 128)下的分片策略组合进行了基准测试。得益于 预填充-解码解耦(Prefill-Decode Disaggregation),我们能够分别讨论预填充和解码的性能-成本权衡。

对于成本估算,我们假设 H200 的名义市场价格为 3.00 美元/小时(注:这不是我们实际的 GPU 价格)。

我们发现设置 batch_size=1 和 DP=1 可获得最佳的预填充性能。不同的 TP 配置在首字延迟和成本之间提供了不同的权衡。下表显示了各种配置和输入长度下的预填充延迟和每百万输入 Token 的成本。

GPT-OSS 120B:

输入长度

8192

32768

65536

128000

EP1 DP1 TP1

0.364s, $0.037

2.421s, $0.062

7.375s, $0.094

23.902s, $0.156

EP2 DP1 TP2

0.190s, $0.039

1.245s, $0.063

3.786s, $0.096

12.116s, $0.158

EP4 DP1 TP4

0.165s, $0.067

0.900s, $0.092

2.449s, $0.125

7.165s, $0.187

EP8 DP1 TP8

0.179s, $0.145

0.839s, $0.171

2.003s, $0.204

5.119s, $0.267

GPT-OSS 120B 在不同并行配置和输入长度下的预填充延迟和每百万输入 token 成本。

GPT-OSS 20B:

输入长度

8192

32768

65536

128000

EP1 DP1 TP1

0.239s, $0.024

1.610s, $0.041

4.895s, $0.062

16.037s, $0.104

EP2 DP1 TP2

0.127s, $0.026

0.833s, $0.042

2.522s, $0.064

8.143s, $0.106

EP4 DP1 TP4

0.108s, $0.044

0.593s, $0.060

1.616s, $0.082

4.766s, $0.124

EP8 DP1 TP8

0.116s, $0.094

0.547s, $0.111

1.310s, $0.133

3.365s, $0.175

GPT-OSS 20B 在不同并行配置和输入长度下的预填充延迟和每百万输入 token 成本。

对于解码,我们发现 EP4 DP1 TP4 是大多数情况下的最佳配置。下方的四个图表展示了 120B 和 20B 模型在序列长度为 8192 和 32768 时,解码速度与每百万输出 Token 成本之间的权衡。

在序列长度 8,192 下,GPT-OSS 120B 的仅解码每百万输出 token 成本与解码速度的关系,对比 EP1、EP2、EP4 和 EP8 配置。
在序列长度 32,768 下,GPT-OSS 120B 的仅解码每百万输出 token 成本与解码速度的关系,对比 EP1、EP2、EP4 和 EP8 配置。
在序列长度 8,192 下,GPT-OSS 20B 的仅解码每百万输出 token 成本与解码速度的关系,对比 EP1、EP2、EP4 和 EP8 配置。
在序列长度 32,768 下,GPT-OSS 20B 的仅解码每百万输出 token 成本与解码速度的关系,对比 EP1、EP2、EP4 和 EP8 配置。

我们还考虑将较小的 20B 模型用作较大 120B 模型的 推测解码 草稿模型。然而,由于激活的参数数量相似(3B 对 5B),由此产生的速度提升微乎其微。

参考资料

预填充与解码解耦

通过投机加速 Sonar​

多节点 DeepSeek 部署实现更低延迟和更高吞吐量

​高效且可移植的混合专家通信

​pplx-kernels

DeepGEMM

FlashInfer:用于 LLM 推理服务的高效且可定制的注意力引擎

使用注意力汇聚实现高效的流式大语言模型

DeepSeek-V3 技术报告​

​OpenAI Harmony 响应格式 | OpenAI Cookbook​

引用

BibTeX
@online{perplexity2025GptOssOnDay0,
  author = {{Perplexity} and Nandor Licker and Lequn Chen and Vladimir Zaytsev and Kevin Hu and Lauren Kolm and Jesse Dwyer},
  title = {{GPT-OSS on day 0}},
  date = {2025-08-08},
  url = {https://www.perplexity.ai/hub/blog/gpt-oss-on-day-0}
}