您的位置:首页 > 其它

苏嵌实践

2020-07-14 06:33 91 查看

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

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

  1. 第一级:代码调整
    代码调整是一种局部的思维方式;基本上不触及算法层级;它面向的是代码,而不是问题; 所以:语句调整,用汇编重写、指令调整、换一种语言实现、换一个编译器、循环展开、参数传递优化等都属于这一级;这个级别的优化需要掌握大量的小的优化技巧和知识,需要不断的积累;
    简单的语句调整、公共表达式提取、废代码删除等当前的很多编译器也能做到了,但也需要了解一些编译器的优化能力使自己的代码配合编译器做好优化;
    用汇编重写并不是简单把高级语言改写为汇编实现,那样写的汇编很可能没有当今的编译器产生的代码好,所以如果决定用汇编实现,那就应该按照汇编的角度来规划自己的实现,适当的参考编译器生成的汇编码也是可取的(特别是新手,我也一样);在某些领域,使用CPU的新特性和新的指令集等将产生巨大的性能收益,这些地方经常采用汇编来实现。
    在优化的第一个级别执行基础代码的优化。 这个级别试图执行9种单独的优化功能:
    -fdefer-pop: 这种优化技术与汇编语言代码在函数完成时如何进行操作有关。 一般
    情况下, 函数的输入值被保存在堆栈中并且被函数访问。 函数返回时, 输入值还在
    堆栈中。 一般情况下, 函数返回之后, 输入值被立即弹出堆栈。这样做会使堆栈中
    的内容有些杂乱。

  2. 第二级:新的视角
    新的视角强调的重点是针对问题的算法;即选择和构造适合于问题的算法;(冒泡排序还是快排的选择问题是这一级早就应该完成的)很多经典算法都对问题作了一些假设(包括我们当前已经完成的算法实现),而在面对实际问题时“新的视角”提示我们应该重新检视这些假设,并尝试不同的思考问题的角度,寻求适合于问题的新算法;
    发掘问题的本来意义,从不同的角度思考面对的问题,使用适合于问题的的算法; 尝试打破一些规则,发掘和怀疑自己的某些假定,恢复问题的本来面目;
    结合了第一个级别的所有优化技术, 再加上一下一些优化:
    -fforce-mem: 这种优化再任何指令使用变量前, 强制把存放再内存位置中的所有变量都复制到寄存器
    中。 对于只涉及单一指令的变量, 这样也许不会有很大的优化效果. 但是对于再很多指令(必须数学操作)
    中都涉及到的变量来说, 这会时很显著的优化, 因为和访问内存中的值相比 ,处理器访问寄存器中的值要
    快的多。

  3. 第三级:表驱动状态机
    将问题抽象为另一种等价的数学模型或假想机器模型,比如构造出某种表驱动状态机;这一级其实是第二级的延伸,只是产生的效果更加明显,但它有其本身的特点(任何算法和优化活动都可以看作是他的投影);这一级一般可以产生无与伦比的快速程序, 要达到这一级需要大量修炼的;并且思考时必须放弃很多已有的概念或者这些概念不再重要,比如:变量、指针、空间、函数、对象等,剩下的只应该是那个表驱动状态机; 我想把这种境界描述为:空寂中,一些输入驱动着一个带有状态的机器按设定好的最短路线运转着;除此之外have nothing; 既:把解决一个问题的算法看作一个机器,它有一些可变的状态、有一些记忆、有一些按状态运行的规则,然后一些输入驱动这个机器运转;这就是第三级要求的思考优化问题的切入点,也就是寻找一部机器,使它运行经过的路径最短(可能是速度也可能是空间等等)
    它整合了第一和第二级别中的左右优化技巧, 还包括一下优化:
    -finline-functions: 这种优化技术不为函数创建单独的汇编语言代码,而是把函数代码包含在调度程序的
    代码中。 对于多次被调用的函数来说, 为每次函数调用复制函数代码。 虽然这样对于减少代码长度不利, 但是
    通过最充分的利用指令缓存代码, 而不是在每次函数调用时进行分支操作, 可以提高性能。
    -fweb: 构建用于保存变量的伪寄存器网络。 伪寄存器包含数据, 就像他们是寄存器一样, 但是可以使用各种
    其他优化技术进行优化, 比如cse和loop优化技术。
    -fgcse-after-reload: 这中技术在完全重新加载生成的且优化后的汇编语言代码之后执行第二次gcse优化,
    帮助消除不同优化方式创建的任何冗余段。

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

静态:
(1) 进入libtest/lib目录,执行命令:
gcc -c -I…/include hello.c
该命令生成目标文件hello.o,注意:参数-I添加头文件搜索目录,这里因为hello.c中有#include “hello.h”,hello.h在libtest/include目录中,这里需要指定该目录通知gcc,否则出现错误提示“找不到头文件hello.h”。
这一步将在libtest/lib目录中生成一个hello.o文件。
(2) 在libtest/lib目录,执行命令:
ar rc libhello.ahello.o
该命令将hello.o添加到静态库文件libhello.a,ar命令就是用来创建、修改库的,也可以从库中提出单个模块,参数r表示在库中插入或者替换模块,c表示创建一个库
这一步将在libtest/lib目录中生成一个libhello.a文件。
(3) 进入libtest/src目录,执行命令
动态:
1.将.c生成.o文件(生成与位置无关的代码 -fPIC)
gcc -c add.c -o add.o -fPIC
objdump -dS mymath >out objdump反汇编
2.使用gcc -shared制作动态库
gcc -shared -o lib库名.so add.o sub.o
斜体样式

三、总结CMake用法删除线格式

  1. 用cmake生成Makefile文件
  2. make编译程序 && 编译成功
    当前目录下已经多出了几个文件
  3. 测试程序
    第一个用cmake管理的程序运行成功
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: