Нарушения доступа к памяти при использовании операций SSE

Я пытался повторно реализовать некоторые существующие векторные и матричные классы для использования команд SSE3, и мне кажется, что я сталкиваюсь с этими ошибками «нарушения доступа к памяти» всякий раз, когда я выполняю серию операций над массивом векторов. Я относительно новичок в SSE, поэтому я начал с простого. Вот весь мой векторный класс:

class SSEVector3D
{
public:

SSEVector3D();
SSEVector3D(float x, float y, float z);

SSEVector3D& operator+=(const SSEVector3D& rhs); //< Elementwise Addition

float x() const;
float y() const;
float z() const;

private:

float m_coords[3] __attribute__ ((aligned (16))); //< The x, y and z coordinates

};

Итак, пока не так много всего, только несколько конструкторов, методов доступа и одна операция. Используя мои (по общему признанию ограниченные) знания о SSE, я реализовал операцию сложения следующим образом:

SSEVector3D& SSEVector3D::operator+=(const SSEVector3D& rhs)
{
__m128 * pLhs = (__m128 *) m_coords;
__m128 * pRhs = (__m128 *) rhs.m_coords;

*pLhs = _mm_add_ps(*pLhs, *pRhs);

return (*this);
}

Чтобы скоростно протестировать мой новый векторный класс по сравнению со старым (чтобы понять, стоит ли его заново реализовывать), я создал простую программу, которая генерирует случайный массив объектов SSEVector3D и складывает их вместе. Ничего сложного

SSEVector3D sseSum(0, 0, 0);

for(i=0; i<sseVectors.size(); i++)
{
sseSum += sseVectors[i];
}

printf("Total: %f %f %f\n", sseSum.x(), sseSum.y(), sseSum.z());

sseVectors переменная представляет собой std :: vector, содержащий элементы типа SSEVector3Dвсе компоненты которого инициализируются случайными числами между -1 а также 1,

Вот проблема, которая у меня возникла. Если размер sseVectors является 8,191 или меньше (число, которое я получил через много проб и ошибок), это работает нормально. Если размер 8,192 или больше, я получаю эту ошибку при попытке запустить ее:

сигнал: SIGSEGV, si_code: 0 (нарушение доступа к памяти по адресу: 0x00000080)

Однако, если я закомментирую этот оператор print в конце, я не получу ошибку, даже если sseVectors имеет размер 8192 или более.

Что-то не так с тем, как я написал этот векторный класс? Я использую Ubuntu 12.04.1 с GCC версии 4.6

3

Решение

Прежде всего, не делай этого

__m128 * pLhs = (__m128 *) m_coords;
__m128 * pRhs = (__m128 *) rhs.m_coords;
*pLhs = _mm_add_ps(*pLhs, *pRhs);

С SSE, всегда загружать и хранить явно через соответствующие встроенные функции, никогда просто разыменовывая. Вместо того, чтобы хранить массив из 3-х чисел в вашем классе, сохраните значение типа _m128, Это должно заставить компилятор корректно выравнивать экземпляры вашего класса, без необходимости align атрибутов.

Обратите внимание, однако, что это не очень хорошо работает с MSVC. MSVC, как правило, не в состоянии справиться с требованиями выравнивания, более строгими, чем 8-байтовые, выровненные для аргументов по значению :-(. В прошлый раз, когда мне нужно было переносить код SSE в Windows, я решил использовать компилятор Intel C ++ для частей SSE вместо MSVC …

1

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

Хитрость заключается в том, чтобы заметить, что __m128 выровнен на 16 байт. использование _malloc_aligned() чтобы убедиться, что ваш массив с плавающей точкой правильно выровнен, тогда вы можете продолжить и привести ваш float к массиву __m128, Также убедитесь, что количество размещаемых вами чисел делится на четыре.

0

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