c语言中循环结构的作用,C语言中对于循环结构优化的一些入门级方法简介

一.代码移动

将在循环里面多次计算,但是结果不会改变的计算,移到循环外面去。

例子:

优化前:

void lower1(char *s){

int i;

for(i=0;i

if(s[i]>='A'&&s[i]<='Z')

s[i]-=('A'-'a');

}

优化后:

void lower2(char *s){

int i;

int len=strlen(s);

for(int i=0;i

if(s[i]>='A'&&s[i]<='Z')

s[i]-=('A'-'a');

}

优化前的版本,由于每次循环都要调用strlen计算s的长度,实际上的复杂度成了O(n2)了,而优化后的版本只需计算一次s的长度,因此性能上比优化前版本要好。

二.减少函数调用

例子:

优化前:

void sum1(vec_ptr v,data_t *dest){

int i;

int len=vec_length(v);

*dest=0;

for(i=0;i

data_t val;

get_vec_element(v,i,&val);

*dest+=val;

}

}

优化后:

data_t get_vec_start(vec_ptr v){

return v->data;

}

void sum2(vec_ptr v,data_t *dest){

int i;

int len=vec_length(v);

data_t *data=get_vec_start(v);

*dest=0;

for(i=0;i

*dest+=data[i];

}

优化前的版本在每次循环中都要调用一次get_vec_element获得相应的项,而优化后的版本只需在循环外调用一次get_vec_start获得开始的内存地址,循环内直接访问内存,无需调用函数。

三.减少内存访问

例子:

优化前:

void sum2(vec_ptr v,data_t *dest){

int i;

int len=vec_length(v);

data_t *data=get_vec_start(v);

*dest=0;

for(i=0;i

*dest+=data[i];

}

优化后:

void sum3(vec_ptr v,data_t *dest){

int i;

int len=vec_length(v);

data_t *data=get_vec_start(v);

data_t acc=0;

for(i=0;i

acc+=data[i];

*dest=acc;

}

优化前的版本每次迭代都要从dest读出值再加上data[i],再将结果写回dest。这样的读写很浪费,因此每次迭代开始从dest读出的值就是上次迭代写回dest的指。优化后的版本通过加入acc临时变量,它循环中累积计算出的结果,循环结束后再写回。

这里给出两个版本相应的汇编结果就可以很清楚看出区别:

优化前:

44aed96b84967f503ab04aae42d62f86.png

优化前的版本每次迭代都要从dest读出值再加上data[i],再将结果写回dest。这样的读写很浪费,因此每次迭代开始从dest读出的值就是上次迭代写回dest的指。优化后的版本通过加入acc临时变量,它循环中累积计算出的结果,循环结束后再写回。

第二行和第四行分别对dest进行了读写。

优化后:

fa0a528061af0dfc0f1dfb7b4ee57f1c.png

从汇编结果可以看出编译器将acc直接放在了寄存器里,循环中无需对内存进行读写。

四.循环展开

循环展开可以减少循环的次数,对程序的性能带了两方面的提高。一是减少了对循环没有直接贡献的计算,比如循环计数变量的计算,分支跳转指令的执行等。二是提供了进一步利用机器特性进行的优化的机会。

例子:

优化前的代码见前一篇博客里的sum3.

优化后:

void sum4(vec_ptr v,data_t *dest){

int i;

int len=vec_length(v);

int limit=len-3;

data_t *data=get_vec_start(v);

data_t acc=0;

for(i=0;i

acc=acc+data[i]+data[i+1];

acc=acc+data[i+2]+data[i+3];

}

for(;i

acc+=data[i];

*dest=acc;

}

通过循环展开,每次迭代将累加4个元素,减少了循环次数,从而减少了总的执行时间(单独使用这种优化方法,对浮点数累乘几乎没有提高,但是整数累乘得益于编译器的重关联代码变化会有大幅度提高)。

这种优化可以直接利用编译器完成,将优化level设定到较高,编译器会自动进行循环展开。使用gcc,可以显式使用-funroll-loops选项。

五.提高并行性

现代处理器大多采用了流水线、超标量等技术,可以实现指令级并行。我们可以利用这个特性对代码做进一步的优化。

2.1使用多个累积变量

优化代码示例

void sum5(vec_ptr v,data_t *dest){

int i;

int len=vec_length(v);

int limit=len-1;

data_t *data=get_vec_start(v);

data_t acc0=0;

data_t acc1=0;

for(i=0;i

acc0+=data[i];

acc1+=data[i+1];

}

for(;i

acc0+=data[i];

*dest=acc0+acc1;

}

这里同时使用了循环展开和使用多个累加变量,一方面减少了循环次数,另一方面指令级并行的特性使得每次迭代的两次加法可以并行执行。基于这两点可以显著减少程序执行的时间。通过增加展开的次数和累加变量的个数,可以进一步提高程序的性能,直到机器指令执行的吞吐量的极限。

2.2重结合变换

除了使用多个累积变量显式利用机器的指令级并行特性外,还可以对运算重新结合变换,打破顺序相关性来享受指令级并行带来的好处。

在sum4中,acc=acc+data[i]+data[i+1]的结合顺序是acc=(acc+data[i])+data[i+1];

我们将之变成acc=acc+(data[i]+data[i+1]);

代码如下:

void sum6(vec_ptr v,data_t *dest){

int i;

int len=vec_length(v);

int limit=len-3;

data_t *data=get_vec_start(v);

data_t acc=0;

for(i=0;i

acc=acc+(data[i]+data[i+1]);

acc=acc+(data[i+2]+data[i+3]);

}

for(;i

acc+=data[i];

*dest=acc;

}

进一步增加循环展开的次数,可以进一步提高程序性能,最终也可以达到机器指令执行的吞吐量的极限。(在循环展示提到的整数乘法的性能提高就在于编译器隐式采取了这种变换,但是由于浮点数不具备结合性,所以编译器没有采用,但是程序员在保证程序结果正确性的情况下,可以显式使用这一点)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/521615.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10分钟Get拥抱无服务的正确姿势

戳蓝字“CSDN云计算”关注我们哦&#xff01;译|孔子东游文|Bob Violino来源|INSIDER PRO无服务器计算旨在实现基础设施的自动化配置以及消除服务器管理的负担&#xff0c;但是你真的准备好使用TA了吗&#xff1f;根据研究公司Markets and Markets 的2018年报告&#xff0c;无服…

深度学习最佳实践系列——权重w初始化

摘要&#xff1a; 本文是深度学习最佳实践系列博客之权重初始化&#xff0c;主要介绍权重初始化的相关问题及方法&#xff0c;文中提及的权重初始化方法均可以应用于普通的神经网络、卷积神经网络和递归神经网络之中。作为深度学习的初学者&#xff0c;我有意识到的一件事情&am…

uft自动化测试工具安装步骤_自动化功能测试和接口测试工具整理

对于自动化测试&#xff0c;原来谈这方面的内容比较少&#xff0c;但是现在我们做DevOps支撑平台的时候&#xff0c;在整个持续集成和交付的过程中&#xff0c;有一个重要的内容就是自动化测试。自动化测试的覆盖面相当大&#xff0c;其中既包括了CS&#xff0c;BS和移动APP的自…

SSM整合Druid数据库连接池

源码地址&#xff1a;https://gitee.com/gb_90/ssm_druid

实操教程丨如何将一个k3s集群集成到Gitlab项目中

作者|RancherLabs来源|CSDN企业博客关于k3sK3s是由Rancher Labs发布的一个轻量级Kubernetes发行版&#xff0c;这款产品专为在资源有限的环境中运行Kubernetes的研发和运维人员设计。它是经过认证的Kubernetes发行版&#xff0c;其最低的系统要求为&#xff1a;系统内核版本&am…

30个免费资源:涵盖机器学习、深度学习、NLP及自动驾驶

摘要&#xff1a; 本文是一份免费资源清单&#xff0c;涵盖机器学习、深度学习、NLP、AI以及自动驾驶&#xff0c;方便相关研究者选择自己感兴趣的内容资源进行学习随着碎片化的生活越来越日常化&#xff0c;大多数人都喜欢看总结性的的文章&#xff0c;这和时间成本有一定的关…

阿里AI界的新伙伴,1秒钟自动生成20000条文案

摘要&#xff1a; 最近&#xff0c;阿里“AI家族”又多了一位新的小伙伴——“AI智能文案”&#xff0c;俗称文案妹。 妹妹具备一个超能力&#xff0c;能仅用1秒钟自动生成20000条文案。 来&#xff0c;大家一起感受一下&#xff1a; 比如说你想买瓶粉底液&#xff0c;根据功效…

华为 招聘 状态 查看_英特尔放弃5G芯片研发:三星受益;爱立信2019年Q1净利润约2.51亿美元;华为也将要与高通和解;天津首个5G电话成功打通...

点击上方“通信人才网” 订阅&#xff01;导读&#xff1a;今日热点 爱立信2019年Q1净利润约2.51亿美元 扭亏为盈近日&#xff0c;爱立信发布截至2019年3月31日的第一季度财报。财报显示&#xff1a;爱立信第一季度净营收为489.06亿瑞典克朗(约合52.93亿美元)&#xff0c;较去年…

异步消息队列中间件

安装&#xff1a; rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpmrpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpmrpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm配置文件&#xff1a; vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app找到loopback_users,把双引…

创纪录!浪潮云海完成OpenStack Rocky版本全球最大规模单一集群测试!

戳蓝字“CSDN云计算”关注我们哦&#xff01;云计算的概念已悄然走过十余年&#xff0c;在助力新兴技术发展的同时&#xff0c;自身也在历经变革。开源作为推动云计算发展的强大动力&#xff0c;于云计算而言&#xff0c;不仅是技术变革的历史潮流&#xff0c;也是相互助推的最…

idea如何反编译字节码指令_美团点评:Java字节码增强技术,线上问题诊断利器...

作者简介&#xff1a;泽恩&#xff0c;美团到店住宿业务研发团队工程师。文章转载于公众号&#xff1a;美团技术团队1. 字节码1.1 什么是字节码&#xff1f;Java之所以可以“一次编译&#xff0c;到处运行”&#xff0c;一是因为JVM针对各种操作系统、平台都进行了定制&#xf…

使用机器学习预测电子竞技游戏《守望先锋》的胜负

摘要&#xff1a; 机器学习可以预测游戏的输赢&#xff1f;来看看Bowen Yang博士是如何构建这一模型的。《守望先锋》中的英雄来自加州大学河滨分校的物理学博士学位的Bowen Yang正在致力于构建一个模型——对游戏中的人物特征进行有意义的学习&#xff0c;来预测电子竞技游戏中…

路由器上的usb接口有什么用_工业主板上有多少种USB接口,红色的USB接口代表什么...

USB接口正式出现是在1996年&#xff0c;一经问世&#xff0c;就成功取代了串口和并口&#xff0c;当然这只是相对于商业电脑和民用电脑而言的&#xff0c;在工控机中还是有串口和并口存在的。USB版本发展至今也已经历好几个阶段&#xff0c;例如USB1.0、USB1.1、USB2.0、USB3.0…

GitHub 热榜第一!这个 Python 项目超 8.4k 标星,网友:太实用!

这个十一&#xff0c;又经历了一波抢票大战。常规办法根本抢不到&#xff0c;大家就把目光转移到“技术手段”上&#xff0c;顺便把一个Python抢票工具&#xff0c;送到了GitHub趋势榜第一&#xff1a;标星超过8.4k&#xff0c;来自名叫文贤平的程序员。这很可能是全GitHub最德…

c语言点按钮弹窗口,【iOS】按钮点击弹窗

拖入一个Round Rect Button&#xff0c;并将Button的文字修改成“点击弹窗”将ViewController.h修改为如下代码&#xff0c;实则在ViewController.h中添加了一行-(IBAction)messageBoxShow;&#xff0c;注册messageBoxShow这个函数。类似于C语言使用函数之前需要在头文件声明这…

cstring 不明确_股价不可预测明确时间点的涨跌

前言最近不少朋友或私信问或群里问几类问题&#xff1a;XXX 股票还能买吗&#xff1f;买了会不会还继续下跌&#xff1f;买了我能不能立刻就涨&#xff1f;XXX 股票能卖吗&#xff1f;我卖了不会还继续涨吧&#xff1f;XXX 股票为什么下跌这么厉害&#xff0c;是要有黑天鹅出现…

11月4日,上海开源基础设施峰会,不见不散!

戳蓝字“CSDN云计算”关注我们哦&#xff01;即日起&#xff0c;登录上海开源基础设施峰会网站&#xff0c;凭“OpenInfra10”优惠码注册就能享受九折优惠。另外&#xff0c;OpenStack基金会还特别为CSDN云计算社区的成员们预留了宝贵位置。11月4日至6日&#xff0c;世界各地的…

5求的值c语言编辑,C语言中怎样求1+3+5~~~~~+9值并 – 手机爱问

2018-04-06C 语言中的原码怎么&#xff1f;数计算机二进制形式表示数分有符号数和无符号数原码、反码、补码都有符号定点数表示方法有符号定点数高位符号位0正1副下都8位整数例原码数本身二进制形式例1000001 -10000001 1正数反码和补码都和原码相同负数反码其原码除符号位之外…

RabbitMQ 下载、安装、配置、验证_rpm版本(Linux环境)

文章目录一、RabbitMQ 安装准备二、RabbitMQ 安装2.1. 环境安装(最小化版本先安装环境)2.2. 安装包下载2.3. rpm安装RabbitMQ2.4. 配置文件修改2.5. 启动RabbitMQ2.6. 查看RabbitMQ是否启动2.7. 查看RabbitMQ 插件列表2.8. 安装RabbitMQ 管控台2.9. 浏览器访问RabbitMQ 管控台三…

python 华泰证券 客户端_华泰证券网上交易系统(高级版)下载 v8.13官方版下载

华泰证券网上交易系统高级版是止录最新的证券交易软件&#xff0c;该版本在原有版本上重新设计改版&#xff01;数据更清晰&#xff0c;交易更快捷&#xff01;新版本分别有行情、选股、资讯、数据和交易五大模块&#xff0c;新版的框架支持了4K高清显示器显示&#xff0c;如果…