Obtenir par programme la taille de la ligne de cache?

177

Toutes les plateformes sont les bienvenues, veuillez préciser la plateforme pour votre réponse.

Une question similaire: comment obtenir par programme la taille de la page du cache du processeur en C ++?

paxos1977
la source
8
FWIW, C ++ 17 fournira une approximation à la compilation de ceci: stackoverflow.com/questions/39680206/…
GManNickG
à part pour C / C ++, si cela ne vous dérange pas d'utiliser l'assembly pour obtenir de telles informations, vous pouvez jeter un coup d'œil (en développant les informations de la réponse de negamartin) au code source de la SDL_GetCPUCacheLineSizefonction de SDL2 , puis jetez un œil à celui cpuid macroqui contient le code source de l'assembly pour chaque du modèle de processeur. Vous pouvez jeter un œil à imgur.com/a/KP57m6s , ou jeter un œil directement à la source vous-même.
haxpor

Réponses:

186

Sous Linux (avec un noyau raisonnablement récent), vous pouvez obtenir ces informations de / sys:

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

Ce répertoire a un sous-répertoire pour chaque niveau de cache. Chacun de ces répertoires contient les fichiers suivants:

coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity

Cela vous donne plus d'informations sur le cache que vous espérez jamais savoir, y compris la taille de la ligne de cache ( coherency_line_size) ainsi que les processeurs qui partagent ce cache. Ceci est très utile si vous effectuez une programmation multithread avec des données partagées (vous obtiendrez de meilleurs résultats si les threads partageant des données partagent également un cache).

spinfire
la source
4
lequel des fichiers contient la taille de la ligne de cache? Je suppose que la cohérence_line_size? ou la physical_line_partition?
paxos1977
27
cohérency_line_size
spinfire
6
Pour être sûr: c'est en octets, oui?
Jakub M.
6
Oui, cohérence_line_size est en octets.
John Zwinck
4
@android: J'utilise une machine fedora-18 x64 avec un processeur core-i5. cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_sizerevient 64dans mon système. Idem pour les dossiers index1,2,3 également.
Abid Rahman K
141

Sur Linux, regardez sysconf (3).

sysconf (_SC_LEVEL1_DCACHE_LINESIZE)

Vous pouvez également l'obtenir à partir de la ligne de commande en utilisant getconf:

$ getconf LEVEL1_DCACHE_LINESIZE
64
ob.
la source
4
les réponses simples sont tout simplement les meilleures!
FrankH.
3
@warunapww C'est en octets.
Maarten Bamelis
enfin! J'espère que plus de gars verront cette réponse pour gagner du temps.
elinx
118

J'ai travaillé sur des trucs de ligne de cache et j'avais besoin d'écrire une fonction multiplateforme. Je l'ai engagé dans un dépôt github à adresse https://github.com/NickStrupat/CacheLineSize , ou vous pouvez simplement utiliser la source ci-dessous. N'hésitez pas à en faire ce que vous voulez.

#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
la source
15
Il serait peut-être préférable d'utiliser sysconf (_SC_LEVEL1_DCACHE_LINESIZE) pour Linux.
Matt
@Matt pourquoi? Juste curieux :-).
user35915
31

Sur x86, vous pouvez utiliser le instruction CPUID avec la fonction 2 pour déterminer diverses propriétés du cache et du TLB. L'analyse de la sortie de la fonction 2 est quelque peu compliquée, je vous renvoie donc à la section 3.1.3 de l' identification du processeur Intel et de l'instruction CPUID (PDF).

Pour obtenir ces données à partir du code C / C ++, vous devez utiliser l'assembly en ligne, les éléments intrinsèques du compilateur ou appeler une fonction d'assemblage externe pour exécuter l'instruction CPUID.

Adam Rosenfield
la source
quelqu'un sait comment faire cela avec d'autres processeurs avec cache intégré?
paxos1977
3
@ceretullis: Euh ... le x86 a un cache intégré. Quels "autres processeurs" recherchez-vous spécifiquement? Ce que vous demandez dépend de la plate-forme.
Billy ONeal
9

Si vous utilisez SDL2, vous pouvez utiliser cette fonction:

int SDL_GetCPUCacheLineSize(void);

Qui renvoie la taille de la taille de la ligne de cache L1, en octets.

Dans ma machine x86_64, exécutez cet extrait de code:

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

Produit CacheLineSize = 64

Je sais que je suis un peu en retard, mais je ne fais qu'ajouter des informations pour les futurs visiteurs. La documentation SDL indique actuellement que le nombre renvoyé est en Ko, mais il est en fait en octets.

Negamartin
la source
Oh mon c'est vraiment utile. Je vais écrire un jeu en SDL2 donc ça va être vraiment utile
Nicholas Humphrey
7

Sur la plateforme Windows:

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

La fonction GetLogicalProcessorInformation vous donnera les caractéristiques des processeurs logiques utilisés par le système. Vous pouvez parcourir le SYSTEM_LOGICAL_PROCESSOR_INFORMATION retourné par la fonction à la recherche d'entrées de type RelationCache. Chacune de ces entrées contient un ProcessorMask qui vous indique à quel (s) processeur (s) l'entrée s'applique, et dans le CACHE_DESCRIPTOR, il vous indique quel type de cache est décrit et quelle est la taille de la ligne de cache pour ce cache.

Lorenzo Boccaccia
la source
4

ARMv6 et supérieur a C0 ou le registre de type de cache. Cependant, il n'est disponible qu'en mode privilégié.

Par exemple, à partir du Manuel de référence technique Cortex ™ -A8 :

Le but du registre de type de cache est de déterminer la longueur de ligne minimale des instructions et du cache de données en octets pour permettre l'invalidation d'une plage d'adresses.

Le registre des types de cache est:

  • un registre en lecture seule
  • accessible uniquement en modes privilégiés.

Le contenu du registre de type de cache dépend de l'implémentation spécifique. La figure 3-2 montre la disposition des bits du registre de type de cache ...


Ne supposez pas que le processeur ARM a un cache (apparemment, certains peuvent être configurés sans un). La méthode standard pour le déterminer est via C0. À partir du BRAS ARM , page B6-6:

Depuis ARMv6, le registre de type de cache du coprocesseur de contrôle système est la méthode mandatée pour définir les caches L1, voir Registre de type de cache à la page B6-14. C'est également la méthode recommandée pour les variantes antérieures de l'architecture. En outre, Considérations relatives aux niveaux supplémentaires de cache à la page B6-12 décrit les directives d'architecture pour la prise en charge du cache de niveau 2.

jww
la source
3

Vous pouvez également essayer de le faire par programme en mesurant un certain timing. Évidemment, ce ne sera pas toujours aussi précis que cpuid et autres, mais il est plus portable. ATLAS le fait à sa phase de configuration, vous voudrez peut-être l'examiner:

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

David Cournapeau
la source