c++ - Programáticamente obtener el tamaño de la línea de caché?
caching operating-system (8)
ARMv6 y superior tiene C0
o el Registro de tipo de caché. Sin embargo, solo está disponible en modo privilegiado.
Por ejemplo, de Cortex ™ -A8 Technical Reference Manual :
El objetivo del Registro de tipo de caché es determinar la longitud mínima de línea de la instrucción y del caché de datos en bytes para permitir la invalidación de un rango de direcciones.
El registro de tipo de caché es:
- un registro de solo lectura
- accesible en modos privilegiados solamente.
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 suponga que el procesador ARM tiene un caché (aparentemente, algunos pueden configurarse 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 Tipo de caché de Coprocesador de control del sistema es el método obligatorio para definir las cachés L1, consulte Registro de tipo de caché en la página B6-14. También es el método recomendado para las 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 la compatibilidad de caché de nivel 2.
Todas las plataformas son bienvenidas, por favor especifique la plataforma para su respuesta.
Una pregunta similar: ¿Cómo obtener programáticamente el tamaño de página del caché de la CPU en C ++?
En Linux (con un kernel 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 el caché que nunca esperaría saber, incluido el tamaño de la caché y qué CPU comparten este caché. Esto es muy útil si está realizando una programación multiproceso con datos compartidos (obtendrá mejores resultados si los subprocesos que comparten datos también comparten una caché).
En Linux, mire sysconf (3).
sysconf (_SC_LEVEL1_DCACHE_LINESIZE)
También puede obtenerlo desde la línea de comando usando getconf:
$ getconf LEVEL1_DCACHE_LINESIZE
64
En la plataforma de Windows:
de http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx
La función GetLogicalProcessorInformation le dará las 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 esas entradas contiene una ProcessorMask que le dice a qué procesador (s) se aplica la entrada, y en CACHE_DESCRIPTOR, le dice qué tipo de caché se está describiendo y qué tan grande es la línea de caché para esa caché.
En x86, puede usar la instrucción CPUID con la función 2 para determinar varias propiedades de la memoria caché y la TLB. Analizar el resultado 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 ++, deberá usar el ensamblaje en línea, los intrínsecos del compilador o llamar a una función de ensamblaje externo para realizar la instrucción CPUID.
He estado trabajando en algunas cosas de la 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 simplemente puede usar la fuente a continuación. Siéntete libre de hacer lo que quieras 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
Si está usando SDL2 puede usar esta función:
int SDL_GetCPUCacheLineSize(void);
Lo cual 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 llegué un poco tarde, solo agregué 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.
También puede intentar hacerlo programáticamente midiendo algunos tiempos. Obviamente, no siempre será tan preciso como cpuid y los gustos, pero es más portátil. ATLAS lo hace en su etapa de configuración, es posible que desee verlo: