为什么LLVM执行引擎比编译代码更快?

我有一个针对LLVM的编译器,我提供了两种运行代码的方法:

  1. 自动运行。 该模式将代码编译为LLVM,并使用ExecutionEngine JIT将其编译为机器代码并运行,而不会生成输出文件。
  2. 编译并单独运行。 这个模式输出一个LLVM .bc文件,我手动优化(用opt ),编译成本地程序集(用llc )编译成机器代码和链接(用gcc ),然后运行。

我期待的方法#2比方法#1更快,或者至less是相同的速度,但是运行一些速度testing,我惊讶地发现#2的速度一直是大约两倍的速度。 这是一个巨大的速度差异。

这两种情况都运行相同的LLVM源代码。 有了方法#1,我还没有想过运行任何LLVM优化过程(这就是为什么我期望它会变慢)。 使用方法#2,我正在使用-O3运行-std-compile-optsllc ,以便最大化优化,但是它并没有在#1附近。 下面是同一个程序的一个例子:

  • #1没有优化:11.833s
  • #2没有优化:22.262s
  • #2优化( -std-compile-opts-O3 ):18.823s

ExecutionEngine是否做了一些我不知道的特殊事情? 有什么办法可以优化编译后的代码,以达到与ExecutionEngine JIT相同的性能?

具有JIT的VM运行某些应用程序比编译的应用程序更快是正常的。 这是因为带有JIT的虚拟机就像是一个模拟虚拟机的模拟器,也可以实时运行编译器。 由于这两个任务都是使用JIT构build到VM中的,因此机器模拟器可以将信息提供给编译器,以便代码可以重新编译以更高效地运行。 它提供的信息不可用于静态编译的代码。

Java VM和Python的PyPy VM等等也都注意到了这种效果。

另一个问题是alignment代码和其他优化。 现在的CPU非常复杂,很难预测哪种技术会导致最终二进制的执行速度更快。

作为一个真实的例子,让我们考虑一下Google的Native Client – 我的意思是原始的nacl编译方法,不包括LLVM(据我所知,目前支持“nativeclient”和“LLVM bitcode”码)。

正如你可以在演示文稿(签出youtube.com)或论文中看到的一样,例如Native Client:便携式,不可信x86本机代码的Sandbox ,甚至它们的alignment技术都会使代码大小变大,在某些情况下,这样的指令alignment例子与noops)给更好的caching命中。

alignment指令与noops和指令重新sorting它在并行计算中已知,在这里它也显示了它的影响。

我希望这个答案给出了一个想法,可能会影响代码速度执行的情况,并且有很多可能的原因,对于不同的代码片段,每一个都需要调查。 永远不会,这是一个有趣的话题,所以如果你find更多的细节,不要犹豫,重新回答你的答案,并让我们知道“Post-Scriptorium”,你有什么发现更多:)。 (也许链接到白皮书/ devblog与新的发现:))。 基准总是值得欢迎的 – 看看: http : //llvm.org/OpenProjects.html#benchmark 。