存储 SSE 操作结果时的对齐要求
alignment requirements when storing the result of SSE operations
考虑使用英特尔 SSE 内在函数的代码片段,如下所示:
void foo(double* in1ptr, double* in2ptr)
{
double result[8];
/* .. stuff .. */
__m128d in1 = _mm_loadu_pd(in1ptr);
__m128d in2 = _mm_loadu_pd(in2ptr);
__m128d* resptr = (__m128d*)(&result[4]); <----------
*resptr = __mm_add_pd(in1,in2);
/* .. stuff .. */
}
在指示的行中 - 当声明 resptr
指向结果数组中索引 4 处的位置时 -
1) 这适用于 gcc
,但这是正确的处理方式吗?
2) 这里的对齐期望是什么,我可以创建指向任意内存位置的 resptr
指针,然后将 SSE 操作的结果存储在该内存位置吗?
load/store 内在函数的存在是为了向编译器传达对齐保证或缺乏对齐保证。如果您的数据是 16B 对齐或 32B 对齐,则不需要它们。
只是转换为 (__m128d*)
遵循暗示 __m128d
具有足够对齐的通常 C 语义。 (编译器使用 movapd
而不是 movupd
,如果地址未对齐,将在 运行 时出错。
在这种情况下,您没有采取任何措施来确保对齐。幸运的是您的本地数组是 16B 对齐的。如果您使用 alignas(16) double result[8];
,该代码将是安全的。
对于未对齐的商店,使用 _mm_storeu_pd
。另请参阅 x86 标签 wiki。
考虑使用英特尔 SSE 内在函数的代码片段,如下所示:
void foo(double* in1ptr, double* in2ptr)
{
double result[8];
/* .. stuff .. */
__m128d in1 = _mm_loadu_pd(in1ptr);
__m128d in2 = _mm_loadu_pd(in2ptr);
__m128d* resptr = (__m128d*)(&result[4]); <----------
*resptr = __mm_add_pd(in1,in2);
/* .. stuff .. */
}
在指示的行中 - 当声明 resptr
指向结果数组中索引 4 处的位置时 -
1) 这适用于 gcc
,但这是正确的处理方式吗?
2) 这里的对齐期望是什么,我可以创建指向任意内存位置的 resptr
指针,然后将 SSE 操作的结果存储在该内存位置吗?
load/store 内在函数的存在是为了向编译器传达对齐保证或缺乏对齐保证。如果您的数据是 16B 对齐或 32B 对齐,则不需要它们。
只是转换为 (__m128d*)
遵循暗示 __m128d
具有足够对齐的通常 C 语义。 (编译器使用 movapd
而不是 movupd
,如果地址未对齐,将在 运行 时出错。
在这种情况下,您没有采取任何措施来确保对齐。幸运的是您的本地数组是 16B 对齐的。如果您使用 alignas(16) double result[8];
,该代码将是安全的。
对于未对齐的商店,使用 _mm_storeu_pd
。另请参阅 x86 标签 wiki。