使用SSE实现矩阵乘法时出现段错误或SIGABRT报错该如何解决?
SSE矩阵乘法报错及对齐、逻辑修正方案
你遇到的报错本质上是逻辑误用SIMD指令和数据未对齐两个问题共同导致的,修正方案如下:
1. 核心逻辑错误说明
当前代码的指令误用是报错的首要原因:
_mm_add_ss是单精度标量加法,仅计算向量第一个元素的和,剩下三个元素保持不变_mm_storeu_ps会一次性写入4个单精度浮点数,你循环步长设为1时,每次都会越界写入C(i,j+1)、C(i,j+2)、C(i,j+3)的内存,直接破坏堆结构,才会出现corrupted size vs. prev_size报错,和对齐无关。
参考代码的步长设为4是正确的,你出现仅1列填充的问题是因为没有用向量加法_mm_add_ps、向量乘法_mm_mul_ps完成4列的并行计算。
2. 数据对齐方案
要使用对齐的加载/存储指令(_mm_load_ps/_mm_store_ps)避免段错误,需要满足两个条件:
- 矩阵内存分配时按16字节对齐:使用
_mm_malloc分配矩阵内存,对齐参数指定为16,释放时配套使用_mm_free,不要用普通的malloc/free - 矩阵大小n为4的倍数,保证每行的字节数
n * sizeof(float)是16的整数倍,每行的首地址天然对齐
3. 修正后的完整代码
// 前置条件:n是4的倍数,A、B、C均通过_mm_malloc分配且16字节对齐 void mat_mult(Matrix A, Matrix B, Matrix C, int n) { for(int i = 0; i < n; ++i) { // 每次并行计算4列,步长固定为4 for(int j = 0; j < n; j += 4) { __m128 vR = _mm_setzero_ps(); for(int k = 0; k < n; k++) { // 广播A(i,k)到向量的四个元素 __m128 vA = _mm_set1_ps(A(i,k)); // 对齐加载B的k行j~j+3列的4个元素 __m128 vB = _mm_load_ps(&B(k,j)); // 向量乘加,同时完成4个列的累加计算 vR = _mm_add_ps(vR, _mm_mul_ps(vA, vB)); } // 对齐存储4个计算结果到C的i行j~j+3列 _mm_store_ps(&C(i,j), vR); } } }
内容的提问来源于stack exchange,提问作者NearFinished_CS
相关产品推荐
相关产品推荐

