Obtenha programaticamente informações precisas sobre a hierarquia de cache da CPU no Linux

9

Estou tentando obter uma descrição precisa da hierarquia de cache de dados da CPU atual no Linux: não apenas o tamanho dos caches de dados individuais L1 / L2 / L3 (e possivelmente L4), mas também a maneira como eles são divididos ou compartilhados núcleos.

Por exemplo, na minha CPU (AMD Ryzen Threadripper 3970X), cada núcleo possui seu próprio cache de dados L1 de 32 KB e cache L2 de 512 KB, no entanto, o cache L3 é compartilhado entre núcleos em um complexo complexo (CCX). Em outras palavras, existem 8 caches L3 distintos, cada um com 16 MB.

A seção "Cache" desta captura de tela da CPU-Z no Windows é basicamente o que estou tentando descobrir:

Captura de tela do CPU-Z

Não tenho problemas em obter essas informações no Windows GetLogicalProcessorInformation().

No entanto, no Linux, parece que sysconf()apenas o tamanho do cache por núcleo para caches de dados L1 e L2 ( _SC_LEVEL1_DCACHE_SIZEe _SC_LEVEL2_DCACHE_SIZE) ou o tamanho total do cache L3 ( _SC_LEVEL3_CACHE_SIZE).

EDIT: saída do lstopo no VMWare . A máquina virtual possui 8 núcleos. As informações de cache L1 e L2 são boas, mas o tamanho do cache L3 não parece estar correto:

Captura de tela do lstopo

François Beaune
fonte
1
Isso pode ajudar ... askubuntu.com/a/214302
Mark Setchell
Eu dei uma olhada no lstopo, este projeto é incrível, mas provavelmente exagero para as minhas necessidades. O que realmente me deixa confuso é a mistura entre os tamanhos de cache por núcleo e não por núcleo retornados por sysconf(). Como entendê-las se não sabemos se os caches são compartilhados ou não?
François Beaune
Você quer que seu programa use isso para decidir algo sobre quantos threads iniciar ou qual máscara de afinidade de CPU definir? Ou você deseja que as informações sejam exibidas para o usuário? De qualquer forma, você pode precisar usar a cpuidinstrução x86 nesse ISA e talvez até incorporar alguns detalhes de layout de cache por modelo. IDK quantos detalhes os vários CPUID folheiam como sandpile.org/x86/cpuid.htm#level_0000_0004h podem representar.
Peter Cordes
1
Você pode experimentar o lstopoLinux no bare metal? (por exemplo, inicialize um USB ativo). Seu resultado falso pode ser culpa da VM, portanto devemos excluir isso. Sem surpresa, ele funciona como esperado no meu desktop i7-6700k, mostrando todos os 4 núcleos no mesmo pacote que compartilham um cache L3. Mas a família Intel Sandybridge é a série de CPUs x86 mais amplamente usada e não alterada recentemente.
Peter Cordes
1
Observe que lstopotambém está disponível para Windows . lstopouse a cpuidinstrução (e talvez a SRATtabela ACPI ). cpuidé relativamente fácil de usar, mas Intel e AMD diferem bastante nesse aspecto. hwloc(ao qual lstopopertence) tem uma interface de API que você pode usar para obter a topologia de cache no Windows e Linux.
Margaret Bloom

Respostas:

3

Uma imagem completa da hierarquia de cache pode ser encontrada programaticamente, abrindo arquivos em /sys(sysfs).

Cada "thread" ou "processador lógico" é representado por um subdiretório in /sys/devices/system/cpu/. Dentro desse diretório, você encontrará um diretório de cache. Por exemplo, informações de cache para o primeiro processador lógico podem ser encontradas aqui:

$ ls /sys/devices/system/cpu/cpu0/cache/
index0
index1
index2
index3
power
uevent

Cada entidade de cache associada a esse processador lógico é representada por um index[0-9]*diretório. O número após o índice não representa o nível. A mesma entidade de cache pode ser listada várias vezes em diferentes processadores lógicos. Dentro desses diretórios, você pode encontrar todas as propriedades da entidade de cache (nível, conjuntos, tamanho da linha etc.).

$ ls /sys/devices/system/cpu/cpu0/cache/index0
coherency_line_size
level
number_of_sets
physical_line_partition
power
shared_cpu_list
shared_cpu_map
size
type
uevent
ways_of_associativity

A documentação completa pode ser encontrada aqui .

Mais importante, para obter a saída desejada, é necessário inspecionar shared_cpu_list:

$ cat /sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list
0,28

Isso mostrará quais processadores lógicos compartilham essa entidade de cache. Inspecionando todas as entidades ( /sys/devices/system/cpu/cpu*/cache/index*/) e eliminando duplicatas usando shared_cpu_list, você pode acessar programaticamente todos os dados necessários.

Observe que seu hipervisor não precisa transmitir informações precisas. Isso mostrará apenas a hierarquia de cache como o kernel convidado a vê.

Mikel Rychliski
fonte