SIMD和动态内存分配[重复]

Posted

技术标签:

【中文标题】SIMD和动态内存分配[重复]【英文标题】:SIMD and dynamic memory allocation [duplicate] 【发布时间】:2012-10-03 16:37:39 【问题描述】:

可能重复:SSE, intrinsics, and alignment

我是 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 方法,一切正常。

谢谢, 帕克萨斯

【问题讨论】:

看起来你是最新的错位受害者。 new 没有充分对齐 16 个字节。 在外面的某个地方一定有一个很好的副本。 是的——肯定是这样。当我将自定义分配器添加到将分配的内存地址与 16 字节边界对齐的类时,一切都开始正常工作了。 尝试:__declspec(align(16)) SimdTest * test = ... @stark 不,那宁愿对齐指针变量本身,这不是必需的,它是分配的内存,其地址分配给需要对齐的指针。 【参考方案1】:

它死了,因为结构没有对齐。 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..
;

【讨论】:

附带说明,这些重载的实现通常还有更多内容,其他new/delete 版本也应该有重载(同样还有std::allocator 的特化)。我知道你知道这一点,只是为了向其他读者评论,所以无论如何都要 +1。【参考方案2】:

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

其实有专门的型号:_M128A。

【讨论】:

我认为不存在 _m128_M128A 类型。而__m128 自动对齐到 16 个字节,但这并不总是有效(例如,在进行动态分配时)。 __m128 类型(是的,它是 __m128 而不是 _m128,我从来没有听说过)如果在堆栈上分配(例如作为自动变量)是正确对齐的。但这在动态分配它们时无济于事(例如使用new)。

以上是关于SIMD和动态内存分配[重复]的主要内容,如果未能解决你的问题,请参考以下文章

动态内存分配如何工作[重复]

c和c ++中的动态内存分配和堆有啥区别

Green Hills Integrity 动态内存分配

删除动态分配的内存的最佳做法是啥?

动态分配 SIMD 向量数组是不是安全?

c语言中啥是动态分配内存?