调整C / C ++编译器以在多核应用程序中获得最佳并行性能:第二部分

news2025/2/27 14:08:35

下面的图5.10 描述了此过程,该过程包括四个步骤:点击领取嵌入式物联网学习路线

1.表征应用程序。

2.优先进行编译器优化。

3.选择基准。

4.评估编译器优化的性能。

图5.10:编译器优化过程

使用编译器的优化始于 对应用程序的表征。此步骤的目标是确定可能优先使用一种优化而不是另一种优化的代码属性,并帮助确定要尝试的优化的优先级。

如果应用程序很大,则可能会受益于高速缓存的优化。如果应用程序包含浮点计算,则自动矢量化可能会带来好处。下表5.4 总结了要考虑的问题和根据答案得出的结论示例。

表5.4:应用程序特征

第二步是 基于对哪些优化可能会带来有益的性能提升的了解来确定编译器优化设置的测试优先级。性能运行需要花费时间和精力,因此至关重要的是优先考虑可能会提高性能的优化,并预见在应用这些优化过程中可能遇到的任何挑战。

例如,某些高级优化需要更改构建环境。如果要衡量这些高级优化的性能,则必须愿意花时间进行这些更改。至少,所需的努力可能会降低优先级。另一个例子是更高的优化对调试信息的影响。

通常,更高的优化会降低调试信息的质量。因此,除了评估过程中评估性能外,还应考虑对其他软件开发要求的影响。如果调试信息降级到不可接受的水平,则可以决定不使用高级优化,也可以研究可以改善调试信息的编译器选项。

第三步,选择基准,包括为您的应用程序选择一个小的输入集,以便可以比较使用不同优化设置编译的应用程序的性能。选择基准时,应牢记以下几点:

1) 基准测试运行应具有可重复性,例如,每次运行的时间不会有显着差异。

2) 基准测试应在短时间内运行,以允许运行许多性能实验;但是,执行时间不能太短,以至于使用相同优化的运行时间差异很大。

3) 基准应该代表您的客户通常的经营状况。

最后一步是使用所需的优化来构建应用程序,运行测试并评估性能。测试应至少进行3次。我的建议是放弃最慢和最快的时间,并以中间时间为代表。

我还建议您在获得结果时检查结果,看看实际结果是否符合您的期望。如果执行性能测试的时间很长,则您可以在其他地方分析和验证收集的运行结果,并尽早发现任何错误或遗漏的假设。

最后,如果测得的性能满足您的性能目标,那么是时候将构建更改投入生产了。如果性能未达到您的目标,则应考虑使用性能分析工具(例如Intel VTune Performance Analyzer)。

通过阅读本系列的第1部分,您应该记住一个关键点:让编译器为您完成工作。

有许多书籍向您展示如何手动执行优化,例如源代码中的展开循环。现在,编译器技术已经到了可以在大多数情况下确定何时进行循环展开的时间。

在开发人员有知识的情况下,编译器无法确定特定的代码段,通常会有一些指令或编译指示可以在其中为编译器提供缺少的信息。

要查看此过程的工作情况,请下载案例研究的PDF,以了解如何将其与MySQL开放源数据库一起使用。

C / C ++编译器的可用性

在开始进行并行化之前,需要改进的另一个领域是C和C ++编译器的可用性。由于以下原因,开发环境(尤其是C和C ++编译器)的性能可提高开发人员的性能:

1)更高的标准合规性和诊断能力可以减少编程错误。

2)更快的编译时间导致每天更多的构建。

3)较小的应用程序代码大小可以使应用程序提供更多功能。

4)代码覆盖率工具可帮助构建强大的测试套件。

生成代码的性能是编译器的关键属性。但是,还有其他一些属性归为可用性属性,这些属性在确定易用性以及最终开发成功方面起着关键作用。

接下来的几节从以下方面描述了增加编译器使用的技术:1) 诊断,2) 兼容性,3) 编译时间,4) 代码大小和5) 代码覆盖率。如果正确采用这些技术,则可以在嵌入式项目的开发阶段提高开发人员的效率并节省相关的成本。

诊断。 用于嵌入式软件开发的两种广泛使用的语言是C和C ++。这些语言中的每一种都已由各种组织标准化。例如,ISO C一致性是编译器遵守ISO C标准的程度。当前,市场上常见两种ISO C标准:C89 [4] 和C99 [5] 。

C89当前是C应用程序的事实上的标准。但是,C99的使用正在增加。ISO C ++标准[6]于1998年获得批准。C++语言是从C89派生的,并且与C89在很大程度上兼容。两种语言之间的差异总结在ISO C ++标准的附录C中。

由于许多异常神秘的功能(例如异常规范和导出模板),很少有C ++编译器提供100%的C ++标准一致性。大多数编译器提供了一个选项来指定更严格的ISO一致性程度。

使用选项来强制执行ISO一致性可以帮助可能对将其应用程序移植到多个编译器环境中的开发人员感兴趣。

编译器诊断程序也有助于移植和开发。许多编译器提供了一个选项来诊断代码中的潜在问题,这些问题可能导致难以调试运行时问题。在代码开发过程中使用此选项可以减少调试时间。

另一项有用的诊断功能是任意诊断。任意诊断程序具有与之相关的编号,该编号允许在停止编译错误消息,警告消息,备注或无诊断之间升级或降级诊断。下表5.8说明 了适用于Linux的英特尔C ++编译器中提供的选项,这些选项提供了上述功能。点击领取嵌入式物联网学习路线

表5.8:诊断选项说明

某些编译器包括一个配置文件,该文件允许在编译期间放置其他选项,并且可以作为进行其他任意诊断的有用位置。

例如,为了 将所有C编译的警告#1011提升为错误, 在配置文件中放置-we1011无需手动将选项添加到每个编译命令行。有关诊断功能(包括可用性和语法)的完整信息,请参见编译器的参考手册。

兼容性。 嵌入式软件开发中的一个挑战是将针对一种架构设计和优化的软件移植到同一系列中的新升级架构上。

一个示例是将运行您的应用程序的系统从基于Intel Pentium III处理器的系统升级到基于Intel Pentium 4处理器的系统。在这种情况下,您可能需要重新编译软件并针对新架构及其性能功能进行优化。

一种备受重视的编译器功能是能够针对新架构进行优化,同时保持与旧架构的兼容性。处理器调度技术解决了升级架构的问题,同时保持了与现场部署的传统硬件的兼容性。

英特尔已经发布了许多指令集扩展,例如MMX技术(多媒体扩展)和流SIMD扩展(SSE,SSE2和SSE3)。例如,Intel Pentium 4处理器支持所有这些指令集扩展,但是较旧的处理器(例如Pentium III微处理器)仅支持这些指令的一部分。

当应用程序在奔腾4处理器上执行时,处理器分派技术允许使用这些新指令;当应用程序在不支持指令的处理器上执行时,处理器分派技术指定备用代码路径。

可以使用三种主要技术使开发人员根据执行体系结构调度代码:

1)丘比特的显式编码:程序员可以向标识执行处理器的函数添加运行时调用,并根据结果调用不同版本的代码。

2)编译器手动处理器分派: 语言支持,用于为每个感兴趣的处理器指定不同版本的代码。下面的图5.11 是一个手动处理器分发示例,该示例在Pentium III处理器上执行时指定一个代码路径,而在其他处理器上执行时指定一个代码路径。

3)自动处理器分派: 编译器确定使用新指令的收益,并为每个感兴趣的处理器自动创建多个版本的代码。

编译器插入代码,以将调用分派到该函数的版本,该版本取决于当时正在执行应用程序的处理器。这些处理器调度技术可帮助开发人员利用较新处理器的功能,同时保持与较旧处理器的向后兼容性。

使用这些技术的缺点是您的应用程序中的代码大小增加。同一例程有多个副本,只有一个副本将在特定平台上使用。提醒开发人员注意代码大小的影响,并考虑仅将技术应用于应用程序中的关键区域。

图5.11:手动分派示例

编译时间。 编译时间定义为编译器完成应用程序编译所需的时间。编译时间受许多因素影响,例如源代码的大小和复杂性,使用的优化级别以及主机速度。以下各节讨论了两种在应用程序开发过程中缩短编译时间的技术。

PCH文件。 在应用程序项目中的几个源文件包含公共头文件的子集的情况下,预编译头(PCH)文件可以缩短编译时间。在处理了一组形成预编译头文件集的头文件之后,PCH文件本质上是编译器的内存转储。

PCH文件通过消除不同源文件对相同头文件的重新编译来缩短编译时间。通过观察到许多源文件在源文件的开头都包含相同的头文件,使PCH文件成为可能。

图5.12:预编译头文件的源示例

上面的图5.12 显示了一种安排头文件以利用PCH文件的方法。首先,公共头文件集是由项目中其他文件包含的单个头文件包含的。

在下面的示例中,global.h 包含通用头文件集的include伪指令,并且包含在源文件file1.cpp和file2.cpp中。文件file2.cpp还包含另一个头文件vector。

使用编译器选项可以在第一次编译期间创建PCH文件,并在以后的编译中使用PCH文件。在使用自动PCH文件进行编译期间,编译器将解析包含文件,并尝试将头文件的顺序与已创建的PCH文件进行匹配。

如果可以使用现有的PCH文件,则将加载PCH文件头并继续编译。否则,编译器将为包含的文件列表创建一个新的PCH文件。#pragma hdrstop 用于告诉编译器尝试将pragma上方的源文件中的包含文件集与现有PCH文件进行匹配。

对于file2.cpp,使用#pragma hdrstop 允许使用file1.cpp使用的同一PCH文件。请注意,在某些情况下,创建和使用太多唯一的PCH文件实际上会减慢编译速度。

应用PCH文件时,用于图5.12中的代码的特定编译命令为:

icc -pch -c file1.cpp

icc -pch -c file2.cpp

尝试 在命令行上使用-pch选项和不使用-pch选项来计时。下表5.9 显示了图5.12和其他两个应用程序中的代码的编译时间减少。

表5.9:使用PCH减少编译时间

POV-Ray [7] 是用于创建复杂图像的图形应用程序。 图形应用程序EON [8]是SPEC CINT2000中的基准应用程序。这些测试在带有512 MB RAM的Red Hat Linux的基于2.8 GHz Pentium 4微处理器的系统上运行。

并行构建。 减少编译时间的第二种技术是使用并行构建。支持并行构建的工具的一个示例是make(带有 -j 选项)。

下表5.10 显示了使用make -j2 命令在双处理器系统上构建POV-Ray和EON的减少编译时间。这些测试在具有512 MB RAM和Red Hat Linux的基于3.2 GHz Pentium 4微处理器的双系统上运行。

点击领取嵌入式物联网学习路线

代码大小 。编译器在嵌入式应用程序的最终代码大小中起着关键作用。开发人员可以掌握一些会影响代码大小的编译器优化设置的知识,并且在代码大小很重要的情况下,可以通过谨慎使用这些选项来减小代码大小。

许多编译器提供了针对大小进行优化的优化开关。两个-O 选项专门针对代码大小进行优化。选项 -O1可 优化代码速度和代码大小,但可以禁用通常会导致更大代码大小的选项,例如循环展开。

选项-Os 以牺牲代码速度为代价来优化代码大小,并且可能在优化过程中选择代码序列,从而导致比其他已知序列更小的代码大小和更低的性能。

除了 上面的-O选项可以启用或禁用优化集之外,开发人员还可以选择禁用特定代码大小增加的优化。一些可用的选项包括:

1)用于分别关闭常见代码大小以增加优化的选项,例如循环展开。

2)禁用代码或库中函数内联的选项。

3)链接到较小版本的库(如精简C ++库)中的选项。

最后的代码大小建议与本章第一部分中详细介绍的高级优化有关。自动矢量化和过程间优化可能会增加代码大小。

例如,自动向量化可以将一个循环变成两个循环:一个循环可以一次迭代该循环的多次迭代,另一个循环可以处理清理循环。通过过程间优化执行的内联可能会增加代码大小。

为帮助减轻自动矢量化或过程间优化所观察到的代码大小增加,请使用配置文件引导的优化,使编译器仅在收益最大的情况下使用这些优化。下表5.11 总结了常见代码大小优化的列表。

表5.11:与代码大小相关的选项

在不需要C ++异常处理的情况下,应谨慎应用选项-fnoexception。许多嵌入式开发人员希望使用C ++语言功能(例如对象),但可能不希望异常处理的开销。

将应用程序中不需要的符号“剥离”也是一种很好的做法。在动态绑定的上下文中,需要一些符号来执行重定位;但是,通过使用(在Linux系统上)可以消除不需要的符号

不需要带状

代码覆盖率。 许多嵌入式开发人员在他们的嵌入式应用程序中使用了一组通用输入的测试套件,这使人确信新实现的代码不会破坏现有的应用程序功能。测试套件的一个共同愿望是,它要执行尽可能多的应用程序代码。

代码覆盖范围是由提供此信息的编译器启用的功能。具体来说,代码覆盖率提供了给定一组特定输入后执行的应用程序代码的百分比。概要文件引导的优化中使用的相同技术可启用某些代码覆盖率工具。

下面的图5.13 是报告示例程序的代码覆盖率工具的屏幕截图。该工具能够突出显示由于运行应用程序输入而未执行的功能。

该工具还可以突出显示已执行功能中尚未执行的区域。然后,测试套件开发人员可以使用该报告来添加提供覆盖率的测试。考虑使用代码覆盖率工具来提高测试套件的效率。

图5.13:代码覆盖工具

优化对调试的影响

调试是软件开发中一个容易理解的方面,通常涉及软件工具的使用,该调试器提供:1) 跟踪应用程序的执行;2) 能够在应用程序的指定位置停止执行;以及3) 能够在执行期间检查和修改数据值。

优化应用程序的权衡之一是调试信息的普遍丢失,这使调试更加困难。优化对调试信息的影响本身就是一个大话题。简而言之,由于以下原因,优化会影响调试信息:

1) 许多优化的x86应用程序都使用基指针(EBP)作为通用寄存器,这使得进行准确的堆栈回溯变得更加困难。

2) 代码运动允许散布来自源代码不同行的指令。在这种情况下,按顺序单步执行源代码行是不可能的。

3) 内联使代码运动问题更加复杂,因为源代码的顺序步进可能会导致显示几个不同的源位置,从而导致潜在的混乱。

表5.12:调试相关选项点击领取嵌入式物联网学习路线

上面的表5.12 描述了几个与调试相关的选项。这些选项特定于Linux上的Intel C ++编译器。但是,其他编译器中也存在类似的选项。

请查阅您的编译器文档以确定可用性。的-g 选项是标准调试选项,使在调试会话期间要被显示的源信息。

如果没有此选项,调试器将只能显示应用程序的汇编语言表示。列出的其他选项与-g 选项结合使用,并提供列出的功能。在调试优化的代码时,请考虑使用补充调试选项。点击领取嵌入式物联网学习路线

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

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

相关文章

Python 实训教学,更便捷的学生邀请及内容分发|ModelWhale 版本更新

中秋国庆假期结束,ModelWhale 又迎来了新一轮的版本更新,让我们调整好节奏,一起奔赴新的旅程! 本次更新中,ModelWhale 主要进行了以下功能迭代: 新增 一键邀请外部用户加入课程(团队版✓&#…

欢迎大家关注我的个人公众号-这个豆包有点粘

欢迎大家关注我的个人公众号-这个豆包有点粘 如果大家不嫌弃的话,可以帮忙关注一下公众号,谢谢大家,个人准备长期运营此账号,文章内容种类繁多,前端学习、时事新闻、心灵鸡汤、幽默段子,一定有一款适合你。…

【学习笔记】minIO分布式文件服务系统

MinIO 一、概述 1.1 minIO是什么? MinIO是专门为海量数据存储、人工智能、大数据分析而设计的对象存储系统。(早前流行的还有FastDFS) 据官方介绍,单个对象最大可存储5T,非常适合存储海量图片、视频、日志文件、备…

培训考试系统如何满足个性化学习需求?

随着科技的不断发展,培训考试系统逐渐成为满足个性化学习需求的重要工具。个性化学习强调根据每个学员的特点和需求,量身定制学习内容和方式,提高学习效果和学习兴趣。 培训考试系统通过个性化内容推荐满足学员的学习需求。系统会根据学员的…

SELECT COUNT(*)会不会导致全表扫描引起慢查询

SELECT COUNT(*)会不会导致全表扫描引起慢查询呢? SELECT COUNT(*) FROM SomeTable 网上有一种说法,针对无 where_clause 的 COUNT(*),MySQL 是有优化的,优化器会选择成本最小的辅助索引查询计数,其实反而性能最高&…

支付宝企业转账到个人账号[新接口版](php源码,亲测)

前言 之前专栏写过一篇企业支付宝转账到个人的文章,里面用的是老接口,官方已经不再维护。最近有人找到帮忙使用新接口实现这个功能,看了下文档以及官方的sdk,为了这一个接口,我还要去下载官方庞大的sdk,而且php低版本的还不支持composer,就很离谱,经过一天的研究,把单…

科技为饮食带来创新,看AI如何打造智能营养时代

在当今社会,快节奏的生活方式、便捷的食品选择以及现代科技的快速发展正深刻地重塑着我们对健康的认知和实践,它已经不再仅仅是一个话题,而是一个备受关注的社会焦点。在这个纷繁复杂的交汇点上,AI技术的介入为我们开辟了前所未有…

项目管理包含哪些内容?

做好项目管理不是一件容易的事儿,只有掌握了正确的技巧,才能事半功倍地完成项目。 下面就按照项目管理的流程来讲一讲项目管理的主要内容包括哪些、如何做好项目管理。 项目管理是指运用系统的理论方法,在有限的条件和资源下,对…

Google SGE 正在添加人工智能图像生成器,现已推出:从搜索中的生成式 AI 中获取灵感的新方法

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

学信息系统项目管理师第4版系列25_项目绩效域(上)

1. 绩效评估是指以员工与组织的共同发展为目标,通过正式的结构化的制度或方法,评价和测量在一定的周期内团队或员工个人的工作行为和工作成果,全面了解员工的发展潜力 1.1. 【高23上选13】 2. 干系人绩效域 2.1. 涉及与干系人相关的活动和…

react native app开发环境搭建

Reactjs是一个响应式的、多场景的web前后端应用开发框架,react native是一种使用reactjs开发框架与native移动设备应用开发技术混合开发的技术,使用react native技术开发出的应用支持跨设备、多终端,本文主要描述react native开发环境搭建。 …

1.Cesium For Unity插件安装

1.Unity安装 先安装Unity Hub,然后在里面安装Unity。 2.新建工程 新建项目 选择项目类型 3. 导入Cesium包 打开新建的项目,在菜单栏选择Edit->Project Settings->Package Manager.并添加Cesium的包信息。 Name: Cesium URL: https://unity.pkg.cesium.com Sco…

CRM系统:快速实现外勤出差人员远程访问企业提升工作效率!

🎬 鸽芷咕:个人主页 🔥 个人专栏:《速学数据结构》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活! 文章目录 快速实现外勤出差人员远程访问企业CRM系统前言1. 无需公网IP,高效低成本实现CRM系统远程访问1.1 下…

推荐5款小众软件,感兴趣自行下载

​ 今天推荐5款十分小众的软件,知道的人不多,但是每个都是非常非常好用的,有兴趣的小伙伴可以自行搜索下载。 1.重复文件清理——Duplicate Cleaner ​ Duplicate Cleaner 是一款专业的重复文件清理工具,可以快速扫描电脑上的重…

【深度学习】DDPM,Diffusion,概率扩散去噪生成模型,原理解读

看过来看过去,唯有此up主,非常牛: Video Explaination(Chinese) 1. DDPM Introduction q q q - 一个固定(或预定义)的正向扩散过程,逐渐向图像添加高斯噪声,直到最终得到纯噪声。 p θ p_θ p…

JavaScript基础入门

javaScript基础知识 $的作用 如果在jquery框架里面的话它代表jquery本身。 其它时候它只是一个变量名,仅此而已。 比如 var $ function(id) { return document.getElementById(id); }; 那么现在 就代表一个函数了,直接 就代表一个函数了,直…

centos下安装elasticsearch-head

1、安装npm sudo yum install npm 2、下载elasticsearch-head cd /home/packages sudo git clone https://github.com/mobz/elasticsearch-head.git 3、将npm镜像换为国内镜像 npm config set registry http://registry.npm.taobao.org/ 4、安装phantomjs sudo npm install p…

亚马逊英国儿童玩具合规政策合规标准是什么?如何办理?

亚马逊儿童玩具合规政策更新 重点 名称 日期 政策实施日期 2023年8月16日 产品下架日期 2023年10月15日 儿童玩具 英国 01 本政策适用的儿童玩具 02 亚马逊儿童玩具政策 03 办理流程 本政策适用的儿童玩具 儿童玩具是指供 14 岁或以下儿童在学习或玩耍时使用的商…

第14章总结:lambda表达式与处理

14.1: lambada表达式 14.1.1:lambada表达式简介 无参数 package fourteen; interface SayhHi{ String say();//抽象方法接口 } public class NoParamDemo { public static void main(String[] args) { //无参数 …

JMeter三种常用的逻辑控制器

一. 如果(if)控制器 1.1 使用js语法来判断: ## 1.2 使用jexl3函数来判断性能好: 二. 循环控制器 三. ForEach控制器 ForEach控制器一般和用户自定义变量或者正则表达式提取器一起使用,其在用户自定义变量或者从正…