2012-02-19 16 views
9

Tengo varias clases que sufren de contención de caché y se asignan con el "nuevo" operador. ¿Puedo de alguna manera asegurarme de que "nuevo" arroje una dirección alineada a una línea de caché?Compartimiento falso en C++

Estoy usando GCC (si no es posible transportable).

+1

Una línea de caché suele tener 64 bytes. Debe tener algunas clases bastante pequeñas y, por lo tanto, debe realizar muchas asignaciones dinámicas bastante pequeñas. –

+0

Algunas son pequeñas, pero la mayoría se superponen (en una línea de caché). – jk4736

+0

¿Asigna sus instancias individualmente o en una matriz? – dasblinkenlight

Respuesta

1

Puede utilizar placement new para construir un objeto en una región determinada de la memoria:

// Instantiate object into a pre-allocated buffer 
    obj = new (buf) TheClass(); 

Para tener una memoria intermedia alineado buf, puede utilizar memalign, o sbrkmmap.

+0

No puedo ver la relación entre la pregunta y 'mmap'. ¿Por qué 'mmap'? – Frunsi

+2

Puede asignar un trozo de memoria alineado utilizando mmap ... – mfontanini

3

Puede usar memalign o _aligned_alloc para glibc o sistemas CRT de Windows, respectivamente. incluso puede usar un asignador personalizado como nedmalloc y hacer que alinee los bloques, lo que también podría darle otras bonificaciones adicionales.

también debe marcarlos con __attribute__((aligned(64))), por si acaso se asignan estáticamente.

2

La manera más fácil de resolver esto sería hacer que los objetos sean lo suficientemente grandes, que no puedan compartir una línea de caché. El uso de gcc se podía establecer la alineación de las clases (estoy suponiendo que los objetos son más pequeños y luego una cacheline ya que sufre de contención):

class foo {} __attribute__((aligned(2 * CL))); 

Es necesario insertar el Cachelinesize correcta para su arquitectura de CL por supuesto (o póngalo en una macro y use eso allí). Usé dos veces el tamaño de una línea de caché, porque por lo que recuerdo new no garantiza que realmente se asegure de que se mantenga la alineación. Como, por lo tanto, no se garantiza que el objeto comience al principio de una línea de caché, podría obtener partes de diferentes objetos en la misma línea de caché (es decir, el final de un objeto y el inicio de otro). Si la alineación siempre se conserva, __attribute__((aligned(CL))) estaría bien. Por supuesto, esto necesitará que cambies tus estructuras y que desperdicies mucho espacio.

También puede escribir su propio new (vea here para saber cómo hacerlo) basado en memalign. Para un tipo de solución más curvo, también podría usar memalign directamente y colocar un objeto dentro del espacio asignado con la colocación nueva. Por supuesto, hace que el código que usa esos objetos sea menos agradable.

Cuestiones relacionadas