适用于C,C ++等的JIT编译器


33

是否有针对C和C ++等已编译语言的即时编译器?(想到的第一个名字是Clang和LLVM!但是我不认为它们目前支持它。)

说明:

我认为该软件可以受益于运行时性能分析反馈以及在运行时对热点进行积极优化的重新编译,即使对于C和C ++等编译为机器的语言也是如此。

概要文件引导的优化可以完成类似的工作,但是不同的是,JIT在不同的环境中会更加灵活。在PGO中,您在运行二进制文件之前先运行它。发行后,它将不会在运行时收集任何环境/输入反馈。因此,如果更改输入模式,则可能会降低性能。但是,即使在这种情况下,JIT也能很好地工作。

但是,我认为JIT编译性能的好处是否超过其自身的开销是有争议的。


1
主题外资源。
DeadMG

1
不确定是否适合该问题,但是出于可用性的考虑,我发现Julia语言中的Cxx软件包很有用。它为您提供了一个交互式C ++提示,类似于@PhilippClaßen答案中所述。
安东内洛

Answers:


33

[请参阅编辑历史,以获取现在已经基本过时的完全不同的答案。]

是的,有几个针对C和/或C ++的JIT编译器。

CLing(您可能会从游戏中猜到)基于Clang / LLVM。它就像一个口译员。也就是说,您给它一些源代码,给它一个运行命令,然后它就会运行。这里的重点主要是方便和快速编译,而不是最大程度的优化。因此,尽管从技术上来说是对问题本身的答案,但这并不完全符合OP的意图。

另一种可能性是NativeJIT。这有点不同地适合了这个问题。特别是,它不接受C或C ++源代码,并对其进行编译和执行。而是一个小型编译器,您可以将其编译为C ++程序。它接受一个在C ++程序中基本上表示为EDSL的表达式,并从中生成实际的机器代码,然后可以执行该机器代码。这更适合一个框架,在该框架中,您可以使用普通的编译器来编译大部分程序,但是有一些直到运行时才知道的表达式,您希望以接近最佳执行速度的方式执行这些表达式。

至于原始问题的明显意图,我认为我的原始答案的基本观点仍然存在:尽管JIT编译器可以适应诸如数据在一次执行之间变化,甚至在一次执行过程中动态变化的情况,现实情况是,至少作为一般规则,这几乎没有什么区别。在大多数情况下,在运行时运行编译器意味着您需要放弃很多优化,所以通常您甚至希望获得的最佳效果是,它的速度接近于常规编译器产生的速度。

虽然它可能假设的情况下提供给JIT编译器的信息可能会使其产生比传统的编译器实质上更好的代码,这种情况发生在实际的情况似乎是相当不寻常的(在这里我已经能够验证大多数情况下,它的发生,实际上是由于源代码中的问题,而不是静态编译模型造成的。


1
JIT为什么不保存类似于缓存的文件,以便他们可以跳过从头开始重新学习所有内容的工作?
JohnMudd 2015年

3
@JohnMudd:我怀疑推理是安全的。例如,修改缓存的代码,然后在VM下一次启动时,它将执行我在其中放置的代码,而不是在其中写入的代码。
杰里·科芬,2015年

4
OTOH,如果您可以修改缓存,那么您也可以修改源文件。
user3125367

1
@ user3125367:是的,但是在许多情况下,编译器会进行各种类型检查,如果直接从缓存中加载已编译的代码,则可能会绕过这种检查。当然,这取决于JIT - Java在加载(已编译的).class文件时会执行很多强制性工作,但许多其他事情会少得多(在许多情况下几乎没有)。
杰里·科芬,2015年

11

是的,有用于C ++的JIT编译器。从纯粹的性能角度来看,我认为配置文件导引优化(PGO)仍然更好。

但是,这并不意味着JIT编译尚未在实践中使用。例如,Apple使用LLVM作为其OpenGL管道的JIT。在该域中,您可以在运行时获得大量更多信息,这些信息可用于删除大量无效代码。

JIT的另一个有趣的应用是Cling,它是基于LLVM和Clang的交互式C ++解释器:https : //root.cern.ch/cling

这是一个示例会话:

[cling]$ #include <iostream>
[cling]$ std::cout << "Hallo, world!" << std::endl;
Hallo, world!
[cling]$ 3 + 5
(int const) 8
[cling]$ int x = 3; x++
(int) 3
(int const) 3
[cling]$ x
(int) 4

它不是玩具项目,但实际上在CERN中用于开发大型强子对撞机的代码。


7

C ++ / CLI异常。当然,C ++ / CLI 不是 C ++,但是非常接近。那就是说,微软的JIT并没有进行您所要求的基于超级聪明/可爱的运行时行为的优化,至少就我所知。因此,这确实无济于事。

http://nestedvm.ibex.org/将MIPS转换为Java字节码,然后将其粘贴。您的问题中这种方法的问题在于,您在到达JIT时会丢弃很多有用的信息。


2

首先,我假设您需要跟踪jit,而不是方法jit。

最好的方法是将代码编译为llvm IR,然后在生成本机可执行文件之前添加跟踪代码。一旦代码块变得足够好使用,并且一旦已经收集了有关变量值的足够信息(不是动态语言中的类型),就可以使用基于变量值的保护措施(从IR)重新编译代码。

我似乎记得在用libclang的名称在clang中制作ac / c ++ jit方面取得了一些进展。


1
AFAIK,libclang是大多数clang功能,是作为库分解出来的。所以,你可以用它来分析源代码来创建复杂的语法着色,绒毛,代码浏览等
哈维尔

@哈维尔,听起来不错。我认为库中有一个函数可以接受源代码的const char *并生成llvm ir,但是现在考虑,最好是基于ir而不是源进行jit。
dan_waterworth 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.