GPT-OSS el día 0

Soporte del día 0 para GPT-OSS en H200 adaptando ROSE con FP8, atención de sumidero y optimizaciones de MoE

AutoresPerplexity Engineering

Perplexity se compromete a poner los mejores modelos de IA a disposición de personas curiosas que exigen respuestas precisas y confiables, así como acciones agénticas. OpenAI anunció recientemente sus modelos de pesos abiertos (gpt-oss-20b y gpt-oss-120b). Como ocurre con muchos modelos líderes, Perplexity se encuentra entre las primeras organizaciones en evaluar gpt-oss-20b y gpt-oss-120b.

En esta publicación, compartimos las decisiones de infraestructura de nuestra pila de inferencia interna que hicieron posible el soporte del día 0. Nos enfocamos en servir estos modelos en GPUs NVIDIA H200, detallando los cambios en el núcleo, las opciones de implementación y las compensaciones entre velocidad y costo.

GPT-OSS en Hopper

Los modelos de pesos abiertos se envían utilizando cuantización MXFP4, lo que ayuda a que quepan en la memoria del hardware de grado de consumidor o logren un rendimiento máximo en NVIDIA Blackwell. Sin embargo, para la evaluación inicial, queríamos ejecutarlos en clústeres Hopper H200 existentes con cambios mínimos en el motor de inferencia. Hopper no cuenta con núcleos tensoriales FP4 dedicados, los cuales fueron introducidos por Blackwell. En consecuencia, decidimos servir los modelos con precisión FP8 para minimizar la necesidad de núcleos personalizados y aprovechar al máximo el hardware disponible.

A nivel general, los LLM transformadores son estructuralmente simples:

Incrustación de entrada

Una secuencia de capas de transformador. Cada una contiene un bloque de atención y un bloque MLP denso o MoE disperso.

Proyección de logit de salida

Al implementar un nuevo modelo de transformador, estamos principalmente interesados en aprender hasta qué punto coinciden con los modelos existentes para identificar los cambios necesarios. OpenAI compartió amablemente una descripción general de sus modelos con anticipación, lo que nos permitió ajustar nuestra configuración de inferencia en consecuencia. Descubrimos que el modelo requería bastantes pequeños cambios.

Atención: GQA con sumideros de atención

Cada cabezal de atención tiene un parámetro de sumidero preentrenado que se incluye en Softmax

Codificación posicional YaRN, similar a DeepSeek-V3

Las proyecciones QKV tienen sesgos, similar a Qwen 2

La proyección de salida tiene sesgo

MLP: Mezcla de expertos dispersa (MoE)

Función de activación SwiGLU, diferente de la mayoría de los modelos de pesos abiertos

Softmax después de Top-K para pesos de expertos

Los expertos tienen sesgos

Esperando que el número de parámetros sea de alrededor de 100B-200B, decidimos:

Ampliar FlashInfer para admitir sumideros de atención

Reutilizar la implementación de MoE ya construida para la familia de modelos DeepSeek-V3

Elegir el escalado de bloques FP8 128x128 como esquema de cuantización, extendiendo los núcleos DeepGEMM para admitir un término de sesgo.

Motor de inferencia interno

Nuestros esfuerzos de inferencia están respaldados por nuestro motor de inferencia interno, ROSE. Estamos desarrollando ROSE para que sea un marco flexible que permita implementar rápidamente nuevos modelos. Además, una vez que nos comprometemos a servir un modelo a escala, proporciona una plataforma para optimizar y aumentar el rendimiento hasta alcanzar el estado del arte.

ROSE expone un motor de LLM, que puede cargar un modelo y generar tokens decodificados para él a través de múltiples decodificadores, incluidos los decodificadores especulativos y MTP. Los modelos en sí están compuestos por un conjunto personalizado de capas, que admiten diversas configuraciones para cuantización y paralelismo. Debajo de las capas, combina núcleos Triton y CUDA que implementan y fusionan eficientemente los cálculos realizados por capas individuales.

ROSE está construido principalmente en Python y depende de PyTorch para las definiciones de modelos. Si bien Python nos permite ser flexibles y adaptarnos a nuevos modelos, estamos migrando la mayoría de los componentes sensibles al rendimiento, como el servicio y la programación por lotes, a Rust.

Para implementar un nuevo modelo, primero definimos la jerarquía del modelo y construimos un convertidor de pesos para él. Una vez contabilizados todos los pesos, definimos un paso hacia adelante para el caso de uso más simple TP=1 y nos aseguramos de que funcione de principio a fin. Finalmente, implementamos y probamos el soporte para diversas formas de paralelismo antes de lanzar un nuevo contenedor e implementar el modelo en un clúster para su evaluación. Luego iteramos sobre el rendimiento, basándonos en los comentarios tanto de los paneles de control como de las pruebas comparativas más detalladas.

ROSE opera con tokens numéricos, con poco conocimiento de formatos de Chat fuera de las pruebas de integración. En paralelo, tuvimos que considerar ajustar la infraestructura circundante para admitir el tokenizador Harmony y asignar correctamente las solicitudes a secuencias de tokens de entrada.

Con el modelo GPT OSS, descubrimos que no se requirieron cambios en nuestros decodificadores, arneses de gráficos CUDA o infraestructura circundante, lo que nos permitió concentrar nuestros esfuerzos en ajustar los núcleos que respaldan el modelo.

Núcleos para GPT-OSS

Atención de sumidero

La atención de sumidero introduce un factor de sesgo adicional antes de softmax, acumulado con el producto de Q y K:

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

Si bien una implementación ingenua es bastante trivial, las implementaciones eficientes de atención, como FlashInfer, paralelizan el cálculo de la atención tanto en cabezales independientes como en la longitud de la secuencia KV. Además, para la estabilidad numérica, Softmax se calcula en línea mientras se resta el elemento máximo:

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

La implementación en línea rastreaba un máximo en ejecución m inicializado en -inf y una escala d en 1. Al inicializar el máximo al valor de sumidero del cabezal actual, aseguraríamos que se acumulara correctamente en el Softmax. Tuvimos cuidado de asegurar que este máximo solo se incluyera en el primer fragmento si la atención se dividía en múltiples bloques a lo largo de la longitud de la secuencia.

Hemos ajustado la plantilla del núcleo FlashInfer FA2, utilizada tanto para prellenado como para decodificación, para incluir los parámetros de sumidero.

MoE

La principal diferencia entre la capa MoE de diferentes modelos suele ser el esquema de enrutamiento. Esperando una variabilidad sustancial, ROSE implementa este núcleo en Triton, lo que nos permite adaptarlo fácilmente a nuevos modelos. En el caso de GPT-OSS, tuvimos que ajustar la puntuación de peso para realizar softmax solo entre los expertos seleccionados Top-K, a diferencia de algunos modelos de estilo DeepSeek que calculan softmax entre todos los expertos. Descubrimos que es fundamental para la precisión calcular los pesos de los expertos en precisión bfloat16.

El desafío con la capa MoE se debió a nuestra decisión de reutilizar los núcleos DeepGEMM existentes, que carecían de soporte para términos de sesgo. Afortunadamente, con el tiempo nos integramos profundamente con ellos, realizando cambios para conectarlos mejor con nuestros núcleos de despacho de todo a todo personalizados. Agregamos soporte de sesgo a DeepGEMM inicializando los registros de acumulador WGMMA con los valores de sesgo cargados desde la memoria. Esto es único durante el procesamiento de un bloque MN, por lo que el costo es probablemente insignificante y la caché L2 garantiza un acceso eficiente a estos valores.

Dado que estos modelos no se benefician fácilmente del paralelismo de datos, reutilizamos los núcleos de despacho y combinación solo para TP. Las entradas para el despacho se replican en todos los rangos, por lo que el despacho selecciona los tokens para los expertos disponibles localmente. La combinación realiza la acumulación ponderada a través de NVLink.

Ajustes de rendimiento

Aunque nuestro objetivo era implementar los modelos rápidamente, queríamos asegurarnos de que el rendimiento fuera razonable. Después de garantizar la exactitud frente a una implementación de referencia proporcionada por OpenAI, perfilamos nuestra implementación utilizando el generador de perfiles de PyTorch predeterminado, prestando atención a las asignaciones de bloques e hilos entre núcleos. La funcionalidad que reutilizamos fue desarrollada para modelos que tenían una dimensión oculta mayor de 7168, sustancialmente mayor que los 2880 de los modelos GPT-OSS. Especializamos los lanzadores de núcleos para elegir mejores dimensiones de cuadrícula, aumentando significativamente el rendimiento.

Tokenización y canales

El formato de Chat de Harmony tiene varios conceptos importantes para estructurar conversaciones, contenido de razonamiento y llamadas a funciones. En este formato, cada mensaje consta de un encabezado y contenido:

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

El encabezado lleva metadatos, lo más importante es el rol (sistema, desarrollador, usuario, asistente, herramienta), el canal y un destinatario como to=functions.<function-name> al invocar una llamada de herramienta.

Los canales (como análisis, comentarios y respuesta final) hacen que las salidas del modelo sean más transparentes y segmentadas. Debido a que el formato impone esta separación, el modelo puede razonar de forma transparente (y ser inspeccionado para depuración) sin filtrar la cadena de pensamiento en producción. Las etiquetas de destinatario (encabezados to=) le dicen al tiempo de ejecución exactamente qué actor debería recibir la siguiente carga útil, ya sea una función, el modelo mismo o el usuario final.

Nuestro motor de inferencia ROSE es independiente del formato. Recibe un lote de tokens de entrada y transmite de vuelta tokens de salida. En nuestra pila de inferencia, la tarea de formatear las entradas en un aviso tokenizado y analizar los resultados del LLM de vuelta en mensajes estructurados es manejada por el servicio de interfaz de API JSON dedicado. Integramos Harmony agregando un nuevo formateador/analizador conectable a esta interfaz, lo que permite que el backend permanezca sin cambios mientras la interfaz gestiona limpiamente las reglas de formato de Chat, las llamadas a herramientas y la transmisión. Esta separación de preocupaciones mantiene la arquitectura modular, lo que permite una rápida adopción de nuevos formatos y características de respuesta con cambios mínimos en el backend.

Costo y rendimiento

Dado el tamaño relativamente pequeño de los modelos GPT-OSS, limitamos la implementación de una réplica a un solo nodo para evitar la sobrecarga de comunicación entre nodos. Nuestra implementación admite combinaciones flexibles de paralelismo de expertos (EP), paralelismo de datos (DP) y paralelismo de tensores (TP). Para determinar la configuración de implementación óptima, evaluamos todas las combinaciones de estrategias de fragmentación en tamaños de lote de 1 a 128. Gracias a la desagregación de prellenado-decodificación, podemos discutir la compensación entre rendimiento y costo por separado para el prellenado y la decodificación.

Para las estimaciones de costos, asumimos una tarifa de mercado nominal de H200 de $3.00/hora (nota: este no es nuestro precio real de GPU).

Descubrimos que establecer batch_size=1 y DP=1 produce el mejor rendimiento de prellenado. Las diferentes configuraciones de TP proporcionan compensaciones variables entre la latencia del primer token y el costo. Las tablas a continuación presentan la latencia de prellenado y el costo por millón de tokens de entrada para varias configuraciones y longitudes de entrada.

GPT-OSS 120B:

Longitud 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

Latencia de prellenado de GPT-OSS 120B y coste por millón de tokens de entrada según la configuración de paralelismo y la longitud de entrada.

GPT-OSS 20B:

Longitud 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

Latencia de prellenado de GPT-OSS 20B y coste por millón de tokens de entrada según la configuración de paralelismo y la longitud de entrada.

Para la decodificación, descubrimos que EP4 DP1 TP4 es la mejor configuración para la mayoría de los casos. Los cuatro gráficos a continuación ilustran la compensación entre la velocidad de decodificación y el costo por millón de tokens de salida tanto para los modelos 120B como 20B con longitudes de secuencia de 8192 y 32768.

Coste únicamente de decodificación por millón de tokens de salida frente a la velocidad de decodificación para GPT-OSS 120B con longitud de secuencia de 8.192, comparando las configuraciones EP1, EP2, EP4 y EP8.
Coste únicamente de decodificación por millón de tokens de salida frente a la velocidad de decodificación para GPT-OSS 120B con longitud de secuencia de 32.768, comparando las configuraciones EP1, EP2, EP4 y EP8.
Coste únicamente de decodificación por millón de tokens de salida frente a la velocidad de decodificación para GPT-OSS 20B con longitud de secuencia de 8.192, comparando las configuraciones EP1, EP2, EP4 y EP8.
Coste únicamente de decodificación por millón de tokens de salida frente a la velocidad de decodificación para GPT-OSS 20B con longitud de secuencia de 32.768, comparando las configuraciones EP1, EP2, EP4 y EP8.

También hemos considerado usar el modelo 20B más pequeño como modelo de borrador de decodificación especulativa para el modelo 120B más grande. Sin embargo, debido a que el número de parámetros activados es similar (3B frente a 5B), las mejoras de velocidad resultantes fueron marginales.

Referencias

Prellenado y decodificación desagregados

Acelerando Sonar a través de la especulación​

Menor latencia y mayor rendimiento con la implementación multinodo de DeepSeek

​Comunicación eficiente y portátil de mezcla de expertos

​pplx-kernels

DeepGEMM

FlashInfer: Motor de atención eficiente y personalizable para el servicio de inferencia LLM

Modelos de lenguaje de transmisión eficientes con sumideros de atención

Informe técnico de DeepSeek-V3​

​Formato de respuesta de OpenAI Harmony | Recetario de OpenAI​

Citación

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