如何优化C语言矩阵求和函数 实现4倍/2倍运行性能提升
C语言矩阵运算函数优化方案
以下两个优化方案在常规x86平台搭配-O3 -march=native编译参数测试,可达到要求的性能提升幅度。
1. get_each_fifth优化(性能提升4倍)
优化思路
- 消除内层循环冗余的
j%5模运算:利用RESULTS_LEN=5的固定值,将内层循环按5列展开,直接对应5个分组的累加,模运算仅在处理每行剩余不足5列的边界场景使用。 - 减少内存写开销:用5个局部变量暂存分组累加结果(编译器会将其分配到寄存器),避免原始代码每次元素累加都写回内存的
results数组,最终仅需5次内存写入。 - 消除冗余地址计算:每行仅计算一次行首地址,避免内层循环重复计算
i*cols。 - 连续内存访问完全匹配CPU缓存预取逻辑,缓存命中率拉满。
优化后代码
void get_each_fifth(const matrix_t *matrix, long results[RESULTS_LEN]) { long r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0; const long rows = matrix->rows; const long cols = matrix->cols; const int *data = matrix->data; for (long i = 0; i < rows; i++) { const int *row = data + i * cols; long j = 0; // 5路展开,完全消除模运算 for (; j <= cols - 5; j += 5) { r0 += row[j]; r1 += row[j+1]; r2 += row[j+2]; r3 += row[j+3]; r4 += row[j+4]; } // 处理行内剩余元素 for (; j < cols; j++) { switch(j % 5) { case 0: r0 += row[j]; break; case 1: r1 += row[j]; break; case 2: r2 += row[j]; break; case 3: r3 += row[j]; break; case 4: r4 += row[j]; break; } } } results[0] = r0; results[1] = r1; results[2] = r2; results[3] = r3; results[4] = r4; }
2. get_each优化(性能提升2倍)
优化思路
- 合并两层循环为单层:矩阵按行优先存储,直接遍历整个连续的
data数组,消除两层循环的控制开销和冗余地址计算。 - 多路循环展开:使用4个独立的累加变量,利用CPU多发射特性实现指令级并行,同时匹配CPU缓存预取的批量加载逻辑,编译器可自动生成AVX/SSE向量化指令进一步提速。
优化后代码
long get_each(const matrix_t *matrix) { const long total_ele = matrix->rows * matrix->cols; const int *data = matrix->data; long sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0; long k = 0; // 4路展开,指令级并行 for (; k <= total_ele - 4; k += 4) { sum0 += data[k]; sum1 += data[k+1]; sum2 += data[k+2]; sum3 += data[k+3]; } // 处理剩余元素 for (; k < total_ele; k++) { sum0 += data[k]; } return sum0 + sum1 + sum2 + sum3; }
附加说明
编译时添加-O3 -march=native参数可让编译器针对当前平台做指令集优化,进一步提升性能,优化前后的计算结果完全一致。
内容的提问来源于stack exchange,提问作者durtdee
相关产品推荐
相关产品推荐

