使用SSE操作时内存访问冲突

时间:2012-09-12 18:14:59

标签: c++ ubuntu vector sse sse3

我一直在尝试重新实现一些现有的向量和矩阵类来使用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类型的元素,其组件全部初始化为-11之间的随机数。

这是我遇到的问题。如果sseVectors的大小为8,191或更小(我通过大量试验和错误得出的数字),这样运行正常。如果大小为8,192或更大,我在尝试运行时会出现此错误:

  

信号:SIGSEGV,si_code:0(地址:0x00000080处的内存访问冲突)

但是,如果我在结尾处注释掉该print语句,即使sseVectors的大小为8,192或更多,我也不会收到任何错误。

我写这个矢量类的方式有问题吗?我正在使用GCC 4.6版运行Ubuntu 12.04.1

2 个答案:

答案 0 :(得分:1)

首先,最重要的是,不要这样做

__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时,我的解决方案是使用英特尔的C ++编译器来处理SSE部件而不是MSVC ...

答案 1 :(得分:0)

诀窍是注意__m128是16字节对齐的。使用_malloc_aligned()确保您的浮点数组正确对齐,然后您可以继续将浮点数转换为__m128数组。还要确保您分配的浮点数可以被4整除。