物联网工程实践实训 DAY2

一、编译器三级优化分别优化了哪些?

GNU编译器提供-O选项供程序优化使用:
-O 提供基础级别的优化
-O2 提供更加高级的代码优化,会占用更长的编译时间
-O3 提供最高级的代码优化
-O4 不优化,这是默认值

  • 编译器优化级别1:在优化的第一个级别执行基础代码的优化,这个级别试图执行9种单独的优化功能:

   (1).-fdefer-pop: 这种优化技术与汇编语言代码在函数完成时如何进行操作有关。

   (2).-fmerge-constans: 使用这种优化技术, 编译器试图合并相同的常量.

     (3) . -fthread-jumps: 使用这种优化技术与编译器如何处理汇编代码中的条件和非条件分支有关。 在某些情况下, 一条跳转指令可能转移到另一条分支语句。 通过一连串跳转, 编译器确定多个跳转之间的最终目标并且把第一个跳转重新定向到最终目标。

     (4).-floop-optimize:通过优化如何生成汇编语言中的循环, 编译器可以在很大程序上提高应用程序的性能。通常, 程序由很多大型且复杂的循环构成。 通过删除在循环内没有改变值的变量赋值操作, 可以减少循环内执行指令的数量, 在很大程度上提高性能。 此外优化那些确定何时离开循环的条件分支,以便减少分支的影响。

     (5).-fif-conversion: if-then语句应该是应用程序中仅次于循环的最消耗时间的部分。简单的if-then语句可能在最终的汇编语言代码中产生众多的条件分支。 通过减少或者删除条件分支, 以及使用条件传送 设置标志和使用运算技巧来替换他们, 编译器可以减少if-then语句中花费的时间量。

  (6)-fif-conversion2: 这种技术结合更加高级的数学特性, 减少实现if-then语句所需的条件分支。

  (7)-fdelayed-branch: 这种技术试图根据指令周期时间重新安排指令。 它还试图把尽可能多的指令移动到条件分支前, 以便最充分的利用处理器的治理缓存。

    (8) -fguess-branch-probability:就像其名称所暗示的, 这种技术试图确定条件分支最可能的结果, 并且相应的移动指令, 这和延迟分支技术类似。因为在编译时预测代码的安排,所以使用这一选项两次编译相同的c或者c++代码很可能会产生不同的汇编语言代码,这取决于编译时编译器认为会使用那些分支。

 (9)-fcprop-registers: 因为在函数中把寄存器分配给变量, 所以编译器执行第二次检查以便减少调度依赖性(两个段要求使用相同的寄存器)并且删除不必要的寄存器复制操作。

 

  •   编译器优化级别2

结合了第一个级别的所有优化技术,再加上一下一些优化:

(1)-fforce-mem: 这种优化在任何指令使用变量前, 强制把存放再内存位置中的所有变量都复制到寄存器中。 对于只涉及单一指令的变量, 这样也许不会有很大的优化效果. 但是对于在很多指令(必须数学操作)中都涉及到的变量来说, 这会时很显著的优化, 因为和访问内存中的值相比 ,处理器访问寄存器中的值要快的多。

(2)-foptimize-sibling-calls: 这种技术处理相关的和/或者递归的函数调用。通常,递归的函数调用可以被展开为一系列一般的指令, 而不是使用分支。

(3)-fstrength-reduce: 这种优化技术对循环执行优化并且删除迭代变量。 迭代变量是捆绑到循环计数器的变量, 比如使用变量, 然后使用循环计数器变量执行数学操作的for-next循环。

(4)-fgcse: 这些优化操作试图分析生成的汇编语言代码并且结合通用片段, 消除冗余的代码段。如果代码使用计算性的goto,gcc指令推荐

(5)-fcse-follow-jumps: 这种特别的通用子表达式消除技术扫描跳转指令, 查找程序中通过任何其他途径都不会到达的目标代码。这种情况最常见的例子就式if-then-else语句的else部分。

(6)-frerun-cse-after-loop: 这种技术在对任何循环已经进行过优化之后重新运行通用子表达式消除例程。这样确保在展开循环代码之后更进一步地优化还编代码。

(7)-fdelete-null-pointer-checks: 这种优化技术扫描生成的汇编语言代码, 查找检查空指针的代码。

(8)-fextensive-optimizations: 这种技术执行从编译时的角度来说代价高昂的各种优化技术,但是它可能对运行时的性能产生负面影响。

(9)-fregmove: 编译器试图重新分配mov指令中使用的寄存器, 并且将其作为其他指令操作数, 以便最大化捆绑的寄存器的数量。

(10)-fschedule-insns: 编译器将试图重新安排指令, 以便消除等待数据的处理器。对于在进行浮点运算时有延迟的处理器来说, 这使处理器在等待浮点结果时可以加载其他指令。

(11)-fsched-interblock: 这种技术使编译器能够跨越指令块调度指令。 这可以非常灵活地移动指令以便等待期间完成的工作最大化。

(12)-fcaller-saves: 这个选项指示编译器对函数调用保存和恢复寄存器, 使函数能够访问寄存器值, 而且不必保存和恢复他们。 如果调用多个函数, 这样能够节省时间, 因为只进行一次寄存器的保存和恢复操作, 而不是在每个函数调用中都进行。

(13)-fpeephole2: 这个选项允许进行任何计算机特定的观察孔优化。

(14)-freorder-blocks: 这种优化技术允许重新安排指令块以便改进分支操作和代码局部性。

(15)-fstrict-aliasing: 这种技术强制实行高级语言的严格变量规则。 对于c和c++程序来说, 它确保不在数据类型之间共享变量. 例如, 整数变量不和单精度浮点变量使用相同的内存位置。

(16)-funit-at-a-time:这种优化技术指示编译器在运行优化例程之前读取整个汇编语言代码。这使编译器可以重新安排不消耗大量时间的代码以便优化指令缓存。

(17)-falign-functions:这个选项用于使函数对准内存中特定边界的开始位置。大多数处理器按照页面读取内存,并且确保全部函数代码位于单一内存页面内, 就不需要叫化代码所需的页面。

(18)-fcrossjumping: 这是对跨越跳转的转换代码处理, 以便组合分散在程序各处的相同代码。 这样可以减少代码的长度,但是也许不会对程序性能有直接影响。

  •   编译器优化级别3

它整合了第一和第二级别中的左右优化技巧, 还包括一下优化:

-finline-functions:这种优化技术不为函数创建单独的汇编语言代码,而是把函数代码包含在调度程序的

代码中。 对于多次被调用的函数来说, 为每次函数调用复制函数代码。 虽然这样对于减少代码长度不利, 但是通过最充分的利用指令缓存代码, 而不是在每次函数调用时进行分支操作, 可以提高性能。

-fweb: 构建用于保存变量的伪寄存器网络。 伪寄存器包含数据, 就像他们是寄存器一样, 但是可以使用各种其他优化技术进行优化, 比如cse和loop优化技术。

-fgcse-after-reload:这中技术在完全重新加载生成的且优化后的汇编语言代码之后执行第二次gcse优化,帮助消除不同优化方式创建的任何冗余段。


二、总结gcc静态库和动态库的制作

1.静态库
1.创建
首先对c文件进行gcc -c 源文件.c 生成 .o文件
ar rcs lib+名称.a .o文件
2.使用
gcc main.c lname(文件的名称需要去掉lib) -L(指在当前路径下)

2.动态库
1.创建
gcc -shared-fPIC-o 库名.so 源文件.c
2.使用
gcc 源文件.c./ 库名.so-o 可执行文件名

三、总结CMake用法

第一步,用cmake生成Makefile文件

注:cmake命令后边跟的就是CMakelist.txt所在的目录,这个目录不必是当前目录,你也可以新建一个build目录或者其他名字的目录来生成build文件,实际项目中也都是这么做的,这样代码会很干净也便于git管理.

 

第二步,make编译程序 && 编译成功

当前目录下已经多出了几个文件,特别是Makefile文件

第三步,测试程序
第一个用cmake管理的程序运行成功

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值