...

Servidor de balanceamento NUMA: Otimização do acesso à memória para hardware de alojamento

Eu mostro como Servidor de balanceamento NUMA no hardware de alojamento simplifica o acesso à memória e reduz as latências, associando processos e dados ao nó NUMA adequado. O fator decisivo é o Otimização do acesso à memória através de acesso local, colocação de tarefas e migração de páginas direcionada para anfitriões Linux com muitos núcleos.

Pontos centrais

  • NUMA separa as CPUs e a memória em nós; os acessos locais fornecem baixo Latência.
  • Automático O balanceamento NUMA migra páginas e coloca tarefas perto do nó.
  • Tamanho da VM por nó, caso contrário existe um risco Eliminação de NUMA.
  • Ferramentas como numactl, lscpu, numad show Topologia e usar.
  • AfinaçãoC-States, Node Interleaving de, Páginas enormes, afinidades.

O que é o NUMA - e porque é importante para o alojamento

O NUMA divide um sistema multiprocessador em , que contêm cada uma as suas próprias CPUs e memória local, tornando os acessos próximos mais rápidos do que os remotos. Enquanto a UMA envia todos os núcleos para um caminho comum, a NUMA evita estrangulamentos devido a local canais de memória por nó. Em ambientes de alojamento com muitas VMs paralelas, cada milissegundo de latência é adicionado, pelo que cada pedido beneficia de forma mensurável. Se pretender obter mais informações de base, pode obter mais informações sobre Arquitetura NUMA. Para mim, uma coisa é certa: se compreender e utilizar os nós, obtém mais largura de banda com o mesmo hardware.

Balanceamento automático de NUMA no kernel Linux - como funciona

O kernel examina periodicamente partes do espaço de endereço e „desmapeia“ páginas para que uma falha de sugestão possa ótimo nó visível. Se a falha ocorrer, o algoritmo avalia se vale a pena migrar a página ou mover a tarefa e evita movimentos desnecessários. Migrar em caso de falha traz Dados mais perto da CPU em execução, a colocação de tarefas NUMA move os processos para mais perto da sua memória. O scanner distribui seu trabalho peça por peça para que a sobrecarga permaneça dentro do ruído da carga normal. Isso resulta em um ajuste fino contínuo que reduz a latência sem exigir regras rígidas de fixação.

Otimização do acesso à memória: local bate remoto

Os acessos locais utilizam o Controlador de memória do seu próprio nó e minimiza os tempos de espera para a interligação. Os acessos remotos custam ciclos através de QPI/UPI ou Infinity Fabric e minimizam assim o tempo de acesso efetivo. Largura de banda. Os números elevados de núcleos exacerbam este efeito porque cada vez mais núcleos estão a competir pelas mesmas ligações. Por isso, planeio de forma a que o código quente e os dados activos se encontrem num único nó. Se ignorarmos isto, perdemos pontos percentuais que determinam o tempo de resposta ou o tempo limite durante os picos de carga.

Tamanhos de VM, eliminação de NUMA e corte de anfitriões

Dimensiono as VMs de modo que as vCPUs e a RAM caibam em um nó NUMA para evitar o acesso entre nós. Muitas vezes, 4-8 vCPUs por nó proporcionam um bom desempenho. Taxas de acerto, dependendo da plataforma e da hierarquia da cache. Páginas enormes também ajudam porque o TLB funciona de forma mais eficiente e as migrações de página ocorrem com menos frequência. Se necessário, defino Afinidade com a CPU para que os processos críticos em termos de latência associem as threads aos núcleos adequados - para mais informações, consulte Afinidade com a CPU. Se as VMs forem distribuídas por vários nós, corre-se o risco de uma destruição NUMA, ou seja, um ping-pong de dados e threads.

Ferramentas na prática: numactl, lscpu, numad

Com „lscpu“ leio Topologia e os nós NUMA, incluindo a atribuição dos núcleos. „numactl -hardware“ mostra-me a memória por nó e as distâncias disponíveis, o que facilita a avaliação dos caminhos. O daemon „numad“ monitora a utilização e ajusta dinamicamente as afinidades quando os centros de carga se movem. Para cenários fixos, eu uso „numactl -cpunodebind/-membind“ para fixar explicitamente processos e memória. Desta forma, combino o balanceamento automático com especificações específicas e controlo o resultado através de „perf“, „numastat“ e „/proc“.

Como meço o impacto: Números-chave e comandos

Avalio sempre o NUMA-Tuning através de Série de medições, e não por intuição. Três indicadores provaram o seu valor: Rácio de visualizações de páginas locais e remotas, taxa de migração e distribuição da latência (P95/P99).

  • Em todo o sistemanumastat„ mostra os acessos locais/remotos e as páginas migradas por nó.
  • Relacionadas com o processo: „/proc//numa_maps“ revela onde a memória está localizada e como foi distribuída.
  • Vista do programadorCpus_allowed_list„ e “Cpus_allowed„ real verificam se as ligações se aplicam.
# Vista de todo o sistema
numastat
numastat -m

# Distribuição e ligações relacionadas com o processo
pid=$(pidof )
numastat -p "$pid"
cat /proc/"$pid"/numa_maps | head
cat /proc/"$pid"/status | grep -E 'Cpus_allowed_list|Mems_allowed_list'
taskset -cp "$pid"

# Contador do kernel para atividade NUMA
grep -E 'numa|migrate' /proc/vmstat

# Eventos de rastreio para análises profundas (ativar por um curto período de tempo)
echo 1 > /sys/kernel/debug/tracing/events/mm/enable
sleep 5; cat /sys/kernel/debug/tracing/trace | grep -i numa; echo 0 > /sys/kernel/debug/tracing/events/mm/enable

Comparo em cada caso A/BO objetivo é reduzir claramente o ruído dos acessos remotos e das migrações, bem como reduzir as latências P95/P99. O objetivo é uma clara redução dos acessos remotos e do ruído de migração, bem como latências P95/P99 mais apertadas. Só quando os valores medidos estiverem a melhorar de forma estável é que eu assumo o controlo da afinação.

Definições de BIOS e firmware que realmente funcionam

Desligo o „Node Interleaving“ na BIOS para que a estrutura NUMA permaneça visível e o kernel local pode planear. Os estados C reduzidos estabilizam os picos de latência porque os núcleos têm menos probabilidades de cair em estados de sono profundo, o que poupa tempo de despertar. Atribuo canais de memória simetricamente para que cada nó possa utilizar a sua capacidade máxima de memória. Largura de banda alcançado. Testo os prefetchers e as funcionalidades RAS com perfis de carga de trabalho, uma vez que ajudam ou prejudicam consoante o padrão de acesso. Meço todas as alterações em relação a uma linha de base e só depois é que as adopto permanentemente.

Parâmetros do kernel e do sysctl que fazem a diferença

O ajuste fino do kernel ajuda-me, Despesas gerais e Tempo de resposta do balanceador para corresponder à carga de trabalho. Começo com predefinições conservadoras e vou avançando passo a passo.

  • kernel.numa_balancingLigar/desligar o equilíbrio automático. Deixo-o ligado para cargas móveis; desligo-o para serviços especiais estritamente fixados como um teste.
  • kernel.numa_balancing_scan_delay_msTempo de espera antes da primeira análise após a criação do processo. Selecione maior se estiverem em execução muitas tarefas de curta duração; menor para serviços de longa duração que exijam uma proximidade rápida.
  • kernel.numa_balancing_scan_period_min_ms / _max_msLargura de banda dos intervalos de pesquisa. Os intervalos estreitos aumentam a capacidade de resposta, mas também a carga da CPU.
  • kernel.numa_balancing_scan_size_mbProporção do espaço de endereçamento por varrimento. Demasiado grande gera tempestades de falhas, demasiado pequeno reage com lentidão.
  • vm.zone_reclaim_modeQuando a memória é escassa, o kernel prefere a recuperação local em vez da alocação remota. Para cargas de trabalho gerais de hospedagem, eu normalmente deixo 0; Para serviços de memória local estritamente sensíveis à latência, testo cuidadosamente valores mais elevados.
  • Páginas enormes transparentes (THP)Em „/sys/kernel/mm/transparent_hugepage/{enabled,defrag}“, normalmente defino para enlouquecer e desfragmentação conservadora. Os perfis rígidos „sempre“ trazem vantagens para a TLB, mas correm o risco de ficarem parados devido à compactação.
  • sched_migration_cost_nsEstimativa do custo da migração de tarefas. Valores mais elevados atenuam a redistribuição de agendadores agressivos.
  • cgroups cpusetCom cpuset.cpus e cpuset.mems Separo os serviços de forma limpa por nó e certifico-me de que Primeiro toque permanece dentro dos nós admissíveis.
# Exemplo: balanceamento conservador mas reativo
sysctl -w kernel.numa_balancing=1
sysctl -w kernel.numa_balancing_scan_delay_ms=30000
sysctl -w kernel.numa_balancing_scan_period_min_ms=60000
sysctl -w kernel.numa_balancing_scan_period_max_ms=300000
sysctl -w kernel.numa_balancing_scan_size_mb=256

# Use o THP com cuidado
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
echo defer > /sys/kernel/mm/transparent_hugepage/defrag

Continua a ser importante: Alterar apenas um parafuso de ajuste por ronda de teste e testar o efeito contra a mesma curva de carga. É assim que eu separo a causa do efeito.

Posicionar corretamente as cargas de trabalho: Bases de dados, caches, contentores

As bases de dados beneficiam quando os pools de buffers permanecem locais por nó NUMA e as threads estão ligadas perto dos seus heaps. Nas caches na memória, defino a fragmentação para para evitar buscas remotas. As plataformas de contentores recebem limites e pedidos para que os pods não saltem entre nós. Para reservas de memória, eu uso Huge Pages, o que facilita o armazenamento de hotsets em Caches ajuste. O quadro seguinte resume as estratégias e os efeitos típicos de forma compacta.

Estratégia Utilização Efeito esperado Nota
Primeiro toque Bases de dados, heaps da JVM Atribuição da parte local Executar a inicialização no nó de destino
Intercalar Carga amplamente distribuída Distribuição homogénea Não é ideal para hotspots
Fixação de tarefas Serviços críticos em termos de latência Latência constante Menos flexível durante as mudanças de carga
Equilíbrio automático Cargas de trabalho mistas Proximidade dinâmica Ponderação das despesas gerais em relação ao lucro
Páginas enormes Grandes pilhas, caches Menos faltas de TLB Planear reservas limpas

Virtualização: NUMA virtual, agendador e personalização de convidados

O Virtual NUMA passa a topologia do anfitrião para o SO convidado de uma forma simplificada, para que o primeiro toque e a Alocador funcionam de forma sensata. Os agendadores do hipervisor prestam atenção à proximidade do nó ao distribuir vCPUs e migrar VMs. Raramente alinho VMs grandes em vários nós, a menos que a carga de trabalho tenha um grande fluxo e se beneficie da intercalação. No convidado, eu personalizo os heaps de JVMs ou bancos de dados para que eles permaneçam locais em nós NUMA visíveis. Para o gerenciamento de memória no convidado, uma olhada em Memória virtual, para controlar o tamanho das páginas e a troca de ficheiros.

Proximidade do PCIe: NVMe e NICs nos nós certos

Se possível, atribuo SSDs NVMe e NICs rápidas ao nó no qual o Carga de trabalho está em execução. Isso evita que as solicitações de E/S cruzem a interconexão e adicionem latência. Eu vinculo NICs de filas múltiplas a conjuntos de núcleos de um nó com RSS/RPS para que os IRQs permaneçam locais. Para pilhas de armazenamento, vale a pena dividir os pools de threads nó a nó. Se prestar atenção a isso, reduzirá visivelmente as latências do P99 e criará espaço para picos de carga.

IRQ e afinidade de fila na prática

Em primeiro lugar, verifico que Nó NUMA dispositivos e fixar IRQs e filas de forma adequada. Isto assegura a manutenção da localidade do caminho de dados.

# Mapeamento de dispositivo para nó
cat /sys/class/net/eth0/device/numa_node
cat /sys/block/nvme0n1/device/numa_node

# Definir afinidade de IRQ especificamente (exemplo: núcleos 0-7 de um nó)
irq=
echo 0-7 > /proc/irq/$irq/smp_affinity_list

# Ligar filas de NICs a núcleos (RPS/RFS)
for q in /sys/class/net/eth0/queues/rx-*; do echo 0-7 > "$q"/rps_cpus; done
sysctl -w net.core.rps_sock_flow_entries=32768
for q in /sys/class/net/eth0/queues/rx-*; do echo 4096 > "$q"/rps_flow_cnt; done

# Melhorar a afinidade da fila NVMe
echo 2 > /sys/block/nvme0n1/queue/rq_affinity
cat /sys/block/nvme0n1/queue/scheduler # "none" preferred

„Executo o “irqbalance" com conhecimento do nó ou defino-o para Exceções para interrupções de hot-path. O resultado são latências mais estáveis, menos saltos de IRQ entre nós e um aumento mensurável nos acessos de E/S locais.

Ligação estática vs. equilíbrio dinâmico - o meio-termo

Utilizo „taskset“ e cgroups para definir regras rígidas quando deterministas Latência conta. Deixo o balanceamento automático de NUMA ativo quando a carga se move e preciso de proximidade adaptativa. Uma mistura geralmente funciona melhor: pinos rígidos para hotpaths, limites mais abertos para trabalho auxiliar. Verifico regularmente se as migrações estão a aumentar visivelmente, pois isso indica um mau planeamento. O objetivo continua a ser escolher as localizações dos dados e dos segmentos de forma a que a migração seja rara mas possível.

NUMA em contentores e Kubernetes

Trago um contentor cpusets e Páginas enormes em linha. Eu atribuo pods/contêineres a um nó NUMA armazenando quantidades consistentes de CPU e memória. Nas orquestrações, defino políticas que favorecem atribuições de nó único e, portanto, respeitam o primeiro toque.

  • Tempo de execução do contentor„-cpuset-cpus“ e „-cpuset-mems“ mantêm as tarefas e a memória juntas; atribui páginas enormes como recursos.
  • Gestor de topologia/CPUAs atribuições estritas ou preferenciais garantem a atribuição de núcleos e áreas de memória relacionados.
  • QoS garantidaOs pedidos/limites fixos minimizam a redistribuição pelo programador.

Eu deliberadamente dividi sidecars e processos auxiliares para outros núcleos dentro de do mesmo nó para que o hotpath não seja perturbado mas não entre na corrida entre nós.

Compreender as topologias de CPU: CCD/CCX, SNC e Cluster-on-Die

As CPUs de servidor actuais dividem as tomadas em Subdomínios com as suas próprias caches e caminhos. Tenho isto em conta quando corto núcleos/heaps:

  • AMD EPYCCCD/CCX e „NUMA por socket“ (NPS=1/2/4) influenciam a precisão com que o NUMA é cortado. Mais nós (NPS=4) aumentam a localidade, mas requerem uma fixação limpa.
  • IntelSub-NUMA Clustering (SNC2/4) divide o LLC em clusters. Bom para cargas com memória limitada, desde que o SO e a carga de trabalho sejam conscientes dos nós.
  • Proximidade L3Eu associo threads que usam os mesmos heaps no mesmo cluster L3 para economizar tráfego de coerência e saltos entre clusters.

Estas opções funcionam como um multiplicador: se utilizadas corretamente, aumentam Localidade Além disso, se forem incorretamente configurados, aumentam a fragmentação e o tráfego remoto.

Introdução passo a passo e plano de reversão

Nunca apresento a afinação NUMA „big bang“. Um resiliente Plano evita surpresas:

  1. Linha de baseTopologia de hardware, latências P50/P95/P99, taxa de transferência, captura de taxa numastat.
  2. HipóteseFormular um objetivo específico (por exemplo, acesso remoto -30%, P99 -20%).
  3. Um passoAlterar apenas um parafuso de ajuste (por exemplo, corte VM, cpuset, política THP, intervalos de varrimento).
  4. CanárioTestar em 5-10% da frota sob carga real, manter a reversão pronta.
  5. AvaliaçãoComparar valores medidos, definir janelas de regressão, registar efeitos secundários.
  6. LançamentoDesenrolar veio a veio, medir de novo depois de cada veio.
  7. ManutençãoVolte a medir trimestralmente (as actualizações do kernel, do firmware e da carga de trabalho alteram o ótimo).

Isto garante que as melhorias são reproduzíveis e podem ser revertidas em minutos em caso de erro.

Erros comuns - e como evitá-los

Um passo em falso típico é a ativação da intercalação de nós na BIOS, que oculta a topologia NUMA e Equilíbrio mais difícil. Igualmente desfavorável: VMs com mais vCPUs do que um nó oferece, além de páginas enormes reservadas de forma pouco limpa. Alguns administradores fixam tudo com força e assim perdem toda a flexibilidade quando as cargas de trabalho mudam. Outros confiam completamente no kernel, embora os hotspots difíceis exijam regras claras. Registo as séries de medições, reconheço os valores anómalos logo no início e ajusto a configuração e as políticas passo a passo.

  • THP „sempre“ sem controlo: a compactação não planeada perturba a latência. Prefiro utilizar o „madvise“ e reservar especificamente páginas enormes.
  • vm.zone_reclaim_mode demasiado agressivo: a recuperação local pode fazer mais mal do que bem no momento errado. Primeiro medir, depois afinar.
  • irqbalance cegoIRQs não críticos movem-se entre nós. Defino excepções ou máscaras fixas para hotpaths.
  • Mistura de intercalação + fixação rígidaPolíticas contraditórias criam pingue-pongue. Decido-me por uma linha clara para cada serviço.
  • Cpusets não limposOs contentores vêem um nó, mas mapeiam a memória para outros nós. Sempre defina „cpuset.mems“ consistentemente com o conjunto de CPU.
  • Caraterísticas do Sub-NUMA activados mas não utilizados: Mais nós sem planeamento aumentam a fragmentação. Ligar apenas após os testes.

Brevemente resumido

O servidor de balanceamento NUMA reúne processos e dados de forma direcionada, tornando os acessos locais mais frequentes e mais eficientes. Latências tornam-se mais curtos. Com um tamanho de VM adequado, uma configuração de BIOS limpa e ferramentas como numactl, é criada uma topologia clara que o kernel utiliza. NUMA virtual, páginas enormes e afinidades complementam o balanceamento automático em vez de o substituir. A ligação de dispositivos de E/S perto dos nós e a utilização de hotpaths elimina o dispendioso acesso remoto. Desta forma, o hardware de alojamento é escalado de forma fiável e cada segundo de CPU proporciona mais carga útil.

Artigos actuais

Hyperthreading da CPU em servidores de alojamento com núcleos lógicos
Servidores e Máquinas Virtuais

CPU hyperthreading em alojamento: benefícios e riscos

O hyperthreading da CPU no alojamento aumenta o desempenho dos núcleos lógicos, mas comporta riscos. Aprenda a afinar o servidor para obter um desempenho ótimo do servidor Web.