Dar una instancia de una clase de un puntero a una estructura
-
05-07-2019 - |
Pregunta
Estoy tratando de obtener la funcionalidad SSE en mi clase vectorial (lo he reescrito tres veces hasta ahora.: \) y estoy haciendo lo siguiente:
#ifndef _POINT_FINAL_H_
#define _POINT_FINAL_H_
#include "math.h"
namespace Vector3D
{
#define SSE_VERSION 3
#if SSE_VERSION >= 2
#include <emmintrin.h> // SSE2
#if SSE_VERSION >= 3
#include <pmmintrin.h> // SSE3
#endif
#else
#include <stdlib.h>
#endif
#if SSE_VERSION >= 2
typedef union { __m128 vector; float numbers[4]; } VectorData;
//typedef union { __m128 vector; struct { float x, y, z, w; }; } VectorData;
#else
typedef struct { float x, y, z, w; } VectorData;
#endif
class Point3D
{
public:
Point3D();
Point3D(float a_X, float a_Y, float a_Z);
Point3D(VectorData* a_Data);
~Point3D();
// a lot of not-so-interesting functions
private:
VectorData* _NewData();
}; // class Point3D
}; // namespace Vector3D
#endif
Funciona! ¡Hurra! Pero es más lento que mi intento anterior. Boo.
He determinado que mi cuello de botella es el malloc que estoy usando para llevar el puntero a una estructura.
VectorData* Point3D::_NewData()
{
#if SSE_VERSION >= 2
return ((VectorData*) _aligned_malloc(sizeof(VectorData), 16));
#else
return ((VectorData*) malloc(sizeof(VectorData)));
#endif
}
Uno de los principales problemas con el uso de SSE en una clase es que debe estar alineado en la memoria para que funcione, lo que significa sobrecargar los operadores nuevos y eliminados, lo que da como resultado un código como este:
BadVector* test1 = new BadVector(1, 2, 3);
BadVector* test2 = new BadVector(4, 5, 6);
*test1 *= test2;
Ya no puedes usar el constructor predeterminado y debes evitar new
como la plaga.
Mi nuevo enfoque es básicamente tener los datos externos a la clase para que la clase no tenga que estar alineada.
Mi pregunta es: ¿hay una mejor manera de obtener un puntero a una instancia (alineada en la memoria) de una estructura o mi enfoque es realmente tonto y hay una forma mucho más limpia?
Solución
Cómo sobre: ??
__declspec( align( 16 ) ) VectorData vd;
?
También puede crear su propia versión de operador nueva de la siguiente manera
void* operator new( size_t size, size_t alignment )
{
return __aligned_malloc( size, alignment );
}
que luego puede hacer asignaciones como sigue
AlignedData* pData = new( 16 ) AlignedData;
para alinear en un límite de 16 bytes.
Si eso no ayuda, entonces puedo estar entendiendo mal lo que estás pidiendo ...
Otros consejos
Probablemente no debería esperar obtener un rendimiento mejorado para vectores de un solo uso. El procesamiento paralelo brilla más cuando se puede combinar el procesamiento paralelo con algún volumen, es decir, cuando se procesan muchos vectores en secuencia.
Lo arreglé. : O
Fue realmente bastante fácil. Todo lo que tenía que hacer era girar
VectorData* m_Point;
en
VectorData m_Point;
y mis problemas se han ido, sin necesidad de hacer malloc o alineación.
¡Pero aprecio la ayuda de todos! : D