C语言局部变量与全局变量性能差异:为何前者快2倍?
为什么局部变量版本的fun_b比全局变量版本的fun_a快2倍?
测试结果
fun_b 4254600908 Duration: 5.168000 sec fun_a 4254600908 Duration: 18.455000 sec
核心性能差异原因
两者的速度差距完全来自变量存储位置和编译器优化空间的本质区别:
寄存器与内存的访问速度差
CPU访问寄存器的速度比访问内存快几个数量级(寄存器延迟仅1-2个时钟周期,内存访问至少几十到上百个周期)。- fun_b中的
result、mask、i都是局部变量,编译器会优先将它们分配到CPU通用寄存器中,整个循环的读写操作都在寄存器内完成,几乎没有内存开销。 - fun_a中的这三个变量是全局变量,存储在进程全局数据段。每次读写都需要从内存加载到寄存器,操作完成后还要写回内存,32次循环就会产生大量重复的内存IO开销,直接拖慢执行速度。
- fun_b中的
编译器优化的限制差异
全局变量的可见范围是整个程序,编译器无法确定其他代码是否会修改这些变量,因此无法进行激进优化:- 对于fun_b,编译器可以轻松将函数内联到主循环中,消除函数调用开销;还能对循环做展开、寄存器复用等优化,进一步提升效率。
- 对于fun_a,由于全局变量的存在,编译器不敢随意优化——比如不能把全局变量一直留在寄存器里(担心被其他线程或函数修改),只能每次都从内存重新读取,优化空间被极大限制。
缓存命中率差异
局部变量存储在栈上,栈内存通常会被CPU的L1高速缓存持续命中;而全局变量的频繁读写容易导致缓存行失效,需要从更低级缓存甚至内存重新加载,进一步放大性能差距。
测试代码
#include <stdio.h> #include <time.h> unsigned int result; unsigned int mask; unsigned int i; unsigned int fun_a(unsigned int value) { result = 0; mask = 1; for (i = 0; i < 32; i++) { if (value & mask) result++; mask <<= 1; } return result; } unsigned int fun_b(unsigned int value) { unsigned int result = 0; unsigned int mask = 1; for (unsigned int i = 0; i < 32; i++) { if (value & mask) result++; mask <<= 1; } return result; } int main(void) { unsigned int N = 0x12345678; clock_t startClock, finishClock; double f; unsigned int A; //////////////////////////////// printf("fun_b\n"); startClock = clock(); A = 0; for (unsigned int i = 0; i < N; i++) { A += fun_b(i); } finishClock = clock(); printf("%u\n", A); f = (double)(finishClock - startClock) / (double)(CLOCKS_PER_SEC); printf("Duration: %f sec\n", f); //////////////////////////////// printf("fun_a\n"); startClock = clock(); A = 0; for (unsigned int i = 0; i < N; i++) { A += fun_a(i); } finishClock = clock(); printf("%u\n", A); f = (double)(finishClock - startClock) / (double)(CLOCKS_PER_SEC); printf("Duration: %f sec\n", f); }
内容的提问来源于stack exchange,提问作者Igor
相关产品推荐
相关产品推荐

