每次Julia都会编译脚本吗?

69
Julia语言每次都要编译脚本,我们不能用Julia来编译二进制文件吗? 我尝试了一个很小的helloworld脚本,使用println函数,Julia花了2到3秒才显示输出!如果我们可以生成二进制文件而不是每次都编译,那就更好了。
更新:自从我提出这个问题以来,Julia发生了一些变化。虽然我不再关注Julia的更新,但如果你正在寻找类似的东西,请查看下面的答案和评论,这些人一直在关注Julia。
另外,很高兴知道现在加载一个脚本只需要大约150毫秒。
2个回答

107

Keno的回答很准确,但是也许我可以详细说明一下正在发生的事情以及我们计划如何处理。

目前仅存在LLVM JIT模式:

  • 有一个非常简单的解释器来解释一些简单的顶级语句。
  • 所有其他代码在执行之前都会被即时编译成机器码。 使用运行时对值的类型进行积极地特化,并通过动态类型推断将其传播到程序中。

这就是Julia即使没有类型注释编写代码时也能获得良好性能的方式:如果您调用f(1),则会得到为Int64专门设计的代码,64位系统上的1 的类型;如果您调用f(1.0),则会得到一种新的及时编译版本,该版本专门针对Float64 ——所有系统上1.0 的类型。由于每个函数的已编译版本知道它将要接收的类型,因此它可以以类似于C的速度运行。您可以通过编写和使用“类型不稳定”的函数,使返回类型取决于运行时数据而不仅仅是类型来破坏它,但在设计核心语言和标准库时,我们已经非常小心地避免了这种情况。

大多数Julia都是用自身编写的,然后被解释,类型推断和即时编译,因此从头开始引导整个系统需要大约15-20秒。为了使其更快,我们采用了分阶段系统,在其中解析,类型推断,然后缓存序列化版本的类型推断AST在文件sys.ji中。然后加载此文件并用于运行julia系统。但是,没有LLVM代码或机器代码被缓存在sys.ji中,因此每次julia启动时仍然需要进行所有LLVM即时编译,因此需要大约2秒钟。

这个2秒的启动延迟相当让人恼火,我们有一个解决计划。基本计划是能够将整个Julia程序编译为二进制文件:可以运行的可执行文件或者可以像使用共享C库一样从其他程序中调用的.so/.dylib共享库。二进制文件的启动时间就像任何其他C程序一样,所以2秒的启动延迟将消失。

附录1:自2013年11月起,Julia的开发版本不再有2秒的启动延迟,因为它预编译了标准库作为二进制代码。启动时间仍然比Python和Ruby慢10倍,因此还有改进的空间,但已经相当快了。下一步将允许预编译软件包和脚本,使它们的启动速度与Julia本身一样快。

附录2:自2015年6月起,Julia的开发版本自动预编译了许多软件包,使它们加载速度更快。下一步是对整个Julia程序进行静态编译。


6
我在过去一年左右的网络评论中看到了许多关于Julia编译可执行文件/共享对象的评论,但没有任何进展的迹象。你能否提供有关该方面进展情况的洞见? - dfreeman
2
Jameson Nash和Isaiah Norton已经取得了很大的进展,但还没有完全达到目标。 - StefanKarpinski
26
这项功能现已完成并合并到Julia主分支。在我的系统上,启动Julia所需的时间从约1.5秒缩短到了约150毫秒,这是一个惊人的10倍速度提升。如果我们能够再次获得10倍的速度提升,这完全有可能,那么Julia的启动时间将与Ruby和Python相当。 - StefanKarpinski
1
@StefanKrpinski,Julia本身启动后,仍需要一些时间来加载我所需的软件包。例如,在使用Julia版本0.3.0-prerelease+3381(2014年6月2日13:19 UTC)时,shell命令“julia -e”using DataFrames“”在我的计算机上需要21秒钟。有没有什么方法可以解决这个问题? - G. Grothendieck
5
供参考,@G.Grothendieck,模块的预编译是julia v0.4的一个新功能,可以大幅提高模块加载速度。 - Maxim
显示剩余2条评论

48

目前Julia在启动时会对其整个标准库进行JIT编译。我们已经意识到这种情况并正在努力缓存LLVM JIT输出以解决此问题,但在此之前,没有其他方法(除了使用REPL)。


22
这已经在 Julia 的夜间版本中实施,并将包含在 0.3 版本中。启动时间大大改善了。 - Isaiah Norton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接