Java可以识别CPU的SIMD优势;或者只是循环展开的优化效果

标签 java performance optimization simd loop-unrolling

这部分代码来 self 的一个 vector 类的dotproduct方法。该方法对目标 vector 数组(1000个 vector )进行内积计算。

当 vector 长度为​​奇数(262145)时,计算时间为4.37秒。当 vector 长度(N)为262144(8的倍数)时,计算时间为1.93秒。

     time1=System.nanotime();
     int count=0;
     for(int j=0;j<1000;i++)
     {

             b=vektors[i]; // selects next vector(b) to multiply as inner product.
                           // each vector has an array of float elements.

             if(((N/2)*2)!=N)
             {
                 for(int i=0;i<N;i++)
                 {
                     t1+=elements[i]*b.elements[i];
                 }
             }
             else if(((N/8)*8)==N)
             {
                 float []vek=new float[8];
                 for(int i=0;i<(N/8);i++)
                 {
                     vek[0]=elements[i]*b.elements[i];
                     vek[1]=elements[i+1]*b.elements[i+1];
                     vek[2]=elements[i+2]*b.elements[i+2];
                     vek[3]=elements[i+3]*b.elements[i+3];
                     vek[4]=elements[i+4]*b.elements[i+4];
                     vek[5]=elements[i+5]*b.elements[i+5];
                     vek[6]=elements[i+6]*b.elements[i+6];
                     vek[7]=elements[i+7]*b.elements[i+7];


                     t1+=vek[0]+vek[1]+vek[2]+vek[3]+vek[4]+vek[5]+vek[6]+vek[7];
                     //t1 is total sum of all dot products.
                 }
             }
     }
     time2=System.nanotime();
     time3=(time2-time1)/1000000000.0; //seconds

问题:时间从 4.37 秒减少到 1.93 秒(快 2 倍)是 JIT 使用 SIMD 指令的明智决定还是我的循环展开的积极影响?

如果 JIT 不能自动进行 SIMD 优化,那么在这个例子中也没有由 JIT 自动进行展开优化,是这样吗?

对于 1M 次迭代( vector )和 vector 大小为 64,加速乘数达到 3.5 倍(缓存优势?)。

谢谢。

最佳答案

您的代码有很多问题。你确定你在衡量你认为你在衡量的东西吗?

您的第一个循环执行此操作,缩进更常规:

 for(int j=0;j<1000;i++) {
     b=vektors[i]; // selects next vector(b) to multiply as inner product.
                   // each vector has an array of float elements.
 }

您的滚动循环涉及一个非常长的依赖加载和存储链。您展开的循环涉及 8 个独立的依赖加载和存储链。如果您使用浮点运算,JVM 无法将一个转换为另一个,因为它们是根本不同的计算。打破依赖的加载存储链可以显着提高现代处理器的速度。

您的滚动循环遍历整个 vector 。您展开的循环仅迭代第一个(大致)八分之一。因此,展开的循环再次计算出根本不同的东西。

我还没有看到 JVM 为类似您的第二个循环的东西生成矢量化代码,但我对 JVM 的作用可能已经过时了几年。运行代码并检查 opto 生成的代码时,尝试使用 -XX:+PrintAssembly

关于Java可以识别CPU的SIMD优势;或者只是循环展开的优化效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17459188/

相关文章:

java - 如何在 Java 中更改 RadioGroup 的颜色

java - jmap/jhat 与 jVisualVM

mysql - 在 REST API Java Spring Boot 中杀死慢速查询

performance - 有哪些不同的技术可以使超形态调用站点更加高效

javascript - 如果 $http.get() 导致没有新数据,则使 AngularJS 跳过运行摘要循环

java - 使用 DocumentFilter 仅接受 JTextField 中的 double 值

java - 远程连接jdbc和mysql通讯链路失败

java - 拦截 JavaScript 卸载事件

c# - 测量每个 Entity Framework 查询的时间

python - scipy.optimize.basinhopping 间隔和接受测试语法