zoukankan      html  css  js  c++  java
  • cpu缓存java性能问题初探

    在内存与cpu寄存器之间,还有一块区域叫做cpu高速缓存,即我们常常说的cache。

    cache分为L1、L2、L3三级缓存,速度递减,离cpu越来越远,L1、L2每个内核自己都有,L3是每个插槽上的多个内核共用一个。cpu按照值使用频道来从1、2、3缓存逐个进行检索,L1如果没有命中,就向下继续检索L2、L3直到内存。

    从CPU到 大约需要的CPU周期 大约需要的时间(单位ns)
    寄存器 1 cycle  
    L1 Cache ~3-4 cycles ~0.5-1 ns
    L2 Cache ~10-20 cycles ~3-7 ns
    L3 Cache ~40-45 cycles ~15 ns
    跨槽传输   ~20 ns
    内存 ~120-240 cycles ~60-120ns

    在上述缓存的存取与检索读取的操作中,最基本的单位(即内核操作缓存的最基本单位)成为缓存行(cache line),一般情况下,cache line的大小为64字节。

    举个例子,我们可以设想,对于顺序存储的一个数组而言,当我们从内存中读取一个数组元素进缓存的时候,要一次读取64字节,那么这样就会将我们需要读取的元素后面的若干个8字节long也一并都进了缓存,并且这是在一个操作里完成的,没有额外的花费。大大提高了性能。

    但如果我们的程序故意捣乱,干扰cpu的这种优化机制呢?

    http://coderplay.iteye.com/blog/1485760  中的一个示例程序,我加了点注释。 (在此谢过原作者)

    public class L1CacheMiss {  
        private static final int RUNS = 10;  
        private static final int DIMENSION_1 = 1024 * 1024;  
        private static final int DIMENSION_2 = 62;
      
        private static long[][] longs;  
      
        public static void main(String[] args) throws Exception {
                
                /*初始化一个1024*1024行、62列的二位数组(矩阵),矩阵的每个元素都是0*/  
            Thread.sleep(10000);  
            longs = new long[DIMENSION_1][];  
            for (int i = 0; i < DIMENSION_1; i++) {  
                longs[i] = new long[DIMENSION_2];  
                for (int j = 0; j < DIMENSION_2; j++) {  
                    longs[i][j] = 0L;  
                }  
            }  
            System.out.println("starting....");  
      
            final long start = System.nanoTime();  
            long sum = 0L;  
            for (int r = 0; r < RUNS; r++) {  
                /*对列遍历,然后逐个累加每列中所有行*/
    //          for (int j = 0; j < DIMENSION_2; j++) {  
    //              for (int i = 0; i < DIMENSION_1; i++) {  
    //                  sum += longs[i][j];  
    //              }  
    //          }  
                      /*对行遍历,然后逐个累加每行中所有列*/
                for (int i = 0; i < DIMENSION_1; i++) {  
                    for (int j = 0; j < DIMENSION_2; j++) {  
                        sum += longs[i][j];  
                    }  
                }  
            }  
            System.out.println("duration = " + (System.nanoTime() - start));  
        }  
    }  

    执行结果:

    starting....       duration = 679,818,029          sum = 0

    starting....       duration = 12,850,546,522     sum = 0

    先对行遍历只用不到1秒,而先对列遍历的话要用12秒! 

    如果在linux环境下,可以用perf stat -e L1-dcache-load-misses java L1CacheMiss   命令来查看L1 cache的未命中次数。

  • 相关阅读:
    姿态估计openpose_pytorch_code浅析(待补充)
    姿态估计之Openpose_原理部分
    win10基础上安装linux系统,添加双系统启动项
    mongodb集群部署
    心无旁骛提升自我
    sqlserver2012 数据库差异备份恢复 记录
    pgsql 常用命令
    pgadmin连接 postgresql远程设置
    vmvare使用桥接和NAT方式连接网络
    使用samba 共享Linux文件到Windows
  • 原文地址:https://www.cnblogs.com/lyhero11/p/5120847.html
Copyright © 2011-2022 走看看