taskset: Configurando Afinidade de CPU no Linux

taskset: Configurando Afinidade de CPU no Linux

O Que Voce Vai Aprender

  • Como fixar um processo em nucleos de CPU especificos com taskset
  • A diferenca entre fixacao no inicio (-c) e reatribuicao de um processo em execucao (-p)
  • Padroes praticos para benchmarking, isolamento de nucleos e NUMA

Resumo Rapido

  • Fixar no inicio -> taskset -c 0,1 ./program
  • Fixar um processo em execucao -> taskset -cp 0-3 <PID>
  • Verificar estado atual -> taskset -cp <PID>
  • A forma de lista (-c) e legivel; a mascara hexadecimal serve para automacao

Pre-requisitos

  • taskset vem com o pacote util-linux (pre-instalado na maioria das distros)
  • Numeros de nucleos comecam em 0. Conte-os com nproc
  • Alterar um processo em execucao requer ser dono do processo (ou root)

O que e afinidade de CPU?

Conclusao: Afinidade de CPU restringe em quais nucleos de CPU um processo ou thread pode executar. taskset e o comando para visualizar e alterar essa configuracao.

Por padrao, o escalonador do Linux pode mover um processo para qualquer nucleo ocioso. Configurar afinidade de CPU significa que o processo so pode executar nos nucleos que voce especificar.

As principais razoes para fixar sao:

  • Localidade de cache: evitar invalidacao de cache L1/L2 causada por migracao de nucleo
  • Isolamento de nucleo: dar a um processo sensivel a latencia um nucleo dedicado, livre de interferencia
  • Benchmarks reprodutiveis: executar nos mesmos nucleos sempre para reduzir ruido nas medicoes

Afinidade especifica um conjunto de nucleos permitidos. Restrinja a um nucleo para fixacao rigida, ou permita varios e deixe o escalonador escolher dentro desse conjunto.

Verificar contagem e numeracao de nucleos

Conclusao: Antes de decidir onde fixar, confirme a contagem de nucleos disponiveis com nproc. Numeros de nucleos comecam em 0.

$ nproc
8

Se imprimir 8, numeros de nucleos validos sao 0-7. Especificar um nucleo inexistente como taskset -c 8 ... retorna um erro.

Use lscpu quando tambem precisar do layout fisico/logico.

$ lscpu

Fixar nucleos no inicio (-c)

Conclusao: Para fixar ao iniciar um comando, use taskset -c <lista-nucleos> <comando>. A forma de lista aceita 0,2 (individual) e 0-3 (intervalo).

A forma basica: iniciar um novo processo fixado em nucleos especificos desde o inicio.

# Iniciar programa apenas nos nucleos 0 e 1
$ taskset -c 0,1 ./program

# Iniciar no intervalo de nucleos 0 a 3
$ taskset -c 0-3 ./program

# Fixar rigidamente em um unico nucleo (nucleo 2)
$ taskset -c 2 ./program

-c (--cpu-list) permite listar numeros de nucleos diretamente, facilitando a leitura. Use , para nucleos individuais, - para intervalos, e combine ambos (por exemplo 0,2,4-7).

Passe opcoes ao comando iniciado adicionando-as normalmente. taskset -c 0,1 stress-ng --cpu 2 funciona sem necessidade de separador --.

Visualizar e alterar um processo em execucao (-p)

Conclusao: Para um processo ja em execucao, use -p (--pid): taskset -cp <PID> para verificar, taskset -cp <lista-nucleos> <PID> para alterar.

Verificar a afinidade atual

$ taskset -cp 1234
pid 1234's current affinity list: 0-7

0-7 significa "pode executar em todos os nucleos" (o padrao). Com -c voce obtem a forma de lista; sem ele, uma mascara hexadecimal.

Reatribuir um processo em execucao

# Reatribuir PID 1234 para nucleos 0 e 1
$ taskset -cp 0,1 1234
pid 1234's current affinity list: 0-7
pid 1234's new affinity list: 0,1

Encontre o PID com ps ou pgrep.

$ pgrep -f program

Atencao a ordem dos argumentos

No modo -p, a lista de nucleos vem primeiro, o PID depois: taskset -cp 0,1 1234, nao taskset -cp 1234 0,1. Invertendo, taskset trata o PID como mascara e falha.

Mascara hexadecimal vs forma de lista

Conclusao: Com -c voce especifica uma lista de nucleos; sem ele, uma mascara hexadecimal. Na mascara, cada bit mapeia um nucleo (bit 0 = nucleo 0).

Nativamente, taskset especifica nucleos como uma mascara hexadecimal. -c e a opcao que troca isso por uma lista legivel.

Nucleos alvo Forma de lista (-c) Mascara hex
Nucleo 0 0 0x1
Nucleos 0,1 0,1 0x3
Apenas nucl 1 1 0x2
Nucleos 0-3 0-3 0xf
Apenas nucl 3 3 0x8

A mascara e mais facil de ler em binario. O bit menos significativo (mais a direita) e o nucleo 0. 0x3 e 0b0011 (nucleos 0 e 1); 0x8 e 0b1000 (nucleo 3).

# Iniciar com mascara (nucleos 0,1 = 0x3)
$ taskset 0x3 ./program

# Verificar com mascara (sem -c)
$ taskset -p 1234
pid 1234's current affinity mask: ff

Para comandos digitados manualmente, a forma de lista (-c) e mais segura. Um unico digito hexadecimal errado aponta para um nucleo diferente. Recorra a mascara apenas quando um script a gera.

Aplicar a todas as threads (-a)

Conclusao: Para fixar todas as threads de um processo multithread, adicione -a (--all-tasks). Sem ele, apenas a thread principal e afetada.

Ao operar em um processo em execucao com -p, por padrao a afinidade se aplica apenas ao PID dado (a thread principal) e nao se propaga para threads filhas existentes. Use -a para fixar todas as threads do processo de uma vez.

# Fixar todas as threads do PID 1234 nos nucleos 0-3
$ taskset -acp 0-3 1234

Mesmo com -a, threads criadas apos a mudanca herdam a afinidade do processo. -a se aplica a threads existentes; threads futuras herdam de qualquer forma. Nao confunda os dois.

Casos de uso reais

Conclusao: Os casos classicos sao benchmarks reprodutiveis, isolamento de processos sensiveis a latencia e manter acesso a memoria local em NUMA.

Tornar benchmarks reprodutiveis

Medir nos mesmos nucleos toda vez remove a variancia de cache-miss causada por migracao de nucleo.

$ taskset -c 2,3 ./benchmark

Isolar processos sensiveis a latencia

Combine com o parametro de boot do kernel isolcpus, que remove nucleos do escalonador do SO, e entao coloque apenas seu processo alvo neles com taskset.

Manter memoria local em NUMA

Em sistemas NUMA, fixar em nucleos no mesmo no que a memoria evita acesso remoto a memoria. Quando tambem precisar controlar alocacao de memoria, numactl e mais adequado (taskset so lida com posicionamento de CPU).

A armadilha do excesso de fixacao

Fixe de forma muito agressiva e um processo nao podera usar outros nucleos ociosos, o que pode torna-lo mais lento. Fixe apenas apos medir e confirmar o beneficio. Nao fixe cegamente.

Erros comuns e solucoes

Conclusao: A maioria envolve um numero de nucleo inexistente, permissoes insuficientes ou ordem errada de argumentos.

sched_setaffinity: Invalid argument

Voce especificou um numero de nucleo que nao existe. Verifique o intervalo com nproc.

# Apenas 8 nucleos (0-7) existem mas nucleo 8 foi solicitado -> erro
$ taskset -c 8 ./program

Operation not permitted

Voce esta tentando alterar o processo de outro usuario. Execute como o dono do processo ou use sudo.

$ sudo taskset -cp 0,1 1234

command not found: taskset

util-linux esta ausente (por exemplo, um container minimo). No Debian/Ubuntu, instale:

$ sudo apt install util-linux

Proximas Leituras