paint-brush
编译器提升:以最短的改变从而提高代码怎么用安全性能! 经途@durganshu
1,383 讀數
1,383 讀數

编译器优化:以最少的调整提高代码性能!

Durganshu Mishra13m2023/11/30
Read on Terminal Reader

太長; 讀書

希望优化 C++ 代码性能的开发人员应该发现编译器优化:一组非常有效的 C++ 标志,可以毫不费力地提高代码性能。唯一的先决条件是你知道自己在做什么。探索适合英特尔 C++ 编译器的标志,例如 -fno-alias、-xHost、-xCORE-AVX512、IPO 等,并在 Jacobi 迭代 C++ 代码上进行实际摊牌。
featured image - 编译器优化:以最少的调整提高代码性能!
Durganshu Mishra HackerNoon profile picture
0-item
1-item


从 C++ 二维码中放峰峰值耐腐蚀性可能性是一两个艰难的主线任务,需细心的深入分析、更复杂的运存点击调低和缓存推广。没能有个两个技巧性可变得简化一些?幸运星的是,有个条近道可用比较少的奋斗保持显得的耐腐蚀性加快——只要是您有科学合理的个人见解并了解自身在做这些。输出编译器推广可显得改善二维码的耐腐蚀性。


现代化编译器是变现极佳功效的的过程 中不或缺的盟友,很大是在智能并行执行程序化层面。这类错综复杂的的辅助工具具有着细细诊断错综复杂的编号机制(需要是无限循环内)并直缝执行程序优化系统的程度。


本文旨在强调编译器优化的功效,重点关注因受欢迎和广泛使用而闻名的英特尔 C++ 编译器


在这故事视频中,我们都揭只开编译器魔法咒语的哪几个层面上,它们的应该将您的编号的变化为高效果杰作,必需的一键纠正比您美感的要少。


亮点:什么是编译器优化? | -开|架构目标 |过程间优化 | -fno-别名 |编译器优化报告

什么是编译器优化?

编译器SEO优化网络包函编译器在编译时期应用领域于原二维码怎么用怎么用的各项系统和切换。但为什么在呢?提升 耐磨性、速率,并在或者环境下提升 添加的设备二维码怎么用怎么用的面积。这SEO优化网络而对于应响二维码怎么用怎么用下达的其他层面都都尤为重要的,属于时间、硬盘实用和万元产值能耗。


任何人编译器总会审理一种的操作步骤将中高级源编号准换为发瘟匣设备编号。这样的牵涉词法浅析、日语语法浅析、语义浅析、在期间编号导出(或 IR)、优化网络和编号导出。


在优化阶段,编译器会仔细寻找转换程序的方法,旨在获得语义等效的输出,从而利用更少的资源或更快地执行。此过程中采用的技术包括但不限于常量折叠、循环优化、函数内联和死代码消除


我不要会研讨大多数需用的选项卡,只是研讨怎么样标识编译器实行机会提升编码功效的目标提高。那,解決妙招???编译器标识。

开发人员可以在编译过程中指定一组编译器标志,这种做法对于使用 GCC 的“ -g”“-pg”等选项来调试和分析信息的人来说很熟悉。接下来,我们将讨论在使用英特尔 C++ 编译器编译应用程序时可以使用的类似编译器标志。这些可能会帮助您提高代码的效率和性能。


CAF 开球 GIF



那么,我们正在做什么?

并不会进一步探究浪费时间的实际,也并不在用列举每编译器因素的枯燥文本文档沉入您。不同,我会们战胜困难理解某些因素为什么要甚至是如何业务。


公司如此推动这一个???


我国将操作一位未优化网络方案的 C++ 变量来承当计算出来换代,并,慢慢说明每一位编译器标签的反应。在那一次研究中,我国将能够操作创造性地将老是换代与根本版使用相比来量测t加速 — 未曾有优化网络方案标签 (-O0) 開始。


提速(或执行命令用时)是在广州POS机上衡量的。在这儿,雅可比如法解求二维偏微分方程式组(泊松方程式组),使用于对四边形网格上的脂肪含量占比做3D建模。


雅可比方法


u(x,y,t) 是时 t 点 (x,y) 的水温。


当分散已经变现时,我们公司处理好不稳状况:

解决稳定状态


在边界线线处APP好几回组狄利克雷边界线线状况。


我本质上上的个 C++ 代码,在可变性面积深浅不一的网格(我称作为粪便率)上连接雅可比迭代的。几乎上,网格面积深浅不一为 500 是因为着推导面积深浅不一为 500x500 的矩阵的特征值,依此种推。


继续执行次雅可比多目标优化的函数公式有以下:


 /* * One Jacobi iteration step */ void jacobi(double *u, double *unew, unsigned sizex, unsigned sizey) { int i, j; for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { unew[i * sizex + j] = 0.25 * (u[i * sizex + (j - 1)] + // left u[i * sizex + (j + 1)] + // right u[(i - 1) * sizex + j] + // top u[(i + 1) * sizex + j]); // bottom } } for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { u[i * sizex + j] = unew[i * sizex + j]; } } }


他们以后进行雅可比多目标优化,是直到残差实现域值(在循环系统内)。残差换算和域值测评是在该函数公式之中顺利完成的,这不关心的话。那 ,目前让他们来结合实际卧室里的大象吧!

基本代码如何执行?

在不会有改善(-O0)的情况下下,当我们取得接下来最终结果:


基本情况下的运行时间(以秒为单位)和 MFLOP/s(“-O0”)


在此里,我们都以 MFLOP/s 来判断耐热性。这将这是我们都开始相对比较的基本知识。


MFLOP/s 指代“每秒100万次浮点运算”。它是一种种检测企业,使用于批量估算机或工作器在浮点运算方便的效能。浮点运算牵涉以浮点文件类型带表的小数或实数的数学知识估算。


MFLOP/s 一般性作为系数或安全性能参数体系,格外是在复杂化数学思维核算时兴的生物学和建筑项目运用中。 MFLOP/s 值越高,控制系统或整理器审理浮点运算的效率越快。


注 1:为了提供稳定的结果,我针对每个分辨率运行可执行文件 5 次,并取 MFLOP/s 值的平均值。

注 2:需要注意的是,Intel C++ 编译器的默认优化是 -O2。因此,在编译源代码时指定-O0很重要。


就让们坚持看着当大家再试一次的不同的编译器标识时那些开机运行期限会该如何转变!

最常见的:-O1、-O2、-O3 和 -Ofast

当人们开始进行编译器优化时,这些是一些最常用的编译器标志。理想情况下, Ofast > O3 > O2 > O1 > O0的性能。然而,这并不一定会发生。这些选项的关键点如下:


-O1:

  • 目标:优化速度,同时避免代码大小增加。
  • 主要特性:适用于代码量较大、分支较多且执行时间不由循环内的代码控制的应用程序。

-氧气:

  • 相对于 -O1 的增强:
    • 启用矢量化。
    • 允许内联内在函数和文件内过程间优化。

-O3:

  • 相对于 -O2 的增强:
    • 启用更积极的循环转换(Fusion、Block-Unroll-and-Jam)。
    • 如果发生循环和内存访问转换,优化只能始终优于 -O2。它甚至会减慢代码速度。
  • 推荐用于:
    • 具有大量循环浮点计算和大型数据集的应用程序。

-奥法斯特:

  • 设置以下标志:
    • “-O3”
    • “- no-prec-div” :它可以进行优化,提供比完整 IEEE 除法更快但精确度稍差的结果。例如,A/B计算为A * (1/B),以提高计算速度。
    • -fp-model fast=2” :启用更积极的浮点优化。


仔细介紹了等等界面带来的SEO优化。


当在雅可比码上在使用这种按钮时,大家赚取这种执行程序作业时长:

-On 标志的比较

很特别,所有的此类优化方案都比我们都的根本编号(配有“-O0”)快得多。下达正常运行期限比根本现象低 2-3 倍。 MFLOP/s 如何样?


-On 标志的比较


嗯,也就是只要!


总体具体情况和系统优化后的 MFLOP/s 之前的存在特别大不同之处。


总体而言,“-O3”表现最好,尽管只有一点点。


“- Ofast ”(“ -no-prec-div -fp-model fast=2 ”)使用的额外标志不会提供任何额外的加速。

目标架构(-xHost、-xCORE-AVX512)

丝机的搭建是的影响编译器优化网络调整的重要的元素。当编译器了解到要用的汇编指令集和硬件设施支技的优化网络调整(如失量化和 SIMD)时,它能能显长改善特点。


举列,我的 Skylake 机气有 3 个 SIMD 标段:1 个 AVX 512 和 2 个 AVX-2 标段。


那一次我真的是可以用他们理论知识搞些什么样的吗???


答案在于战略编译器标志。尝试“ -xHost ”,更准确地说,“ -xCORE-AVX512 ”等选项可以让我们充分利用机器功能的潜力,并进行定制优化以获得最佳性能。


左右是这么多标签的代表什么意思的短时间陈述:


-x主机:

  • 目标:指定编译器应生成针对主机最高指令集优化的代码。
  • 主要特性:利用硬件上可用的最新特性和功能。它可以给目标系统带来惊人的加速。
  • 注意事项:虽然此标志针对主机体系结构进行了优化,但它可能会导致二进制文件无法在具有不同指令集体系结构的不同计算机之间移植。

-xCORE-AVX512:

  • 目标:明确指示编译器生成利用英特尔高级矢量扩展 512 (AVX-512) 指令集的代码。

  • 主要特点: AVX-512 是一种先进的 SIMD(单指令、多数据)指令集,与 AVX2 等以前的版本相比,它提供更宽的矢量寄存器和附加操作。启用此标志允许编译器利用这些高级功能来优化性能。

  • 注意事项:可移植性又是这里的罪魁祸首。使用 AVX-512 指令生成的二进制文件可能无法在不支持该指令集的处理器上以最佳方式运行。它们可能根本不起作用!


AVX-512装置信息操作Zmm寄存器,她是一列512位宽的寄存器。等寄存器是矢量素材除理的根本。


默认情况下,“ -xCORE-AVX512 ”假定程序不太可能从 zmm 寄存器的使用中受益。除非保证性能增益,否则编译器会避免使用 zmm 寄存器。


如果打算不受限制地使用 zmm 寄存器,“ ”可以设置为高。这也是我们要做的事情。


千万别忘啦看到以了解简略这说明。


就让们看等等标志的意思该怎样适用人群于企业的源代码:

-xHost 和 -xCORE-AVX512 的影响

呜呼!


如今的,公司的最短分别率已进阶 1200 MFLOP/s 小关。别分别率的 MFLOP/s 值都是所多。


需要目光的是,人们在无任意本质性手动式干涉的情况报告下就具有了等最后——只需在应用领域系统软件编译步骤中并到一下编译器圆形标志如要。


同时,必需表示的是,编译后的可执行力文档仅与利用相当指令码集的丝机兼容。


调整与可移殖性的衡量是显然的,是因为对当前指令表集调整的代碼应该会牺性跨区别产品安装的可移殖性。以至于,相应要得知你在做任何!!


注意:如果您的硬件不支持 AVX-512,请不要担心。英特尔 C++ 编译器支持 AVX、AVX-2 甚至 SSE 的优化。该包含您需要了解的一切!

过程间优化 (IPO)

整个时候间SEO优化牵涉跨各个方程或整个时候具体分析和转型码,撼动一个方程的区间。


IPO 都是个多部骤流程,侧重点关注度子编译程序内不一样的功能模块或子编译程序当中的等交互。 IPO 就可以还涉及许许多多不一样的品类的推广,还涉及前向代替、接间赋值转型和内联。


英特尔编译器能够四种普通的 IPO 形式:单文件名下载编译和多文件名下载编译(全系统软件改进)[ ]。有两只普通的编译器logo制定这些中的各个方面个:


-首次公开募股:

  • 目标:启用过程间优化,允许编译器在编译期间分析和优化整个程序,而不仅仅是单个源文件。

  • 主要特点:-整个程序优化:“ -ipo ”对所有源文件进行分析和优化,考虑整个程序中函数和过程之间的交互。- 跨函数和跨模块优化:该标志有利于内联函数、同步优化以及跨不同程序部分的数据流分析。

  • 注意事项:它需要单独的链接步骤。使用“ -ipo ”编译后,需要特定的链接步骤来生成最终的可执行文件。编译器在链接期间根据整个程序视图执行额外的优化。


-ip:

  • 目标:启用过程间分析传播,允许编译器执行一些过程间优化,而不需要单独的链接步骤。

  • 主要功能:-分析和传播:“ -ip ”使编译器能够在编译期间跨不同函数和模块执行研究和数据传播。但是,它不会执行需要完整程序视图的所有优化。- 更快的编译:与“ -ipo ”不同,“ -ip ”不需要单独的链接步骤,从而加快编译时间。当快速反馈至关重要时,这在开发过程中会很有用。

  • 注意事项:仅发生一些有限的过程间优化,包括函数内联。


-ipo 基本上作为更诸多的整个过程间优化网络的功能,所以它涵盖直接的链接转换步驟,但价格是编译的时间更长。 [ ] -ip 是一种种最快的速度的代用情况报告,是可以执行命令几个流程间提高,不用再单独的的图片链接布骤,使其时候開發和检查过程。[ ]


由于我们只讨论性能和不同的优化、编译时间或可执行文件的大小不是我们关心的,因此我们将重点关注“ -ipo ”。

-ipo的影响

-fno-别名

整个出现调优都决定于您对硬件设备的知晓度或您来进行的实验设计度。但这还假如不是整个。假如各位体验制定编译器是怎样正确看待各位的代碼,各位或许会察觉另一未知的调优。


让公司们在此瞅瞅公司的编号:


 /* * One Jacobi iteration step */ void jacobi(double *u, double *unew, unsigned sizex, unsigned sizey) { int i, j; for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { unew[i * sizex + j] = 0.25 * (u[i * sizex + (j - 1)] + // left u[i * sizex + (j + 1)] + // right u[(i - 1) * sizex + j] + // top u[(i + 1) * sizex + j]); // bottom } } for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { u[i * sizex + j] = unew[i * sizex + j]; } } }


jacobi() 函数采用几个指针作为参数,然后在嵌套的 for 循环中执行某些操作。当任何编译器在源文件中看到这个函数时,都必须非常小心。


为甚么??


使用u计算unew 的表达式涉及 4 个相邻u值的平均值。如果uunew都指向同一个位置怎么办?这将成为别名指针的经典问题[ ]。


中国现代编译器十分的聪慧,因为确定安全性高,这些假如有可能会发生別称。关于如此一来的景象,两人制止了每有可能会导致编码语义和打出的seo。


在我们的例子中,我们知道uunew是不同的内存位置,并且用于存储不同的值。因此,我们可以轻松地让编译器知道这里不会有任何别名。


大家该要怎么制作呢?


有两种方法。首先是C 语言的“ ”关键字。但这需要更改代码。我们暂时不想这样。


有什么简单的吗?让我们尝试一下“ -fno-alias ”。


-fno-别名:

  • 目标:指示编译器不要假设程序中存在别名。

  • 主要特点:假设没有别名,编译器可以更自由地优化代码,从而潜在地提高性能。

  • 注意事项:开发人员在使用此标志时必须小心,因为如果出现任何不必要的别名,程序可能会给出意外的输出。


越来越多要素能否参考。


这当我们对当我们的码并不是情况怎样才能?

-fno-alias 的效果

好的,当前你们有食物了!!!


让我们在在此里推动了确实不错的加速度,基本上是之间提高的 3 倍。在这种提高脚下的小秘密是哪个?


进行提示编译器不必有效市场理论別称,人们赋于了它降低强 不断循环升级优化的恣意。


仔细检查汇编代码(虽然这里没有共享)和生成的编译优化报告(见下文)揭示了编译器对和的精明应用。这些转换有助于实现高度优化的性能,展示编译器指令对代码效率的重大影响。

最终图表

他是各种SEO互为会比较的方式:


所有优化标志的比较

编译器优化报告 (-qopt-report)

英特尔 C++ 编译器提供了一项有价值的功能,允许用户生成优化报告,总结为优化目的所做的所有调整 [ ]。这份综合报告以 YAML 文件格式保存,提供编译器在代码中应用的优化的详细列表。详细说明请参见官方文档“ ”。

接下来是什么?

我探讨了了些编译器圆形标志图案,以上圆形标志图案都可以显长提供编号的性能参数,而不用再我现实做越来越多某件事。一个的前提条件是:别盲目性工作起来;保证 你掌握自我在做啥子!


如此的编译器标制了解一百多个,本古事仅推荐之中的三个。因为,最该察看您最好编译器的关方编译器方案(十分是与改进涉及到的的表格)。


除非此类编译器标志的意思之余,也有非常大的堆技術,假如矢量图化、SIMD 发挥函数公式、 和,这些可以庞大地提升 代碼的能。


同样,英特尔 C++ 编译器(以及所有流行的编译器)也支持 pragma 指令,这是非常好的功能。值得在上检查一些编译指示,如ivdep、parallel、simd、vector等。


这就是 Giphy 上的所有人

建议阅读

[1] [2] [3] [4] [5] [6] [7] [8]


上的精選图片视频。


也发布信息。


바카라사이트 바카라사이트 온라인바카라