跳到主要内容

AOT与JIT的区别

目前,程序主要有两种运行方式:静态编译动态解释

  • 静态编译的代码程序在执行前全部被翻译为机器码,通常将这种类型称为 AOT(Ahead of time),即“提前编译”;
  • 动态解释的程序则是对代码程序边翻译边运行,通常将这种类型称为 JIT(Just in time),即“即时编译”。

AOT 程序的典型代表是用 C/C++ 开发的应用,其必须在执行前编译成机器码,然后再交给操作系统具体执行;而 JIT 的代表非常多,如 JavaScript、Python 等动态解释的程序。 事实上,所有脚本语言都支持 JIT 模式。但需要注意的是 JIT 和 AOT 指的是程序运行方式,和编程语言本身并非强关联的,有的语言既可以以 JIT 方式运行也可以以 AOT 方式运行,如 Java 和 Python。它们可以在第一次执行时编译成中间字节码,之后就可以直接执行字节码。 也许有人会说,中间字节码并非机器码,在程序执行时仍然需要动态将字节码转为机器码。理论上讲这没有错,不过通常区分是否为 AOT 的标准就是看代码在执行之前是否需要编译,只要需要编译,无论其编译产物是字节码还是机器码,都属于 AOT 的方式。

优缺点对比

下面是 JIT 和 AOT 两种编译方式的优点对比。在 JIT 中其优点为:

  1. 可以根据当前硬件情况实时编译生成最优机器指令
  2. 可以根据当前程序的运行情况生成最优的机器指令序列
  3. 当程序需要支持动态链接时,只能使用JIT的编译方式
  4. 可以根据进程中内存的实际情况调整代码,使内存能够更充分的利用

但是 JIT 缺点也非常明显:

  1. 编译需要占用运行时Runtime的资源,会导致进程执行时候卡顿
  2. 编译占用运行时间,对某些代码编译优化不能完全支持,需在流畅和时间权衡
  3. 在编译准备和识别频繁使用的方法需要占用时间,初始编译不能达到最高性能

相对而言,JIT 的缺点也是 AOT 的优点所在:

  1. 在程序运行前编译,可以避免在运行时的编译性能消耗和内存消耗
  2. 可以在程序运行初期就达到最高性能
  3. 可以显著的加快程序的执行效率

其 AOT 的优点之下,也会带来一些问题:

  1. 在程序运行前编译会使程序安装的时间增加
  2. 将提前编译的内容保存起来,会占用更多的内存
  3. 牺牲高级语言的一致性问题

在AI框架中区别

目前主流的AI框架,都会带有前端的表达层,再加上AI编译器对硬件使能,因此AI框架跟AI编译器之间关系非常紧密,部分如MindSpore、TensorFlow等AI框架中默认包含了自己的AI 编译器。目前PyTorch2.X版本升级后,也默认自带Inductor功能特性,可以对接多个不同的AI编译器。

静态编译的代码程序在执行前全部被翻译为机器码,这种AOT(Ahead of time),即提前编译的方式,AOT更适合移动、嵌入式深度学习应用。在MLIR + TensorFLow框架中目前支持AOT和JIT的编译方式,不过在AI领域,目前AOT的典型代表有: 1)推理引擎,在训练的之后AI编译器把网络模型提前固化下来,然后在推理场景直接使用提前编译好的模型结构,进行推理部署; 2)静态图生成,通过AI编译器对神经网络模型表示称为统一的IR描述,接着在真正运行时执行编译后的内容。

image.png

另一方面,动态解释的程序则是对代码程序边翻译边运行,称为JIT(Just in time),即即时编译。典型的代表有: 1)PyTorch框架中的JIT特性,可以将Python代码实时编译成本地机器代码,实现对深度学习模型的优化和加速。 2)清华发布的计图(Jittor),完全基于动态编译JIT,内部使用创新的元算子和统一计算图的深度学习框架,元算子和Numpy一样易于使用,并且超越Numpy能够实现更复杂更高效的操作。基于元算子开发的深度学习模型,可以被计图实时的自动优化并且运行在指定的硬件上。

image.png