一,运行模式
在探索高性能编码时,一定要注意编译选项,不同编译优化级别场景下,同一个问题的答案可能截然相反!
如果是在visual studio里面运行,那就简单区分debug和release即可。
二,cache友好
1,二维数组的访问
二维数组的访问最好不要跳内存。
#include <stdio.h> #include "time.h" #define N 30000 #define M 1000 typedef struct { int a[N]; }Node; #define OUTCLOCK \ printf("%d ",clock()-theClock); \ theClock=clock(); int main() { clock_t theClock = clock(); Node *p = (Node *)malloc(sizeof(Node)*M); OUTCLOCK for (int j = 0; j < N; j++)for (int i = 0; i < M; i++)p[i].a[j] = i * j + 1; OUTCLOCK for (int i = 0; i < M; i++)for (int j = 0; j < N; j++)p[i].a[j] = i * j + 1; OUTCLOCK return 0; }debug模式运行,输出:17 81 68
release模式运行,输出:0 45 51
分析:
一般来说,for (int i = 0; i < M; i++)for (int j = 0; j < N; j++)这种遍历更快,因为符号cache友好。debug模式是符合结论的。
但是,release模式下,for (int j = 0; j < N; j++)for (int i = 0; i < M; i++)这种写法触发了编译器优化,反而优化后的性能比for (int i = 0; i < M; i++)for (int j = 0; j < N; j++)这种遍历更快。
2,大批量内存拷贝
大批量内存拷贝,用memcpy代替赋值语句
int main() { clock_t theClock=clock(); Node *p=(Node *)malloc(sizeof(Node)*M); int *p2=(int *)malloc(sizeof(int)*N*M); OUTCLOCK for(int i=0;i<M;i++)for(int j=0;j<N;j++)p2[i*N+j]=p[i].a[j]; OUTCLOCK memcpy(p2,p, sizeof(int)*N*M); OUTCLOCK return 0; }运行结果:
0 2811 276