我有一些代码可以处理__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 ++结构(不是__m128i
)编写数据结构。当您要使用非标准C ++的内部函数时,可以通过_mm_loadu_ps
这样的内部函数“进入SSE世界”,然后使用_mm_storeu_ps
这样的内部函数将“ SSE世界”留给标准C ++。不要依赖隐式的SSE加载和存储。我在执行此操作时看到了太多错误。
您可以尝试将结构更改为:
如果使用自动矢量化或显式OpenMP4 / Cilk / pragmas驱动的矢量化,则可以通过以下方式强制编译器对矢量化循环使用未对齐的负载:
C具有-fmax-type-align
。如果设置-fmax-type-align=8
,则不会生成16字节对齐的指令。