查找哪个代码段比另一个更快

时间:2017-11-13 22:00:08

标签: c++ performance optimization

假设我们有两个C ++代码段,用于执行相同的任务。我们如何确定哪些代码运行得更快?

举一个例子,假设有一个全局数组“some_struct_type numbers []”。在函数内部,我可以通过两种方式读取此数组的位置(我不想改变数组的内容)

  1. some_struct_type val = numbers [i];
  2. some_struct_type * val =& numbers [i]
  3. 我认为第二个更快。但我无法衡量确定的时间,因为它可以忽略不计。

    所以在这种情况下,如何确定哪个代码段运行得更快?有没有办法编译单行代码或一组行和视图 有几行汇编指令?

    我很感激你对此事的看法。

2 个答案:

答案 0 :(得分:3)

基础知识是运行这段代码很多次,至少需要几秒钟才能完成,并测量时间。

很难,非常很难,以这种方式得到任何有意义的数字,原因有很多:

  • 今天的编译器非常擅长优化代码,但优化依赖于上下文。查看单行并尝试优化它通常没有意义。当同一行出现在不同的上下文中时,应用的优化可能会有所不同。
  • 短代码可以比周围的循环代码快得多。
  • 不仅编译器进行优化,处理器还有缓存,指令管道,并尝试预测分支代码。例如,下次读取之前读取的值将更快地读取。
  • ...

正因为如此,通常最好将代码保留在程序中的位置,并使用分析工具查看代码的哪些部分使用最多的处理资源。然后,您可以再次更改这些部件和配置文件。

在编写新代码时,更喜欢可读代码,看似最佳代码。选择正确的算法,这也取决于您的输入大小。例如,如果输入非常小,insertion sort可能比quicksort更快。但是不要编写自己的排序代码,如果输入不是特殊的,请使用一般的库。并且不要过早优化。

答案 1 :(得分:2)

Eugene Sh.是正确的,这两行不做同样的事情 - 第一行将numbers[i]的值复制到局部变量中,而第二行存储{的地址{1}}转换为指针局部变量。如果您只使用numbers[i]的地址并参考numbers[i]来执行您所需的操作,那么它可能会比批量复制该值更快,但这取决于许多因素,如numbers[i]的大小等。

关于一般优化问题,有以下几点需要考虑......

使用Profiler

衡量代码速度的最佳方法是使用分析工具。根据您的目标平台,有许多不同的工具可供使用 - 请参阅(例如)How can I profile C++ code running in Linux?What's the best free C++ profiler for Windows?

你真的想要使用一个分析器,因为出于多种原因,仅仅从查看程序中最昂贵的部分来看,这是多么难以分辨......

指令数!=处理器周期数

使用分析器的一个原因是,通过查看两个代码哪个代码运行得更快,通常很难分辨。即使在汇编代码中,您也无法简单地计算指令数,因为许多指令需要多个处理器周期才能完成。这在目标平台上有很大差异。例如,在某些平台上,将值1加载到CPU寄存器的最快方法是直截了当的:

struct

而在其他平台上,最快的方法实际上是清除寄存器然后递增它,如下所示:

MOV r0, #1

第二种情况有更多的指令行,但这并不一定意味着它更慢。

其他并发症

很难分辨哪些代码最需要优化的另一个原因是大多数现代计算机都采用了相当复杂的缓存,可以显着提高性能。多次执行缓存循环通常比从未缓存的位置加载单个数据要便宜。很难准确预测导致缓存未命中的原因,但是当使用分析器时,您不必预测 - 它会为您进行测量。

避免过早优化

对于大多数项目,优化代码最好留到相对较晚的过程中。如果您过早地开始优化,您可能会发现您花费了大量时间来优化与您的程序的其他功能相比相对便宜的功能。也就是说,有一些值得注意的反例 - 如果您正在构建一个大型数据库工具,您可能会合理地预期性能将成为一个重要的卖点。