2009-11-16 10 views
9

Recientemente me he encontrado con lo que creo que es un problema de uso compartido falso y he buscado Sutter's article para alinear mis datos a líneas de caché. Se sugiere el siguiente código C++:Alineación de línea de caché (Necesita aclaración del artículo)

// C++ (using C++0x alignment syntax) 
template<typename T> 
struct cache_line_storage { 
    [[ align(CACHE_LINE_SIZE) ]] T data; 
    char pad[ CACHE_LINE_SIZE > sizeof(T) 
     ? CACHE_LINE_SIZE - sizeof(T) 
     : 1 ]; 
}; 

puedo ver cómo esto funciona cuando CACHE_LINE_SIZE > sizeof(T) es cierto - la estructura cache_line_storage sólo termina tomando una línea de caché completa de la memoria. Sin embargo, cuando el sizeof(T) es más grande que una sola línea de caché, creo que deberíamos rellenar los datos por CACHE_LINE_SIZE - T % CACHE_LINE_SIZE bytes, de modo que la estructura resultante tenga un tamaño que sea un múltiplo entero del tamaño de la línea de caché. ¿Qué está mal con mi comprensión? ¿Por qué es suficiente el relleno con 1 byte?

Respuesta

7

No puede tener matrices de tamaño 0, por lo que se requiere 1 para compilarlas. Sin embargo, la versión actual del borrador de la especificación dice que dicho relleno no es necesario; el compilador debe rellenar la alineación de la estructura.

Tenga en cuenta también que este código está mal formado si CACHE_LINE_SIZE es menor que alignof(T). Para solucionar esto, probablemente debería usar [[align(CACHE_LINE_SIZE), align(T)]], lo que asegurará que nunca se elija una alineación más pequeña.

+0

+1, aunque en la práctica, no conozco ningún caso en el que una alineación de estructuras pueda ser mayor que el tamaño de la caché. Después de que todas las restricciones de alineación de tipo usualmente provienen de restricciones de caché. – Bahbar

+1

¿La alineación se aplica a la estructura o al primer elemento de la estructura en su sugerencia? –

+1

Pero en cuanto a la mecánica de compartir falsamente ... para evitarlo, ¿no debería 'T' alinearse con un múltiplo entero del tamaño de la línea de caché, incluso si' sizeof (T)> CACHE_LINE_SIZE'? ¿O esto no es necesario? – int3

3

Imagínese

#define CACHE_LINE_SIZE 32 
sizeof(T) == 48 

Ahora, consideremos cómo [[ align(CACHE_LINE_SIZE) ]], funciona. por ejemplo:

[[ align(32) ]] Foo foo; 

Esto obligará sizeof(Foo) == 32n por alguna n. es decir, align() lo rellenará, si es necesario, para que cosas como Foo foo[10]; tengan cada foo[i] alineado según lo solicitado.

Por lo tanto, en nuestro caso, con sizeof(T) == 48, esto significa sizeof(cache_line_storage<T>) == 64.

Así que la alineación le da el relleno que estaba esperando.

Sin embargo, este es un 'error' en la plantilla. Considere este caso:

#define CACHE_LINE_SIZE 32 
sizeof(T) == 32 

Aquí nos encontramos con char pad[1];. Lo que significa sizeof(cache_line_storage<T>) == 64. Probablemente no es lo que quieres!

creo que tendría que ser modificado un poco la plantilla:

template <typename T, int padding> 
struct pad_or_not 
{ 
    T data; 
    char pad[padding]; 
}; 

// specialize the 0 case 
// As it is late, I am SURE I've got the specialization syntax wrong... 
template <typename T, int> 
struct pad_or_not<0> 
{ 
    T data; 
}; 

template<typename T> 
struct cache_line_storage { 
    [[ align(CACHE_LINE_SIZE) ]] pad_or_not<T, (sizeof(T) > CACHE_LINE_SIZE ? 0 : CACHE_LINE_SIZE - sizeof(T)) > data; 
}; 

o algo por el estilo.

Cuestiones relacionadas