GPT-OSS no Dia 0

Suporte no dia 0 para GPT-OSS no H200 através da adaptação do ROSE com FP8, attention sink e otimizações de MoE

AutoresPerplexity Engineering

O Perplexity está empenhado em disponibilizar os melhores modelos de IA para pessoas curiosas que exigem respostas precisas e confiáveis e ações de agentes. A OpenAI anunciou recentemente os seus modelos de pesos abertos (gpt-oss-20b e gpt-oss-120b). Tal como acontece com muitos modelos líderes, o Perplexity está entre as primeiras organizações a avaliar o gpt-oss-20b e o gpt-oss-120b.

Nesta publicação, partilhamos as decisões de infraestrutura da nossa pilha de inferência interna que tornaram possível o suporte no Dia 0. Concentramo-nos na execução destes modelos em GPUs NVIDIA H200, detalhando as alterações de kernel, as escolhas de implementação e as compensações entre velocidade e custo.

GPT-OSS no Hopper

Os modelos de pesos abertos são enviados com quantização MXFP4, o que os ajuda a caber na memória de hardware de nível de consumidor ou a atingir o rendimento máximo no NVIDIA Blackwell. No entanto, para a avaliação inicial, queríamos executá-los em clusters Hopper H200 existentes com alterações mínimas no motor de inferência. O Hopper não possui núcleos de tensor FP4 dedicados, que foram introduzidos pelo Blackwell. Consequentemente, decidimos servir os modelos com precisão FP8 para minimizar a necessidade de kernels personalizados e aproveitar ao máximo o hardware disponível.

Num nível elevado, os LLMs de transformadores são estruturalmente simples:

Incorporação de entrada

Uma sequência de camadas de transformador. Cada uma contém um bloco de atenção e um MLP denso ou um bloco MoE esparso.

Projeção de logits de saída

Ao implementar um novo modelo de transformador, estamos principalmente interessados em saber até que ponto eles correspondem aos modelos existentes para identificar as alterações necessárias. A OpenAI gentilmente partilhou uma visão geral dos seus modelos com antecedência, permitindo-nos ajustar a nossa configuração de inferência em conformidade. Descobrimos que o modelo exigia um bom número de pequenas alterações.

Atenção: GQA com Attention Sinks

Cada cabeça de atenção tem um parâmetro de sink pré-treinado que é contabilizado no Softmax

Codificação posicional YaRN, semelhante ao DeepSeek-V3

As projeções QKV têm vieses, semelhantes ao Qwen 2

A projeção de saída tem viés

MLP: Mistura esparsa de especialistas (MoE)

Função de ativação SwiGLU, diferente da maioria dos modelos de pesos abertos

Softmax após Top-K para pesos de especialistas

Os especialistas têm vieses

Esperando que o número de parâmetros ficasse entre 100B e 200B, decidimos:

Estender o FlashInfer para suportar attention sinks

Reutilizar a implementação de MoE já construída para a família de modelos DeepSeek-V3

Escolher o dimensionamento de blocos FP8 128x128 como esquema de quantização, estendendo os kernels DeepGEMM para suportar um termo de viés.

Motor de Inferência Interno

Os nossos esforços de inferência são sustentados pelo nosso motor de inferência interno, ROSE. Estamos a desenvolver o ROSE para ser uma estrutura flexível que permite a implementação rápida de novos modelos. Além disso, assim que nos comprometemos a servir um modelo em grande escala, ele fornece uma plataforma para otimizar e impulsionar o desempenho para alcançar o estado da arte.

O ROSE expõe um motor LLM, que pode carregar um modelo e gerar tokens Descodificados para ele através de múltiplos descodificadores, incluindo descodificadores especulativos e MTP. Os próprios modelos são compostos por um conjunto personalizado de camadas, que suportam várias configurações conhecidas para quantização e paralelismo. Por baixo das camadas, agrupa kernels Triton e CUDA que implementam e fundem eficientemente os cálculos executados por camadas individuais.

O ROSE é construído principalmente em Python e depende do PyTorch para definições de modelo. Embora o Python nos permita ser flexíveis e adaptar-nos a novos modelos, estamos a migrar a maioria dos componentes sensíveis ao desempenho, como o agendamento de lotes e de serviço, para Rust.

Para implementar um novo modelo, primeiro definimos a hierarquia do modelo e construímos um conversor de peso para ele. Depois de todos os pesos serem contabilizados, definimos uma passagem direta para o caso de uso TP=1 mais simples e garantimos que funciona de ponta a ponta. Por fim, implementamos e testamos o suporte para várias formas de paralelismo antes de lançarmos um novo contentor e implantarmos o modelo num cluster para avaliação. Em seguida, iteramos no desempenho, confiando no feedback de painéis e benchmarks mais granulares.

O ROSE opera em tokens numéricos, com pouco conhecimento de formatos de chat fora dos testes de integração. Em paralelo, tivemos de analisar o ajuste da infraestrutura circundante para suportar o tokenizador Harmony e mapear corretamente os pedidos para sequências de tokens de entrada.

Com o modelo GPT OSS, descobrimos que não foram necessárias alterações nos nossos descodificadores, arreios de gráficos CUDA ou infraestrutura circundante, o que nos permitiu concentrar os nossos esforços no ajuste dos kernels que sustentam o modelo.

Kernels para GPT-OSS

Atenção Sink

A atenção sink introduz um fator de viés extra antes do softmax, acumulado com o produto de Q e K:

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

Embora uma implementação ingénua seja bastante trivial, implementações de atenção eficientes, como o FlashInfer, paralelizam o cálculo da atenção tanto em cabeças independentes como ao longo do comprimento da sequência KV. Além disso, para estabilidade numérica, o Softmax é calculado online, subtraindo também o elemento máximo para estabilidade numérica:

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

A implementação online acompanhou um máximo em execução m inicializado para -inf e uma escala d para 1. Ao inicializar o máximo para o valor de sink da cabeça atual, garantiríamos que ele seria acumulado no Softmax corretamente. Tivemos de ter o cuidado de garantir que este máximo só seria incluído no primeiro bloco se a atenção fosse dividida em vários blocos ao longo do comprimento da sequência.

Ajustámos o modelo de kernel FlashInfer FA2, usado tanto para prefill quanto para descodificação, para incluir os parâmetros de sink.

MoE

A principal diferença entre a camada MoE de diferentes modelos é geralmente o esquema de encaminhamento. Esperando uma variabilidade substancial, o ROSE implementa este kernel em Triton, permitindo-nos adaptá-lo facilmente a novos modelos. No caso do GPT-OSS, tivemos de ajustar a pontuação de peso para executar o softmax apenas nos especialistas selecionados Top-K, ao contrário de alguns modelos ao estilo DeepSeek que calculam o softmax em todos os especialistas. Consideramos crítico para a precisão calcular os pesos dos especialistas em precisão bfloat16.

O desafio com a camada MoE deveu-se à nossa decisão de reutilizar os kernels DeepGEMM existentes, que careciam de suporte para termos de viés. Felizmente, com o tempo integrámo-nos profundamente com eles, fazendo alterações para melhor conectá-los com os nossos kernels de despacho all-to-all personalizados. Adicionamos suporte de viés ao DeepGEMM inicializando os registos acumuladores WGMMA para os valores de viés carregados da memória. Esta é uma operação única durante o processamento de um bloco MN, pelo que o custo é provavelmente negligenciável e a cache L2 garante o acesso eficiente a estes valores.

Uma vez que estes modelos não beneficiam prontamente do paralelismo de dados, reutilizamos os kernels de despacho e combinação exclusivos de TP. As entradas para o despacho são replicadas em todas as ordens, pelo que o despacho seleciona os tokens para os especialistas disponíveis localmente. O Combine executa a acumulação ponderada através do NVLink.

Ajustes de Desempenho

Apesar de o nosso objetivo ser implementar os modelos rapidamente, queríamos garantir que o desempenho ainda era razoável. Após garantir a correção em relação a uma implementação de referência fornecida pela OpenAI, criamos perfis da nossa implementação usando o profiler padrão do PyTorch, prestando atenção às alocações de blocos e tópicos nos kernels. A funcionalidade que reutilizamos foi criada para modelos que tinham uma dimensão oculta maior de 7168, substancialmente maior do que a de 2880 dos modelos GPT-OSS. Especializamos os lançadores de kernel para escolher melhores dimensões de grelha, impulsionando significativamente o rendimento.

Tokenização e canais

O formato de chat do Harmony tem vários conceitos importantes para estruturar conversas, conteúdo de raciocínio e chamadas de função. Neste formato, cada mensagem consiste num cabeçalho e num conteúdo:

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

O cabeçalho transporta metadados — mais importante, a função (sistema, programador, utilizador, assistente, ferramenta), o canal e um destinatário como to=functions.<function-name> ao invocar uma chamada de ferramenta.

Os canais (como análise, comentários e resposta final) tornam as saídas do modelo mais transparentes e segmentadas. Como o formato impõe esta separação, o modelo pode raciocinar de forma transparente (e ser inspecionado para depuração) sem vazar a cadeia de pensamento para a produção. As etiquetas de destinatário (cabeçalhos to=) dizem exatamente ao runtime qual o ator que deve receber a próxima carga útil — quer seja uma função, o próprio modelo ou o utilizador final.

O nosso motor de inferência ROSE é agnóstico em relação ao formato. Recebe um lote de tokens de entrada e transmite de volta tokens de saída. Na nossa pilha de inferência, a tarefa de formatar entradas num prompt tokenizado e analisar os resultados do LLM de volta em mensagens estruturadas é tratada pelo serviço front-end da API JSON dedicado. Integramos o Harmony adicionando um novo formatador/analisador intercalável a este front-end, permitindo que o back-end permaneça inalterado enquanto o front-end gere de forma limpa as regras de formato de chat, chamadas de ferramenta e transmissão. Esta separação de preocupações mantém a arquitetura modular, permitindo a rápida adoção de novos formatos e recursos de resposta com alterações mínimas no back-end.

Custo e Desempenho

Dada a dimensão relativamente pequena dos modelos GPT-OSS, limitamos a implementação de uma réplica a um único nó para evitar a sobrecarga de comunicação entre nós. A nossa implementação suporta combinações flexíveis de paralelismo de especialistas (EP), paralelismo de dados (DP) e paralelismo de tensores (TP). Para determinar a configuração de otimização ideal, avaliamos todas as combinações de estratégias de fragmentação em tamanhos de lote de 1 a 128. Graças à Desagregação Prefill-Decode, podemos discutir a compensação entre desempenho e custo separadamente para o prefill e a descodificação.

Para estimativas de custos, assumimos uma taxa de mercado nominal de H200 de $3,00/hora (nota: este não é o nosso preço real de GPU).

Descobrimos que definir batch_size=1 e DP=1 produz o melhor desempenho de prefill. Diferentes configurações de TP fornecem então compensações variadas entre a latência do primeiro token e o custo. As tabelas abaixo apresentam a latência de prefill e o custo por milhão de tokens de entrada para várias configurações e comprimentos de entrada.

GPT-OSS 120B:

Comprimento de Entrada

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

Latência de pré-preenchimento do GPT-OSS 120B e custo por milhão de tokens de entrada, por configuração de paralelismo e comprimento de entrada.

GPT-OSS 20B:

Comprimento de Entrada

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

Latência de pré-preenchimento do GPT-OSS 20B e custo por milhão de tokens de entrada, por configuração de paralelismo e comprimento de entrada.

Para a descodificação, descubrimos que o EP4 DP1 TP4 é a melhor configuração para a maioria dos casos. Os quatro gráficos abaixo ilustram a compensação entre a velocidade de descodificação e o custo por milhão de tokens de saída para os modelos de 120B e 20B em comprimentos de sequência de 8192 e 32768.

Custo somente de decodificação por milhão de tokens de saída versus velocidade de decodificação para o GPT-OSS 120B no comprimento de sequência 8.192, comparando as configurações EP1, EP2, EP4 e EP8.
Custo somente de decodificação por milhão de tokens de saída versus velocidade de decodificação para o GPT-OSS 120B no comprimento de sequência 32.768, comparando as configurações EP1, EP2, EP4 e EP8.
Custo somente de decodificação por milhão de tokens de saída versus velocidade de decodificação para o GPT-OSS 20B no comprimento de sequência 8.192, comparando as configurações EP1, EP2, EP4 e EP8.
Custo somente de decodificação por milhão de tokens de saída versus velocidade de decodificação para o GPT-OSS 20B no comprimento de sequência 32.768, comparando as configurações EP1, EP2, EP4 e EP8.

Também considerámos a utilização do modelo menor de 20B como um modelo de rascunho de descodificação especulativa para o modelo maior de 120B. No entanto, como o número de parâmetros ativados é semelhante (3B vs. 5B), os acertos de velocidade resultantes foram marginais.

Referências

Prefill e Descodificação Desagregados

Acelerar o Sonar Através da Especulação​

Menor Latência e Maior Rendimento com a Implementação DeepSeek Multi-nó

​Comunicação Eficiente e Portátil de Mistura de Especialistas

​pplx-kernels

DeepGEMM

FlashInfer: Motor de Atenção Eficiente e Personalizável para Serviço de Inferência LLM

Modelos de Linguagem de Streaming Eficientes com Attention Sinks

Relatório Técnico do DeepSeek-V3​

​Formato de Resposta OpenAI Harmony | Livro de Receitas OpenAI​

Citação

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}
}