【问题标题】:SIMD and dynamic memory allocation [duplicate]SIMD和动态内存分配[重复]
【发布时间】:2012-09-24 15:26:47
【问题描述】:

可能重复:
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 不,那宁愿对齐指针变量本身,这不是必需的,它是分配的内存,其地址分配给需要对齐的指针。

标签: c++ memory-management sse simd


【解决方案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)。
猜你喜欢
  • 2015-02-27
  • 1970-01-01
  • 2014-10-03
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
相关资源
最近更新 更多