- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
强者恒强:x86高性能编程笺注之循环(上)
读者须知:《强者恒强:x86高性能编程笺注》该系列文章将分享x86高性能开发方面的实践和思考。主要内容目录如下,欢迎各位业界同仁与我们讨论交流相关话题。
什么是性能
流水线
分支
循环
缓存
预取
大页
锁
RCU
无锁
SIMD指令
循环一般是程序中计算最密集的代码段,也最容易成为性能的热点。在熟悉了CPU的流水线之后,有很多很多技巧可以提升执行循环的效率,但程序性能的优化如果仅仅是“堆砌”技巧,那么想必也不会吸引如你这般聪慧的读者。就如同BUG总是会出现在自己认为一定没问题的地方一样,一些被奉为“万金油”式的优化手段也可能正是性能下降的本因。对于自己写出来的代码,无论是优化性能还是单纯的DEBUG,“都像是在看一场情节跌宕的犯罪电影,在这里面,你既是侦探,同时也是凶手”。很少有人会愿意将自己“绳之以法”,因此也只有很少的人能够看到片尾的彩蛋。
循环之所以容易成为热点,完全出于它的天然属性——调用的次数足够多。与其外围的代码相比,可能是几个数量级的差距。再加上数据依赖,内部分支等等因素,使得循环往往成为Profiling时重点关怀的对象。但循环也因为“重复再重复”这一天然属性,提供了一些可资利用的优势。循环内部的代码,因其重复调用,使得CPU的指令缓存可以保持一个很高的命中率,批量的重复操作,可以引入一些并行操作机制等等。但CPU的流水线是否可以满效率的运行,还是取决于我们之前介绍的很多其他因素。
另外关于循环的性能优化,最有意思的一点可能就是,完全按照理论的指导“优化”了代码,实际的性能反而有所下降。无论是gcc还是clang,在其数十载的发展过程中,都积累了深厚的循环优化处理方法。如果仅仅将编译器认为是缺乏头脑的“执行者”,那么在性能优化的路上,将会失去一个重要的伙伴。为了说明如何去“配合”而非“驾驭”编译器,本文也将在介绍理论的基础上,更加侧重实践的经验,以测试例的方式摸清编译器的脾气。
数据依赖
a = 100;b = 200;
单纯对两个变量写入数据,并不产生数据依赖。无论是这两条语句执行的先后顺序如何,或并行执行,都不影响程序的最终结果。数据依赖往往产生于对同一个变量的读写之间:
a = 100;b = a + 100;
以上两组代码虽然最终结果完全相同,但在计算机看来却是完全不同的两行代码。前一组可以以任意顺序执行;而后面一组代码却只能先给a赋值,再执行对b的赋值,使得这两个语句之间产生依赖。一般来说,数据依赖存在三种形式:
read-after-write:写入的变量后续将被读取
write-after-read:读取的变量后续将被写入
write-after-write:写入的变量后续被重新写入
以上三种依赖类型又可以分别叫做”flow dependence“antidependence”和”output dependence”
举一个简单的例子:
for (i = 0; i 4; i++) {
? ?a[i] = b[i];
? ?c[i] = c[i + 1] + a[i];}
假设a、b、c三个数组长度都为4。在每一次的循环中,a数组中的某些元素将首先被写入赋值,之后将读取新值计算。c数组中的单独元素虽然在一次循环之中没有被同时读写,但在不同的循环迭代之间存在对同一个元素的读写操作。那么对于a数组的0~3号元素,都存在read-after-write依赖,对于c数组的1~3号元素,都存在write-after-read依赖。而对a和c的重新赋值,又与它们的初始化指令之间,存在write-after-write依赖。
如上说述,在循环的每次迭代之间,也会存在依赖关系。如对数组a的操作,其read-after-write(flow dependence)依赖关系都只存在于同一次迭代内,则称这种依赖为”loop-independent”;而对于数组c,其依赖关系存在于循环的不同次迭代之间,则称这种依赖为”loop-carried”。
数据依赖对循环最大的影响,是它限定了执行的顺序。从之前关于CPU流水线的介绍中可以知道,在微指令的执行层面,CPU会尽力让乱序执行核心并行执行指令,这也是影响IPC的一个重要因素。而数据间的相互依赖会破坏这种并行关系,进而拉低程序的性能。数据依赖以及它们与循环迭代之间的关系可以帮助我们分析循环的优化方式。尽最大可能地减少数据依赖,增加程序的并行化程度是我们追求的整体目标之一。
Loop Distribution and Fusion
从这一节开始会陆续介绍几种常见的循环优化技巧。但如前所述,理论与实践相结合才能真正发挥人的主观能动性,并激活人与客观世界的奖励反馈机制。所以针对每一种技巧,除了讲解原理和举个栗子之外,还会给出真实的
您可能关注的文档
最近下载
- 基于KPI(关键绩效指标)的绩效考核.pptx VIP
- 工程点工签证单.doc
- 14K207 管道设备防腐蚀设计与施工(OCR).pdf VIP
- 临床护理文书书写规范 (1) PPT课件.pptx VIP
- SHARERESTRICTIONAGREEMENT(股东限制协议).doc VIP
- [最新版]市政道路工程监理实施细则100页(参考价值高编制).doc VIP
- 2025-2030中国航行数据记录器行业市场发展趋势与前景展望战略研究报告.docx
- 基于TMR传感器的地磁信号采集与校准研究.pdf
- 影响生物修复的环境条件.ppt VIP
- 2023北京人大附中初二(上)期中物理(含答案).pdf VIP
文档评论(0)