Возможный дубликат:
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, все работает нормально.
Спасибо,
Паксас
Он умирает, потому что структура не выровнена. Распределитель 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..
};
MSDN заявляет, что _m128 автоматически выровнены на 16 байтов, не __m128, а _m128. Но в любом случае я думаю, что остальные правы, насколько я помню, есть два вида команд перемещения, одна для выровненных movAps и одна для невыровненных — movUps. Сначала требуется 16b aligment, а другие нет. Не знаю, может ли компилятор использовать оба, но я попробовал этот тип _m128.
На самом деле для этого есть специальный тип: _M128A.