He escrito una clase de vectores tridimensionales utilizando una gran cantidad de intrínsecos del compilador SSE. Todo funcionó bien hasta que comencé a instalar clases con el vector 3D como miembro con nuevas. Experimenté caídas extrañas en el modo de lanzamiento, pero no en el modo de depuración y viceversa.SSE, intrínsecos y alineación
Así que leí algunos artículos y pensé que necesitaba alinear las clases que poseen una instancia de la clase de vector 3D a 16 bytes también. Así que me acaba de agregar _MM_ALIGN16
(__declspec(align(16)
) delante de las clases de este modo:
_MM_ALIGN16 struct Sphere
{
// ....
Vector3 point;
float radius
};
que parecía resolver el problema al principio. Pero después de cambiar un código, mi programa comenzó a fallar de maneras extrañas. Busqué en la web un poco más y encontré un artículo de blog. Probé lo que el autor, Ernst Hot, hizo para resolver el problema y también me funciona. Añadí nuevo y borrar los operadores a mis clases de la siguiente manera:
_MM_ALIGN16 struct Sphere
{
// ....
void *operator new (unsigned int size)
{ return _mm_malloc(size, 16); }
void operator delete (void *p)
{ _mm_free(p); }
Vector3 point;
float radius
};
Ernst menciona que este abordaje podría ser problemático también, pero él sólo enlaces a un foro que ya no existe, sin explicar por qué podría ser problemático.
Así que mis preguntas son:
Cuál es el problema con la definición de los operadores?
¿Por qué no agregar
_MM_ALIGN16
a la definición de clase suficiente?¿Cuál es la mejor manera de manejar los problemas de alineación que vienen con los intrínsecos de SSE?
En el primer caso, ¿estás asignando tus estructuras en la pila o en el montón? No estoy seguro de que malloc regrese la memoria alineada de forma predeterminada, mientras que _mm_malloc sin duda lo haría, ¿a qué te refieres con "después de un tiempo mi programa comenzó a colapsar de nuevo"? ¿Te refieres después de dejarlo funcionando por un tiempo (y qué estaba haciendo)? – Thomas
Los problemas comenzaron cuando comencé a asignar las estructuras en el montón. Con la frase "después de un tiempo" quiero decir que comenzó a fallar después de que cambie el código. Supongo que la alineación fue correcta por accidente y luego la destruí. Creo que malloc no devuelve la memoria 16 bytes alineados, que es el problema, supongo. Mi pregunta es realmente cuál es el problema con el enfoque del operador y cuál es la mejor manera de administrar el código utilizando los intrínsecos de SSE. –
De hecho, no necesita especificar la alineación de 'Esfera' (usando esta cosa' _MM_ALIGN16'), ya que el compilador es lo suficientemente inteligente como para ver que 'Esfera' tiene un miembro alineado 16 y ajusta automáticamente' Esfera' s requisitos de alineación (dado que 'Vector3' está alineado correctamente). Esa es la razón por la que no tiene que alinear explícitamente 'Vector3' si ya tiene un miembro' __m128'. Solo la asignación dinámica es un problema y esto puede superarse al sobrecargar 'operator new/delete', como está escrito en el blog (y generalmente cosas adicionales, como 'std :: allocator'). –