1. 计算机底层原理

1 相关书籍推荐

  1. 读书原则:不求甚解,观其大略,大体读明白,先拿来用,用着用着,很多道理你就明白了
  2. 底层知识相关书籍
    1. 《编码:隐匿在计算机软硬件背后的语言》
    2. 《深入理解计算机系统》
    3. C语言:《C程序设计语言》、《C Primer Plus》
    4. 数据结构:《Java数据结构与算法》、《算法》、《算法导论》、《计算机程序设计艺术》
    5. 操作系统:《Linux内核源码解析》、《Linux内核设计与实现》、《 30天自制操作系统》
    6. 网络:《TCP/IP详解-卷一》
    7. 编译原理:《编译原理》、《编程语言实现模式》
    8. 数据库:《SQLite源码》、《 Derby》(JDK自带数据库)

2 CPU的制作过程

  1. Intel cpu的制作过程视频:https://haokan.baidu.com/v?vid=11928468945249380709&pd=bjh&fr=bjhauthor&type=video
  2. cpu制作过程文字描述:https://www.sohu.com/a/255397866_468626

3 CPU原理

  1. 计算机需要解决的最根本问题:如何代表数字
  2. 晶体管是如何工作的:https://haokan.baidu.com/v?vid=16026741635006191272&pd=bjh&fr=bjhauthor&type=video
  3. 晶体管工作原理:https://www.bilibili.com/video/av47388949?p=2

4 CPU的基本组成

  1. CPU有很多针脚,每个针脚1次可以接收1个电信号(1或0),通过这些针脚一次性可以读取到一堆的1和0,硬件上讲,就是给哪个针脚通电,哪些就是1,不通电就是0,我们需要将数据通过针脚输入给CPU,有几种方式,可以手工输入,不断自己通电断电,但太费劲,因此产生了内存,存放数据和运算过程,CPU可以自动从内存中读取这些数据,所以说内存的本质就是一个特别大的字节数组,存储了一堆电信号

  2. 总线:电线汇总到一起就是总线,CPU一次要从内存读取64个电信号,那么就有64个电线连到内存上

  3. 主板:连接cpu、内存、显卡、usb等各种元器件,主板中有很多电路

  4. 操作系统位数:32位和64位表示支持cpu一次性读取多少位数字,32位就是一次性可以读取32个数字。cpu可能一次性能读64位,但总线不一定,总线可能一次性只能读32位或128,

  5. PC:Program Counter,程序计数器,用于记录当前正执行的指令地址

  6. Registers:寄存器,用于暂时存储CPU计算需要用到的数据,一颗CPU上有上百个寄存器,所谓64操作系统,就是指寄存器一次性可以存放64bit的数据

  7. ALU:Arithmetic & Logic Unit,运算单元,负责运算

  8. CU:Control Unit 控制单元

  9. MMU:Memory Management Unit,内存管理单元

  10. cache:缓存

    在这里插入图片描述

5 四核八线程是的含义

  1. 四核表示CPU有4个核心,而8线程,指1个核心中,包含1个ALU和2组Registers+PC,这样4*2就是8线程,图中CPU指CPU核心而不是物理CPU

  2. 如果1个CPU核心中,如果只包含1个ALU和1组Registers+PC,此时Thread1的指令存放在PC中,而数据存放在Registers

  3. 一旦Thread2需要执行,就必须将Thread1的指令和数据先从PC和Registers中拿出,然后才能将Thread2的数据和指令放入,ALU才会对Thread2数据进行处理,这个过程叫做线程切换(context switch)

  4. 线程切换会耗费CPU资源

  5. 因此四核八线程,表示虽然CPU只有4个核心数,但可以一次性将多个线程数据存入到不同的Registers和PC中,ALU可以直接针对不同Registers+PC进行计算,而不需要将数据和指令来回拿出放入

    在这里插入图片描述

6 汇编语言(机器语言)的执行过程

  1. 汇编语言的本质:是机器语言的助记符,例如将01001000记作mov,10110011记为sub
  2. 执行过程:例如计算2+3
    1. 计算机通电
    2. CPU将2和3分别从内存,读取到两个寄存器中
    3. 然后PC发现指令是add
    4. 时钟发生器不断震荡通断电(CPU频率就是指每秒钟可以震荡的次数,GHz表示每秒钟可以震荡几十亿次),从而推动CPU内部一步一步执行(执行多少步取决于指令需要的时钟周期,即一个指令需要震荡几次才能完成)
    5. ALU计算出结果后,将结果存放到一个新的寄存器中
    6. 将数据写回到内存或写回给显卡输出

7 CPU缓存

  1. CPU从内存中取数据时间较长,远高于处理器的频率,因此这段时间CPU只能等待,为了减少CPU访问内存所需平均时间,产生缓存

  2. 缓存分为L1 cache、L2 cache、L3 cache

  3. CPU访问数据时,先尝试从缓存中获取,如果该数据在缓存中存在,称为缓存命中,则直接从缓存中获取数据,如果不存在,先将数据从内存加载到缓存再获取

  4. 当从内存中将数据加载到缓存中时,由于CPU对内存的访问呈局部性,因此可以保证CPU随后需要用到的数据、指令都被一次性加载进缓存,从而提升缓存的命中率

    1. 时间局限性:如果CPU执行了程序的某个指令、访问了某个数据,那么很有可能在接下来的运算中,还会执行该指令、访问该数据
    2. 空间局限性:一旦CPU访问了某个存储单元,那么在不久以后,CPU很有可能会访问其附近的存储单元
  5. CPU到到各存储器的时间

    存储器 时间
    Registers <1ns
    L1 cache 约1ns
    L2 cache 约3ns
    L3 cache 约15ns
    内存 约80ns

8 缓存行

在这里插入图片描述

  1. CPU读取数据时,按缓存行读,一次读一行数据,当CPU核心1读x变量时,先到自身的L1中查找是否有该数据,如果没有,继续到L2中查找,直到查找到内存中

  2. 当从内存中读取变量x时,会将与x处于同一缓存行的变量y一起读入,然后将内存中该缓存行,先复制传输给L3,再复制传输给L2,一直复制到L3中,这样L1、L2、L3中都有一份数据

  3. CPU核心1处理完该缓存行后,会将该缓存行内容写回到内存

  4. 如果在CPU核心1将数据写回内存前,CPU核心2上读取y,那么x也会被读入,等到CPU2处理完y后,会将未修改的x值,重新写入内存,导致CPU核心1的修改失效

  5. 为防止这种情况的产生,产生缓存一致性协议,当某个CPU核心中修改了缓存行中任意数据,会强制其他CPU核心强制重新从内存读取这个缓存行中数据,缓存一致性协议也叫缓存锁

  6. Intel采用的缓存一致性协议叫做MESI,MESI代表缓存的四种状态,某个缓存行被修改过后,在修改它的CPU核心上,就变为Modified状态,而在其他CPU核心上,变为Invalid状态,CPU核心发现缓存行中数据未Invalid状态后,就会从内存重新读数据进来

  7. 但对于那些跨越了多个缓存行数据,比如一个long类型数据,跨越了两个缓存行,此时如果想保存一致性,就需要总线锁,也就是当CPU核心需要访问某块内存时,将内存到L3中间的总线锁住,这样其他CPU核心就暂时无法读取内存中内容, 当该CPU核心访问完成后再解除总线锁,其他CPU核心才能访问

  8. 总线锁效率太低,因此底层能使用mesi时,就不会使用总线锁

  9. 缓存行大小:不是固定值,Intel中缓存行为64字节,是实践后决定的,缓存行越大,局部性空间效率越高,但会导致读取时间越慢,因此需要取一个折中值

  10. 但由于缓存一致性协议,会导致伪共享问题,所谓的伪共享,就是两个不同线程同时修改同一缓存行中不同值时,无法真正同时进行修改,因为缓存一致性在第一个线程修改值后,要求第二个线程强制从内存重新读取

    package com.mashibing.springboot;
    
    public class T03_CacheLinePadding {
         
        //jdk8写法:400+ms
      	//1. jdk8中允许在属性上加@Contended注解,保证该成员变量不会与其他带有@Contended注解的变量位于同一缓存行,需要加启动参数 -XX:-RestrictContended才会生效,经测试intellij2020最新版中,自动加上了-XX:-RestrictContended参数,不需要自己配置即可生效
      	//2. 如果只在x上加@Contended不会生效
    //    @Contended
    //    volatile long x;
    //    @Contended
    //    volatile long y;
    
        //jdk7中写法:400+ms
      	//jdk7中,需要使用如下写法人为进行缓存行对齐,从而提高效率,但这种方式只对Intel的CPU有效,但对于其他CPU可能不生效,而jdk8中@Contended可以自动识别底层CPU缓存行大小,从而保证不会与其他变量位于同一缓存行
        public long p1, p2, p3, p4, p5, p6, p7;
        private volatile long x;
        public long p8, p9, p10, p11, p12, p13, p14;
        private volatile long y;
    
        //不考虑缓存行对齐的写法:2000ms
    //    volatile long x;
    //    volatile long y;
    
        public static void main(String[]
  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值