深入拆解Java虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
立即订阅
28017 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 为什么我们要学习Java虚拟机?
免费
模块一:Java虚拟机基本原理 (12讲)
01 | Java代码是怎么运行的?
02 | Java的基本类型
03 | Java虚拟机是如何加载Java类的?
04 | JVM是如何执行方法调用的?(上)
05 | JVM是如何执行方法调用的?(下)
06 | JVM是如何处理异常的?
07 | JVM是如何实现反射的?
08 | JVM是怎么实现invokedynamic的?(上)
09 | JVM是怎么实现invokedynamic的?(下)
10 | Java对象的内存布局
11 | 垃圾回收(上)
12 | 垃圾回收(下)
模块二:高效编译 (12讲)
【工具篇】 常用工具介绍
13 | Java内存模型
14 | Java虚拟机是怎么实现synchronized的?
15 | Java语法糖与Java编译器
16 | 即时编译(上)
17 | 即时编译(下)
18 | 即时编译器的中间表达形式
19 | Java字节码(基础篇)
20 | 方法内联(上)
21 | 方法内联(下)
22 | HotSpot虚拟机的intrinsic
23 | 逃逸分析
模块三:代码优化 (10讲)
24 | 字段访问相关优化
25 | 循环优化
26 | 向量化
27 | 注解处理器
28 | 基准测试框架JMH(上)
29 | 基准测试框架JMH(下)
30 | Java虚拟机的监控及诊断工具(命令行篇)
31 | Java虚拟机的监控及诊断工具(GUI篇)
32 | JNI的运行机制
33 | Java Agent与字节码注入
模块四:黑科技 (3讲)
34 | Graal:用Java编译Java
35 | Truffle:语言实现框架
36 | SubstrateVM:AOT编译框架
尾声 (1讲)
尾声 | 道阻且长,努力加餐
深入拆解Java虚拟机
登录|注册

26 | 向量化

郑雨迪 2018-09-19
在上一篇的实践环节中,我给你留了一个题目:如何进一步优化下面这段代码。
void foo(byte[] dst, byte[] src) {
for (int i = 0; i < dst.length - 4; i += 4) {
dst[i] = src[i];
dst[i+1] = src[i+1];
dst[i+2] = src[i+2];
dst[i+3] = src[i+3];
}
... // post-loop
}
由于 X86_64 平台不支持内存间的直接移动,上面代码中的dst[i] = src[i]通常会被编译为两条内存访问指令:第一条指令把src[i]的值读取至寄存器中,而第二条指令则把寄存器中的值写入至dst[i]中。
因此,上面这段代码中的一个循环迭代将会执行四条内存读取指令,以及四条内存写入指令。
由于数组元素在内存中是连续的,当从src[i]的内存地址处读取 32 位的内容时,我们将一并读取src[i]src[i+3]的值。同样,当向dst[i]的内存地址处写入 32 位的内容时,我们将一并写入dst[i]dst[i+3]的值。
通过综合这两个批量操作,我们可以使用一条内存读取指令以及一条内存写入指令,完成上面代码中循环体内的全部工作。如果我们用x[i:i+3]来指代x[i]x[i+3]合并后的值,那么上述优化可以被表述成如下所示的代码:
void foo(byte[] dst, byte[] src) {
for (int i = 0; i < dst.length - 4; i += 4) {
dst[i:i+3] = src[i:i+3];
}
... // post-loop
}

SIMD 指令

在前面的示例中,我们使用的是 byte 数组,四个数组元素并起来也才 4 个字节。如果换成 int 数组,或者 long 数组,那么四个数组元素并起来将会是 16 字节或 32 字节。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Java虚拟机》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(6)

  • godtrue
    小结一下
    1:向量化优化-本质是一次性多干一些活,免得来回折腾费时费力,通过减少来回折腾的工作量来提高性能。他是怎么实现的呢?他是借助CPU的SIMD指令,通过单条指令控制多组数据的运算,实现了CPU指令级别的并行。
    2:这么好为什么不大批量的使用哪?他有几种方式呢?
    使用向量化优化是有一些前提条件的,目前HotSpot 虚拟机运用向量化优化的方式有两种。第一种使用HotSpot intrinsic,在调用特定的方法的时候替换为使用了SIMD指令的高效实现。第二种是依赖即时编译器进行的自动向量化,自动向量化也有苛刻的使用前提条件。

    作者回复: 赞

    2018-09-20
    10
  • 罗布圆滚滚
    好棒哦!学到很多
    2018-09-19
    3
  • 随心而至
    SIMD,寄存器每次存好几条数据,那么就一次性拿这么多数据放到寄存器中,统一用一个向量相关的指令来算。这样一下子就可以算了循环中的很多次,相当于我们在并行执行某个循环。
    另外从寄存器中读写数据比内存快了很多很多倍。
    2019-10-29
  • Joker
    666,学到了
    2019-08-16
  • 渡劫达摩

        dst[i:i+3] = src[i:i+3]还有这种写法?是大哥省略了部分代码吗?
    2019-04-27
  • Geek_488a8e
    之前用过TI的DSP芯片,里边有很多支持向量处理的计算指令,比如复数乘法,共轭相乘等,但是这些计算指令器不多,而且不能在一个指令周期完成计算,所以大量使用后会影响指令流水,反而不如能在一个指令周期完成计算的单数据加法器

    作者回复: 我们做自动向量化也会考虑值不值得的问题。

    比如说X86不能在通用寄存器上计算,有时候需要额外的mov指令移到XMM中(如果不是直接从内存中加载的话)。

    另外,某些reduce操作,比如求向量内所有元素的和,X86无法用单条指令实现,只有两两相加的指令,因此需要好几条向量指令协作完成。这种情况下,我们便会放弃自动向量化。

    2018-09-20
收起评论
6
返回
顶部