Como o Linux detecta o número de CPUs "possíveis"

Sep 16 2020

Eu tenho uma CPU AMD com 8 núcleos e 2 threads por núcleo. O Linux (corretamente) mostra isso como 16 "cpus". No entanto, o sysfs realmente mostra 32 cpus "possíveis", com 16 deles ausentes e offline:

$ cat /sys/devices/system/cpu/possible 0-31 $ cat /sys/devices/system/cpu/present
0-15

$ cat /sys/devices/system/cpu/online 0-15 $ cat /sys/devices/system/cpu/offline 
16-31

Para ser claro, não há nada de errado aqui; há de fato 16 CPUs lógicas presentes e online. O que não estou claro é por que o Linux detecta 16 CPUs lógicas adicionais que não estão presentes, mas são possíveis.

Acho que estes são os documentos relevantes do kernel: https://www.kernel.org/doc/html/latest/core-api/cpu_hotplug.html. Mas não vejo nenhuma indicação de como o número de CPUs possíveis é escolhido. (Observe que é muito menor do que o kernel_maxnúmero de CPUs, que é 8191 no meu sistema.)

(Um pouco de fundo adicional: eu tenho algum código que precisa analisar esses valores. Fazer a coisa certa parece simples, mas eu gostaria de ter uma docstring clara explicando por que o número de CPUs possíveis pode exceder o número de CPUs presentes em um computador desktop comum.)

Respostas

2 Gilles'SO-stopbeingevil' Sep 16 2020 at 02:40

Uma CPU é “possível” se houver espaço para ela na memória do kernel. O número de CPUs possíveis é o número máximo de CPUs que podem ser colocadas online, incluindo aquelas que são conectadas a quente após a inicialização.

A documentação desta parte do sysfs está em Como as informações da topologia da CPU são exportadas via sysfs :

possível: CPUs que receberam recursos alocados e podem ser colocadas online se estiverem presentes. [cpu_possible_mask]

Mas a documentação mais detalhada do cpu_possible_maskestá no hotplug da CPU no Kernel :

Bitmap de possíveis CPUs que podem estar disponíveis no sistema. Isso é usado para alocar alguma memória de tempo de inicialização para variáveis ​​per_cpu que não foram projetadas para aumentar / diminuir à medida que CPUs são disponibilizadas ou removidas. Uma vez definido durante a fase de descoberta do tempo de inicialização, o mapa é estático, ou seja, nenhum bit é adicionado ou removido a qualquer momento. Ajustá-lo com precisão para as necessidades do seu sistema antecipadamente pode economizar alguma memória de inicialização.

Este parâmetro pode ser configurado por meio de opções de linha de comando . No caso provável de seu hardware não suportar a conexão de outra CPU sem reinicializar e você não pretende hibernar seu sistema e fazê-lo acordar com mais CPUs, você pode economizar uma pequena quantidade de memória do kernel passando possible_cpus=16o kernel linha de comando. Em um PC ou servidor típico, a quantia provavelmente é muito pequena para que valha o esforço.

Na ausência de opções de linha de comando, acho que você precisa ler o código - fonte para descobrir o que está acontecendo. Se o kernel é compilado sem suporte a hotplug de CPU ( CONFIG_HOTPLUG_CPU), ele apenas verifica quantas CPUs estão presentes no momento da inicialização. Se o kernel tem suporte para hotplug de CPU, de acordo com um comentário para prefill_possible_mapno código-fonte:

  • Se o BIOS especificou CPUs desativadas em ACPI / mptables, use isso.
  • O usuário pode sobrescrever com possible_cpus = NUM
  • Caso contrário, não reserve CPUs adicionais.

Não verifiquei se é isso que o código faz.

Observe que o princípio do que significa "possíveis CPUs" se aplica a todas as arquiteturas, mas as maneiras de determinar o número de CPUs são específicas da arquitetura. Em minha resposta, presumo que x86.