使用+=运算符时C代码运行变慢的原因排查求助
问题描述
编辑:我删除了问题中的部分内容以避免混淆,感谢各位解答,我本应自行排查。
我正在编写一个用谱函数对信号重采样的程序,原本用C语言实现,但转成C++编码时遇到了性能问题。
以下是核心代码片段:test()函数通过指针传递数组调用test3(tmp),当我用+=运算符填充第一个函数的数组时,代码运行速度明显变慢。
注:我用零值做初始化和计算,且所有数组必须是double类型。
测试代码
#include <stdio.h> #include <stdlib.h> void test3(double *tmp); void test() { double *tmp; int k; tmp = (double *) calloc(250 * 6, sizeof(double)); for (k = 0; k < 1000; ++k) test3(tmp); free(tmp); } void test3(double *tmp) { int k; double *fx; double *srf; double *ptr; int p; int l; int c; double a; fx = (double *) calloc(2100 * 6, sizeof(double)); srf = (double *) calloc(2100 * 250, sizeof(double)); for (int k = 0; k < 2100 * 6; ++k) fx[k] = 0; for (int k = 0; k < 2100 * 250; ++k) srf[k] = 0; ptr = (double *) calloc(250 * 6, sizeof(double)); for (p = 0; p < 6; ++p) { for (l = 0; l < 250; ++l) { ptr[l + p*250] = 0.0; for (c = 0; c < 2100; ++c) ptr[l+p*250] += fx[c+p*2100] * srf[c+l*2100]; } } for (k = 0; k < 250 * 6; ++k) tmp[k] = ptr[k]; free(ptr); free(fx); free(srf); } int main(int argc, char *argv[]) { test(); return 0; }
编译与运行信息
编译命令:
gcc -O2 -o test test.c -lm
运行time ./test得到的结果:
./test_lut 3.84s user 0.11s system 98% cpu 4.008 total
优化方案
- 删除冗余初始化:
calloc会自动将分配的内存初始化为0,后续手动循环给fx、srf、ptr赋值0完全多余,直接删除这些循环能减少无意义的内存操作。 - 减少动态内存分配次数:
test3每次调用都要分配、释放三块大内存,1000次调用会产生3000次内存申请/释放操作,这是主要性能瓶颈之一。可以将fx、srf的分配移到test函数中,只做一次分配后传递给test3,避免重复开销。 - 优化缓存命中率:当前
srf[c+l*2100]的访问模式属于跨列访问(按二维数组逻辑),CPU缓存利用率极低。可以调整srf的存储顺序为c*250 + l,让内存访问符合连续存储规律,大幅提升缓存效率。 - 移除中间数组
ptr:直接在tmp上完成累加计算,省去ptr的分配、赋值和拷贝步骤,减少内存占用与数据拷贝开销。
修改后的核心代码示例:
void test() { double *tmp = (double *) calloc(250 * 6, sizeof(double)); double *fx = (double *) calloc(2100 * 6, sizeof(double)); double *srf = (double *) calloc(2100 * 250, sizeof(double)); for (int k = 0; k < 1000; ++k) test3(tmp, fx, srf); free(tmp); free(fx); free(srf); } void test3(double *tmp, double *fx, double *srf) { int p, l, c; for (p = 0; p < 6; ++p) { for (l = 0; l < 250; ++l) { double sum = 0.0; for (c = 0; c < 2100; ++c) sum += fx[c+p*2100] * srf[c+l*2100]; tmp[l + p*250] = sum; } } }
内容的提问来源于stack exchange,提问作者Stéphane Guillaso
相关产品推荐
相关产品推荐

