C++性能剖析教程之循环展开

📅 2026/7/13 6:28:40
C++性能剖析教程之循环展开
什么是循环展开循环展开英文中称Loop unwinding或loop unrolling是一种牺牲程序的尺寸来加快程序的执行速度的优化方法。可以由程序员完成也可由编译器自动优化完成。循环展开最常用来降低循环开销为具有多个功能单元的处理器提供指令级并行。也有利于指令流水线的调度。循环展开能从两方面改进程序的性能减少了不直接有助于程序结果的操作的数量例如循环索引计算和分支条件。提供了一些方法可以进一步变化代码减少整个计算中关键路径上的操作数量。循环展开对程序性能的影响我们直接以实际代码向大家展示循环展开的作用首先看未经过循环展开优化的代码12345678910111213141516#include iostream#include chronointmain(){auto start std::chrono::system_clock::now();intsum 0;intcount 10000;//循环10000次累加for(inti 0;i count;i){sum i;}auto end std::chrono::system_clock::now();std::chrono::durationdouble dura end - start;std::cout 共耗时 dura.count() s std::endl;return0;}类似于上面的这段代码是我们平常工作中经常见到的函数目的就是求得12……99989999的累加和每次循环把i累加到sum变量上循环次数一共10000次。代码运行结果如下可以看出代码运行耗时0.0000279秒。下面我们将循环展开一次即把上述代码中的循环改为如下代码1234for(inti 0;i count;i 2){sum i;sum i1;}即每次循环将i和i1一起累加到sum变量上这样可以把循环次数从10000次降低到5000次由于CPU的高度流水线化连续两个加法指令增加耗时很低所以此版本代码可以一定程度上提高程序运行速度运行结果如下代码运行耗时0.0000159秒相较于未优化代码速度快了将近一倍。当然我们可以继续增加循环展开次数以进一步提高程序运行速度但是这个增加循环展开次数也是有限度的当达到了CPU的最高吞吐量之后继续增加循环展开次数是没有意义的。上述循环展开后的代码依然有进一步优化的空间那就是消除连续指令的相关性以达到指令级并行我们可以看到循环展开后的代码循环体中有两条语句sum i 和 sum i1第二条语句sum i1依赖于第一条命来sum i的执行结果所以这两条语句只能依次执行限制了CPU进一步提高性能的可能。如果我们将循环体改为如下代码123456intsum10,sum20;for(inti0;i count;i2){sum1 i;sum2 i1;}sum sum1 sum2;我们新建了两个变量sum1和sum2用于存储循环展开时两个累加语句的累加结果最后在循环体外将两部分结果相加得到最终结果。该代码中两个累加语句之间是互不相关的所以CPU可以并行执行这两条指令以达到性能的进一步提高。下面是运行结果代码运行耗时0.0000073秒相较于只进行循环展开的代码速度又快了将近一倍。总结由上面三段代码的运行速度对比可以看出循环展开对程序性能有着很重要的影响可以减少分支预测错误次数增加取消数据相关进一步利用并行执行提高速度的机会。但是并不建议大家进行手动的循环展开在代码中进行循环展开会导致程序的可读性下降代码膨胀。为了直观感受循环展开对性能的影响上述代码运行结果均是在不开编译器优化的情况下进行的测试其实在我们开启了编译器优化的时候编译器会自动对我们的循环代码进行循环展开让我们可以在保持了代码可读性的同时又能享受到循环展开对我们程序性能的提高。好了以上就是这篇文章的全部内容了希望本文的内容对大家的学习或者工作具有一定的参考学习价值