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

时间:2018-01-30 01:10:49

标签: c++ templates jit

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

我的问题是:你可以在运行时但在编译时不能进行哪种优化?

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

你可以在运行时做的事情

  • 检查是否存在异乎寻常的指令(AMD vs intel,....)
  • 检测缓存拓扑
  • 检测内存大小
  • 核心数

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

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

答案 2 :(得分:0)

与上述答案相反:

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

  2. 对于给定体系结构的处理器,缓存大小通常相同。例如,英特尔的L1缓存大小通常为4kb,L2缓存大小为32kb,L3缓存大小为4Mb。

  3. 只有在出于某种原因,编写一个可以使用超过4Gb内存的大型程序时,才需要优化内存大小。

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

  5. 尽管如此,即使使用多核优化也无法使用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 ifs(如果switch语句是作为一系列ifs实现的话)。