Complexidade de Encaminhamento em Redes de IA: ECMP, Encaminhamento Adaptativo, DCQCN e Porque os Profissionais de HPC São Obcecados por Isso

Os artigos anteriores percorreram cabos, NICs, switches e topologias. Este é sobre o que acontece acima disso: como os pacotes encontram caminho através de uma malha com vários switches e o que impede essa malha de colapsar quando dez mil GPUs decidem fazer all-reduce no mesmo instante.

O tráfego de IA é fundamentalmente diferente do de um centro de dados normal. Um frontend web envia milhões de pequenas ligações TCP. Um treino de IA envia alguns fluxos enormes e perfeitamente sincronizados para destinos conhecidos, e todos esperam pelo mais lento. As técnicas que funcionam no primeiro caso desfazem-se no segundo.

Aviso desde já: a maioria dos clientes da Kentino opera clusters de 1 a 4 nós. A essa escala, nenhum destes problemas morde de facto. Ligue quatro nós com um único switch de 100 GbE (ou sem switch — ver N05), use RoCE simples com os valores por omissão e nunca pense em ECMP ou DCQCN. Escrevemos isto na mesma porque (a) é um pano de fundo útil para decisões de dimensionamento e (b) no dia em que passar de quatro nós para dezasseis, tudo isto passa subitamente a importar.

O que é o ECMP e porque chegou até à era da IA

ECMP — Equal-Cost Multi-Path — é o truque de encaminhamento que faz funcionar as malhas leaf-spine e fat-tree. Quando existem vários caminhos de custo igual do leaf A para o leaf B (através dos spines S1..S4), o switch calcula um hash sobre campos do pacote e usa-o para escolher um spine. O hash clássico de 5 tuplos é (src IP, dst IP, src port, dst port, protocol).

Para cargas de trabalho cloud tradicionais — milhões de ligações TCP de curta duração — o ECMP funciona lindamente. A lei dos grandes números faz o balanceamento por si. Com 10,000 fluxos e 8 spines fica a poucos pontos percentuais do equilíbrio perfeito.

Tráfego web — o ECMP funciona
  • Mais de 10 000 fluxos TCP de curta duração
  • A lei dos grandes números equilibra os spines
  • Distribuição de carga quase perfeita
  • Colisão de hash ECMP: rara
Treino de IA — o ECMP falha
  • 8 fluxos elefante, todos em simultâneo
  • O hash de 5 tuplos manda vários fluxos para o mesmo spine
  • Spine saturado = all-reduce a meia velocidade
  • Probabilidade de colisão: ~97% com 8 fluxos/8 spines

O ECMP foi concebido para muitos fluxos pequenos. O treino de IA envia alguns fluxos enormes e sincronizados — o equilíbrio estatístico deixa de funcionar.

O problema dos fluxos elefante

O treino de IA é o oposto do tráfego web. Um passo de treino: cada GPU calcula um gradiente, cada GPU envia o seu gradiente a todas as outras (all-reduce), todas esperam pela transferência mais lenta e repete-se.

O all-reduce é um número reduzido de fluxos muito grandes. Um ring-allreduce em 8 nós com NICs de 200 Gbps são 8 fluxos em simultâneo, cada um com vários gigabytes, todos à velocidade da linha, todos a começar no mesmo instante. O artigo da Meta sobre RoCE à escala documenta-o com clareza: nos clusters de IA, um número ínfimo de fluxos «elefante» representa quase todos os bytes e todos querem a rede ao mesmo tempo.

O hash de 5 tuplos do ECMP detesta isto. Com N fluxos elefante em S caminhos, a probabilidade de não haver colisões é S! / ((S-N)! · S^N). Para 8 fluxos em 8 spines: cerca de 2.4%. Mesmo 32 spines para 8 fluxos chegam apenas a ~33%. Acrescentar spines não altera o lançamento da moeda — dá-lhe mais ligações vazias enquanto dois fluxos disputam uma só.

Uma colisão sobrecarrega a ligação ao spine na proporção 2:1, os fluxos afetados correm a metade da velocidade e, como o passo espera pelo fluxo mais lento, a iteração corre a metade da velocidade. Medições em clusters de produção reportam perdas de desempenho até 40% no all-reduce devido a colisões de ECMP.

Contornar o problema: hashing melhorado, balanceamento ao nível do pacote, encaminhamento adaptativo

Quatro respostas reais, por ordem crescente de dificuldade de implementação:

1. Melhor hashing (E-ECMP, com conhecimento das QP). A correção mais barata. O hashing clássico de 5 tuplos concentra o tráfego RDMA num único tuplo por par de QP — um fluxo de all-reduce é mesmo um único balde ECMP. Faça o hash incluir também o número da QP de destino RoCE e leve a aplicação a espalhar o tráfego por muitas QPs («QP scaling»). Os números da Meta: até 40% de melhoria no all-reduce. Continua a ser estatístico — as colisões ficam mais raras, não desaparecem.

2. Flowlet switching. Deteta um intervalo sem tráfego e volta a calcular o hash a partir daí. Funciona para TCP, mal para RoCE contínuo.

3. Balanceamento ao nível do pacote / packet spraying. Hash por pacote, aceitando reordenação, com a NIC a reconstruir a ordem. Elimina o problema dos fluxos elefante, mas exige cooperação entre NIC e switch. É o que faz o NVIDIA Spectrum-X — spraying por pacote com reordenação por hardware na SuperNIC.

4. Encaminhamento adaptativo. O switch acompanha o congestionamento por porta e escolhe o caminho de custo igual menos carregado no momento da comutação, em vez de fazer hash às cegas. Combinado com packet spraying, é o que o InfiniBand tem há quinze anos. Trazê-lo para Ethernet é a grande novidade do NVIDIA Spectrum-X (ASICs Spectrum-4/5 + SuperNICs BlueField ou ConnectX-8); do Cisco Silicon One G200/P200; e do Broadcom Tomahawk 5 / Jericho 3-AI com malha escalonada baseada em células.

Para clusters de 1 a 8 nós, o encaminhamento adaptativo é exagero. Para tarefas de 64 ou mais GPUs a escalar até 1,000 GPUs, é a diferença entre «o estrangulamento é a rede» e «o estrangulamento são as GPUs». É por isso que todos os fornecedores sérios de Ethernet para IA construíram ou licenciaram silício de encaminhamento adaptativo entre 2024 e 2026.

Controlo de congestionamento: porque é que «basta não descartar pacotes» não sai de graça

A outra metade da complexidade do encaminhamento é o que acontece quando chega tráfego a mais a uma porta de switch ao mesmo tempo. Duas opções: uma rede com perdas descarta pacotes e as extremidades recuam (a Internet aberta); uma rede sem perdas pressiona o switch a montante para que faça uma pausa — não há descartes, mas o congestionamento propaga-se para trás.

Historicamente, o RoCE exige uma malha sem perdas. As NICs RDMA lidam mal com a perda de pacotes — um único pacote descartado despoleta a retransmissão go-back-N de toda a mensagem, o que a 100 GbE significa reenviar megabytes. RoCEv2 com go-back-N é essencialmente inutilizável numa rede com perdas em utilização elevada.

PFC — Priority Flow Control (IEEE 802.1Qbb) é o que faz a Ethernet comportar-se sem perdas. Quando a fila de saída de uma prioridade num switch ultrapassa um limiar, este envia uma trama PAUSE a montante a pedir ao emissor que pare de transmitir essa prioridade. Oito prioridades, oito sinais independentes de parar/seguir.

Bloqueio de cabeça de fila e fluxos vítima

As pausas PFC são grosseiras. Uma pausa diz «pare de enviar a prioridade 3 nesta ligação» — não sabe que fluxo causou o congestionamento. Se dez fluxos partilharem a prioridade 3 e um deles estiver congestionado a jusante, o PFC pausa os dez. Os outros nove «fluxos vítima» são castigados por um problema alheio. Isto é o bloqueio de cabeça de fila, a dor central da Ethernet sem perdas à escala.

A B C Leaf 1 pausa PFC ← trunk Leaf 2 X congestionado Y normal fluxo pesado A→X PFC pausa TODA a prio 3 B,C → Y também bloqueados

Bloqueio de cabeça de fila: A→X provoca PFC no trunk. B e C, que falam com Y (que está bem), são também pausados — são fluxos vítima.

Impasse de PFC: se a topologia e o tráfego formarem uma dependência cíclica de ligações pausadas — A espera por B, B por C, C por A — toda a malha bloqueia. Já foi observado em produção. Os switches modernos têm deteção de impasses; as topologias Clos modernas são imunes a impasses por construção; mas qualquer instalação RoCE séria tem, ainda assim, um plano de recuperação.

O objetivo do controlo de congestionamento moderno para IA é manter os buffers suficientemente pequenos para que o PFC nunca dispare em regime permanente. O PFC fica armado como rede de segurança para microrrajadas genuínas. O mecanismo que o impede de disparar é o DCQCN.

DCQCN — o controlo de congestionamento padrão para RoCEv2

O DCQCN (DataCenter Quantized Congestion Notification) é o algoritmo em que o RoCE sem perdas convergiu. Desenvolvido pela Microsoft e pela Mellanox (SIGCOMM 2015). Em 2025–2026 é o que as NICs ConnectX/BlueField da NVIDIA executam por omissão e o que a Azure reporta como padrão de produção em «~85% do tráfego Azure, RDMA, em todas as regiões públicas».

O DCQCN tem três papéis: o CP (Congestion Point) é o switch, que marca pacotes com ECN quando a profundidade da fila de saída ultrapassa um limiar (de forma probabilística, de 0% em Kmin até Pmax em Kmax); o NP (Notification Point) é a NIC recetora, que gera um CNP (Congestion Notification Packet) de volta para o emissor quando há marcas ECN (com taxa limitada, tipicamente um por 50 µs por fluxo); o RP (Reaction Point) é a NIC emissora, que reduz multiplicativamente o débito da QP ao receber um CNP e o aumenta aditivamente (depois hiperaditivamente) na ausência deles.

Configuração típica de switch para DCQCN em 100 GbE:

# Perfil ECN ao estilo NVIDIA Cumulus na prioridade RoCE sem perdas (prioridade 3)
interface swp1..swp32
  qos remark dscp-to-tc 26 to 3       # DSCP 26 → TC 3
  qos congestion-mark ecn priority 3
  qos ecn-kmin       5KB              # início da marcação
  qos ecn-kmax     200KB              # marcação em Pmax
  qos ecn-pmax       1%
  qos pfc priority 3
  qos pfc xoff     400KB              # pausa PFC (bem acima de Kmax)
  qos pfc xon      300KB

Kmin/Kmax/Pmax é o trio mais afinado em RoCE. Kmin pequeno (alguns pacotes), para que o ECN entre em ação antes de o buffer se esgotar; Kmax bastante maior, para que a marcação suba gradualmente; o limiar de pausa do PFC bem acima de Kmax, para que o PFC só dispare se o DCQCN tiver sido demasiado lento. A instalação original da Microsoft: Kmin = 5 KB, Kmax = 200 KB, Pmax = 1%.

Fraquezas conhecidas do DCQCN: colapso por incast (100 emissores atingem um recetor, a fila enche mais depressa do que os CNPs conseguem propagar-se de volta e o PFC dispara — o DCQCN+ responde a isto); injustiça de cauda longa (os fluxos que arrancam mais tarde ficam estrangulados durante mais tempo); sensibilidade aos parâmetros (um Kmin afinado para 4 nós não se generaliza a 64). Resumo honesto: o DCQCN é o valor por omissão porque funciona na maior parte do tempo. HPCC, Swift, EQDS e um TIMELY ressuscitado existem como propostas de substituição, mas nenhum o destronou até 2026.

ECN, DCTCP e onde encaixa o TCP puro

Uma separação clara, porque estes conceitos são frequentemente confundidos:

  • ECN — mecanismo da camada IP (RFC 3168) em que os switches marcam em vez de descartar. É um sinal, não reage nada por si.
  • DCQCN — a reação do ponto terminal RDMA. Lê o ECN através dos CNPs e ajusta o débito.
  • DCTCP — a reação do ponto terminal TCP. Lê o ECN nos ACKs e escala a janela pela fração de pacotes marcados. Microsoft + Stanford, SIGCOMM 2010, presente no Windows Server e no Linux.
Tráfego Protocolo Controlo de congestionamento
Gradiente GPU a GPU (all-reduce, NCCL sobre RoCE) RoCEv2 DCQCN (ECN + CNP + débito)
Armazenamento (NFS/RDMA, BeeGFS sobre RDMA) RoCEv2 DCQCN
Armazenamento (NFS sobre TCP, S3 para object store) TCP DCTCP (ou BBR, ou CUBIC)
Kubernetes / orquestração / plano de controlo TCP CUBIC por omissão, DCTCP se afinado
Telemetria / Prometheus / SSH TCP CUBIC

Se opera uma malha puramente RoCE, está a usar DCQCN — conheça os seus valores por omissão. Se tiver também armazenamento e controlo em TCP no mesmo cabo, vale a pena ativar o DCTCP (net.ipv4.tcp_ecn = 1 mais switches com suporte de ECN).

Porque é que o tráfego de IA pressiona tudo isto mais do que um centro de dados tradicional

Três propriedades para as quais o controlo de congestionamento clássico não foi desenhado:

  1. Rajadas sincronizadas. Todas as GPUs começam o all-reduce no mesmo nanossegundo. De zero a 100% de utilização em microssegundos. Não há aquecimento que permita ao slow-start encontrar o débito. O DCQCN arranca à velocidade da linha exatamente por esta razão.
  2. Poucos fluxos, muito grandes. A lei dos grandes números não o salva. 8 fluxos → colisões ECMP frequentes; 8 recetores → bloqueio de cabeça de fila grave por PFC.
  3. O caminho crítico é a ligação mais lenta. O tempo de um passo de all-reduce = tempo de conclusão do fluxo mais lento. Não há «caso médio». Uma probabilidade de 1% de uma colisão má acumula-se ao longo de meses de treino.

É por isto que as pessoas de HPC e de IA são obcecadas com redes de uma forma que os operadores à escala web historicamente não foram. A web é elástica — os pedidos lentos demoram um pouco mais para alguns utilizadores. O treino de IA não é: todo o trabalho corre à velocidade do seu componente sincronizado mais lento.

A complexidade sem switch (antevisão do N05)

O N05 trata de topologias sem switch — ligação direta, malha, anel, toro 2D/3D, tesserato — para clusters pequenos em que comprar um switch de 100 GbE é exagero. Quando se retira o switch, cada nó passa a ser um router: várias NICs, vários caminhos, e alguém tem de escolher o salto seguinte.

A resposta padrão em 2026 é o FRR (FRRouting) em cada nó, configurado com BGP unnumbered. O BGP unnumbered usa endereços IPv6 link-local para o peering, pelo que não é preciso atribuir endereços IPv4 em cada ligação. Cada nó anuncia o seu loopback, aprende os loopbacks dos vizinhos e a tabela de encaminhamento do Linux escolhe o salto seguinte certo.

# Configuração FRR mínima para um nó numa malha sem switch:
router bgp 65001
  bgp router-id 10.0.0.1
  neighbor enp1s0 interface remote-as external
  neighbor enp2s0 interface remote-as external
  neighbor enp3s0 interface remote-as external
  address-family ipv4 unicast
    network 10.0.0.1/32         # loopback deste nó
    redistribute connected
  exit-address-family

Doze linhas por nó e ECMP por tantos pares de NIC quantos o nó tiver — com as mesmas ressalvas do ECMP nos switches. Numa malha de 4 nós, as colisões ECMP aparecem também do lado do host. Mitigue com mais QPs ou aceite a perda (pequena com 4 nós). «Sem switch» não quer dizer «sem complexidade de encaminhamento» — apenas a desloca para os hosts.

Quando é que isto lhe interessa

A maioria dos leitores não precisará de fazer nada disto.

  • 1 a 4 nós, um switch, RoCE para armazenamento e treino multi-GPU ocasional: deixe o switch nos valores por omissão. O DCQCN e os limiares de ECN de origem servem. O PFC está ativo e provavelmente nunca o verá pausar. As colisões ECMP são reais, mas o impacto num treino de 4 nós fica numa percentagem de um dígito.
  • 4 a 16 nós, cluster de treino dedicado: ative o DCQCN explicitamente, defina Kmin/Kmax/Pmax em 5 KB / 200 KB / 1% (a referência da Azure), ligue o QP scaling no NCCL e monitorize os contadores de pausas PFC e as taxas de CNP. Se as pausas PFC estiverem a aumentar, o DCQCN não está suficientemente agressivo — baixe o Kmin.
  • 16 ou mais nós, ou mais de 1,000 GPUs: o encaminhamento adaptativo paga-se a si próprio. Compre Spectrum-X com SuperNICs correspondentes, ou InfiniBand e deixe de se preocupar com ECMP, ou associe-se a quem já operou uma malha desta dimensão. O custo de errar são meses de tempo de treino.
  • Cluster sem switch, de qualquer dimensão: FRR + BGP unnumbered. 1 a 2 dias de configuração e testes por cada duplicação do número de nós. A grande armadilha é esquecer o ECMP do lado do kernel (net.ipv4.fib_multipath_hash_policy = 1 para hashing ao nível L4).

O instinto «compro mais largura de banda para nunca haver congestionamento» está errado. O tráfego de IA sincronizado cria procura instantânea à velocidade da linha em todos os caminhos, por muitos spines que existam. A largura de banda resolve problemas de débito, não problemas de coordenação.

O que fazer a seguir

Se algo disto puder afetar o seu cluster:

  1. Inventarie o seu tráfego. RoCE? TCP? Que ligações transportam ambos? Não é possível afinar o DCQCN sem saber que fluxos beneficiam.
  2. Leia os valores de origem de DCQCN/ECN/PFC do seu switch. Os perfis «otimizados para IA» dos fabricantes variam muito. Alguns vêm com o PFC desativado. Outros usam Kmin = velocidade da porta × 5 µs — uma heurística sensata, nem sempre acertada.
  3. Ative os contadores. Pausas PFC RX/TX, CNP RX/TX, marcas ECN, utilização ECMP por ligação. Sem isto, não é possível saber se a malha está saudável sob carga.
  4. Meça com uma carga de trabalho real. O nccl-tests/all_reduce_perf diz-lhe mais em cinco minutos do que uma semana de iperf sintético.
  5. Decida se tem um problema de colisões ECMP antes de gastar dinheiro em encaminhamento adaptativo. A maioria dos clusters de 1 a 16 nós não tem; a maioria dos de 64 ou mais nós tem.

O N08 trata da configuração efetiva de RDMA — índices GID, MTU, variáveis de ambiente do NCCL e a afinação de mlx5_core por NIC que transforma uma ligação RoCE funcional numa ligação rápida. É aí que esta teoria se converte em comandos que se escrevem.


Este texto faz parte da Kentino Wiki, uma série de referência sobre computação de IA, robótica e os sistemas que os ligam. Comentários e correções são bem-vindos em info@kentino.com.