JIT 编译的运行速度能否比编译时模板实例化更快?

Can JIT compilation run faster than compile time template instantiation?

本文关键字:编译 实例化 运行 速度 JIT      更新时间:2023-10-16

>我最近听到很多人说JIT编译产生非常快的代码,甚至比任何静态编译器都能产生更快。当涉及到C++STL风格的模板化代码时,我发现这很难相信,但是这些人(通常来自C#/Java背景)坚持认为情况确实如此。

因此,我的问题是:您可以在运行时进行哪些类型的优化,但不能在编译时进行?

编辑:澄清:我更感兴趣的是那种不可能静态做的事情,而不是任何一个行业的典型案例。

JIT 编译器可以测量进行条件跳转的可能性,并相应地调整发出的代码。静态编译器也可以执行此操作,但不能自动执行此操作;它需要程序员的提示。

显然,这只是众多因素中的一个,但它确实表明,在适当的条件下,JIT 可能会更快。

运行时可以做的事情

  • 检查存在哪些奇特指令(AMD 与英特尔,....)
  • 检测缓存拓扑
  • 检测内存大小
  • 内核数

以及我从列表中错过的其他内容

这是否使事情总是快 10 倍,不。但它肯定提供了在编译时不可用的优化机会(对于广泛分布的代码;显然,如果您知道它只会在 3 种不同的硬件配置上,那么您可以进行自定义构建等)

与上面声称的答案相反:

  1. 静态编译器可以轻松使用特定于体系结构的扩展。例如,Visual Studio有一个可以打开和关闭的SIMD扩展选项。

  2. 给定体系结构的处理器的缓存大小通常相同。例如,英特尔通常具有 4kB 的一级高速缓存大小、32kB 的二级高速缓存大小和 4MB 的三级高速缓存大小。

  3. 仅当您出于某种原因编写可以使用超过 4GB 内存的大型程序时,才需要优化内存大小。

  4. 这实际上可能是一种优化,其中使用 JIT 编译器实际上很有用。但是,您可以创建的线程数多于内核数,这意味着这些线程将在具有更多内核的 CPU 中使用单独的内核,并且只是内核较少的 CPU 中的线程。我也认为假设 CPU 有 4 个内核是相当安全的。

尽管如此,即使使用多核优化也不会使使用 JIT 编译器有用,因为程序的安装程序可以检查可用的内核数,并安装针对该计算机的内核数优化的程序的适当版本。

我不认为 JIT 编译比静态编译产生更好的性能。您始终可以创建代码的多个版本,每个版本都针对特定设备进行了优化。我能想到的唯一可以使 JIT 代码更快的优化类型是当您收到输入时,并且您用于处理它的任何代码都可以以这样的方式进行优化,以使代码在最常见的情况下更快(JIT 编译器可能能够发现), 但对于罕见的情况来说速度较慢。即使这样,您也可以执行该优化(但是,静态编译器将无法执行此优化)。

例如,假设您可以对数学算法执行优化,该算法会导致值 1-100 出错,但所有较大的数字都适用于此优化。您注意到可以轻松预先计算值 1-100,因此执行以下操作:

switch(num) {
case 0: {
//code
}
//...until case 100
}
//main calculation code

但是,这是低效的(假设 switch 语句未编译为跳转表),因为很少输入情况 0-100,因为它们是在没有计算机帮助的情况下在精神上找到的。JIT 可能会发现这更有效(在看到很少输入 0-100 范围内的值时):

if(num < 101) {
switch(num) {
/...same as other code above
}
}
//main calculation code

在此版本的代码中,如果最常见的情况,则只执行 1 if,而不是在极少数情况下平均执行 50 个 if(如果 switch 语句实现为一系列 if)。