当前位置: 首页 > 知识库问答 >
问题:

Java自动矢量化示例

史劲
2023-03-14

我试图找到一个简洁的例子,它显示了x86-64系统上java中的自动矢量化。

我在for循环中使用y[I]=y[I]x[I]实现了以下代码。这段代码可以从自动矢量化中受益,所以我认为java应该在运行时使用SSE或AVX指令编译它,以加快速度<但是,我在生成的本机代码中找不到矢量化的指令。

VecOpMicroBenchmark。java应该受益于自动矢量化:

    /**
     * Run with this command to show native assembly:<br/>
     * java -XX:+UnlockDiagnosticVMOptions
     * -XX:CompileCommand=print,VecOpMicroBenchmark.profile VecOpMicroBenchmark
     */
    public class VecOpMicroBenchmark {

        private static final int LENGTH = 1024;

        private static long profile(float[] x, float[] y) {
            long t = System.nanoTime();

            for (int i = 0; i < LENGTH; i++) {
                y[i] = y[i] + x[i]; // line 14
            }

            t = System.nanoTime() - t;

            return t;
        }

        public static void main(String[] args) throws Exception {
            float[] x = new float[LENGTH];
            float[] y = new float[LENGTH];

            // to let the JIT compiler do its work, repeatedly invoke
            // the method under test and then do a little nap
            long minDuration = Long.MAX_VALUE;
            for (int i = 0; i < 1000; i++) {
                long duration = profile(x, y);
                minDuration = Math.min(minDuration, duration);
            }
            Thread.sleep(10);

            System.out.println("\n\nduration: " + minDuration + "ns");
        }
    }

为了了解它是否得到矢量化,我执行了以下操作:

  1. 打开eclipse并创建上述文件
  2. 右键单击文件并从下拉框中选择运行

它现在应该向控制台打印大量信息,其中一部分是JIT编译器生成的反汇编本机代码。如果您看到许多消息,但没有诸如mov、push、add等汇编指令,那么您可能会在某处找到以下消息无法加载hsdis-amd64。所以库不可加载;PrintAssembly被禁用,这意味着java找不到文件hsdis-amd64。所以——它不在正确的目录中,或者没有正确的名称。

<代码>hsdis-amd64。因此,反汇编程序是显示生成的本机代码所必需的。JIT编译器将java字节码编译为本机机器代码后,hsdis-amd64。因此,使用来反汇编本机代码,使其具有可读性。您可以在“如何在JVM中查看JIT编译代码?”中找到有关如何获取/安装它的更多信息。

0x00007fac90ee9859: nopl    0x0(%rax)
0x00007fac90ee9860: cmp     0xc(%rdx),%esi    ; implicit exception: dispatches to 0x00007fac90ee997f
0x00007fac90ee9863: jnb     0x7fac90ee9989
0x00007fac90ee9869: movsxd  %esi,%rbx
0x00007fac90ee986c: vmovss  0x10(%rdx,%rbx,4),%xmm0  ;*faload {reexecute=0 rethrow=0 return_oop=0}
                                            ; - VecOpMicroBenchmark::profile@16 (line 14)

0x00007fac90ee9872: cmp     0xc(%rdi),%esi    ; implicit exception: dispatches to 0x00007fac90ee9997
0x00007fac90ee9875: jnb     0x7fac90ee99a1
0x00007fac90ee987b: movsxd  %esi,%rbx
0x00007fac90ee987e: vmovss  0x10(%rdi,%rbx,4),%xmm1  ;*faload {reexecute=0 rethrow=0 return_oop=0}
                                            ; - VecOpMicroBenchmark::profile@20 (line 14)

0x00007fac90ee9884: vaddss  %xmm1,%xmm0,%xmm0
0x00007fac90ee9888: movsxd  %esi,%rbx
0x00007fac90ee988b: vmovss  %xmm0,0x10(%rdx,%rbx,4)  ;*fastore {reexecute=0 rethrow=0 return_oop=0}
                                            ; - VecOpMicroBenchmark::profile@22 (line 14)

所以它使用的是AVX指令vaddss。但是,如果我在这里是正确的,vadds表示添加标量单精度浮点值,这只会将一个浮点值添加到另一个浮点值(这里,标量表示仅一个,而这里single表示32位,即float,而不是double
这里我期望的是vaddps,这意味着添加压缩单精度浮点值,这是一条真正的SIMD指令(SIMD=单指令,多数据=矢量化指令)。这里,“打包”是指在一个寄存器中打包的多个浮点。

关于。。ss和。。ps,请参阅http://www.songho.ca/misc/sse/sse.html :

SSE定义了两种类型的操作;标量和压缩。标量运算只对最低有效数据元素(位0~31)进行运算,压缩运算并行计算所有四个元素。SSE指令的后缀-ss表示标量操作(单标量),而-ps表示压缩操作(并行标量)。

奎斯顿:我的java示例是否不正确,或者为什么输出中没有SIMD指令?

共有1个答案

薄哲
2023-03-14

main()方法中,放入i

0x00007f20c83da588: vmovdqu 0x10(%rbx,%r11,4),%ymm0
0x00007f20c83da58f: vaddps  0x10(%r13,%r11,4),%ymm0,%ymm0
0x00007f20c83da596: vmovdqu %ymm0,0x10(%rbx,%r11,4)  ;*fastore {reexecute=0 rethrow=0 return_oop=0}
                                            ; - VecOpMicroBenchmark::profile@22 (line 14)

问题中的代码实际上可以通过使用自动矢量化的即时编译器进行优化。然而,正如Peter Cordes在评论中指出的那样,JIT需要相当多的处理,因此它相当不愿意决定应该完全优化一些代码。
解决方案只是在程序的一次执行中更频繁地执行代码,不仅仅是1000次,而是100000次或一百万次。
当多次执行file()方法时,即时编译器确信代码非常重要,整个运行时将受益于完全优化,因此它再次优化代码,然后它还使用真正的向量指令,如vaddps

Java中自动矢量化的更多细节

 类似资料:
  • 我不明白为什么Visual C不能自动矢量化这个循环......有什么想法吗? 我得到: 其中,原因代码1200为: 循环包含阻止矢量化的循环携带的数据依赖项。循环的不同迭代相互干扰,这样对循环进行矢量化将产生错误的答案,而自动矢量器无法向自己证明不存在此类数据依赖关系。 但为什么呢?

  • 问题内容: 我需要可视化大型矢量图形。这是道路地图,道路只是线。有图书馆吗?如果该库支持放大/缩小并且易于扩展,那就太好了。例如,实施道路选择或一些不错的鼠标悬停效果。该许可证应允许在商业项目中使用。 谢谢菲利普 编辑:是否有理由不使用Graphics2D或SWT Graphics?(该项目在SWT上,不涉及任何SVG。) 问题答案: 看看Apache Batik Batik是基于Java的工具包

  • 矢量或者说向量,可以通过2~4个分量表示一个向量,比如通过vec3(1,0,0)表示三维空间中一个沿着x轴正方向的三维方向向量,如果你有高中数学的基础,应该对向量有一定的了解,对于三维坐标的相关几何运算也有一定的概念。 关键字 数据类型 vec2 二维向量,具有xy两个分量,分量是浮点数 vec3 三维向量 ,具有xyz三个分量,分量是浮点数 vec4 四维向量 ,具有xyzw四个分量,分量是浮点

  • 我正在处理一个课堂问题,要求我在3D空间中模拟太阳系内行星/卫星/小行星的运动。学期初我们从矢量、质量和力开始,所以我仍在努力掌握它。 *我的问题在第4步和第5步中有详细说明。如果我一路上有什么错误,请告诉我。任何意见和指导将不胜感激。 提供的信息 空间中的每个物体都具有以下特征: 质量 位置向量 我必须使用牛顿万有引力定律: 问题 给定时间t,更新空间中每个物体的位置和速度。那么,如果t是10秒

  • Vector是由连续整数索引的值的集合。 使用Clojure中的矢量方法创建矢量。 例子 (Example) 以下是在Clojure中创建矢量的示例。 (ns clojure.examples.example (:require [clojure.set :as set]) (:gen-class)) (defn example [] (println (vector 1 2 3

  • 新的RyuJIT编译器是否生成过向量(SIMD)CPU指令,以及何时生成? 旁注:系统。Numerics命名空间包含允许显式使用向量操作的类型,向量操作可能生成也可能不生成SIMD指令,具体取决于CPU、CLR版本、JITer版本,无论是否直接编译为本机代码。这个问题具体是关于非矢量代码(例如C或F中的)何时会生成SIMD指令。