首页 > 其他 > 详细

初识计算机底层(CPU)

时间:2021-02-07 12:10:13      阅读:17      评论:0      收藏:0      [点我收藏+]

相关书籍推荐

读书的原则:不求甚解,观其大略

?《编码:隐匿在计算机软硬件背后的语言》

?《深入理解计算机系统》

?语言:C JAVA K&R《C程序设计语言》《C Primer Plus》

? 数据结构与算法: -- 毕生的学习 leetCode

–《Java数据结构与算法》《算法》

–《算法导论》《计算机程序设计艺术》//

?操作系统:Linux内核源码解析 Linux内核设计与实现 30天自制操作系统

?网络:机工《TCP/IP详解》卷一 翻译一般

?编译原理:机工 龙书 《编译原理》 《编程语言实现模式》马语

?数据库:SQLite源码 Derby - JDK自带数据库

硬件基础知识

CPU的制作过程

Intel cpu的制作过程

https://haokan.baidu.com/v?vid=11928468945249380709&pd=bjh&fr=bjhauthor&type=video

CPU是如何制作的(文字描述)

https://www.sohu.com/a/255397866_468626

CPU的原理

计算机需要解决的最根本问题:如何代表数字

晶体管是如何工作的:

https://haokan.baidu.com/v?vid=16026741635006191272&pd=bjh&fr=bjhauthor&type=video

晶体管的工作原理:

https://www.bilibili.com/video/av47388949?p=2

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

汇编语言的本质:机器语言的助记符 其实它就是机器语言

计算机通电 -> CPU读取内存中程序(电信号输入)

->时钟发生器不断震荡通断电 ->推动CPU内部一步一步执行

(执行多少步取决于指令需要的时钟周期)

->计算完成->写回(电信号)->写给显卡输出(sout,或者图形)

量子计算机

量子比特,同时表示1 0

CPU的基本组成

PC -> Program Counter 程序计数器 (记录当前指令地址)

Registers -> 暂时存储CPU计算需要用到的数据

ALU -> Arithmetic & Logic Unit 运算单元

CU -> Control Unit 控制单元

MMU -> Memory Management Unit 内存管理单元

cache

缓存

一致性协议:https://www.cnblogs.com/z00377750/p/9180644.html

缓存行:

缓存行越大,局部性空间效率越高,但读取时间慢

缓存行越小,局部性空间效率越低,但读取时间快

取一个折中值,目前多用:64字节

测试:Test1 时间比Test2 时间执行大概慢1秒左右

public class Test1 {

    public static volatile long[] arr = new long[2];

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(()->{
            for (long i = 0; i < 10000_0000L; i++) {
                arr[0] = i;
            }
        });

        Thread t2 = new Thread(()->{
            for (long i = 0; i < 10000_0000L; i++) {
                arr[1] = i;
            }
        });

        final long start = System.nanoTime();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println((System.nanoTime() - start)/100_0000);
    }
}
public class Test2 {

    public static volatile long[] arr = new long[16];

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(()->{
            for (long i = 0; i < 10000_0000L; i++) {
                arr[0] = i;
            }
        });

        Thread t2 = new Thread(()->{
            for (long i = 0; i < 10000_0000L; i++) {
                arr[8] = i;
            }
        });

        final long start = System.nanoTime();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println((System.nanoTime() - start)/100_0000);
    }
}

缓存行对齐:对于有些特别敏感的数字,会存在线程高竞争的访问,为了保证不发生伪共享,可以使用缓存航对齐的编程方式

JDK7中,很多采用long padding提高效率

JDK8,加入了@Contended注解(实验)需要加上:JVM   -XX:-RestrictContended

public class Test3 {

    @Contended
    volatile long x;
    @Contended
    volatile long y;

    public static void main(String[] args) throws Exception {
        Test3 test3 = new Test3();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000_0000L; i++) {
                test3.x = i;
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000_0000L; i++) {
                test3.y = i;
            }
        });

        final long start = System.nanoTime();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println((System.nanoTime() - start)/100_0000);
    }
}

乱序执行

参考:https://preshing.com/20120515/memory-reordering-caught-in-the-act/

指令重排序的样例:

public class 指令重排序Demo {
    private static int x = 0, y = 0;
    private static int a = 0, b =0;

    public static void main(String[] args) throws InterruptedException {
        int i = 0;
        for(;;) {
            i++;
            x = 0; y = 0;
            a = 0; b = 0;
            Thread one = new Thread(new Runnable() {
                @Override
                public void run() {
                    //由于线程one先启动,下面这句话让它等一等线程two. 读着可根据自己电脑的实际性能适当调整等待时间.
                    //shortWait(100000);
                    a = 1;
                    x = b;
                }
            });

            Thread other = new Thread(new Runnable() {
                @Override
                public void run() {
                    b = 1;
                    y = a;
                }
            });
            one.start();other.start();
            one.join();other.join();
            String result = "第" + i + "次 (" + x + "," + y + ")";
            if(x == 0 && y == 0) {
                System.err.println(result);     // 肯定会有x 和 y 都为0 的时候
                break;
            } else {
                System.out.println(result);
            }
        }
    }
}

CPU层面怎么禁止指令重排序?

Intel 使用的是原语

技术分享图片

volatile 关键字使用的是Lock锁,实现的锁屏障。

禁止乱序

CPU层面:Intel -> 原语(mfence lfence sfence) 或者锁总线

JVM层级:8个hanppens-before原则 4个内存屏障 (LL LS SL SS)

jvm 里面对于内存屏障的实现有4 种

    1. LoadLoad:对于这样的语句Load1;LoadLoad;Load2,在Load2及后续的读操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕;
    2. StoreStore:对于这样的语句Store1;StoreStore;Store2,在Store2及后续的写操作执行前,保证Store1的写入操作对其他处理器可见;
    3. LoadStore:对于这样的语句Load1;LoadStore;Store2,在Store2及后续的写入操作被刷出前,保证Load1要读取的数据被读取完毕;
    4. StoreLoad:对于这样的语句Store1;StoreLoad;Load2,在Load2及后续的读操作要读取的数据被访问前,保证Store1的写入操作对其他处理器可见;

StoreStoreBarrier

volatile 写操作

StoreLoadBarrier

LoadLoadBarrier

volatile 读操作

LoadStoreBarrier 

happens-before原则:

??happens-before原则是Java内存模型中定义的两个操作之间的偏序关系。

  比如说操作A先行发生于操作B,那么在B操作发生之前,A操作产生的“影响”都会被操作B感知到。这里的影响是指修改了内存中的共享变量、发送了消息、调用了方法等。

    1. 程序顺序规则: 一个线程中的每个操作,happens-before 于该线程中的任意后续操作;
    2. 监视器锁规则: 对每一个锁的解锁,happens-before 于随后对该锁的加锁;
    3. Volatile 变量规则:对一个 volatile 域的写,happens-before 于任意后续对这个volatile域的读;
    4. 线程启动规则:Thread 的 start() 方法先行发生于这个线程的每一个操作;
    5. 线程终止原则:线程的所有操作都先行于此线程的终止检测,可以通过 Thread.join() 方法结束、Thread.isAlive() 的返回值等手段检测线程的终止;
    6. 线程中断原则:对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过 Thread.interrupt 方法检测线程是否中断;
    7. 对象终结规则:一个对象的初始化完成先于发生它的finalize()方法的开始;
    8. 传递性: 如果 A happens-before B, B happens-before C, 那么A happens-before C;

as-if-serial : 不管硬件什么顺序,单线程执行的结果不变,看上去像是serial

合并写(不重要)

Write Combining Buffer

一般是4个字节

由于ALU速度太快,所以在写入L1的同时,写入一个WC Buffer,满了之后,再直接更新到L2

技术分享图片

NUMA

Non Uniform Memory Access

ZGC - NUMA aware       分配内存会优先分配该线程所在CPU的最近内存

    先了解UMA:多个cpu访问一块内存

     技术分享图片

 

 NUMA  每个cpu附近有个内存,访问就近的内存比访问别家的内存要快得多

技术分享图片

 

初识计算机底层(CPU)

原文:https://www.cnblogs.com/abiu/p/14376310.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!