Consciência NUMA e fixação de CPU para servidores dedicados
16 min de leitura - 16 de junho de 2026

Como inspecionar a topologia NUMA e atribuir cargas de trabalho Linux aos núcleos e à memória adequados. Abrange numactl, taskset, systemd, configurações do BIOS e estratégias específicas para cargas de trabalho.
Consciência NUMA e fixação de CPU para servidores dedicados
Em qualquer servidor multi-socket, onde um processo é executado e onde a sua memória reside são duas questões diferentes, e deixá-las desincronizadas é uma das formas mais fáceis de comprometer o desempenho. O reconhecimento NUMA e o pinning da CPU são os dois controlos que resolvem este problema. Esta publicação aborda como funciona o NUMA, como o inspecionar no Linux e como fixar corretamente as cargas de trabalho para bases de dados, formação em IA e serviços sensíveis à latência.
Como funciona o NUMA em servidores multi-socket
Um nó NUMA (Non-Uniform Memory Access) é um grupo de núcleos de CPU ligados a um bloco local de RAM através de um controlador de memória dedicado. Num servidor de dois soquetes, tem-se normalmente dois nós. Qualquer núcleo pode ler qualquer endereço, mas o acesso local é de cerca de 80 ns, enquanto um salto entre sockets através da UPI da Intel ou da Infinity Fabric da AMD é de cerca de 130–150 ns. Em sistemas maiores com mais sockets, o pior caso de um nó pode ultrapassar os 250 ns.
A largura de banda segue o mesmo padrão. Um sistema Sapphire Rapids de dois soquetes consegue sustentar cerca de 600 GB/s quando os núcleos acedem à memória local, mas a ligação entre soquetes é uma fração disso, pelo que o tráfego que a atravessa fica rapidamente congestionado. Os processadores com muitos núcleos tornam isto mais granular: o Sub-NUMA Clustering (SNC) da Intel e o Nodes Per Socket (NPS) da AMD dividem cada soquete em múltiplos domínios NUMA, pelo que uma caixa de «dois soquetes» pode facilmente apresentar quatro ou oito nós ao Linux.
Sem reconhecimento NUMA, o agendador do Linux migra alegremente um segmento entre sockets enquanto o seu conjunto de trabalho permanece no nó original. Cada acesso subsequente torna-se remoto. O sintoma visível é uma elevada utilização da CPU com baixo rendimento real, porque os núcleos passam o tempo à espera da memória. Os dispositivos de E/S agravam esta situação. Uma GPU ou NIC está ligada a uma raiz PCIe específica, que pertence a um nó NUMA. Se o processo que a alimenta for executado no outro soquete, todas as transferências DMA atravessam a interconexão.
Inspecionar a topologia NUMA no Linux
Quatro ferramentas cobrem quase tudo o que precisa:
lscpupara um resumo rápido de sockets e nós.numactl --hardwarepara os totais de memória dos nós e a matriz de distâncias entre nós.numastatpara contadores de acertos/erros por processo.lstopo(do hwloc) para a hierarquia de cache e a localização dos dispositivos PCIe.
Comece com numactl --hardware. Apresenta cada nó, os núcleos e a memória que lhe pertencem, bem como a matriz de distâncias. Um valor de 10 é local, 20+ é remoto. Se vir um único nó numa caixa com vários sockets, o seu BIOS tem o Node Interleaving ativado e está a ocultar a topologia; corrija isso primeiro (ver abaixo).
Para um processo específico, numastat -p <PID> detalha onde a sua memória está realmente alocada. Quatro contadores são importantes:
numa_hit: memória alocada no nó pretendido. É desejável que este valor seja alto.numa_miss: o nó pretendido estava cheio, a alocação foi desviada para outro local.numa_foreign: outro nó tentou alocar localmente e não conseguiu, o que indica pressão de memória.other_node: páginas alocadas num nó diferente daquele onde o processo está a ser executado. Valores elevados aqui são o sinal clássico de um mau pinning.
Para cargas de trabalho de GPU ou NIC, execute lstopo-no-graphics e verifique a que nó NUMA cada dispositivo PCIe está ligado. Se os núcleos que controlam o dispositivo estiverem no outro nó, essa é a primeira coisa a corrigir.
Políticas de fixação de CPU e de memória
A fixação de CPU (ou afinidade de CPU) vincula um processo a núcleos específicos para que o agendador não o possa migrar. Por si só, isso não é suficiente, porque o Linux usa uma política de memória de primeiro toque por predefinição: as páginas são alocadas no nó que primeiro escrever nelas. Se um thread iniciar no nó errado antes de ser fixado, a sua memória permanece lá. É necessário controlar tanto a colocação como a alocação em conjunto.
Três ferramentas cobrem os casos mais comuns:
| Ferramenta | Controlos | Utilizar para |
|---|---|---|
taskset | Apenas núcleos de CPU | Ligação rápida e pontual de um processo existente |
numactl | Núcleos da CPU e memória | Iniciar cargas de trabalho com localidade estrita |
| systemd | Núcleos da CPU e memória, persistente | Serviços que necessitam de fixação entre reinicializações |
numactl suporta quatro políticas de memória:
--membind=N: alocar apenas no nó N, falhar se estiver cheio.--preferred=N: dar preferência ao nó N, recorrer a outros se necessário.--interleave=all: round-robin entre nós para uma distribuição uniforme da largura de banda.--localalloc: alocar no nó em que a CPU em execução se encontra.
Fixar uma carga de trabalho a um nó
Primeiro, identifique quais os núcleos que pertencem ao seu nó de destino:
numactl --hardwareEm seguida, inicie a aplicação vinculada a esse nó, tanto para os núcleos como para a memória:
numactl --cpunodebind=0 --membind=0 ./your_applicationPara um processo já em execução, ajuste a afinidade da CPU com taskset:
taskset -cp 0-7 <PID>Para que se mantenha após um reinício, defina-a na unidade systemd:
[Service]
CPUAffinity=0-7
NUMAPolicy=bind
NUMAMask=0Recarregue e reinicie:
sudo systemctl daemon-reload && sudo systemctl restart <service>Quando estiver a fixar manualmente, desative o auto-balanceador do kernel para que não interfira com a sua colocação:
sysctl -w kernel.numa_balancing=0Adicione-o a /etc/sysctl.conf para que seja permanente. Em seguida, verifique com numastat -p <PID> durante alguns minutos de carga de trabalho real. Se other_node permanecer perto de zero, a fixação está a surtir efeito.
Escolher uma estratégia com base na carga de trabalho
A política certa depende de se a sua carga de trabalho beneficia mais de baixa latência ou de largura de banda agregada em todos os nós.
| Carga de trabalho | Política | Porquê |
|---|---|---|
| Bases de dados (PostgreSQL, MySQL, SQL Server) | --cpunodebind + --membind | Buffers partilhados de grande dimensão, percursos de consulta sensíveis à latência |
| Cache na memória (Redis, Memcached) | Ligação de nó único | Tudo é acesso à RAM, a latência remota é imediatamente visível |
| Treinamento e inferência de IA/ML | Ligação ao nó NUMA da GPU | Evita transferências de tensores que atravessam raízes PCIe |
| Análise (Spark, Elasticsearch) | --interleave=all | Conjuntos de trabalho de grande dimensão requerem largura de banda em todos os nós |
| APIs sensíveis à latência, negociação | Afinidade estrita de pinos + IRQ | A previsibilidade é mais importante do que o pico de throughput |
| Intensivo em rede (RoCEv2, InfiniBand) | Pin para o nó NUMA da NIC, núcleos dedicados para IRQs | Mantém o processamento de interrupções local e fora do caminho dos threads da aplicação |
Especificamente para cargas de trabalho de GPU, execute lstopo para descobrir em que nó NUMA a GPU se encontra e, em seguida, inicie o processo de treino ou inferência com numactl --cpunodebind=N --membind=N para esse mesmo N. Esta é uma das vantagens mais fáceis de obter num servidor GPU com vários soquetes, porque a localização padrão do agendador está frequentemente errada.
Para cargas de trabalho HPC e MPI que abrangem ambos os sockets, fixe cada rank a um único nó com localalloc em vez de intercalar tudo. Cada rank obtém memória local, e o paralelismo ocorre ao nível do rank.
Uma observação prática: se fixar a um único nó, deixe 2–4 GB de margem nele. Um nó a funcionar quase na capacidade máxima aciona a recuperação de memória, o que lhe custa a latência que estava a tentar poupar.
Configurações do BIOS e do kernel a verificar
A precisão dos resultados da ferramenta depende da topologia que o firmware expõe. Algumas definições a confirmar:
- Intercalamento de nós: desative-o. Quando ativado, o BIOS apresenta toda a memória como um único conjunto plano e oculta totalmente o NUMA do sistema operativo.
numactl --hardwareMostrará um nó numa caixa com vários soquetes, se for esse o caso. - Clustering Sub-NUMA (Intel) ou Nós por Soquete (AMD): ative em processadores com muitos núcleos quando desejar uma localização mais precisa. Confirme
lscpuapós o reinício. vm.zone_reclaim_mode: defina como 0 para a maioria dos servidores de produção. Um valor diferente de zero recupera agressivamente a memória local em vez de alocar remotamente, o que pode evacuar o cache de páginas útil.kernel.numa_balancing: mantenha ativado para cargas de trabalho de uso geral, desative quando estiver a fixar manualmente. O equilibrador automático migrará páginas e threads de formas que entram em conflito com a sua política.
Se estiver a executar o ajuste NUMA em hardware físico, onde controla a BIOS, os parâmetros do kernel e a afinidade de IRQ, pode aplicar tudo o que foi referido acima sem contornar as abstrações do hipervisor. Essa é a principal razão pela qual este tipo de trabalho é mais fácil em hardware dedicado do que em máquinas virtuais na nuvem.
Para servidores dedicados multi-socket com acesso root total, consulte os servidores dedicados da FDC.

Perfis ajustados para otimização da carga de trabalho do servidor Linux
Como escolher, aplicar e personalizar perfis ajustados para GPU, base de dados e servidores Linux de elevada largura de banda, com exemplos e dicas de implementação Ansible.
16 min de leitura - 9 de junho de 2026
Linux OOM Killer Tuning para VPS: um guia prático
12 min de leitura - 8 de junho de 2026