【问题标题】:Can JIT compilation run faster than compile time template instantiation?JIT 编译可以比编译时模板实例化运行得更快吗?
【发布时间】:2018-07-08 19:23:36
【问题描述】:

我最近听到很多人说 JIT 编译生成的代码非常快,甚至比任何静态编译器都快。当涉及到 C++ STL 样式的模板代码时,我很难相信这一点,但这些人(通常来自 C#/Java 背景)坚持认为确实如此。

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

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

【问题讨论】:

标签: c++ templates jit


【解决方案1】:

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

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

【讨论】:

  • 有趣。您是否了解收集统计信息以进行此描述的开销是多少?
  • @masaers 对不起,我没有。我只记得读到这是一种实际使用的技术。
  • 别担心,只是好奇。
  • 请注意,一些静态 AOT 编译器也支持配置文件引导的优化。例如,icc。
【解决方案2】:

你可以在运行时做的事情

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

以及我在列表中遗漏的其他内容

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

【讨论】:

  • 静态编译可以做这些事情。
  • 这些更像是静态编译器为了便于移植而通常避免做的事情,而不是静态不可能做的事情,不是吗?
  • @masaers 静态编译器不可能知道将运行的每台机器上的缓存布局。它怎么知道我是在 4 核还是 8 核上运行(我的意思是我的实际机器,你在你的机器上编译)它唯一能做的就是不关心,或者生成所有可能的优化并在运行时选择,这将有开销
  • 您假设用户无法从源代码编译,这在许多情况下是正确的,但远非如此。
  • ©pm100 在安装时选择呢?
【解决方案3】:

与上面声称的答案相反:

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

  2. 对于给定架构的处理器,缓存大小通常相同。例如,英特尔的 L1 缓存大小通常为 4kB,L2 缓存大小为 32kB,L3 缓存大小为 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)。

【讨论】:

  • 当然。如果调整得当,它可能是这样的——但大多数人不会制作一打单独调整的版本。所以 JIT 可以更胖并不意味着它必须更快。看看stackoverflow.com/a/5641664/2193968
  • 但在许多情况下,从源代码编译并针对将运行代码的确切机器进行编译是可行的。
  • “4kb”千位还是千字节?
猜你喜欢
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
  • 2011-05-25
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
相关资源
最近更新 更多