news 2026/7/13 6:28:32

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++性能剖析教程之循环展开

什么是循环展开?

循环展开,英文中称Loop unwinding或loop unrolling,是一种牺牲程序的尺寸来加快程序的执行速度的优化方法。可以由程序员完成,也可由编译器自动优化完成。循环展开最常用来降低循环开销,为具有多个功能单元的处理器提供指令级并行。也有利于指令流水线的调度。

循环展开能从两方面改进程序的性能:

  • 减少了不直接有助于程序结果的操作的数量,例如循环索引计算和分支条件。
  • 提供了一些方法,可以进一步变化代码,减少整个计算中关键路径上的操作数量。

循环展开对程序性能的影响

我们直接以实际代码向大家展示循环展开的作用,首先看未经过循环展开优化的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#include <iostream>

#include <chrono>

intmain(){

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::duration<double> dura = end - start;

std::cout <<"共耗时:"<< dura.count() <<"s"<< std::endl;

return0;

}

类似于上面的这段代码是我们平常工作中经常见到的,函数目的就是求得1+2+……+9998+9999的累加和,每次循环把i累加到sum变量上,循环次数一共10000次。代码运行结果如下:

可以看出代码运行耗时0.0000279秒。

下面我们将循环展开一次,即把上述代码中的循环改为如下代码:

1

2

3

4

for(inti = 0;i < count;i += 2){

sum += i;

sum += i+1;

}

即每次循环将i和i+1一起累加到sum变量上,这样可以把循环次数从10000次降低到5000次,由于CPU的高度流水线化,连续两个加法指令增加耗时很低,所以此版本代码可以一定程度上提高程序运行速度,运行结果如下:

代码运行耗时0.0000159秒,相较于未优化代码速度快了将近一倍。

当然,我们可以继续增加循环展开次数以进一步提高程序运行速度,但是这个增加循环展开次数也是有限度的,当达到了CPU的最高吞吐量之后,继续增加循环展开次数是没有意义的。

上述循环展开后的代码依然有进一步优化的空间,那就是消除连续指令的相关性,以达到指令级并行,我们可以看到循环展开后的代码,循环体中有两条语句:sum += i 和 sum += i+1,第二条语句sum += i+1依赖于第一条命来sum += i的执行结果,所以这两条语句只能依次执行,限制了CPU进一步提高性能的可能。如果我们将循环体改为如下代码:

1

2

3

4

5

6

intsum1=0,sum2=0;

for(inti=0;i < count;i+=2){

sum1 += i;

sum2 += i+1;

}

sum = sum1 + sum2;

我们新建了两个变量sum1和sum2用于存储循环展开时两个累加语句的累加结果,最后在循环体外将两部分结果相加得到最终结果。该代码中两个累加语句之间是互不相关的,所以CPU可以并行执行这两条指令,以达到性能的进一步提高。下面是运行结果:

代码运行耗时0.0000073秒,相较于只进行循环展开的代码速度又快了将近一倍。

总结

由上面三段代码的运行速度对比可以看出,循环展开对程序性能有着很重要的影响,可以减少分支预测错误次数,增加取消数据相关进一步利用并行执行提高速度的机会。但是,并不建议大家进行手动的循环展开,在代码中进行循环展开会导致程序的可读性下降,代码膨胀。为了直观感受循环展开对性能的影响,上述代码运行结果均是在不开编译器优化的情况下进行的测试,其实在我们开启了编译器优化的时候,编译器会自动对我们的循环代码进行循环展开,让我们可以在保持了代码可读性的同时,又能享受到循环展开对我们程序性能的提高。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 6:26:59

高压安全隔离技术:ISOM8710与PIC18LF26K40的工业应用

1. 高压安全隔离的工业应用背景在工业自动化、电力电子和医疗设备等领域&#xff0c;高压安全隔离是确保系统可靠运行的关键技术。想象一下&#xff0c;当你的控制电路需要监测380V交流电机的工作状态时&#xff0c;如果没有隔离措施&#xff0c;任何故障都可能导致高压直接窜入…

作者头像 李华
网站建设 2026/7/13 6:24:37

C++11 Attributes:统一代码属性语法,提升可移植性与表达力

1. 项目概述&#xff1a;为什么我们需要C11 Attributes&#xff1f;如果你写过一段时间的C&#xff0c;尤其是接触过跨平台或者编译器扩展的项目&#xff0c;大概率见过这些“魔法注释”&#xff1a;__attribute__((packed))、__declspec(dllexport)&#xff0c;或者为了消除未…

作者头像 李华
网站建设 2026/7/13 6:23:45

L9958与TM4C129XNCZAD的高性能电机控制系统设计

1. 项目背景与核心器件选型在工业自动化、机器人控制和精密仪器领域&#xff0c;电机控制系统的性能直接影响设备的动态响应、定位精度和能效表现。这次我们要探讨的是基于L9958电机驱动芯片和TM4C129XNCZAD微控制器的组合方案&#xff0c;这套系统特别适合需要高动态响应和精密…

作者头像 李华
网站建设 2026/7/13 6:20:50

RoB: Peek 探测机制 (The Peek Mechanism)

Peek 探测机制 (The Peek Mechanism) 在高性能网络中,响应数据的乱序到达是常态。假设你发送了 A →\rightarrow→ B →\rightarrow→ C 三个请求,但由于路径拥塞,响应回来的顺序变成了 B →\rightarrow

作者头像 李华
网站建设 2026/7/13 6:20:15

UE4/UE5 Sequencer电影感运镜:从分镜到渲染的实战指南

1. 项目概述&#xff1a;从游戏镜头到电影叙事在虚幻引擎&#xff08;UE4/UE5&#xff09;里做游戏&#xff0c;和用它来讲一个电影感的故事&#xff0c;是两件完全不同的事。很多开发者&#xff0c;包括我自己刚上手时&#xff0c;都踩过这个坑&#xff1a;我们花大力气把角色…

作者头像 李华
网站建设 2026/7/13 6:20:10

Typora 1.8.5 双模式宽度调整:编辑区与源码区分别设置 1200px 与 100%

Typora 1.8.5 双模式宽度精细配置指南&#xff1a;编辑区与源码区独立优化方案作为一名长期使用 Typora 的深度用户&#xff0c;你是否遇到过这样的困扰&#xff1a;在编辑模式下精心调整的完美布局&#xff0c;切换到源码模式后却变得支离破碎&#xff1f;或者在大尺寸显示器上…

作者头像 李华