热点循环条件优化器的奇怪行为

2022-09-04 23:26:55

基于围绕这个问题的答案的讨论,我发现了Java Hotspot优化器的一个非常奇怪的行为。观察到的行为至少在Oracle VM 1.7.0_17中可以看到,但在较旧的Java 6版本中似乎也会发生。

首先,我已经意识到优化器显然知道标准API中的某些方法是不变的并且没有副作用。在执行类似 的循环时,不会为每次迭代计算表达式,但优化程序知道该方法没有相关的副作用,并且只要不在循环中修改,结果就是不变的。double x=0.5; for(double d = 0; d < Math.sin(x); d += 0.001);Math.sin(x)Math.sinx

现在我注意到,简单地从0.5更改为1.0就禁用了这种优化。进一步的测试表明,仅当 abs(x) < asin(1/sqrt(2)) 时,才会启用优化。有没有一个很好的理由,我没有看到,或者这是对优化条件的不必要的限制?x

编辑:优化似乎是在 hotspot/src/share/vm/opto/subnode 中实现的.cpp


答案 1

我认为你的问题是关于Oracle JVM的,因为Math的实现是依赖于实现的。以下是关于Dalvik实现的良好答案,例如:Java Math类的本机代码

一般

  1. sin(a) * sin(a) + cos(a) * cos(a) = 1
  2. sin(pi/2 - a) = cos(a)
  3. sin(-a) = -sin(a)
  4. cos(-a) = cos(a)

所以我们不需要<0或x的sin/cos函数实现,>pi/4。

我想这就是答案(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5005861):

我们了解almabench结果和关于三角函数性能的osnews文章。然而,多年来,在 x86 上实现 sin/cos 的 HotSpot 已经并将继续使用 fsin/fcos x87 指令,在这些指令满足实现质量要求的范围内,基本上是 [-pi/4, pi/4]。在该范围之外,fsin/fcos 的结果可以位于范围 [-1, 1] 中的任何位置,与参数的真正弦/余弦关系不大。例如,fsin(Math.PI)只能获得结果正确的一半左右。这样做的原因是fsin/fcos指令实现使用不太理想的算法来减少参数;参数减少过程在 bug 4857011 中进行了解释。

结论:您已经看到了参数约简算法在行动中的结果,而不是优化的限制。


答案 2

推荐