Menor latencia e maior capacidade de procesamento coa implementación multinode de DeepSeek

A implementación multi-GPU mellora o rendemento do modelo MoE en velocidade e escala ao mesmo tempo

AutoresPerplexity Research

Na maioría dos sistemas, a latencia e a capacidade de procesamento adoitan ser obxectivos en conflito que requiren compromisos durante o deseño e a implementación. Por exemplo, nos modelos de linguaxe grandes densos, aumentar o tamaño do lote pode mellorar a capacidade de procesamento pero tamén incrementa a latencia; aumentar o paralelismo de tensores nunha soa máquina pode reducir a latencia pero diminúe o número de réplicas, o que leva a unha menor capacidade de procesamento.

Os modelos de mestura de expertos (MoE), como DeepSeek-V3/R1, demostraron recentemente unhas excelentes capacidades de modelo e eficiencia operativa. Por exemplo, o modelo DeepSeek-V3/R1 ten un total de 671B parámetros, pero cada token só usa 37B parámetros durante a inferencia. Esta arquitectura de modelos presenta tanto desafíos como oportunidades para os sistemas de inferencia.

Este artigo demostra que, ao contrario dos sistemas convencionais, os modelos MoE como DeepSeek-V3/R1 poden alcanzar simultaneamente unha maior capacidade de procesamento e unha menor latencia ao utilizar máis GPUs en implementacións multinode na maioría dos escenarios.

Arquitecturas de implementación

Despregamento nun único nodo a través de NVLink, coa atención e a computación experta distribuídas entre as GPU.
Despregamento multinodo a través de InfiniBand, con grupos de GPU conectados dentro dos nodos e entre eles.

Debido ao gran número de pequenos expertos que ten o modelo, as implementacións deben distribuírse en varios dispositivos. Consideramos tanto implementacións nun único nodo nun único nodo con 8 GPUs H200 como implementacións multinode en 8 GPUs H100.

Ambas as arquitecturas de implementación aproveitan o paralelismo de datos, orquestrado a través do noso programador de solicitudes interno. A implementación do paralelismo de datos implica o lanzamento de múltiples instancias de motores de inferencia, cada unha operando de forma independente para atender e manter as solicitudes. O programador de solicitudes, que interactúa co motor a través de gRPC, é o responsábel de distribuír as solicitudes o máis uniformemente posíbel, á vez que facilita a reutilización de KV, enviando solicitudes cun prefixo coincidido parcial aos servidores que conteñen a caché. As instancias do motor non abranguen varios nodos. Opcionalmente, poden usar o paralelismo de tensores para fragmentar a atención en varios dispositivos. As instancias están interconectadas mediante NVLink no caso dun único nodo ou InfiniBand no caso multinode, despachando e recollendo expertos.

A configuración de implementación nun único nodo ofrece unha latencia superior con tamaños de lote pequenos; porén, o rendemento degrádese rapidamente en condicións de carga aumentada.

Para implementar o motor de servizo, lanzamos un pod por nodo que aloja múltiples instancias de motor. PyTorch é o responsábel de configurar a comunicación distribuída e negociar a inicialización de NVSHMEM. Para a comunicación, baseámonos nos kernels CUDA personalizados descritos nunha entrada de blog anterior. A implementación das dúas implementacións é practicamente idéntica, e o modelo escolle os kernels correctos para usar en función da estrutura que implementa o paralelismo de expertos.

Técnicas de paralelización

Antes de afondar nas nosas comparacións de rendemento, é esencial comprender as principais estratexias de paralelización que fan posíbel implementar modelos MoE masivos como DeepSeek-V3/R1.

Paralelismo de tensores

Na inferencia de LLM, o paralelismo de tensores (TP) utilízase habitualmente para reducir o uso de memoria e o cálculo por GPU, reducindo así a latencia. Habitualmente, podemos fragmentar as proxeccións Linear nas capas de atención e MLP ao longo das dimensións de filas ou columnas, e fragmentar as operacións de atención ao longo da dimensión da cabeza de atención.

Con TP, a arquitectura de Llama-3 non ten ningún cálculo duplicado para a proxección Linear e as operacións de atención entre GPUs, o que é un método de fragmentación ideal. Con todo, nos modelos DeepSeek-V3/R1, o TP non pode acadar isto.

Os modelos DeepSeek-V3/R1 usan atención multilatente (MLA). Unha capa MLA usa primeiro unha proxección Linear kv_a_proj para calcular o vector latente, e despois usa outra proxección Linear kv_b_proj para transformalo no espazo de cada cabeza de atención. Dado que todas as cabezas de atención comparten o mesmo vector latente, o TP non pode fragmentar o vector latente, polo que todos os rangos de TP necesitan replicar os parámetros e o cálculo de kv_a_proj e kv_b_proj. De forma similar, dado que MLA almacena o vector latente na caché KV, cada rango de TP almacena unha copia idéntica da caché KV.

A pesar de certa duplicación en MLA, o paralelismo de tensores aínda ofrece unha redución parcial nas demandas de cálculo, polo que resulta valioso para escenarios que requiren altas velocidades de saída.

Paralelismo de expertos

Os modelos DeepSeek-V3/R1 substitúen as capas MLP por capas MoE. Unha capa MoE ten 256 expertos encamiñados e un experto compartido. Cada token envíase a 8 expertos encamiñados diferentes para o seu cálculo, e os resultados Súmanse ponderadamente. Cada token tamén se calcula no experto compartido, e o resultado súmase ao resultado dos expertos encamiñados.

O paralelismo de expertos (EP) serve como enfoque de fragmentación típico para as capas MoE, coa xestión por parte de cada GPU de 256 / EP expertos encamiñados á vez que mantén unha copia do experto compartido. En comparación co TP, a vantaxe do EP é que pode distribuír o cálculo entre máis GPUs, o que reduce o uso de cálculo e memoria por GPU.

Antes de realizar o cálculo de expertos, todas as GPUs deben realizar unha comunicación AllToAll para enviar os tokens ás GPUs onde se atopan os expertos correspondentes; despois do cálculo de expertos, necesítase outra comunicación AllToAll para recoller os resultados do cálculo de varias GPUs e realizar a suma ponderada. Implementamos unha versión optimizada destes dous kernels de comunicación AllToAll, Dispatch e Combine, usando NVSHMEM. Na nosa entrada de blog anterior, detallamos a implementación, e os nosos kernels foron de código aberto en GitHub.

Paralelismo de datos

Con EP, podemos distribuír o cálculo de MoE entre 128 ou incluso máis GPUs. Con todo, o cálculo de MLA non se pode particionar con EP. Neste punto, podemos introducir o paralelismo de datos (DP). Cada grupo de DP ten unha copia completa da capa MLA. Cada grupo de DP acepta diferentes entradas e realiza o cálculo da capa MLA de forma independente.

O DP e o TP da capa MLA pódense combinar, dividindo un grupo de DP en varios rangos de TP. O EP da capa MoE pódese combinar co DP/TP da capa MLA. EP = DP * TP. Por exemplo, en 16 máquinas, EP128 DP32 TP4 significa distribuír expertos encamiñados entre 128 GPUs, con cada 4 GPUs formando un grupo de DP, para un total de 32 grupos de DP independentes.

Nodo único fronte a multinode

Os 671B parámetros de DeepSeek superan a capacidade de memoria dunha única máquina H100 de 8 GPUs (80 GB * 8), pero unha única máquina H200 de 8 GPUs pode acomodar por completo todo o modelo (141 GB * 8). Usando a configuración EP8 DP8 TP1, o modelo usa uns 100 GB de memoria por GPU, deixando aproximadamente 40 GB para a caché KV e outros resultados intermedios. Un token ocupa 70.272 bytes de caché KV. Asumindo que cada solicitude ten 5.000 tokens, cada GPU pode acomodar aproximadamente 100 solicitudes.

Queriamos comprender as diferenzas de rendemento entre as implementacións nun único nodo e multinode baixo diferentes configuracións. Usamos unha máquina H200 para a implementación nun único nodo e ata 16 máquinas H100 para as implementacións multinode. Para cada contorna de implementación, usamos combinacións de TP 1, 2, 4, 8 e tamaños de lote por GPU de 1, 2, 4, 8, 16, 32, 64, 128. Asumimos que cada solicitude tiña unha lonxitude de caché KV de 5.000 tokens. Tamén asumimos que a predición multitoken (MTP) predí 1 token adicional (é dicir, a lonxitude da consulta de cada solicitude é 2), e asumimos conservadoramente unha taxa de aceptación do 60%. A seguinte figura mostra a capacidade de procesamento e a velocidade de saída para diferentes configuracións.

Fronteiras de Pareto de latencia-rendemento para diferentes configuracións de paralelismo de expertos.

O eixe horizontal representa a velocidade de saída por solicitude en tokens/s. O eixe vertical usa unha escala logarítmica para mostrar a capacidade de procesamento por máquina en tokens/s. Marcamos a fronteira de Pareto para cada configuración de EP con liñas de diferentes cores.

En escenarios con requisitos de velocidade de saída extremadamente altos, o uso de EP8 DP1 TP8 nun único nodo cun tamaño de lote de 1 pode acadar unha velocidade de saída superior a 100 tokens/s, pero a capacidade de procesamento é extremadamente baixa, equivalente á velocidade de saída. Neste escenario, todo o lote ten só 2 tokens, que se poden enviar a un máximo de 2*8=16 expertos, activando un total de como máximo 57B parámetros.

No rango de velocidade de saída de 80-40 tokens/s, a medida que aumenta a capacidade de procesamento, a velocidade de saída diminúe significativamente. Pola contra, EP128 ten unha capacidade de procesamento un 5x maior que a implementación nun único nodo á mesma velocidade de saída.

Este fenómeno pódese explicar examinando como se comportan as implementacións nun único nodo: aumentar o tamaño do lote correlaciónase directamente cun aumento dos expertos activados. Cando o tamaño do lote é 1, o número medio de expertos activados por GPU é 2 * 8 / 8 = 2. Cando o lote é o suficientemente grande, todos os expertos están activados, o que significa que cada GPU activa 256 / 8 = 32 expertos. Activar máis expertos significa que a GPU necesita ler máis parámetros da memoria, o que aumenta significativamente a presión sobre o ancho de banda da memoria. Dado que a fase de descodificación dos modelos de linguaxe grandes xa ten un cuello de botella no ancho de banda da memoria en lugar de no rendemento de cálculo, aumentar o tamaño do lote na implementación nun único nodo reduce significativamente a velocidade de saída.

A comparación das catro configuracións de implementación multinode (EP16, EP32, EP64 e EP128) revela que os valores de EP máis altos desprazan a fronteira de Pareto cara a melloras simultáneas na capacidade de procesamento e na velocidade de saída.

Usar un número de EP máis alto significa que a cada GPU se lle asignan menos expertos. Por exemplo, EP128 significa que cada GPU é responsábel de 256 / 128 = 2 expertos, polo que a presión sobre o ancho de banda da memoria redúcese significativamente. Noutras palabras, ao usar un número de EP maior, gañamos efectivamente máis ancho de banda de memoria. Cando o tamaño do lote por GPU é inferior a 64, aumentar o tamaño do lote non afecta significativamente á velocidade de cálculo dos expertos porque aumentar o número de entradas non aumenta significativamente a presión sobre o ancho de banda da memoria. Polo tanto, observamos que ao usar EP128, aumentar o tamaño do lote non afecta á velocidade de saída de forma tan significativa.

Curiosamente, en tamaños de lote maiores (64 solicitudes por GPU), observamos un novo fenómeno: a capacidade de procesamento da implementación nun único nodo é lixeiramente superior á da implementación multinode. Parte da razón é que o NVLink intranodo ten un ancho de banda superior ao InfiniBand internodo. Outra parte débese a limitacións na nosa implementación. Analizaremos este fenómeno con máis detalle máis adiante.

Debido ás limitacións de capacidade de memoria, a configuración EP8 DP8 TP1 non pode acadar un tamaño de lote de 128 por GPU, polo que a implementación multinode segue a ser unha mellor opción en escenarios que buscan unha maior capacidade de procesamento.

Solapamento de cálculo e comunicación

Tal e como se introduciu brevemente anteriormente sobre o paralelismo de expertos, as GPUs están inactivas durante a comunicación da capa MoE. Para reducir o desperdicio e baixar a latencia, necesitamos atopar tarefas de cálculo independentes dos datos para encher este tempo de inactividade.

Programacións de computación e comunicación sen solapamento, con solapamento na distribución e cunha canalización de cinco etapas.

A parte superior da figura anterior mostra o fluxo de cálculo dunha capa. O cálculo de MoE depende de Dispatch, e o cálculo da seguinte capa depende do resultado de Combine.

Colocamos o experto compartido en cada GPU. Deste xeito, o cálculo do experto compartido non require comunicación AllToAll. Polo tanto, podemos realizar o cálculo do experto compartido inmediatamente despois de Dispatch Send, e despois agardar a que se complete Dispatch Recv. Chamamos a este esquema de solapamento "Dispatch Overlap".

Dispatch Overlap ofrece unha implementación directa e unha ampla aplicabilidade. Esta técnica agocha o tempo de cálculo do experto compartido en todos os tamaños de EP e tamaños de lote.

Para aumentar aínda máis o solapamento de cálculo e comunicación, utilizamos o microlote mencionado no informe técnico de DeepSeek para romper a dependencia dos datos. Como se mostra na parte inferior da figura, dividimos o cálculo dunha capa Transformer en 5 etapas:

Etapa 1: InputNorm, QKVProj, AppendKV, BMM

Etapa 2: BMM, Attn, OProj, PostNorm, Gate

Etapa 3: Dispatch Send, experto compartido

Etapa 4: Dispatch Recv, MoE, Combine Send

Etapa 5: Combine Recv

Nas primeiras 3 capas Transformer densas, usamos todo o lote. Nas seguintes 58 capas Transformer MoE, dividimos uniformemente o lote en dous microlotes. Os dous microlotes executaranse alternativamente, desfasados por 3 etapas. Dado que non hai dependencia de datos entre estes dous microlotes, podemos cambiar ao cálculo doutro microlote despois de Dispatch Send e despois de Combine Send.

Desglose da latencia

A continuación, comparamos os efectos do solapamento mediante un experimento, así como as diferenzas de rendemento entre a implementación nun único nodo EP8 e a implementación multinode EP128. Para facilitar a comparación, usamos GPUs H100 para o seguinte experimento. Usamos TP1, un tamaño de lote de 128 por GPU, unha lonxitude de consulta de 2 por solicitude e unha lonxitude de caché KV de 5000.

Latencia da capa por kernel nas configuracións de paralelismo de expertos e de solapamento comparadas.

A figura anterior mostra o tempo total gastado nunha capa Transformer MoE e a proporción de latencia de diferentes tipos de kernels. Agás para Dispatch, Combine e GroupGEMM, o tempo de execución doutros kernels debería ser o mesmo nas series EP8, EP128 NoOverlap e EP128 DispatchOverlap porque o tamaño do lote é o mesmo.

Solapamento

Imos comparar primeiro os efectos dos tres métodos de solapamento. NoOverlap tardou 2667 µs en total, DispatchOverlap tardou 2651 µs, o que aforra 16 µs ou só un 0,6%. MicroBatch mostrou unha mellora moi significativa, tardando 1896 µs, o que supón unha aceleración do 29%. Tanto o tempo de Dispatch como o de Combine reducíronse significativamente. Dispatch baixou de 593 µs a 367 µs, e Combine de 1012 µs a 237 µs.

Teña en conta que para os kernels de cálculo, dividir un lote de tamaño 128 en dous lotes de tamaño 64 aumenta o tempo total de execución. Polo tanto, aínda que o tempo dedicado á comunicación se reduciu en 1001 µs, o tempo total só se reduciu en 771 µs. Explicaremos a razón usando o modelo Roofline na seguinte sección.

Por este motivo, o uso de microlotes non sempre mellora o rendemento.

Cambios na velocidade de saída e no rendemento por nodo con microsegmentación, representados fronte ao tamaño do lote por GPU.

A figura anterior mostra a mellora do rendemento de Microbatch en comparación con DispatchOverlap para tamaños de lote de 4 a 128. Cando o tamaño do lote é inferior a 32, Microbatch diminúe o rendemento nun 5%-40%. Cando o tamaño do lote é maior ou igual a 32, Microbatch pode mellorar o rendemento nun 10%-35%.

EP8 fronte a EP128

Imos volver á figura anterior e comparar EP8 e EP128 Microbatch. EP8 tardou 1802 µs en total, lixeiramente menos que os 1896 µs de EP128. Ademais do aumento do tempo de execución do kernel aportado por Microbatch mencionado anteriormente, as principais diferenzas están en GroupGEMM, usado para o cálculo de MoE, e nos dous kernels de comunicación, Dispatch e Combine.

GroupGEMM de EP8 tardou 555 µs, mentres que o de EP128 tardou 270 µs, o que se reduce á metade. Esta é a vantaxe fundamental da implementación multinode.

Desafortunadamente, o tempo dedicado á comunicación aumentou en 213 µs, o que compensou en gran medida a vantaxe de GroupGEMM. En probas de rendemento separadas dos nosos kernels de comunicación, atopamos que só poden acadar a metade do ancho de banda de InfiniBand. Continuaremos optimizando os nosos kernels de comunicación.

Outro kernel que queda significativamente atrás é GEMM. Microbatch aumentou GEMM en 95 µs. Analizaremos GEMM con máis profundidade na sección Roofline a continuación. Consideramos que a implementación actual de GEMM aínda non acadou o rendemento óptimo.

Roofline

O modelo Roofline é unha boa ferramenta para analizar o rendemento dos kernels. O seu eixe horizontal é a intensidade aritmética, a relación entre FLOP e bytes de E/S de memoria. O valor do eixe horizontal pódese calcular directamente a partir da semántica do kernel. O eixe vertical representa o rendemento acadado, calculado dividindo FLOP entre a latencia de referencia.

O límite superior teórico do rendemento do kernel está determinado directamente polas especificacións da GPU. O rendemento máximo en FP8 da H100 é de 1979 TFLOP/s, representado como unha liña horizontal no modelo Roofline. O ancho de banda de memoria da H100 é de 3,35 TB/s, representado como a pendente dunha liña que pasa pola orixe. As dúas liñas dan os límites de rendemento para os kernels limitados polo cálculo e pola memoria, respectivamente.

A continuación, debatemos sobre o rendemento dos kernels GroupGEMM e GEMM.

GroupGEMM

O kernel GroupGEMM en MoE realiza o seguinte cálculo: hai un total de g grupos, o i-ésimo grupo ten m_i tokens, realizando unha multiplicación de matrices de [m_i, k] x [k, n] -> [m_i, n]. Nas probas de rendemento, asumimos que o número de tokens en cada grupo é o mesmo, denotado como m_i = m. Entón, o recuento de FLOP para GroupGEMM é 2 * g * m * k * n, e os bytes de E/S de memoria son g * (m * k + n * k + m * n).

No modelo DeepSeek-V3/R1, hai 256 expertos, e cada token envíase a 8 expertos para o seu cálculo. Asumindo un tamaño de lote de 128, unha lonxitude de consulta de 2 e usando a configuración EP128 DP128, o número medio de tokens recibidos por cada experto (é dicir, m) é 128 * 2 * 8 * 128 / 256 = 1024. De forma similar, podemos calcular m para outras configuracións e tamaños de lote.

Usamos a implementación de GroupGEMM de DeepGEMM para as probas de rendemento. Os puntos de proba cubriron combinacións de configuracións EP8, EP16, EP32, EP64, EP128 con TP1 e tamaños de lote de 1 a 128.

Rendemento de GroupGEMM en relación coas liñas de referencia de computación e de ancho de banda de memoria.

A figura anterior mostra o modelo Roofline para GroupGEMM baixo diferentes configuracións de EP. Diferentes EP corresponden a un número diferente de grupos. A figura ilustra liñas de rendemento case superpostas, o que indica que o rendemento de GroupGEMM está determinado predominantemente polo recuento total de tokens (representado como g * m).

As estrelas marcan os puntos de datos correspondentes a un tamaño de lote de 128 por GPU para cada configuración de EP. Comparando estes puntos de datos marcados, podemos ver que a medida que aumenta o EP (e o DP aumenta síncronamente), o número de tokens por experto m tamén aumenta. En EP8, m=128, mentres que en EP128, m=2048.

A medida que m aumenta, a intensidade aritmética tamén aumenta. Na maioría das configuracións, GroupGEMM está limitado polo ancho de banda da memoria, polo que aumentar m mellora o rendemento.

GEMM

O kernel GEMM corresponde ás proxeccións Linear no modelo, como a proxección Q/K/V/O. Para unha multiplicación de matrices de [m, k] x [k, n] -> [m, n], o recuento de FLOP é 2 * m * k * n, e os bytes de E/S de memoria son m * k + n * k + m * n. Tamén podemos probar a latencia para tamaños de lote de 1 a 128.

Rendemento de GEMM en relación coas liñas de referencia de computación e de ancho de banda de memoria.

A figura anterior mostra o modelo Roofline para GEMM baixo diferentes configuracións de EP. Podemos ver que o rendemento de GEMM está limitado polo ancho de banda de memoria. A medida que aumenta o tamaño do lote, a intensidade aritmética tamén aumenta, mellorando así o rendemento.

Microbatch

Cando usamos microlotes, dividimos o lote uniformemente en dúas partes. A partir das dúas figuras anteriores, podemos ver que cando m pasa a ser m/2, a eficiencia da multiplicación de matrices diminúe. Polo tanto, executar dúas multiplicacións de matrices de tamaño m/2 leva máis tempo que executar unha multiplicación de matrices de tamaño m.

Predición multitoken

Ao longo deste artigo, asumimos o uso da predición multitoken (MTP) para a descodificación especulativa. MTP cambia a lonxitude da consulta por solicitude de 1 a 2. Para a multiplicación de matrices, isto é equivalente a cambiar m a m * 2, aumentando así a eficiencia da multiplicación de matrices. Por outra banda, se debuxamos o modelo Roofline para MLA, atopariamos que aumentar a lonxitude da consulta aumenta significativamente a eficiencia do kernel MLA.

Polo tanto, o uso de MTP xoga un papel importante na eficiencia do modelo.

Implementación e optimizacións

Nosa sección, introduciremos algúns detalles de implementación e optimización para o noso modelo DeepSeek-V3/R1.

Cuantización

DeepSeek-V3/R1 foi adestrado de xeito nativo en FP8 usando un esquema de cuantización por bloque, con pesos cuantizados estaticamente e activacións cuantizadas sobre a marcha. En lugar de calcular un factor de escala por canle ou por matriz estaticamente, os factores de escala calcúlanse en vectores de 128 elementos para as activacións e mosaicos de 128x128 elementos para as matrices, o que limita a degradación da precisión debido á cuantización.

En Perplexity, baseámonos nunha mestura de kernels CUDA e Triton para admitir a inferencia; CUDA utilízase para os kernels máis sensibles ao rendemento e modificados con menos frecuencia (como a atención e GEMM), mentres que Triton implementa unha ampla gama de kernels de activación, normalización e utilidade. Triton permitiunos adaptar rapidamente os kernels ao esquema de cuantización por bloque.

Para as capas lineares e MoE, mesturamos os kernels de Deep GEMM cos nosos propios kernels de Triton GEMM, xa que notamos que para certas dimensións de matrices e tamaños de lote baixos, Split-K ofrece unha menor latencia. Se a capa non cuantizada realiza unha multiplicación (M, K) x (K, N), necesita un factor de escala (M x ceil_div(K, 128)) x (ceil_div(K, 128), ceil_div(N, 128)) para a cuantización por bloque. Para a cuantización por bloque, os factores de escala para as activacións calcúlanse sobre a marcha, en lugar de precalibrarse. Dado que os factores de escala de activación agrúpanse só ao longo da dimensión K e non ao longo da M, os kernels só requiren lixeiras alteracións para admitir o esquema.

Cálculo en lote de SiLU e multiplicación, amosando os tensores de entrada dos expertos, os tensores de saída e os factores de escala.

A función de activación SiLU utilizada por DeepSeek-V3/R1 requiriu cambios substanciais para admitir gráficos CUDA, cuantización por bloque e contaxes de tokens encamiñados dinamicamente. A cuantización por bloque pode ser problemática xa que introduce reducións horizontais, con todo o kernel xa fragmentaba as activacións ao longo da súa dimensión oculta en bloques de 1024 elementos. Dentro dun bloque, o tensor que se vai cuantizar fragmentábase aínda máis en bloques de 128 para calcular o valor absoluto máis grande, e Triton xeraba reducións máximas cruzadas entre warps eficientes, engadindo unha sobrecarga mínima.

Para admitir o encamiñamento de MoE baixo gráficos CUDA, os kernels deben coñecer a información de encamiñamento que indica o número de tokens por experto, en lugar de programar o traballo en función do tamaño dos búferes que foron asignados para conter o límite superior das contaxes de tokens. Non podemos dividir o problema en función das dimensións do tensor de entrada, polo que lanzamos un número fixo de kernels persistentes que leen a información de encamiñamento para determinar cantos tokens están poboados e dividen dinamicamente o traballo de procesamento das activacións entre eles.

Xa elevamos algúns dos nosos kernels ao proxecto FlashInfer e, no futuro, abriremos o código de máis partes do noso software.

Capa MLA

Usamos FlashInfer para o cálculo de MLA. FlashInfer admite configuracións de táboa de paxinas flexibles e un rendemento extremadamente alto.

Fusionamos q_a_proj e kv_a_proj nun único qkv_a_proj. A latencia reduciuse de 15,4 µs + 14,8 µs = 30,2 µs a 16,7 µs.

Descompoñemos kv_b_proj en dúas matrices, k_b_proj e v_b_proj. Escribimos un kernel BMM cuantizado por bloque en FP8 para os cálculos relacionados con estas dúas matrices.

Gráfico CUDA

O gráfico CUDA pode reducir significativamente a sobrecarga de lanzamento de kernels, o cal é crucial para o rendemento. Creamos un gráfico CUDA para cada tamaño de lote.

Antes de desenvolver o noso kernel AllToAll, usabamos torch.all_to_all_single() para a comunicación AllToAll. Esta operación require que todas as GPUs usen o mesmo tamaño de lote. Con todo, diferentes grupos de DP poden executar diferentes tamaños de lote.

Para garantir que all_to_all_single() sexa compatible con diferentes grupos de DP que usan diferentes tamaños de lote, usamos primeiro unha operación allreduce() antes de cada execución do modelo para obter o tamaño máximo de lote entre todos os grupos de DP. Despois fixemos que todos os grupos de DP usasen este tamaño de lote para executarse.

A pesar de que este enfoque garante que podemos usar o gráfico CUDA, ten tres desvantaxes. Primeiro, require unha operación allreduce() adicional. Segundo, os grupos de DP con tamaños de lote máis pequenos víñense obrigados a engadir recheo. Terceiro, fai que o noso código de implementación sexa complexo.

Despois de implementar o noso propio kernel AllToAll, xa non necesitamos que todas as GPUs usen o mesmo tamaño de lote. Polo tanto, xa non necesitamos realizar operacións allreduce() adicionais nin engadir recheo aos tamaños de lote.

Encamiñador MoE

O encamiñador MoE está implementado en Triton, baseándose nunha ordenación modificada derivada da biblioteca estándar que tamén fai un seguimento dos índices dos elementos ordenados. A implementación compártese en todos os modelos MoE, xa que o encamiñamento de Mixtral é un caso especial das rutas de DeepSeek onde o grupo Top-K é o mesmo que o grupo de todos os expertos. Os kernels escasos consumen os índices e puntuacións Top-K directamente, mentres que os esquemas densos de despacho/combinación que dependen de all-to-all requiren que a información de encamiñamento se agrupe por experto en lugar de por base de token.

Traballo futuro

No traballo futuro, planeamos optimizar aínda máis o rendemento do modelo DeepSeek.

A seguinte optimización máis importante é a desagrego de preenchimento (Prefill Disaggregation). As fases de preenchimento (Prefill) e descodificación (Decode) do modelo DeepSeek-V3/R1 teñen características de cálculo moi diferentes. Ambas poden usar diferentes estratexias de optimización e esquemas de implementación.

Para a capa MLA, na fase de descodificación, usamos a absorción de matrices para reducir o recuento de FLOP do cálculo de MLA. Na fase de preenchimento, proxectar primeiro o vector latente no espazo K/V e despois calcular en forma de atención multihead (MHA) funcionaría mellor.

Se o preenchimento e a descodificación se executan na mesma GPU, para reducir o impacto do preenchimento na velocidade de saída da descodificación, adoitamos usar preenchimento fragmentado (chunked prefill) para dividir a consulta en varios anacos para o preenchimento. Dado que a caché KV almacena o vector latente, convértese en difícil converter MLA en forma MHA.

Para a capa MoE, na fase de descodificación, usamos un EP e un DP o máis grandes posíbeis para aumentar o número de tokens de entrada por experto, mellorando así o rendemento de GroupGEMM. Na fase de preenchimento, debido a que o número de tokens xa é suficientemente grande, GroupGEMM xa está limitado polo cálculo. Polo tanto, para o preenchimento, podemos usar un EP e un DP máis pequenos.

Se o preenchimento e a descodificación se executan na mesma GPU, mentres calquera grupo de DP estea realizando o preenchimento, a latencia das capas MoE en todas as GPUs aumentará, afectando significativamente á velocidade de saída da descodificación.

Ademais da desagrego de preenchimento, tamén planeamos optimizar os seguintes aspectos:

Rendemento de AllToAll: O noso kernel AllToAll actualmente só pode acadar 1/3 do ancho de banda de InfiniBand. Continuaremos optimizando este kernel.

Descodificación especulativa ao estilo EAGLE: Nos datos anteriores, asumimos o uso de descodificación especulativa para predicir 1 token. EAGLE pode usar unha estrutura de árbore para predicir múltiples tokens, mellorando a lonxitude de aceptación, o que pode aumentar significativamente a velocidade de saída.

Kernel GEMM: No modelo Roofline mostrado anteriormente, podemos atopar que a eficiencia do kernel GEMM aínda está lonxe do límite teórico. Continuaremos optimizando este kernel.

GB200 NVL72: Na última solución GB200 NVL72 de NVIDIA, 72 GPUs Blackwell están interconectadas a través de NVLink de alta velocidade. Para os modelos de arquitectura MoE, isto é un reto e unha oportunidade moi grandes.

Conclusión

A implementación multinode dos modelos DeepSeek MoE consegue o que normalmente é imposíbel cos LLMs densos: mellorar simultaneamente tanto a capacidade de procesamento coma a latencia. Ao distribuír os expertos entre máis GPUs, reducimos a presión sobre o ancho de banda de memoria por dispositivo, o que permite un procesamento máis rápido e unha maior capacidade de procesamento do sistema. Os nosos experimentos mostran que as configuracións EP128 acadan unha capacidade de procesamento ata 5 veces maior a velocidades de saída equivalentes en comparación coas implementacións nun único nodo.

As técnicas de solapamento entre cálculo e comunicación, como os microlotes, reducen significativamente a sobrecarga de comunicación multinode, e a nosa implementación mostra unha aceleración de ata o 40%. Os nosos kernels de comunicación AllToAll personalizados e as implementacións de kernels optimizadas permitiron a implementación eficiente do modelo de 671B parámetros.

A medida que as arquitecturas MoE gañan popularidade pola súa capacidade, estas estratexias de implementación ofrecen información valiosa para escalar tales modelos de forma eficiente.

Referencias

Informe técnico de DeepSeek-V3

Visión xeral do sistema de inferencia de DeepSeek-V3/R1

Megatron-LM: Adestramento de modelos de linguaxe de miles de millóns de parámetros mediante paralelismo de modelos

EAGLE: A mostraxe especulativa require repensar a incerteza das características

Cita

BibTeX
@online{perplexity2025LowerLatencyAndHigherThroughputWithMultiNodeDeepseekDeployment,
  author = {{Perplexity} and Lequn Chen and Nandor Licker and Erin McKnight},
  title = {{Lower latency and higher throughput with multi-node DeepSeek deployment}},
  date = {2025-04-18},
  url = {https://perplexity.coolkeypoint.com/hub/blog/lower-latency-and-higher-throughput-with-multi-node-deepseek-deployment}
}