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

时间:2011-05-13 07:06:14

标签: llvm

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

  1. 自动运行。此模式将代码编译为LLVM,并使用ExecutionEngine JIT将其编译为机器代码,并在不生成输出文件的情况下运行它。
  2. 编译并单独运行。此模式输出LLVM .bc文件,我手动优化(使用opt),编译为本机程序集(使用llc)编译为机器代码并链接(使用gcc),以及运行。
  3. 我期待方法#2比方法#1更快,或者至少相同的速度,但运行一些速度测试,我惊讶地发现#2的运行速度一直是慢两倍。这是一个巨大的速度差异。

    两种情况都运行相同的LLVM源代码。方法#1,我还没有打算运行任何LLVM优化传递(这就是为什么我期望它更慢)。方法#2,我正在opt-std-compile-optsllc-O3一起运行,以最大限度地优化,但它不会在#1附近。以下是同一程序的示例运行:

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

    ExecutionEngine是否做了一些我不知道的特别事情?有没有办法让我优化编译代码以达到与ExecutionEngine JIT相同的性能?

2 个答案:

答案 0 :(得分:29)

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

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

答案 1 :(得分:14)

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

作为一个现实生活中的例子,让我们考虑一下Google的Native Client - 我的意思是原始的nacl编译方法,而不是LLVM(因为据我所知,目前有支持“nativeclient”和“LLVM bitcode”的方向(modyfied)代码)。

正如您在演示文稿(请查看youtube.com)或papers中看到的那样,Native Client: A Sandbox for Portable, Untrusted x86 Native Code,甚至他们的对齐技术也会使代码大小更大,在某些情况下会使指令对齐(对于使用noops的例子可以提供更好的缓存命中率。

将指令与noops对齐并在重新排序中对并行计算中的指令进行重新排序,此处也显示了它的影响。

我希望这个答案能够了解有多少情况可能会对代码速度执行产生影响,而且这是造成不同代码片段的许多可能原因,并且每个代码都需要调查。从来没有,这是一个有趣的话题,所以如果你找到更多的细节,不要犹豫重复你的答案,让我们知道“Post-Scriptorium”,你发现了什么:)。 (也许链接到白皮书/ devblog与新发现:))。我们随时欢迎基准测试 - 看看:http://llvm.org/OpenProjects.html#benchmark