Donner à une instance de classe un pointeur sur une structure
-
05-07-2019 - |
Question
J'essaie d'obtenir la fonctionnalité SSE dans ma classe de vecteurs (je l'ai réécrite trois fois jusqu'à présent.: \) et je procède comme suit:
#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
Cela fonctionne! Hourra! Mais c'est plus lent que ma précédente tentative. Boo.
J'ai déterminé que mon goulot de bouteille était le malloc que j'utilise pour obtenir un pointeur sur une structure.
VectorData* Point3D::_NewData()
{
#if SSE_VERSION >= 2
return ((VectorData*) _aligned_malloc(sizeof(VectorData), 16));
#else
return ((VectorData*) malloc(sizeof(VectorData)));
#endif
}
L’un des principaux problèmes liés à l’utilisation de SSE dans une classe est qu’elle doit être alignée en mémoire pour fonctionner, ce qui implique de surcharger les nouveaux opérateurs et les opérateurs de suppression, ce qui entraîne un code comme celui-ci:
BadVector* test1 = new BadVector(1, 2, 3);
BadVector* test2 = new BadVector(4, 5, 6);
*test1 *= test2;
Vous ne pouvez plus utiliser le constructeur par défaut et vous devez éviter new
comme le fléau.
Ma nouvelle approche consiste essentiellement à avoir les données externes à la classe afin que celle-ci n'ait pas à être alignée.
Ma question est la suivante: existe-t-il un meilleur moyen d'obtenir un pointeur sur une instance (alignée sur la mémoire) d'une structure ou mon approche est-elle vraiment idiote et la méthode est-elle beaucoup plus propre?
La solution
Que diriez-vous de:
__declspec( align( 16 ) ) VectorData vd;
?
Vous pouvez également créer votre propre version de l'opérateur new comme suit
void* operator new( size_t size, size_t alignment )
{
return __aligned_malloc( size, alignment );
}
qui peut ensuite faire une allocation comme suit
AlignedData* pData = new( 16 ) AlignedData;
pour aligner sur une limite de 16 octets.
Si cela ne vous aide pas, je risque de ne pas comprendre ce que vous demandez ...
Autres conseils
Vous ne devriez probablement pas vous attendre à de meilleures performances pour les vecteurs à usage unique. Le traitement en parallèle est plus brillant lorsque vous pouvez combiner le traitement en parallèle avec un certain volume, c'est-à-dire lorsque vous traitez de nombreux vecteurs en séquence.
Je l'ai corrigé. : O
C'était vraiment plutôt facile. Tout ce que je devais faire était de tourner
VectorData* m_Point;
dans
VectorData m_Point;
et mes problèmes ont disparu, sans besoin de malloc ou d'alignement.
Mais j'apprécie l'aide de tous! : D