2009-09-11 26 views
1

J'essaie d'obtenir la fonctionnalité SSE dans ma classe de vecteurs (je l'ai réécrit trois fois jusqu'à présent.: \) Et je fais ce qui suit:Donner une instance d'une classe un pointeur à une structure

#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 tentative précédente. Huer.

J'ai déterminé que mon col de bouteille est le malloc que j'utilise pour obtenir un pointeur vers 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 avec l'utilisation SSE dans une classe est qu'il doit être stocké en mémoire pour que cela fonctionne, ce qui signifie une surcharge de la nouvelle et de supprimer les opérateurs, ce qui code comme ceci:

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 la peste.

Ma nouvelle approche consiste essentiellement à avoir les données externes de la classe afin que la classe ne doive pas être alignée.

Ma question est la suivante: y a-t-il un meilleur moyen d'obtenir un pointeur vers une instance (alignée sur la mémoire) d'une structure ou est-ce que mon approche est vraiment bête?

Répondre

2

Que diriez-vous:

__declspec(align(16)) VectorData vd; 

?

Vous pouvez également créer votre propre version de l'opérateur nouveau comme suit

void* operator new(size_t size, size_t alignment) 
{ 
    return __aligned_malloc(size, alignment); 
} 

qui peut alors faire allocationas suit

AlignedData* pData = new(16) AlignedData; 

pour aligner à une limite de 16 octets.

Si c'est d'aucune aide alors je peux être ce que vous comprennent mal demandez ...

+1

Vous voulez dire _declspec, je suppose? – cedrou

+0

LOL n'a vraiment pas remarqué cette faute de frappe !! – Goz

1

vous devriez vous attendre probablement pas d'obtenir de meilleures performances pour les vecteurs à usage unique. Le traitement parallèle est le plus brillant lorsque vous pouvez combiner le traitement parallèle avec un certain volume, c'est-à-dire lors du traitement de nombreux vecteurs en séquence.

0

Je l'ai corrigé. : O

C'était vraiment plutôt facile. Tout ce que je devais faire était tour

VectorData* m_Point; 

dans

VectorData m_Point; 

et sont partis mes problèmes, sans avoir besoin de malloc ou l'alignement.

Mais j'apprécie l'aide de tout le monde! : D

+0

Désolé, mais j'en doute. Oui, le compilateur MS sur x86-64 s'aligne sur une limite de 16 octets (pas pour les plates-formes 32 bits).Je doute que ICC _always_ alignera 16 octets sur la pile si ce n'est pas explicitement dit, aussi, exactement _because_ il essaie de générer du code vraiment rapide. Un declspec sera nécessaire, resp. l'option gcc correspondante. – gimpf

+0

Et, oui, malloc() était une mauvaise idée en premier lieu ... – gimpf