Предоставление экземпляру класса указателя на структуру
-
05-07-2019 - |
Вопрос
Я пытаюсь получить функциональность SSE в своем векторном классе (на данный момент я переписывал его три раза.:\) и я делаю следующее:
#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
Это работает!Ура!Но это медленнее, чем моя предыдущая попытка.Бу.
Я определил, что мое бутылочное горлышко - это malloc, который я использую для получения указателя на структуру.
VectorData* Point3D::_NewData()
{
#if SSE_VERSION >= 2
return ((VectorData*) _aligned_malloc(sizeof(VectorData), 16));
#else
return ((VectorData*) malloc(sizeof(VectorData)));
#endif
}
Одна из основных проблем при использовании SSE в классе заключается в том, что для его работы он должен быть выровнен в памяти, что означает перегрузку операторов new и delete, что приводит к подобному коду:
BadVector* test1 = new BadVector(1, 2, 3);
BadVector* test2 = new BadVector(4, 5, 6);
*test1 *= test2;
Вы больше не можете использовать конструктор по умолчанию, и вам следует избегать new
как от чумы.
Мой новый подход в основном заключается в том, чтобы данные были внешними по отношению к классу, поэтому класс не нужно выравнивать.
Мой вопрос заключается в следующем:есть ли лучший способ получить указатель на экземпляр структуры (выровненный по памяти) или мой подход действительно глупый и есть гораздо более чистый способ?
Решение
Как насчет:
__declspec( align( 16 ) ) VectorData vd;
?
Вы также можете создать свою собственную версию operator new следующим образом
void* operator new( size_t size, size_t alignment )
{
return __aligned_malloc( size, alignment );
}
который затем может произвести распределение следующим образом
AlignedData* pData = new( 16 ) AlignedData;
для выравнивания по границе в 16 байт.
Если это не поможет, то, возможно, я неправильно понимаю, о чем вы просите...
Другие советы
Вероятно, не стоит ожидать улучшения производительности для одноразовых векторов. Параллельная обработка сияет ярче, когда вы можете объединить параллельную обработку с некоторым объемом, то есть при последовательной обработке многих векторов.
Я все починил.:O
Это было действительно довольно просто.Все, что мне нужно было сделать, это повернуть
VectorData* m_Point;
в
VectorData m_Point;
и мои проблемы исчезли, больше не нужно использовать malloc или выравнивание.
Но я ценю помощь каждого!:D