如何比较同一算法的两种实现? (通过检查他们的汇编代码)(How to compare two

2019-10-29 05:59发布

假设我有装配的相同算法的两种实现方法。 我想通过检查两个片段代码哪一个是快就知道了。

我想人们可能考虑的参数是:操作码数,分枝数,函数帧数。

我的问题是:

  1. 我可以假设每个操作码的执行是一个循环?
  2. 什么是分公司,其打破了管道的开销?
  3. 什么是调用一个函数的影响和开销?
  4. 是否有ARM和x86的分析有区别吗?

现在的问题是理论,因为我有两个实现; 长一个130的指令,一个是184组的指令长。

我想知道,如果它绝对是真的要说130组的指令长片段比184组的指令长执行得更快?

“更好==更快”

Answer 1:

这肯定是不正确的说,130指令代码比184指令代码更快。 这是很容易有1000条指令运行超过100个,反之亦然两个平台更快。

1我可以假设每个操作码的执行是一个循环?

通过看广告的MIPS / MHz的开始,尽管销售数字它给了什么是可能的一个粗略的想法。 如果该数量大于一,则每时钟多于一个的指令是可能的。

2这是分公司的,其打破了管道的开销?

从任何地方绝对没有影响非常显着的影响,无论是系统上。 一个时钟数百是潜在的罚款。

3什么是调用一个函数的影响和开销?

很大程度上取决于函数和函数调用的函数。 根据不同的调用约定,你可能需要的寄存器保存到堆栈,或重新排列寄存器的内容为参数准备要调用的函数。 如果按值传递一个结构struct的副本可能需要在堆栈上进行,更大的结构传递的更大的副本。 一旦在功能的堆栈帧,可能需要制备,等等,有涉及许多因素。 这个问题和答案也是独立的平台。

4是否有ARM和x86的分析有区别吗?

yes和no,这两个系统使用流水线,分支预测等,以保持MIPS / MHz的向上的所有现代的技巧。 ARM是要给每MHz更好的MIPS比86,86是可变的指令长度可能会给单位缓存更多的指令。 您如何分析缓存,内存和分析的系统侧外围系统大致相同。 的指令和核心的比较相似,不同取决于你正在分析哪些方面。 臂没有微代码,在x86可能是这样,你真的不看有多少寄存器真的有,这样的事情。 同时在x86你可以在与手臂的存储系统更好看,因为他们一般都不片上系统。 这取决于你买什么ARM芯片,你可能会失去很多芯片的边界可见性,可能不会看到所有的内存和外设总线,例如。 (X86正在发生变化,通过把芯片PCIE现在例如)在你提到的皮质,一类东西的情况下,你将有芯片知名度的类似边缘那些会使用更大/更便宜的基于DRAM的内存芯片外,而不是微控制器就像在芯片上的资源。

底线你的最后一个问题:

“我想知道,如果它绝对是真的要说130组的指令长片段比184级的指令执行长快?”

这肯定是不正确的说,130指令片段比184指令片段更快。 它可能会更快,可能会比较慢,它可能是大致相同的。 随着更多的信息,我们也许能够做一个很好的陈述或它可能仍然是不确定的。 很容易选择执行速度比1000条指令,同样容易选择1000个指令执行速度超过100个指令(即使我添加没有分支,没有循环,只是线性执行)100个指令



Answer 2:

在不希望轻率,答案

  1. 没有
  2. 这就要看你的硬件
  3. 这就要看你的硬件

你真的需要在目标硬件上测试的东西,或有充分了解你的硬件仿真器,为了回答你的问题,你的意思的方式...

对于你的问题的最后一部分,你需要定义“好” ......好。



Answer 3:

既然你问有关的Cortex A9 ,该数据表在附录B中的指令周期数。 这些计数通常假设内存总线速度足够快,以保持CPU的繁忙。 在现实中这种情况很少见。 许多视频/音频算法将在如何访问内存的一大胜利。

每个操作一个周期

当然,如果你想精确计数你不能假设这一点。 但是,如果您决定选择哪种算法,您可以通过查看内部循环中的指令得到最好的算法的感觉。 在这里,你的cache应该允许代码执行按在数据表中的指令计数。 如果计数接近,那么你可能需要看每个指令。 加载/存储更昂贵,通常倍数等一些算法,尤其是crytographic,将有很大的胜用汇编不很好地映射到C 。 例如, clzror ,使用进位进行多字算术等

科开销

附录B,或任何数据表具有周期计数的处理器。 对于一个ARM926其为约3个周期。 编译器仅在一排,以避免分支产生两个有条件的操作码,否则,它的分支。 如果该算法较大,分支可能会破坏缓存。 答案取决于你的CPU,缓存和内存。 根据皮质A9数据表(B.5),仅存在一个周期的开销来固定分支。

功能开销

这是大致相同的分支开销 。 然而,编译器也将产生影响。 吉姆指出是否缓存对齐功能。 该编译器执行叶函数的优化等。随着现代gcc版本中,如果所有的功能都是静态的,编译器通常会在网上时,它是有利的。 如果算法是特别大的,寄存器溢出可能是有利的。 然而,随着你的一百八十四分之一百三十零说明例子,这似乎不太可能。 编译器选项将明显的影响开销。 您可以使用objdump -S检查序言/结尾,然后确定您的硬件周期数。

ARM真正的x86

当然还有在循环计数技术的差异。 在CISC 86还具有可变指令大小。 该分析变得复杂。 它是在ARM稍微容易些。

通常情况下,你想棒球场的东西,然后实际上探查运行它们。 估计可以帮助的算法指导发展。 环/内存调整等为您的硬件。 喜欢的东西instruction emulationpagealignment faults等可能会占主导地位,并让所有的周期计数分析毫无意义。 如果算法是在user space ,每抢占,可以从运行运行否定缓存胜。 这可能是一个算法会更好地工作,在一个小负载的系统和其他将更高的负载下更好地工作。

循环计数的注意事项

查看后处理objdump的在获得周期盘点了一些并发症的发生。 基本上是一个典型的CPU是几个阶段(管线)和不同的条件会导致停顿 。 由于CPU的变得更加复杂,管线通常变得更长,这意味着有更多的条件,或者能够失速阶段。 然而, 盘点估计可以指导算法的开发和评估他们的帮助。 像存储器定时分支预测的东西可以是一样重要的,这取决于该算法上。 即, 循环次数并不完全没用,但它们都没有完成要么。 剖析应确认实际的算法倍。 如果他们发散,指令重新排序,预取和其它技术可以使他们更加接近。 这种循环数和活跃剖析分歧的事实本身也可能是有帮助的。



Answer 4:

你的问题是几乎完全没有意义的: 它可能取决于你的输入。

大多数CPU有类似的东西一个分支预测错误惩罚(如传统的ARM,其扔掉的指令获取/解码任何的分支,IIRC)。 ARM和x86也允许条件执行, 可以比分支更快。 如果这两个都依赖于输入数据,那么不同的输入将按照不同的代码路径。

也许一个版本大量使用条件执行,这是一种浪费,当条件是假的。 也许另一个被使用执行没有分支(除了在末尾的返回),用于特定的情况下,一些分析信息进行编译。 有许多,许多原因编译器可以采取相同的源和产生一个“优化的”输出,其为另一个用于一个输入速度越来越慢。

许多优化具有这种特性-例如,一个循环的开始对准16个字节在某些处理器上有帮助,但不是当只执行一次循环。



Answer 5:

一些教科书的答案,从这个问题的Cortex™-A系列程序员指南 , chapter 17

虽然循环定时信息可在技术参考手册(TRM)为您所使用的处理器中找到,它是非常困难的工作,甚至一个微不足道的一段代码将多少个周期需要执行。 指令通过管道的运动是依赖于周围指令的进展,并可以通过存储系统活性显著影响。 待装载或指令获取该小姐高速缓存可以为数万次的熄火代码。 标准数据处理指令(逻辑和算术)将只需要一个或两个周期来执行,但是这并没有给的全貌。 相反,我们必须使用分析工具,或内置于处理器的系统性能监控,提取有关性能的有用信息。

下还可以阅读17.4 Cortex-A9 micro-architecture optimizations ,其回答你的问题非常非常多。



文章来源: How to compare two implementations of the same algorithm? (by examine their Assembly code)