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

为什么LLVM执行引擎比编译代码快?,llvm,Llvm,我有一个针对LLVM的编译器,我提供了两种运行代码的方法: 自动运行它。此模式将代码编译为LLVM,并使用ExecutionEngine JIT动态地将其编译为机器代码,并在不生成输出文件的情况下运行 编译它并单独运行。此模式输出一个LLVM.bc文件,我手动优化(使用opt),编译到本机程序集(使用llc),编译到机器代码并链接(使用gcc),然后运行 我原以为进近2比进近1快,或者至少相同的速度,但通过一些速度测试,我惊讶地发现进近2的速度始终是进近1的两倍。这是一个巨大的速度差 这两种情况

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

  • 自动运行它。此模式将代码编译为LLVM,并使用ExecutionEngine JIT动态地将其编译为机器代码,并在不生成输出文件的情况下运行
  • 编译它并单独运行。此模式输出一个LLVM.bc文件,我手动优化(使用
    opt
    ),编译到本机程序集(使用
    llc
    ),编译到机器代码并链接(使用
    gcc
    ),然后运行
  • 我原以为进近2比进近1快,或者至少相同的速度,但通过一些速度测试,我惊讶地发现进近2的速度始终是进近1的两倍。这是一个巨大的速度差

    这两种情况都运行相同的LLVM源代码。对于方法1,我还没有费心运行任何LLVM优化过程(这就是为什么我希望它会慢一些)。使用方法2,我使用
    -std compile opts运行
    opt
    ,使用
    -O3
    运行
    llc
    ,以最大限度地优化,但它没有接近1。以下是同一程序的运行示例:

    • #1未经优化:11.833s
    • #2未经优化:22.262s
    • #2优化(
      -std编译选项
      -O3
      ):18.823s

    ExecutionEngine是否在做一些我不知道的特殊事情?我有没有办法优化编译后的代码,以获得与ExecutionEngine JIT相同的性能?

    具有JIT的VM运行某些应用程序的速度通常比编译后的应用程序快。这是因为具有JIT的VM就像模拟虚拟计算机的模拟器,并且实时运行编译器。因为这两个任务都是通过JIT内置到VM中的,所以机器模拟器可以向编译器提供信息,以便重新编译代码以更高效地运行。它提供的信息对静态编译代码不可用


    Java虚拟机和Python的PyPy虚拟机等也注意到了这种效果。

    另一个问题是调整代码和其他优化。现在的cpu是如此的复杂,以至于很难预测哪种技术可以更快地执行最终的二进制文件

    作为一个真实的例子,让我们考虑一下谷歌的本地客户端——我指的是原始的NaCL编译方法,而不是LLVM(原因是,据我所知,目前有方向支持“NATEVEClient”和“LLVM位代码”(MODYEMAGE)代码)。 正如您在演示文稿(请访问youtube.com)或类似的文章中所看到的,即使它们的对齐技术也会使代码变大,在某些情况下,指令对齐(例如使用noops)可以提供更好的缓存命中

    将指令与noop对齐,并对其进行指令重新排序,这在并行计算中是众所周知的,这里也显示了它的影响


    我希望这个答案能告诉我们环境对代码执行速度的影响有多大,不同代码段的原因有很多,每个都需要调查。无论如何,这是一个有趣的话题,所以如果你发现了更多的细节,不要急于重新编辑你的答案,并在“后脚本室”中告诉我们,你发现了什么更多:)。(可能会链接到白皮书/devblog,其中包含新发现:))。基准测试总是受欢迎的-看看:。

    您是否在执行测试的实际机器上生成了二进制文件?@smerlin是的。我想你会问,因为生成的代码将针对特定的机器进行优化。但是我检查了一下;它默认为针对运行编译器的机器进行优化。有些事情看起来确实不对劲。如果您向llc提供-O0,将会是什么?就生成的代码而言,这将完全等同于EE。您的cpu架构是什么?您是否尝试使用lli运行编译的.bc文件?您可以向您显示.bc文件和jit中的llvm ir转储吗?请在编译时尝试使用
    -march=native
    。这能缩小差距吗?谢谢。这是有道理的。你认为这种效应足以产生两倍的加速吗?您是否有任何指向在JVM或PyPy上运行的其他实验的链接来证明这一效果?实际上,JIT或在线二进制重新编译方法可以快10倍以上。当前系统的关键性能问题是缓存性能的巨大差距。虽然片内内存随机访问约为1ns和5nS(1gops),但片外随机访问为50-500ns(20 Mops到2Mops),磁盘随机访问超过1Ms(1kop),JIT可以优化以避免这些未命中-使用大规模或深管道线多核轻松实现2倍和100倍。没有什么是免费的-通常使用的机制是耗电的。