Java JIT循环展开策略?

Posted

技术标签:

【中文标题】Java JIT循环展开策略?【英文标题】:Java JIT loop unrolling policy? 【发布时间】:2011-11-06 18:40:35 【问题描述】:

JIT 的循环展开策略是什么?或者,如果没有简单的答案,那么有什么方法可以检查循环展开的位置/时间?

GNode child = null;
for(int i=0;i<8;i++)
   child = octree.getNeighbor(nn, i, MethodFlag.NONE);
   if(child==null)
      break;
   RecurseForce(leaf, child, dsq, epssq);

基本上,我上面有一段代码具有静态迭代次数(八次),当我离开 for 循环时它会很糟糕。但是当我手动展开循环时,它的效果要好得多。我很想知道 JIT 是否真的展开了循环,如果没有,那是为什么。

【问题讨论】:

这是一个非常非常具体的问题,您需要针对特定JVM特定版本进行分析> 在特定平台上。我猜他们的“为什么”只能通过深入分析 JIT 代码来回答。 您遗漏了一个关键细节:您使用的是哪个 JVM? @aioobe 它的 Java 热点 64 位,1.6.x 【参考方案1】:

如果 JVM 展开循环可能最好由 printing the generated assembly 实际回答。请注意,这需要您的代码实际作为热点执行(即 JVM 认为它值得进行昂贵的优化)。

为什么 JVM 决定一种或另一种方式是一个更难的问题,可能需要对 JIT 代码进行深入分析。

【讨论】:

谢谢。打印程序集是一种可能的方式,但我想知道是否有任何公开的 API 可以调查这一点。类似于在 JIT 完成循环展开时调用的方法,我可以计算它被调用的次数以及调用它的上下文。我查看了 JVMTI 并没有找到任何东西。 我很确定没有这样的 API,仅仅是因为它高度依赖于实现,并且仅对 大多数应用程序的使用有限. 谢谢。我想我在玩过 JVMTI 和 Eclipse JDT 之后期待太多了。 实际上整个事情不仅仅是实现和代码特定的,甚至可以通过命令行选项来影响它。看看-XX:LoopUnrollLimit=【参考方案2】:

查看循环中是否正在执行循环展开的另一种方法是在运行代码时将-XX:LoopUnrollLimit=1 指定为argument to the JVM。

如果您有一个可执行的 jar,那么如何使用它的示例如下:

java -XX:LoopUnrollLimit=1 -jar your-jar.jar

这个标志将

使用小于该值的服务器编译器中间表示节点数展开循环体

这将直接解决您的问题,而无需查看生成的程序集

【讨论】:

以上是关于Java JIT循环展开策略?的主要内容,如果未能解决你的问题,请参考以下文章

Java在Debug的时候,有些变量能无限展开(循环了)?

优化编译器如何决定何时展开循环以及展开循环的程度?

为啥 clang 无法展开循环(即 gcc 展开)?

展开循环有效,for循环无效[重复]

循环展开与循环平铺

在 MSVC C++ 中强制循环展开