C/ c++的JIT优化器

JIT optimizer for C/C++

本文关键字:优化 JIT c++      更新时间:2023-10-16

我正在阅读有关JIT相对于预编译的优点的文章,其中提到的优点之一是JIT可以根据实际运行时数据调整分支预测。我在大学时编写编译器已经很久了,但在我看来,在大多数情况下(没有显式gotos的情况下),预编译代码也可以实现类似的功能。

考虑以下代码:

   test x
   jne L2:
L1: ...
   jmp L3:
L2: ...
L3:

如果我们有一些运行时工具可以看到'jne L2'为真多少次,它可以物理地交换L1:块和L2:块中的所有指令。当然,它必须知道在交换期间没有线程在两个块内,但这些都是细节…

   test x
   jeq L1:
L2: ...
   jmp L3:
L1: ...
L3:

我知道当程序代码在只读内存中加载时也存在问题,等,但这是一个想法。

所以我的问题是,这样的JIT优化是可行的C/c++还是我错过了一些根本的原因,为什么这不能做到?有针对C/c++的JIT优化器吗?

据我所知,c++没有JIT编译器;然而,GCC确实支持反馈导向优化(FDO),它可以使用运行时分析来优化分支预测等。

查看以"-fprofile"开头的GCC选项(提示:"-fprofile-use"使用生成的运行时配置文件来执行优化,而"-fprofile-generate"用于生成运行时配置文件)。

大多数现代CPU支持分支预测。它们有一个小的缓存,允许CPU在运行时重新排序。这个缓存在大小上是相当有限的,但这可能意味着您无法获得想象中的那么多好处。有些cpu甚至可以同时执行两个分支,而丢弃未被占用的分支上完成的工作。


编辑:使用JIT编译器的最大优势来自于这样的代码。
if (debug) {
   // do something
}

jit非常擅长检测和优化不做任何事情的代码。(如果你有一个微基准测试,表明Java比C快得多,很可能是JIT检测到你的测试没有做任何C编译器没有做的事情)

你可能会问,为什么C没有这样的东西?因为它有"更好"的东西

#if DEBUG
    // do something
#endif

如果DEBUG很少更改,并且这些标志很少,那么您可以编译每个有用的组合,这是最佳的。

这种方法的问题是可伸缩性。您添加的每个标志都可以使生成的预编译二进制文件的数量增加一倍。

如果你有很多这样的标志,并且编译每个组合是不切实际的,你需要依赖分支预测来动态优化你的代码

您指的是跟踪或重新优化JIT,而不仅仅是任何旧的JIT,像这样的东西还没有为C或c++做(至少没有公开)。但是,您可能想要检查LLVM是否没有使用Clang或GCC前端的分支(考虑到它既是编译器又是JIT),因为我已经看到一些主题表明它可能被实现。

HP Dynamo二进制重编译器证明,在c++编译器生成的优化代码上,有可能实现高达20%的加速。Dynamo并不是一个真正的JIT编译器,因为它从任意机器码开始,而不是一些更高级的表示,如JVM字节码或。net CIL,但原则上c++的JIT只会比Dynamo更高效。参见:http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.12.7138&等级= 1

Dynamo是为HP PA-RISC架构创建的,从未作为商业产品提供,因此它在当前由x86变体主导的世界中没有多大用处。我想知道VMware, Connectix或Parallels是否曾经尝试过在他们的重新编译器中添加优化通道,或者他们已经摆脱了二进制转换,转而支持最新x86 cpu的虚拟化功能。