自从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章中有所描述.

java – CPU的div指令和HotSpot的JIT代码之间的性能差距很大的更多相关文章

  1. 汇编 – “LES”8086指令未按预期工作

    当我调试编译的exe时,我注意到ES和DI寄存器没有加载正确的值.在加载段和从RAM偏移之前,需要将DS寄存器设置为实际指向数据段.默认情况下,DS指向您的PSP,而PSP不是您希望它指向的位置.

  2. delphi – 某些CPU在紧循环中的ADC / SBB和INC / DEC存在问题

    我在Delphi中编写一个简单的BigInteger类型.它主要由TLimb的动态数组组成,TLimb是一个32位无符号整数,32位大小的字段也保存BigInteger的符号位.要添加两个BigInteger,我创建一个适当大小的新BigInteger,然后在一些记账后,调用以下过程,将三个指针传递给左右操作数和结果的数组的各个开始,以及分别为左右肢数.普通代码:这个代码运行良好,我非常满意,直到

  3. Delphi中的COM方法偏移

    在Delphi中,如何找到COM方法的地址?解决方法您可以使用vmtoffset汇编程序指令获取接口方法相对于接口方法表开头的字节偏移量.看一下System.pas中_IntfCast的实现,例如:第一个表达式加0;第二,8.但是,您无法对这些表达式进行参数化.它们是编译时常量,因此您无法在运行时选择所需的方法.您需要提前表示所有可能的方法名称.你真正需要挂钩的是QueryInterface.完成后,您可以返回所需的任何代理对象,可以拦截对所有其他方法的调用.

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

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

  5. 将目标地址保持在寄存器中,直到指令退出

    我想使用精确的基于事件的采样(PEBS)在XeonE5SandyBridge上记录特定事件的所有地址(例如高速缓存未命中).但是,CoreTMi7处理器和英特尔至强5500处理器的性能分析指南(第24页)包含以下警告:AsthePEBSmechanismcapturesthevaluesoftheregisteratcompletionoftheinstruction,thedereference

  6. c# – T4在网站项目中具有相对路径的汇编指令?

    我在VisualStudio中有一个网站项目,我正在尝试从站点的bin目录中引用一些程序集.到目前为止,根路径是唯一有效的路径:其他人提到使用msbuild变量,但这对我不起作用:我很确定相对路径只是平坦无法工作:如果不使用root路径,有没有办法让这个工作在网站项目的上下文中?解决方法T4模板中的装配参考需要GAC或绝对路径.但是,您可以使用已知路径中的相对路径:例如:

  7. x86_64上无用的jp / jnp汇编指令

    我试图找出jp/jnp指令在LLVM生成的C代码中的用途.样品:装配输出:jne正在检查值!=1.5并跳过赋值,但jp在这种情况下做了什么?

  8. c – 转置2D阵列

    你如何有效地转置矩阵?有没有这个库,或者你会使用什么算法?现在,对于32位寄存器中的8位字节,ARM没有完全随机指令,但您可以使用移位和SEL(选择)指令来合成所需的内容,并且可以在一个指令中进行第二组混洗.使用PKHBT和PKHTB指令进行指导.最后,如果您正在使用具有NEON矢量化的大型ARM处理器,则可以使用16×16块上的16个元素向量执行此类操作.

  9. c – 如何获取gdb tui程序集输出以显示指令?

    我想看到程序集输出,但发现在TUI中,它会输出函数签名偏移量:这很酷,除了我用C编程并且函数签名完全解析的事实,所以我得到名称空间和模板参数使函数sig2或更多行.这当然会在TUI中被截断,因此它甚至不会显示汇编指令.有没有办法缩短,更改前缀或根本不输出此前缀到汇编指令?

  10. 获取C/C++中的指令地址

    获取指令地址的任何方法?我曾试图用标记指令并获取标签的地址,但似乎只能在GCC编译器中使用&&操作符.如果有其他编译器怎么办?对这个问题的任何想法?解决方法我不确定C语言或C语言标准是否适用于教学;你可以想象,你可以运行一个编译成由一大群人类奴隶执行的C程序.你可以自己运行一个简单的小程序,用铅笔和纸,你可以使用C解释器等…

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部