SIMD и динамическое распределение памяти

Возможный дубликат:
SSE, внутренности и выравнивание

Я новичок в программировании SIMD, поэтому, пожалуйста, извините, если я задаю очевидный вопрос.

Я немного поэкспериментировал и дошел до того, что хочу сохранить значение SIMD в динамически распределенной структуре.

Вот код:

struct SimdTest
{
__m128      m_simdVal;

void setZero()
{
__m128 tmp = _mm_setzero_ps();
m_simdVal = tmp; // <<--- CRASH ---
}
};

TEST( Plane, dynamicallyAllocatedPlane )
{
SimdTest* test = new SimdTest();

test->setZero();

delete test;
}

Когда метод, помеченный комментарием CRASH, выполняется, код падает со следующим исключением:

Unhandled exception at 0x775315de in test-core.exe: 0xC0000005: Access violation reading location 0x00000000

Может ли кто-нибудь объяснить, почему прерывается операция присваивания и как SIMD-содержащие объекты распределяются динамически, чтобы они нормально работали?

Мне нужно добавить, что если я статически создаю экземпляр объекта SimdTest и вызываю метод setZero, все работает нормально.

Спасибо,
Паксас

4

Решение

Он умирает, потому что структура не выровнена. Распределитель CRT только обещает выравнивание до 8, 16 здесь требуется. Вам нужно будет использовать _aligned_malloc () в MSVC, чтобы получить правильно выровненную память, выделенную для кучи.

Два способа сделать это. Поскольку это структура POD, вы можете просто привести:

#include <malloc.h>
...
SimdTest* test = (SimdTest*)_aligned_malloc(sizeof SimdTest, 16);
test->setZero();
_aligned_free(test);

Или вы можете переопределить операторы new / delete для структуры:

struct SimdTest
{
void* operator new(size_t size) { return _aligned_malloc(size, 16); }
void operator delete(void* mem) { return _aligned_free(mem); }
// etc..
};
5

Другие решения

MSDN заявляет, что _m128 автоматически выровнены на 16 байтов, не __m128, а _m128. Но в любом случае я думаю, что остальные правы, насколько я помню, есть два вида команд перемещения, одна для выровненных movAps и одна для невыровненных — movUps. Сначала требуется 16b aligment, а другие нет. Не знаю, может ли компилятор использовать оба, но я попробовал этот тип _m128.

На самом деле для этого есть специальный тип: _M128A.

-1

По вопросам рекламы [email protected]