Alineando a la línea de caché y conociendo el tamaño de la línea de caché

Para evitar el intercambio falso, quiero alinear cada elemento de una matriz con una línea de caché. Así que primero necesito saber el tamaño de una línea de caché, así que 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. En primer lugar, ¿cómo puedo encontrar el tamaño de línea de caché. En segundo lugar, ¿cómo me alineo con una línea de caché en C. Estoy usando el comstackdor gcc?

Así que la estructura estaría siguiendo, por ejemplo, asumiendo 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, asumiendo por supuesto que 0-63 está alineado con una línea de caché.

Para conocer los tamaños, debe buscarlos en la documentación del procesador, pero no existe una 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, basadas en los estándares de intels. En x86, las líneas de caché tienen 64 bytes, sin embargo, para evitar el intercambio falso, debe seguir las pautas del procesador al que se dirige (intel tiene algunas notas especiales en sus procesadores basados ​​en netburst), generalmente necesita alinearse con 64 bytes para esto. (Intel dice que también debes evitar cruzar los límites de 16 bytes).

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

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

 $ getconf LEVEL1_DCACHE_LINESIZE 64 

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

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

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

No hay una forma completamente portátil de obtener el tamaño de cacheline. Pero si está en 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 del cacheline, cuántos 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 que obtiene la caché).

En cuanto a la alineación de sus estructuras de datos, tampoco hay 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 la estructura con variables no utilizadas hasta que coincida con la alineación que desea.

Para alinear tus mallocs (), todos los comstackdores convencionales también tienen funciones malloc alineadas para ese propósito.

Otra forma simple es simplemente cat / proc / cpuinfo:

cat / proc / cpuinfo | grep cache_alignment

Posix_memalign o valloc se pueden usar para alinear la memoria asignada a una línea de caché.

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

https://github.com/NickStrupat/Aligned