Programmgesteuert die Cache-Zeilengröße ermitteln?

177

Alle Plattformen sind willkommen. Bitte geben Sie die Plattform für Ihre Antwort an.

Eine ähnliche Frage: Wie kann die Seitengröße des CPU-Cache in C ++ programmgesteuert ermittelt werden?

paxos1977
quelle
8
FWIW, C ++ 17 bietet eine Annäherung zur Kompilierungszeit: stackoverflow.com/questions/39680206/…
GManNickG
Abgesehen von C / C ++ können Sie, wenn es Ihnen nichts ausmacht, Assembly zu verwenden, um solche Informationen abzurufen, einen Blick (Erweiterung der Informationen aus Negamartins Antwort) auf den Quellcode von SDL2 werfen und SDL_GetCPUCacheLineSizedann einen Blick darauf werfen, cpuid macrowelcher Assembly-Quellcode für jeden vorhanden ist des Prozessormodells. Sie können einen Blick auf imgur.com/a/KP57m6s werfen oder direkt einen Blick auf die Quelle werfen .
Haxpor

Antworten:

186

Unter Linux (mit einem relativ neuen Kernel) können Sie diese Informationen aus / sys abrufen:

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

Dieses Verzeichnis verfügt über ein Unterverzeichnis für jede Cache-Ebene. Jedes dieser Verzeichnisse enthält die folgenden Dateien:

coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity

Auf diese Weise erhalten Sie mehr Informationen über den Cache, als Sie jemals erhoffen würden, einschließlich der Cacheline-Größe ( coherency_line_size) sowie der CPUs, die diesen Cache gemeinsam nutzen. Dies ist sehr nützlich, wenn Sie Multithread-Programmierung mit gemeinsam genutzten Daten durchführen (Sie erhalten bessere Ergebnisse, wenn die Threads, die Daten gemeinsam nutzen, auch einen Cache gemeinsam nutzen).

Spinfire
quelle
4
Welche der Dateien enthält die Cache-Zeilengröße? Ich gehe von der Kohärenz_Liniengröße aus? oder die physische_Linienpartition?
paxos1977
27
kohärenz_line_size
spinfire
6
Um sicher zu sein: das ist in Bytes, ja?
Jakub M.
6
Ja, kohärenz_Liniengröße wird in Bytes angegeben.
John Zwinck
4
@android: Ich benutze Fedora-18 x64 Maschine mit Core-i5 Prozessor. cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_sizekehrt 64in meinem System zurück. Gleiches gilt auch für index1,2,3-Ordner.
Abid Rahman K
141

Unter Linux schauen Sie sich sysconf (3) an.

sysconf (_SC_LEVEL1_DCACHE_LINESIZE)

Sie können es auch über die Befehlszeile mit getconf abrufen:

$ getconf LEVEL1_DCACHE_LINESIZE
64
ob.
quelle
4
einfache Antworten sind einfach die besten!
FrankH.
3
@warunapww Es ist in Bytes.
Maarten Bamelis
endlich! Ich hoffe, mehr Leute sehen diese Antwort, um Zeit zu sparen.
Elinx
118

Ich habe an einigen Cache-Zeilen gearbeitet und musste eine plattformübergreifende Funktion schreiben. Ich habe es einem Github-Repo unter https://github.com/NickStrupat/CacheLineSize übergeben , oder Sie können einfach die folgende Quelle verwenden. Fühlen Sie sich frei, damit zu tun, was Sie wollen.

#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
Nick Strupat
quelle
15
Könnte besser sein, sysconf (_SC_LEVEL1_DCACHE_LINESIZE) für Linux zu verwenden.
Matt
@ Matt warum? Nur neugierig :-).
Benutzer35915
31

Auf x86 können Sie die verwenden CPUID- Befehl mit Funktion 2 verwenden, um verschiedene Eigenschaften des Caches und des TLB zu bestimmen. Das Parsen der Ausgabe von Funktion 2 ist etwas kompliziert, daher verweise ich Sie auf Abschnitt 3.1.3 der Intel-Prozessoridentifikation und der CPUID-Anweisung (PDF).

Um diese Daten aus C / C ++ - Code abzurufen, müssen Sie Inline-Assemblys, Compiler-Intrinsics oder eine externe Assembly-Funktion aufrufen, um die CPUID-Anweisung auszuführen.

Adam Rosenfield
quelle
Weiß jemand, wie man das mit anderen Prozessoren mit eingebautem Cache macht?
paxos1977
3
@ceretullis: Errr ... der x86 hat einen Cache eingebaut. Welche "anderen Prozessoren" suchen Sie speziell? Was Sie verlangen, ist plattformabhängig.
Billy ONeal
9

Wenn Sie SDL2 verwenden, können Sie diese Funktion verwenden:

int SDL_GetCPUCacheLineSize(void);

Dies gibt die Größe der L1-Cache-Zeilengröße in Byte zurück.

Führen Sie auf meinem x86_64-Computer dieses Code-Snippet aus:

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

Produziert CacheLineSize = 64

Ich weiß, dass ich etwas spät dran bin, aber nur Informationen für zukünftige Besucher hinzufüge. In der SDL-Dokumentation heißt es derzeit, dass die zurückgegebene Nummer in KB angegeben ist, tatsächlich jedoch in Byte.

Negamartin
quelle
Oh mein Gott, das ist wirklich hilfreich. Ich werde ein Spiel in SDL2 schreiben, also wird dies wirklich nützlich sein
Nicholas Humphrey
7

Auf der Windows-Plattform:

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

Mit der Funktion GetLogicalProcessorInformation erhalten Sie Eigenschaften der vom System verwendeten logischen Prozessoren. Sie können die von der Funktion zurückgegebene SYSTEM_LOGICAL_PROCESSOR_INFORMATION durchsuchen und nach Einträgen vom Typ RelationCache suchen. Jeder dieser Einträge enthält eine ProcessorMask, die angibt, für welche Prozessoren der Eintrag gilt, und im CACHE_DESCRIPTOR angibt, welcher Cache-Typ beschrieben wird und wie groß die Cache-Zeile für diesen Cache ist.

Lorenzo Boccaccia
quelle
4

ARMv6 und höher hat C0 oder das Cache Type Register. Es ist jedoch nur im privilegierten Modus verfügbar.

Zum Beispiel aus dem technischen Referenzhandbuch für Cortex ™ -A8 :

Der Zweck des Cache-Typregisters besteht darin, die minimale Zeilenlänge des Befehls- und Datencaches in Bytes zu bestimmen, damit ein Adressbereich ungültig gemacht werden kann.

Das Cache-Typ-Register lautet:

  • ein schreibgeschütztes Register
  • Nur in privilegierten Modi verfügbar.

Der Inhalt des Cache-Typregisters hängt von der spezifischen Implementierung ab. Abbildung 3-2 zeigt die Bitanordnung des Cache-Typregisters ...


Gehen Sie nicht davon aus, dass der ARM-Prozessor über einen Cache verfügt (anscheinend können einige ohne einen konfiguriert werden). Die Standardmethode zur Bestimmung ist via C0. Aus dem ARM ARM , Seite B6-6:

In ARMv6 ist das Systemsteuerungs-Coprozessor-Cache-Typ-Register die vorgeschriebene Methode zum Definieren der L1-Caches (siehe Cache-Typ-Register auf Seite B6-14). Dies ist auch die empfohlene Methode für frühere Varianten der Architektur. Darüber hinaus werden in Überlegungen zu zusätzlichen Cache-Ebenen auf Seite B6-12 Architekturrichtlinien für die Cache-Unterstützung der Ebene 2 beschrieben.

jww
quelle
3

Sie können auch versuchen, dies programmgesteuert zu tun, indem Sie das Timing messen. Natürlich ist es nicht immer so präzise wie cpuid und dergleichen, aber es ist portabler. ATLAS führt dies in der Konfigurationsphase durch. Vielleicht möchten Sie es sich ansehen:

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

David Cournapeau
quelle