3

我一直在尝试重新实现一些现有的向量和矩阵类以使用 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

这是我遇到的问题。如果大小sseVectors8,191或小于(我通过大量试验和错误得出的数字),则运行良好。如果大小是8,192或更大,当我尝试运行它时会出现此错误:

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

但是,如果我在最后注释掉该打印语句,即使sseVectors大小为 8,192 或更大,我也不会收到错误消息。

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

4

2 回答 2

1

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

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

使用 SSE,始终通过适当的内在函数显式地进行加载和存储,而不是仅仅通过取消引用。不要在你的类中存储一个包含 3 个浮点数的数组,而是存储一个 type 的值_m128。这应该使编译器正确对齐类的实例,而不需要任何align属性。

但是请注意,这不适用于 MSVC。MSVC 似乎通常无法处理比按值参数对齐的 8 字节更强的对齐要求:-(。上次我需要将 SSE 代码移植到 Windows 时,我的解决方案是使用 Intel 的 C++ 编译器来处理 SSE 部分而不是 MSVC...

于 2012-10-01T11:45:44.717 回答
0

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

于 2014-01-16T03:25:52.133 回答