深入理解计算机系统(5.1)------优化程序性能

  你能获得的对程序最大的加速比就是当你第一次让它工作起来的时候。

  在讲解如何优化程序性能之前,我们首先要明确写程序最主要的目标就是使它在所有可能的情况下都能正常工作,一个运行的很快的程序但是却是错误的结果是没有任何用处的,所以我们在进行程序性能优化之前,首先要保证程序能正常运行,且结果是我们需要的。

  而且在很多情况下,让程序跑的更快是我们必须要解决的问题。比如一个程序要实时处理视频帧或者网络包,那么一个运行的很慢的程序就不能解决此问题。再比如一个计算任务计算量非常大,需要数日或者数周,如果我们哪怕只是让它运行的快20%也会产生重大影响。

1、编写高效程序的切入点

  ①、选择一组合适的算法和数据结构。

  ②、编写出编译器能够有效优化以转换成高效可执行的源代码。

  ③、多线程并行处理运算。

  对于第一点,程序=数据结构+算法,选择合适的数据结构和算法无疑对于提高程序的运行效率有很大的影响。第二点对于编程者则需要理解编译器的优化能力以及局限性,编写程序看上去只是一点小小的改动,可能都会引起编译器优化方式很大的变化;第三点技术主要这对运算量特别大的运算,我们将一个大的任务分成多个小任务,这些任务又可以在多核和多处理器的某种组合上并行的计算,这里我们也需要知道,即使是利用并行性,每个并行的线程都要以最高性能的方式执行。

2、编译器的优化能力和局限性

  正确性,正确性,正确性!!!这个要着重提醒,所以编译器必须很小心的对程序使用安全的优化。限制编译器只进行安全的优化,会消除一些造成错误的运行结果,但是这也意味着程序员必须花费更大的力气写出程序使编译器能够将之转换为有效机器代码。

  对于下面两个程序:

void add1(int *xp,int *yp){
     *xp += *yp;
     *xp += *yp;    
}

  

void add2(int *xp,int *yp){
     *xp += 2* *yp;
}

  对上上面两个函数add1和add2,它们都是将存储在由指针 yp 指示的位置处的值两次加到指针 xp 指示的位置处的值。但是明显add2的执行效率要高,它只要求 3 次存储器的引用(读*xp,读*yp,写*xp),而add1需要 6 次存储器引用(2次读*xp,2次读*yp,2次写*xp)。

  下面有评论指出乘法指令要比加法指令慢很多,这里的add1是两次加法指令,而add2是一次乘法指令,按道理来讲是add1要比add2快,但我这里为什么说add2要快呢?我们可以看一下汇编级别的代码:

  我们通过执行 gcc -O0 -S add1.c 优化级别为0,生成汇编代码:

  

  同理通过执行 gcc -O0 -S add2.c 优化级别为0,生成汇编代码:

  

   很明显,add2的乘法指令被转换成一次加法指令了,虽然乘法指令确实比加法指令慢。但是要注意这里是乘以2,如果倍数大于2,那就不一定了。

  因此,如果编译器要优化add1,我们可以认为add2是其优化后的代码。但实际上真的是这样吗?如果 xp 等于 yp,那么变成如下:

void add1(int *xp,int *xp){
     *xp += *xp;
     *xp += *xp;    
}

   

void add2(int *xp,int *xp){
     *xp += 2* *xp;
}

  我们可以看到,这个时候对于 add1,xp的值会增加 4 倍,但是 add2 当中,xp 的值只增加 3 倍。由于编译器不知道参数 xp 和 yp 是否相等,它必须假定他们有可能相等,所以不会产生 add2 作为 add1 的优化版本。

  在各种编译器中,我们前面说过的 gcc 编译器,可以通过加参数O0 -->> O1 -->> O2 -->> O3,分别是从没有优化到优化级别最高。但是基本上编译器都不会对程序进行各种激进的优化,所以程序员必须以一种简化编译器生成高效代码的任务来编写程序。如何编写,请接着往下面看。

3、程序的性能表示

  处理器活动的顺序是由时钟控制的,时钟提供了某个频率的规律信号,通常用千兆赫兹(GHz),即十亿周期每秒来表示。例如,当表明一个系统有“4GHz”处理器,这表示处理器时钟运行频率为 4*109 千兆赫兹。每个时钟周期的时间是时钟频率的倒数。通常用纳秒(nanosecond,1 纳秒等于10-9秒),或者皮秒(picosecond,1 皮秒等于10-12秒)来表示,一个 4GHz 的十周周期为0.25纳秒,或者说250皮秒。从程序员的角度来看,用时钟周期来表示度量标准要比用纳秒或者皮秒来表示有用的多。

  用时钟周期来表示,度量值表示的是执行了多少条指令,而不是时钟运行的有多快。

4、提高程序的性能方法

  这本书的作者讲解如何优化程序性能主要从两个方面入手,第一个是与机器无关,第二个是与机器相关。

  与机器无关:

  ①、消除循环的低效率:将每次循环中执行多次但计算结果不改变的部分提出循环,这样只需计算一次,而不用循环一次,计算一次。以此提高算法效率。

  ②、减少过程调用:也就是减少函数方法的调用,因为函数方法的调用会带来相当大的开销。但是这样也会带来一个缺点,就是破坏程序的模块化,所以我们需要权衡利弊。

  ③、消除不必要的存储器引用:在循环中不停地对指针所指向的变量赋值的时候,我们可以用一个中间变量代替指针,以增加速度。

  ④、选择合适的算法和数据结构:为遇到的问题选择合适的算法和数据结构,避免使用产生糟糕性能的算法或编码技术。

  与机器相关:

  ①、理解现代处理器

  在代码级上,看上去似乎是一次执行条指令,每条指令都从寄存器或存储器中取值,执行一个操作后,并把结果存到一个寄存器或存储器位置。但是实际上,在处理器中是同时对多条指令求值,称为指令级并行。现代微处理器了不起的成就就是它们采用复杂而奇异的微处理结构,多条指令可以并行执行,同时又呈现出一种简单的顺序执行指令的表象。

  当一系列操作必须按照严格的顺序执行时,就会遇到延迟界限,因为在下一条指令开始之前,这条指令必须结束。当代码中的数据相关限制令处理器利用指令级并行的能力时,延迟界限能够限定程序性能。吞吐量界限刻画了处理器功能单元的原始计算能力。这个界限是程序性能的终极限制。

  下图是一个现代微处理器的简化示意图:

  

  指令控制单元(Instruction Control Unit,ICU)从指令高速缓存(instruction cache)中读取指令,并产生一系列基本操作。指令高速缓存是一个特殊的高速缓存存储器,它存储最近访问的指令。通常ICU会在当前正在执行的指令很早之前取指,这样它才有足够的时间对指令译码,并把操作发给执行单元 EU(Execution Unit ,EU),然后由EU完成ICU产生的基本操作。

  ②、提高并行性

  循环分割,利用功能单元的流水线化的能力提高代码性能。对于一个可结合和可交换的合并操作来说,比如说整数加法和乘法,我们可以通过将一组合并操作分割成两个或更多的部分,通过在最后合并结果来提高性能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: Understand是一种功能强大的软件开发工具,它提供了多种语言和平台的静态代码分析功能,用于帮助开发人员理解和改进他们的代码质量。 5.1是Understand的一个特定版本号,它表示 Understad软件的第5个大版本中的一个小更新。 Windows64表示这个Understand版本适用于运行在Windows操作系统的64位机器上。 通过使用Understand 5.1-windows64,开发人员可以对代码进行全面的分析和评估,以确保代码的质量和可维护性。它可以帮助开发人员识别潜在的代码缺陷、冗余代码和性能问题,并提供解决方案来改善代码质量。 该版本还具备了适用于Windows 64位机器的优化和兼容性,以确保在这样的机器上能够运行和运行分析任务的平稳性。 总之,Understand 5.1-windows64是一款适用于在Windows 64位操作系统上运行的强大的软件开发工具,它为开发人员提供了全面的代码分析功能,帮助他们提高代码质量和可维护性。 ### 回答2: understand 5.1-windows64 指的是一个软件的版本和系统要求。Understand 是一款用于源代码分析的软件工具,用于帮助开发人员理解和浏览复杂的代码。5.1 是这个软件的版本号,表示该软件经过一系列的更新和改进。windows64 表示该软件支持 64 位的 Windows 操作系统。 对于开发人员来说,使用 Understand 5.1-windows64 有几个优势。首先,它可以帮助他们更好地理解和分析源代码。该软件提供了多种功能,如交互式图表、图形视图和搜索功能,可以帮助开发人员深入了解代码的结构和关系,从而更高效地调试和优化代码。 其次,Understand 5.1-windows64 具有良好的兼容性,可以在 Windows 64 位系统上正常运行。64 位操作系统相比于32位操作系统具有更大的内存容量和更快的处理速度,这对于处理大型代码库和复杂的分析任务非常重要。使用 64 位系统可以提高软件工具的性能和效率。 此外,Understand 5.1-windows64 的更新版本可能还会解决了一些 bug,增加了新功能或提高了软件的稳定性。开发人员可以从该软件的版本迭代中获益。 总之,Understand 5.1-windows64 是一款功能强大的源代码分析工具,适用于 Windows 64 位系统。它可以帮助开发人员更好地理解和分析源代码,提高开发效率,并且与 64 位操作系统相对应,能够更好地支持大型代码库和复杂的分析任务。 ### 回答3: understand5.1-windows64是一款用于软件开发的工具,它是在Windows操作系统下工作的64位版本。Understand是一个功能强大的代码理解工具,它可以帮助程序员对代码进行深入的分析和理解。 使用understand5.1-windows64,程序员可以对源代码进行静态分析,了解代码的结构、功能和相互关系。它支持多种编程语言,包括C、C++、C#、Java等。程序员可以快速地浏览代码,并通过各种视图和图表来可视化分析结果。 此外,understand5.1-windows64还提供了全面的代码检查和度量功能,帮助程序员评估代码的质量和健壮性。它可以检测潜在的错误、重复的代码和性能问题,并生成报告供程序员参考和改进。 另外,understand5.1-windows64还支持代码重构和搜索功能。程序员可以通过重构工具对代码进行重构,提高代码的可读性和可维护性。搜索功能可以帮助程序员快速定位特定的代码片段,提高开发效率。 总而言之,understand5.1-windows64是一款功能强大且易于使用的代码理解工具。它提供了丰富的分析和度量功能,帮助程序员更好地理解和改进源代码。无论是初学者还是经验丰富的开发人员,都可以从中受益并提高代码开发的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员可乐、

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值