如何指示编译器为__m128生成未对齐的载荷

问题描述 投票:9回答:4

我有一些代码可以处理__m128值。我在这些值上使用x86-64 SSE内部函数,并且发现如果这些值在内存中未对齐,则会崩溃。这是由于我的编译器(在这种情况下为clang)仅生成对齐的加载指令。

我是否可以指示编译器全局或针对某些值(可能带有某种注释)生成未对齐的载荷?


我之所以具有未对齐的值,是因为我试图节省内存。我的struct大致如下:

#pragma pack(push, 4)
struct Foobar {
    __m128 a;
    __m128 b;
    int c;
};
#pragma pack(pop)

然后,我将创建这些结构的数组。数组中的第二个元素开始于36个字节,而不是16的倍数。]

我知道我可以切换到数组表示形式的结构,或者删除打包的杂注(以将结构的大小从36字节增加到48字节为代价);但我也知道,不对齐的负载现在并不那么昂贵,所以我想先尝试一下。


更新为回答以下一些评论:

我的实际代码更接近于此:

struct Vector4 {
    __m128 data;
    Vector4(__m128 v) : data(v) {}
};
struct Foobar {
    Vector4 a;
    Vector4 b;
    int c;
}

然后我有了一些实用程序功能,例如:

inline Vector4 add( const Vector4& a, const Vector4 &b ) {
    return Vector4(_mm_add_ps(a.data, b.data));
}

inline Vector4 subtract( const Vector4& a, const Vector4& b ) {
    return Vector4(_mm_sub_ps(a.data, b.data));
}

// etc..

我经常结合使用这些实用程序。假的例子:

Foobar myArray[1000];
myArray[i+1].b = sub(add(myArray[i].a, myArray[i].b), myArray[i+1].a);

[查看“ Z Bozon”的答案时,我的代码实际上更改为:

struct Vector4 {
    float data[4];
};

inline Vector4 add( const Vector4& a, const Vector4 &b ) {
    Vector4 result;
    _mm_storeu_ps(result.data, _mm_add_ps(_mm_loadu_ps(a.data), _mm_loadu_ps(b.data)));
    return result;
}

我担心的是,当如上组合使用实用程序功能时,所生成的代码可能具有冗余的加载/存储指令。事实证明这不是问题。我测试了我的编译器(clang),并已将其全部删除。我会接受Z Bozon的回答。

我有一些适用于__m128值的代码。我在这些值上使用x86-64 SSE内部函数,并且发现如果这些值在内存中未对齐,则会崩溃。这是由于我的编译器(...

c++ x86-64 sse simd intrinsics
4个回答
3
投票

我认为您应该使用标准的C ++结构(不是__m128i)编写数据结构。当您要使用非标准C ++的内部函数时,可以通过_mm_loadu_ps这样的内部函数“进入SSE世界”,然后使用_mm_storeu_ps这样的内部函数将“ SSE世界”留给标准C ++。不要依赖隐式的SSE加载和存储。我在执行此操作时看到了太多错误。


0
投票

您可以尝试将结构更改为:


0
投票

如果使用自动矢量化或显式OpenMP4 / Cilk / pragmas驱动的矢量化,则可以通过以下方式强制编译器对矢量化循环使用未对齐的负载:


0
投票

C具有-fmax-type-align。如果设置-fmax-type-align=8,则不会生成16字节对齐的指令。

© www.soinside.com 2019 - 2024. All rights reserved.