c linux caching computer-architecture memory-alignment

Alineación a la línea de caché y conocer el tamaño de la línea de caché



linux caching (6)

Para evitar el uso compartido falso, quiero alinear cada elemento de una matriz con una línea de caché. Entonces, primero necesito saber el tamaño de una línea de caché, así que le asigno a cada elemento esa cantidad de bytes. En segundo lugar, quiero que el inicio de la matriz se alinee con una línea de caché.

Estoy usando Linux y la plataforma x86 de 8 núcleos. Primero, ¿cómo puedo encontrar el tamaño de la línea de caché? En segundo lugar, ¿cómo me alineo con una línea de caché en C. Estoy usando el compilador gcc?

Entonces la estructura estaría siguiendo, por ejemplo, suponiendo un tamaño de línea de caché de 64.

element[0] occupies bytes 0-63 element[1] occupies bytes 64-127 element[2] occupies bytes 128-191

y así sucesivamente, suponiendo por supuesto que 0-63 está alineado con una línea de caché.


Estoy usando Linux y la plataforma x86 de 8 núcleos. Primero, ¿cómo puedo encontrar el tamaño de la línea de caché?

$ getconf LEVEL1_DCACHE_LINESIZE 64

Pase el valor como una definición de macro al compilador.

$ gcc -DLEVEL1_DCACHE_LINESIZE=`getconf LEVEL1_DCACHE_LINESIZE` ...

En tiempo de ejecución, sysconf(_SC_LEVEL1_DCACHE_LINESIZE) se puede usar para obtener el tamaño de caché L1.


No hay una forma completamente portátil de obtener el tamaño de la caché. Pero si tiene x86 / 64, puede llamar a la instrucción cpuid para obtener todo lo que necesita saber sobre el caché, incluido el tamaño, el tamaño de la caché, el número de niveles, etc.

http://softpixel.com/~cwright/programming/simd/cpuid.php

(desplácese hacia abajo un poco, la página trata sobre SIMD, pero tiene una sección para obtener la línea de caché).

En cuanto a la alineación de sus estructuras de datos, tampoco existe una forma completamente portátil de hacerlo. GCC y VS10 tienen diferentes formas de especificar la alineación de una estructura. Una forma de "piratear" es rellenar su estructura con variables no utilizadas hasta que coincida con la alineación que desea.

Para alinear sus mallocs (), todos los compiladores mainstream también tienen funciones malloc alineadas para ese propósito.


Otra forma simple es simplemente cat the / proc / cpuinfo:

cat / proc / cpuinfo | grep cache_alignment


Para conocer los tamaños, debe buscarlos usando la documentación del procesador, afaik no hay forma programática de hacerlo. En el lado positivo, sin embargo, la mayoría de las líneas de caché son de un tamaño estándar, según los estándares intels. En x86, las líneas de caché son de 64 bytes, sin embargo, para evitar el uso compartido falso, debe seguir las pautas del procesador al que se dirige (intel tiene algunas notas especiales en sus procesadores basados ​​en red), generalmente necesita alinear a 64 bytes para este (Intel dice que también debes evitar cruzar límites de 16 bytes).

Para hacer esto en C o C ++, se requiere el uso de la función aligned_alloc estándar o uno de los especificadores específicos del compilador, como __attribute__((align(64))) o __declspec(align(64)) . Para rellenar entre miembros en una estructura para dividirlos en diferentes líneas de caché, debe insertar un miembro lo suficientemente grande como para alinearlo con el siguiente 64 byte boundery


Si alguien tiene curiosidad acerca de cómo hacer esto fácilmente en C ++, he creado una biblioteca con una CacheAligned<T> que maneja la determinación del tamaño de la línea de caché, así como la alineación para su objeto T , a la que se hace referencia llamando a .Ref() en su objeto CacheAligned<T> . También puede usar Aligned<typename T, size_t Alignment> si conoce el tamaño de la línea de caché de antemano, o simplemente quiere seguir con el valor muy común de 64 (bytes).

https://github.com/NickStrupat/Aligned