关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »写Java也得了解CPU缓存

    写Java也得了解CPU缓存

    2014-08-24 00:00:00 出处:ITJS
    分享

    CPU,一般认为写C/C++的才需要了解,写高级语言的(Java/C#/pathon…)并不需要了解那么底层的东西。我一开始也是这么想的,但直到碰到LMAX的Disruptor,以及马丁的博文,才发现写Java的,更加不能忽视CPU。经过一段时间的阅读,希望总结一下自己的阅读后的感悟。ITJS的这篇文章主要谈谈CPU缓存对Java编程的影响,不涉及具体CPU缓存的机制和实现。

    现代CPU的缓存结构一般分三层,L1,L2和L3。如下图所示:

    CPU三级缓存示意图

     

    级别越小的缓存,越接近CPU, 意味着速度越快且容量越少。

    L1是最接近CPU的,它容量最小,速度最快,每个核上都有一个L1 Cache(准确地说每个核上有两个L1 Cache, 一个存数据 L1d Cache, 一个存指令 L1i Cache);

    L2 Cache 更大一些,例如256K,速度要慢一些,一般情况下每个核上都有一个独立的L2 Cache;

    L3 Cache是三级缓存中最大的一级,例如12MB,同时也是最慢的一级,在同一个CPU插槽之间的核共享一个L3 Cache。

    当CPU运作时,它首先去L1寻找它所需要的数据,然后去L2,然后去L3。如果三级缓存都没找到它需要的数据,则从内存里获取数据。寻找的路径越长,耗时越长。所以如果要非常频繁的获取某些数据,保证这些数据在L1缓存里。这样速度将非常快。下表表示了CPU到各缓存和内存之间的大概速度:

    从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

    利用CPU-Z可以查看CPU缓存的信息:

    CPU-Z

    在linux下可以使用下列命令查看proc文件系统或者sys下的设备描述。

    有了上面对CPU的大概了解,我们来看看缓存行(Cache line)。缓存,是由缓存行组成的。一般一行缓存行有64字节(由上图”64-byte line size”可知)。所以使用缓存时,并不是一个一个字节使用,而是一行缓存行、一行缓存行这样使用;换句话说,CPU存取缓存都是按照一行,为最小单位操作的。

    这意味着,如果没有好好利用缓存行的话,程序可能会遇到性能的问题。可看下面的程序:

    public class L1CacheMiss {
        private static final int RUNS = 10;
        private static final int DIMENSION_1 = 1024 * 1024;
        private static final int DIMENSION_2 = 6;
    
        private static long[][] longs;
    
        public static void main(String[] args) throws Exception {
            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….");
    
            long sum = 0L;
            for (int r = 0; r < RUNS; r++) {
    
                final long start = System.nanoTime();
    
                //slow
    //            for (int j = 0; j < DIMENSION_2; j++) {
    //                for (int I = 0; I < DIMENSION_1; i++) {
    //                    sum += longs[i][j];
    //                }
    //            }
    
                //fast
                for (int I = 0; I < DIMENSION_1; i++) {
                    for (int j = 0; j < DIMENSION_2; j++) {
                        sum += longs[i][j];
                    }
                }
    
                System.out.println((System.nanoTime() - start));
            }
    
        }
    }

     

    以我所使用的Xeon E3 CPU和64位操作系统和64位JVM为例,如这里所说,假设编译器采用行主序存储数组。

    64位系统,Java数组对象头固定占16字节(未证实),而long类型占8个字节。所以16+8*6=64字节,刚好等于一条缓存行的长度:

    缓存行效果

    如32-36行代码所示,每次开始内循环时,从内存抓取的数据块实际上覆盖了longs[i][0]到longs[i][5]的全部数据(刚好64字节)。因此,内循环时所有的数据都在L1缓存可以命中,遍历将非常快。

    假如,将32-36行代码注释而用25-29行代码代替,那么将会造成大量的缓存失效。因为每次从内存抓取的都是同行不同列的数据块(如longs[i][0]到longs[i][5]的全部数据),但循环下一个的目标,却是同列不同行(如longs[0][0]下一个是longs[1][0],造成了longs[0][1]-longs[0][5]无法重复利用)。运行时间的差距如下图,单位是微秒(us):

    程序运行效果对比

    最后,我们都希望需要的数据都在L1缓存里,但事实上经常事与愿违,所以缓存失效 (Cache Miss)是常有的事,也是我们需要避免的事。

    一般来说,缓存失效有三种情况:
    1. 第一次访问数据, 在cache中根本不存在这条数据, 所以cache miss, 可以通过prefetch解决。
    2. cache冲突, 需要通过补齐来解决(伪共享的产生)。
    3. cache满, 一般情况下我们需要减少操作的数据大小, 尽量按数据的物理顺序访问数据。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    电脑屏幕不小心竖起来了?别慌,快捷键搞定

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    IT头条

    Synology 更新 ActiveProtect Manager 1.1 以增强企业网络弹性和合规性

    00:43

    新的 Rubrik Agent Cloud 加速了可信的企业 AI 代理部署

    00:34

    宇树科技 G1人形机器人,拉动一辆重达1.4吨的汽车

    00:21

    Cloudera 调查发现,96% 的企业已将 AI 集成到核心业务流程中,这表明 AI 已从竞争优势转变为强制性实践

    02:05

    投资者反对马斯克 1 万亿美元薪酬方案,要求重组特斯拉董事会

    01:18

    技术热点

    大型网站的 HTTPS 实践(三):基于协议和配置的优化

    ubuntu下右键菜单添加新建word、excel文档等快捷方式

    Sublime Text 简明教程

    用户定义SQL Server函数的描述

    怎么在windows 7开始菜单中添加下载选项?

    SQL Server 2016将有哪些功能改进?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。