Dare a un'istanza di una classe un puntatore a una struttura
-
05-07-2019 - |
Domanda
Sto cercando di ottenere la funzionalità SSE nella mia classe vettoriale (l'ho riscritta tre volte finora.: \) e sto facendo quanto segue:
#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
Funziona! Evviva! Ma è più lento del mio precedente tentativo. Boo.
Ho determinato che il mio collo di bottiglia è il malloc che sto usando per ottenere un puntatore a una struttura.
VectorData* Point3D::_NewData()
{
#if SSE_VERSION >= 2
return ((VectorData*) _aligned_malloc(sizeof(VectorData), 16));
#else
return ((VectorData*) malloc(sizeof(VectorData)));
#endif
}
Uno dei principali problemi con l'utilizzo di SSE in una classe è che deve essere allineato in memoria affinché funzioni, il che significa sovraccaricare i nuovi operatori ed eliminare, con conseguente codice come questo:
BadVector* test1 = new BadVector(1, 2, 3);
BadVector* test2 = new BadVector(4, 5, 6);
*test1 *= test2;
Non puoi più usare il costruttore predefinito e devi evitare new
come la peste.
Il mio nuovo approccio è sostanzialmente quello di avere i dati esterni alla classe in modo che la classe non debba essere allineata.
La mia domanda è: c'è un modo migliore per ottenere un puntatore a un'istanza (allineata sulla memoria) di una struttura o il mio approccio è davvero stupido e c'è un modo molto più pulito?
Soluzione
Che ne dici di:
__declspec( align( 16 ) ) VectorData vd;
Puoi anche creare la tua nuova versione dell'operatore come segue
void* operator new( size_t size, size_t alignment )
{
return __aligned_malloc( size, alignment );
}
che può quindi effettuare le allocazioni come segue
AlignedData* pData = new( 16 ) AlignedData;
per allinearsi ad un limite di 16 byte.
Se questo non è di aiuto, allora potrei fraintendere quello che stai chiedendo ...
Altri suggerimenti
Probabilmente non dovresti aspettarti di migliorare le prestazioni per i vettori monouso. L'elaborazione parallela brilla di più quando è possibile combinare l'elaborazione parallela con un certo volume, vale a dire quando si elaborano molti in sequenza.
L'ho risolto. : O
È stato davvero piuttosto semplice. Tutto quello che dovevo fare era girare
VectorData* m_Point;
in
VectorData m_Point;
e i miei problemi sono spariti, senza bisogno di malloc o allineamento.
Ma apprezzo l'aiuto di tutti! : D