加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – CPU的div指令和HotSpot的JIT代码之间的性能差距很大

发布时间:2020-12-15 00:21:29 所属栏目:Java 来源:网络整理
导读:自从CPU开始以来,一般知道整数除法指令是昂贵的.我去看看今天的CPU有多少亿的晶体管,我发现硬件idiv指令仍然比JIT编译器能够发出的代码(不包含idiv指令)对于常数除数显着更差. 为了把它放在一个专门的微型基准中,我写了以下内容: @BenchmarkMode(Mode.Avera
自从CPU开始以来,一般知道整数除法指令是昂贵的.我去看看今天的CPU有多少亿的晶体管,我发现硬件idiv指令仍然比JIT编译器能够发出的代码(不包含idiv指令)对于常数除数显着更差.

为了把它放在一个专门的微型基准中,我写了以下内容:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@OperationsPerInvocation(MeasureDiv.ARRAY_SIZE)
@Warmup(iterations = 8,time = 500,timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5,time = 1,timeUnit = TimeUnit.SECONDS)
@State(Scope.Thread)
@Fork(1)
public class MeasureDiv
{
  public static final int ARRAY_SIZE = 128;
  public static final long DIVIDEND_BASE = 239520948509234807L;
  static final int DIVISOR = 10;
  final long[] input = new long[ARRAY_SIZE];

  @Setup(Level.Iteration) public void setup() {
    for (int i = 0; i < input.length; i++) {
      input[i] = DIVISOR;
    }
  }

  @Benchmark public long divVar() {
    long sum = 0;
    for (int i = 0; i < ARRAY_SIZE; i++) {
      final long in = input[i];
      final long dividend = DIVIDEND_BASE + i;
      final long divisor = in;
      final long quotient = dividend / divisor;
      sum += quotient;
    }
    return sum;
  }

  @Benchmark public long divConst() {
    long sum = 0;
    for (int i = 0; i < ARRAY_SIZE; i++) {
      final long in = input[i];
      final long dividend = DIVIDEND_BASE + in;
      final int divisor = DIVISOR;
      final long quotient = dividend / divisor;
      sum += quotient;
    }
    return sum;
  }
}

简而言之,我有两个方法在各方面相同,除了一个(divVar)由数组读取的数字执行除法,而另一个除以编译时常数.结果如下:

Benchmark            Mode  Cnt  Score   Error  Units
MeasureDiv.divConst  avgt    5  1.228 ± 0.032  ns/op
MeasureDiv.divVar    avgt    5  8.913 ± 0.192  ns/op

性能比是非常不寻常的.我的期望是,现代英特尔处理器具有足够的房地产,其工程师有足够的兴趣,在硬件中实现复杂但性能分割算法.然而,JIT编译器通过向其发送一些执行相同作业的其他指令的流,只需七倍.如果有什么,专用微代码应该能够利用CPU甚至比JIT可以通过汇编指令的公共API来做的更好.

怎么来笨拙还是慢得多,根本的限制是什么?

想到的一个解释是假设存在一个除法算法,该算法首次涉及红利的进程.然后,JIT编译器将有一个头开始,因为它将评估在编译时仅涉及除数的第一部分,并仅将算法的第二部分作为运行时代码发出.那个假设是否正确?

解决方法

如用户pvg通过注释所解释的,假设的算法确实存在并且是目前已知的最佳算法.该算法涉及在准备步骤中除以同一除数,因此整体上根本不可约束.它在经典出版物 Hacker’s Delight的第10章中有所描述.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读