¿Obtener programáticamente el tamaño de línea de caché?

177

Todas las plataformas son bienvenidas, especifique la plataforma para su respuesta.

Una pregunta similar: ¿Cómo obtener programáticamente el tamaño de página de caché de la CPU en C ++?

paxos1977
fuente
8
FWIW, C ++ 17 proporcionará una aproximación en tiempo de compilación de esto: stackoverflow.com/questions/39680206/…
GManNickG
aparte de C / C ++, si no le importa usar el ensamblaje para obtener dicha información, puede echar un vistazo (expandiendo la información de la respuesta de negamartin) al código fuente de SDL_GetCPUCacheLineSizefunción de SDL2 , luego eche un vistazo a cpuid macrocuál tiene el código fuente del ensamblaje para cada del modelo de procesador. Puede echar un vistazo a imgur.com/a/KP57m6s o echar un vistazo directamente a la fuente usted mismo.
haxpor

Respuestas:

186

En Linux (con un núcleo razonablemente reciente), puede obtener esta información de / sys:

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

Este directorio tiene un subdirectorio para cada nivel de caché. Cada uno de esos directorios contiene los siguientes archivos:

coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity

Esto le brinda más información sobre la memoria caché de la que esperaría saber, incluido el tamaño de la línea de memoria caché ( coherency_line_size) y las CPU que comparten esta memoria caché. Esto es muy útil si está haciendo programación multiproceso con datos compartidos (obtendrá mejores resultados si los hilos que comparten datos también comparten un caché).

spinfire
fuente
44
¿Cuál de los archivos contiene el tamaño de línea de caché? ¿Asumo el tamaño_línea_coherencia? o la parte_línea_física?
paxos1977
27
coherency_line_size
spinfire
66
Para estar seguro: esto está en Bytes, ¿sí?
Jakub M.
66
Sí, coherency_line_size está en bytes.
John Zwinck
44
@android: uso la máquina fedora-18 x64 con procesador core-i5. cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_sizevuelve 64en mi sistema Lo mismo para las carpetas index1,2,3 también.
Abid Rahman K
141

En Linux, mire sysconf (3).

sysconf (_SC_LEVEL1_DCACHE_LINESIZE)

También puede obtenerlo desde la línea de comandos usando getconf:

$ getconf LEVEL1_DCACHE_LINESIZE
64
ob.
fuente
44
¡Las respuestas simples son las mejores!
FrankH.
3
@warunapww Está en bytes.
Maarten Bamelis
¡finalmente! Espero que más chicos vean esta respuesta para ahorrar tiempo.
elinx
118

He estado trabajando en algunas cosas de línea de caché y necesitaba escribir una función multiplataforma. Lo comprometí con un repositorio de github en https://github.com/NickStrupat/CacheLineSize , o puede usar la fuente a continuación. Siéntase libre de hacer lo que quiera con él.

#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
fuente
15
Podría ser mejor usar sysconf (_SC_LEVEL1_DCACHE_LINESIZE) para Linux.
Matt
@ Matt por qué? Sólo curioso :-).
user35915
31

En x86, puede usar la instrucción CPUID con la función 2 para determinar varias propiedades de la memoria caché y el TLB. Analizar la salida de la función 2 es algo complicado, así que lo referiré a la sección 3.1.3 de la Identificación del procesador Intel y la Instrucción CPUID (PDF).

Para obtener estos datos del código C / C ++, necesitará usar ensamblado en línea, intrínseco del compilador o llamar a una función de ensamblaje externo para realizar la instrucción CPUID.

Adam Rosenfield
fuente
Alguien sabe cómo hacer esto con otros procesadores con caché incorporado?
paxos1977
3
@ceretullis: Errr ... el x86 ha construido en caché. ¿Qué "otros procesadores" estás buscando específicamente? Lo que estás pidiendo depende de la plataforma.
Billy ONeal
9

Si está usando SDL2, puede usar esta función:

int SDL_GetCPUCacheLineSize(void);

Que devuelve el tamaño del tamaño de la línea de caché L1, en bytes.

En mi máquina x86_64, ejecutando este fragmento de código:

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

Produce CacheLineSize = 64

Sé que llego un poco tarde, pero solo agrego información para futuros visitantes. La documentación de SDL actualmente dice que el número devuelto está en KB, pero en realidad está en bytes.

negamartin
fuente
Oh, esto es realmente útil. Voy a escribir un juego en SDL2, así que esto será realmente útil
Nicholas Humphrey
7

En la plataforma de Windows:

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

La función GetLogicalProcessorInformation le dará características de los procesadores lógicos en uso por el sistema. Puede recorrer el SYSTEM_LOGICAL_PROCESSOR_INFORMATION devuelto por la función buscando entradas de tipo RelationCache. Cada una de estas entradas contiene un ProcessorMask que le dice a qué procesador (s) se aplica la entrada, y en CACHE_DESCRIPTOR, le dice qué tipo de caché se describe y qué tan grande es la línea de caché para ese caché.

Lorenzo Boccaccia
fuente
4

ARMv6 y superior tiene C0o el registro de tipo de caché. Sin embargo, solo está disponible en modo privilegiado.

Por ejemplo, del Manual de referencia técnica Cortex ™ -A8 :

El propósito del Registro de tipo de caché es determinar la longitud mínima de línea de la caché de instrucciones y datos en bytes para permitir que se invalide un rango de direcciones.

El registro de tipo de caché es:

  • un registro de solo lectura
  • accesible solo en modos privilegiados.

El contenido del registro de tipo de caché depende de la implementación específica. La figura 3-2 muestra la disposición de bits del registro de tipo de caché ...


No asuma que el procesador ARM tiene un caché (aparentemente, algunos se pueden configurar sin uno). La forma estándar de determinarlo es a través de C0. Desde ARM ARM , página B6-6:

Desde ARMv6, el registro del Tipo de caché del coprocesador de control del sistema es el método obligatorio para definir los cachés L1, consulte Registro del tipo de caché en la página B6-14. También es el método recomendado para variantes anteriores de la arquitectura. Además, Consideraciones para niveles adicionales de caché en la página B6-12 describe las pautas de arquitectura para el soporte de caché de nivel 2.

revs jww
fuente
3

También puede intentar hacerlo mediante programación midiendo algunos tiempos. Obviamente, no siempre será tan preciso como cpuid y similares, pero es más portátil. ATLAS lo hace en su etapa de configuración, es posible que desee verlo:

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

David Cournapeau
fuente