SSE _mm_load_ps 导致分段错误
Posted
技术标签:
【中文标题】SSE _mm_load_ps 导致分段错误【英文标题】:SSE _mm_load_ps causing segmentation faults 【发布时间】:2014-02-12 08:17:54 【问题描述】:所以我在学习使用 SSE 内在函数编程的玩具示例时遇到了麻烦。我在这里读到其他线程,有时 _mm_load_ps 函数的分段错误是由于未正确对齐事物引起的,但我认为它应该由 attribute((aligned(16 ))) 我做的事情。此外,当我在代码中注释掉第 23 行或第 24 行(或两者)时,问题就会消失,但显然这会使代码无法正常工作。
#include <iostream>
using namespace std;
int main()
float temp1[] __attribute__((__aligned__(16))) = 1.1,1.2,1.3,14.5,3.1,5.2,2.3,3.4;
float temp2[] __attribute__((__aligned__(16))) = 1.2,2.3,3.4,3.5,1.2,2.3,4.2,2.2;
float temp3[8];
__m128 m, *m_result;
__m128 arr1 = _mm_load_ps(temp1);
__m128 arr2 = _mm_load_ps(temp2);
m = _mm_mul_ps(arr1, arr2);
*m_result = _mm_add_ps(m, m);
_mm_store_ps(temp3, *m_result);
for(int i = 0; i < 4; i++)
cout << temp3[i] << endl;
m_result++;
arr1 = _mm_load_ps(temp1+4);
arr2 = _mm_load_ps(temp2+4);
m = _mm_mul_ps(arr1, arr2);
*m_result = _mm_add_ps(m,m);
_mm_store_ps(temp3, *m_result);
for(int i = 0; i < 4; i++)
cout << temp3[i] << endl;
return 0;
第 23 行是 arr1 = _mm_load_ps(temp1+4)。对我来说很奇怪,我可以做一个或另一个,但不能同时做。任何帮助将不胜感激,谢谢!
【问题讨论】:
您已将 temp1 与 16 字节对齐,但随后添加了 4 以确保它不是 16 字节对齐... 对不起,我不跟,我不是必须用_mm_load_ps(temp1+4)来加载接下来的4个值吗? @jcoder: +4 (floats) 是 +16 字节,所以负载没问题 - 这里的问题是两个商店。 ...当然还有悬空指针。 @PaulR 绝对。请无视我的评论...在我喝了至少 2 杯咖啡之前,我不应该发表评论!对于错误的评论,我深表歉意。 【参考方案1】:您的问题是您声明了一个指针__m128 *m_result
,但您从未为它分配任何空间。稍后您还会执行m_result++
,它指向另一个尚未分配的内存地址。这里没有理由使用指针。
#include <xmmintrin.h> // SSE
#include <iostream>
using namespace std;
int main()
float temp1[] __attribute__((__aligned__(16))) = 1.1,1.2,1.3,14.5,3.1,5.2,2.3,3.4;
float temp2[] __attribute__((__aligned__(16))) = 1.2,2.3,3.4,3.5,1.2,2.3,4.2,2.2;
float temp3[8];
__m128 m, m_result;
__m128 arr1 = _mm_load_ps(temp1);
__m128 arr2 = _mm_load_ps(temp2);
m = _mm_mul_ps(arr1, arr2);
m_result = _mm_add_ps(m, m);
_mm_store_ps(temp3, m_result);
for(int i = 0; i < 4; i++)
cout << temp3[i] << endl;
arr1 = _mm_load_ps(temp1+4);
arr2 = _mm_load_ps(temp2+4);
m = _mm_mul_ps(arr1, arr2);
m_result = _mm_add_ps(m,m);
_mm_store_ps(temp3, m_result);
for(int i = 0; i < 4; i++)
cout << temp3[i] << endl;
return 0;
【讨论】:
还要注意temp3
可能未对齐。
好点。我刚刚尝试了代码并且它有效。这可能是因为它是在 64 位模式下编译的,它将堆栈上的变量对齐到 16 个字节。
是的,编译为 64 位既是福也是祸。另请注意,您在这里不需要 SSE4.1 - 上面的代码中除了 SSE2 之外什么都没有。
再次正确。我虽然他说他用过_mm_dp_ps
,但我现在看不到。
@PaulR,实际上,这里除了 SSE 之外什么都没有。甚至不需要 SSE2。【参考方案2】:
(1) m_result
只是一个wild pointer:
__m128 m, *m_result;
将所有出现的*m_result
更改为m_result
并去掉m_result++;
。 (m_result
只是一个临时向量变量,您随后将其存储到temp3
)。
(2) 您的两个商店可能未对齐,因为 temp3
没有保证对齐 - 要么更改:
float temp3[8];
到:
float temp3[8] __attribute__((__aligned__(16)));
或使用_mm_storeu_ps
:
_mm_storeu_ps(temp3, m_result);
^^^
【讨论】:
+1 因为你的答案比我的好一点。虽然我认为这里的正确术语是野指针而不是悬空指针。野指针是尚未初始化到已分配内存的指针,而悬空指针是指向已释放内存的指针。 en.wikipedia.org/wiki/Dangling_pointer 你说得对——严格来说这是一个野指针——我一直称它们为悬空指针,不管它们是野指针还是悬空指针,这是一个很难改掉的习惯。我会解决的。以上是关于SSE _mm_load_ps 导致分段错误的主要内容,如果未能解决你的问题,请参考以下文章