A livello di codice ottenere la dimensione della linea della cache?


177

Tutte le piattaforme sono benvenute, si prega di specificare la piattaforma per la risposta.

Una domanda simile: come ottenere a livello di codice le dimensioni della pagina della cache della CPU in C ++?


8
FWIW, C ++ 17 fornirà un'approssimazione in fase di compilazione di questo: stackoverflow.com/questions/39680206/...
GManNickG

a parte C / C ++, se non ti dispiace usare assembly per ottenere tali informazioni, puoi dare un'occhiata (espandere le informazioni dalla risposta di negamartin) al codice della SDL_GetCPUCacheLineSizefunzione sorgente di SDL2 , quindi dare un'occhiata a cpuid macroquale ha il codice sorgente di assembly per ogni del modello di processore. Puoi dare un'occhiata a imgur.com/a/KP57m6s o dare un'occhiata direttamente alla fonte.
haxpor,

Risposte:


186

Su Linux (con un kernel abbastanza recente), puoi ottenere queste informazioni da / sys:

/sys/devices/system/cpu/cpu0/cache/

Questa directory ha una sottodirectory per ogni livello di cache. Ciascuna di queste directory contiene i seguenti file:

coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity

Questo ti dà maggiori informazioni sulla cache che potresti mai sperare di conoscere, comprese le dimensioni della cache ( coherency_line_size) e quali CPU condividono questa cache. Questo è molto utile se stai facendo una programmazione multithread con dati condivisi (otterrai risultati migliori se i thread che condividono i dati condividono anche una cache).


4
quale dei file contiene la dimensione della linea della cache? Sto assumendo il coherency_line_size? o la fisica_partita_partizione?
paxos1977,

27
coherency_line_size
spinfire

6
A dire il vero: questo è in byte, sì?
Jakub M.

6
Sì, coherency_line_size è in byte.
John Zwinck,

4
@android: utilizzo una macchina x64 fedora-18 con processore core-i5. cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_sizeritorna 64nel mio sistema. Lo stesso vale anche per le cartelle index1,2,3.
Abid Rahman K

141

Su Linux guarda sysconf (3).

sysconf (_SC_LEVEL1_DCACHE_LINESIZE)

Puoi anche ottenerlo dalla riga di comando usando getconf:

$ getconf LEVEL1_DCACHE_LINESIZE
64

4
le risposte semplici sono solo le migliori!
FrankH.

3
@warunapww È in byte.
Maarten Bamelis,

finalmente! spero che più ragazzi vedano questa risposta per risparmiare tempo.
elinx,

118

Ho lavorato su alcuni elementi della cache e avevo bisogno di scrivere una funzione multipiattaforma. L'ho commesso in un repository github su https://github.com/NickStrupat/CacheLineSize , oppure puoi semplicemente utilizzare la fonte di seguito. Sentiti libero di fare quello che vuoi con esso.

#ifndef GET_CACHE_LINE_SIZE_H_INCLUDED
#define GET_CACHE_LINE_SIZE_H_INCLUDED

// Author: Nick Strupat
// Date: October 29, 2010
// Returns the cache line size (in bytes) of the processor, or 0 on failure

#include <stddef.h>
size_t cache_line_size();

#if defined(__APPLE__)

#include <sys/sysctl.h>
size_t cache_line_size() {
    size_t line_size = 0;
    size_t sizeof_line_size = sizeof(line_size);
    sysctlbyname("hw.cachelinesize", &line_size, &sizeof_line_size, 0, 0);
    return line_size;
}

#elif defined(_WIN32)

#include <stdlib.h>
#include <windows.h>
size_t cache_line_size() {
    size_t line_size = 0;
    DWORD buffer_size = 0;
    DWORD i = 0;
    SYSTEM_LOGICAL_PROCESSOR_INFORMATION * buffer = 0;

    GetLogicalProcessorInformation(0, &buffer_size);
    buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)malloc(buffer_size);
    GetLogicalProcessorInformation(&buffer[0], &buffer_size);

    for (i = 0; i != buffer_size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
        if (buffer[i].Relationship == RelationCache && buffer[i].Cache.Level == 1) {
            line_size = buffer[i].Cache.LineSize;
            break;
        }
    }

    free(buffer);
    return line_size;
}

#elif defined(linux)

#include <stdio.h>
size_t cache_line_size() {
    FILE * p = 0;
    p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
    unsigned int i = 0;
    if (p) {
        fscanf(p, "%d", &i);
        fclose(p);
    }
    return i;
}

#else
#error Unrecognized platform
#endif

#endif

15
Potrebbe essere meglio usare sysconf (_SC_LEVEL1_DCACHE_LINESIZE) per Linux.
Matt

@Matt perché? Solo curioso :-).
user35915,

31

Su x86, è possibile utilizzare l' istruzione CPUID con la funzione 2 per determinare varie proprietà della cache e del TLB. L'analisi dell'output della funzione 2 è alquanto complicata, quindi ti riferirò alla sezione 3.1.3 dell'identificazione del processore Intel e all'istruzione CPUID (PDF).

Per ottenere questi dati dal codice C / C ++, è necessario utilizzare assembly inline, intrinseci del compilatore o chiamare una funzione di assembly esterna per eseguire l'istruzione CPUID.


qualcuno sa come farlo con altri processori con cache integrata?
paxos1977,

3
@ceretullis: Errr ... x86 ha incorporato la cache. Quali "altri processori" stai specificamente cercando? Quello che stai chiedendo dipende dalla piattaforma.
Billy ONeal,

9

Se stai usando SDL2 puoi usare questa funzione:

int SDL_GetCPUCacheLineSize(void);

Che restituisce la dimensione della dimensione della linea della cache L1, in byte.

Nella mia macchina x86_64, eseguendo questo snippet di codice:

printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize());

produce CacheLineSize = 64

So di essere un po 'in ritardo, ma sto solo aggiungendo informazioni per i futuri visitatori. La documentazione SDL attualmente afferma che il numero restituito è in KB, ma in realtà è in byte.


Oh mio questo è davvero utile. Scriverò un gioco in SDL2, quindi questo sarà davvero utile
Nicholas Humphrey,

7

Sulla piattaforma Windows:

da http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx

La funzione GetLogicalProcessorInformation fornirà le caratteristiche dei processori logici in uso dal sistema. È possibile utilizzare SYSTEM_LOGICAL_PROCESSOR_INFORMATION restituito dalla funzione alla ricerca di voci di tipo RelationCache. Ciascuna di queste voci contiene una ProcessorMask che indica a quale processore (i) si applica la voce e in CACHE_DESCRIPTOR, indica quale tipo di cache viene descritta e quanto è grande la linea della cache per quella cache.


4

ARMv6 e successivi hanno C0o il registro del tipo di cache. Tuttavia, è disponibile solo in modalità privilegiata.

Ad esempio, dal Manuale di riferimento tecnico Cortex ™ -A8 :

Lo scopo del registro del tipo di cache è determinare la lunghezza minima della riga della cache delle istruzioni e dei dati in byte per consentire l'invalidazione di un intervallo di indirizzi.

Il registro del tipo di cache è:

  • un registro di sola lettura
  • accessibile solo in modalità privilegiata.

Il contenuto del registro del tipo di cache dipende dall'implementazione specifica. La Figura 3-2 mostra la disposizione dei bit del registro del tipo di cache ...


Non dare per scontato che il processore ARM abbia una cache (apparentemente, alcuni possono essere configurati senza uno). Il modo standard per determinarlo è tramite C0. Dal BRACCIO ARM , pagina B6-6:

Da ARMv6, il registro Tipo di cache del coprocessore di controllo del sistema è il metodo obbligatorio per definire le cache L1, vedere Registro del tipo di cache a pagina B6-14. È anche il metodo consigliato per le varianti precedenti dell'architettura. Inoltre, le considerazioni sui livelli aggiuntivi di cache a pagina B6-12 descrivono le linee guida sull'architettura per il supporto della cache di livello 2.


3

Puoi anche provare a farlo programmaticamente misurando alcuni tempi. Ovviamente, non sarà sempre preciso come cpuid e simili, ma è più portatile. ATLAS lo fa nella sua fase di configurazione, potresti volerlo guardare:

http://math-atlas.sourceforge.net/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.