SSE编程求和报错求助:size=8时触发读取访问违例
SSE优化代码内存访问错误排查(size=8时崩溃)
嘿,我帮你找到了问题所在——你的代码触发了内存越界访问,还有个小语法错误得先修正。咱们一步步拆解:
核心崩溃原因:错误的存储指令导致内存越界
在你的sub_func_sse函数里,最后一步用了_mm_store_pd(ans + start_idx_ans, sum);,这个指令的作用是把__m128d寄存器里的2个double值连续写入内存。但你的需求是每个连续4个数的和只需要存1个double到ans_sse里,这就出问题了:
当size=8时,ans_sse的大小是8/4=2(也就是索引0和1):
- 第一次调用
sub_func_sse时,start_idx_ans=0,会写入ans_sse[0]和ans_sse[1],这时候还在合法内存范围内; - 第二次调用时,
start_idx_ans=1,会写入ans_sse[1]和ans_sse[2],但ans_sse只分配到索引1,ans_sse[2]属于未分配的内存,直接触发了访问违规错误。
另外,你代码里的arith_t = double是非法语法,得改成typedef double arith_t;才能编译通过。
修正后的代码
我把问题点都修复了,还优化了一些细节(比如循环变量用size_t避免类型警告):
#include <iostream> #include <immintrin.h> #include <vector> using namespace std; typedef double arith_t; // 修正语法错误 void init(arith_t *v, size_t size) { // 去掉不必要的指针引用 for (size_t i = 0; i < size; ++i) { // 用size_t匹配参数类型,避免类型转换警告 v[i] = i / 10.0; } } // SSE实现连续4个数求和 void sub_func_sse(arith_t *v, size_t size, int start_idx, arith_t *ans, size_t start_idx_ans) { __m128d first_part = _mm_loadu_pd(v + start_idx); __m128d second_part = _mm_loadu_pd(v + start_idx + 2); __m128d sum = _mm_add_pd(first_part, second_part); sum = _mm_hadd_pd(sum, sum); // 用_mm_store_sd存储单个double值,避免越界 _mm_store_sd(ans + start_idx_ans, sum); } int main() { const size_t size = 8; arith_t *v = new arith_t[size]; arith_t *ans_sse = new arith_t[size / 4]; init(v, size); init(ans_sse, size / 4); int num_repeat = 1; arith_t total_time_sse = 0; for (int p = 0; p < num_repeat; ++p) { for (size_t idx = 0, ans_idx = 0; idx < size; idx += 4, ans_idx++) { sub_func_sse(v, size, idx, ans_sse, ans_idx); } } for (size_t i = 0; i < size / 4; ++i) { cout << ans_sse[i] << endl; } delete[] ans_sse; delete[] v; return 0; }
额外提示
_mm_hadd_pd(sum, sum)执行后,寄存器的两个元素都是4个数的总和,所以只需要存其中一个就行,_mm_store_sd刚好用来存储单个double值;- 如果你的数组是内存对齐的(比如用
_mm_malloc分配),可以把_mm_loadu_pd换成_mm_load_pd,能获得更好的性能; - 新手排查内存问题时,可以用Valgrind这类工具,能快速定位越界、泄漏等问题。
内容的提问来源于stack exchange,提问作者NN_05
相关产品推荐
相关产品推荐

