4

可能重复:
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

2 回答 2

5

它死了,因为结构没有对齐。CRT 分配器只承诺与 8 对齐,此处需要 16。您需要在 MSVC 上使用 _aligned_malloc() 来获得正确对齐的堆分配内存。

有两种方法可以解决它。由于这是一个 POD 结构,您可以直接转换:

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

或者您可以覆盖结构的新/删除运算符:

struct SimdTest
{
    void* operator new(size_t size) { return _aligned_malloc(size, 16); }
    void operator delete(void* mem) { return _aligned_free(mem); }
    // etc..
};
于 2012-10-03T19:22:11.390 回答
-1

MSDN 声明 _m128 自动对齐 16 个字节,而不是 __m128,而是 _m128。但无论如何我猜其他人是对的,因为我记得有两种移动指令,一种用于对齐的 movAps,一种用于未对齐的 - movUps。首先需要 16b 对齐,其他不需要。不知道编译器是否能够同时使用两者,但我尝试过这种 _m128 类型。

实际上有特殊类型:_M128A。

于 2012-10-03T17:49:12.967 回答