计算机底层原理概述

简介: 计算机底层原理概述

# 计算机底层原理

## 计算机的组成

### 计算机的五大组成部分

控制器(CU)、运算器(ALU)、存储器(Memory)、输入设备(Input)和输出设备(Output)

## 核心构成的缩写以及专业名词解释

CU:控制单元/控制器(Control Unit)

PC:程序计数器(Program Counter)

ALU:算术逻辑单元/运算器(Arithmetic and Logic Unit)

CPU:中央处理器(Central Processing Unit)

GPU:图形处理器(Graphics Processing Unit)

RAM:随机访问储存器(Random Access Memory)

SSD:固态硬盘(Solid State Disk或Solid State Drive)

HDD:机械硬盘(Hard Disk Drive)

## 核心构成的作用及简单解释

CU:主要是控制系统

PC:记录这一个地址存放下一条执行的指令在哪里 cpu执行完一条就去内存取下一条

ALU:功能是进行数学(算数)运算和逻辑运算 由一系列的简单电路构成([ALU详细运算逻辑笔记](https://zhuanlan.zhihu.com/p/402376655))

Register:寄存器 是CPU暂时存放数据的地方 或者保存那些中间结果 或等待处理的数据

CPU:主要功能有四个 分别是顺序控制、操作控制、时间控制、数据加工

GPU:是一种主要做图像和图形相关运算工作的微处理器 使显卡减少了对CPU的依赖 并进行部分原本CPU的工作

RAM:它是与CPU直接交换数据的内部存储器 特点是可以随时读写 而且速度很快 但它的缺点同样很明显 就是当电源关闭时不能保存数据

SSD:由控制单元和存储单元(FLASH芯片、DRAM芯片)组成 它的主要功能就是存放计算机内部的数据和文件 是计算机内部的一个主要仓库

HDD:同样是存储数据介质之一 是传统普通硬盘 主要由:盘片、磁头、盘片转轴及控制电机、磁头控制器、数据转换器、接口、缓存等几个部分组成 工作时通过磁头在磁片的寻道动作来实现存储功能的

***附:一张计算机组成简图***

计算机硬件关系简图1.png![计算机硬件关系简图1](./计算机硬件关系简图1.png)

计算机硬件关系简图2.png![计算机硬件关系简图2](./计算机硬件关系简图2.png)

## CPU与缓存、内存的关系

CPU内部有缓存 缓存有缓存级别 目前主流的是三级缓存设计(L1 L2 L3)

~~~

L1容量最小 速度最快 每个核都有L1缓存 L1又专门针对指令和数据分成L1d(数据缓存)、L1i(指令缓存)

L2容量比L1大 速度比L1慢 每个核都有L2缓存

L3容量最大 速度最慢 多个核共享一个L3缓存

~~~

***附:一张单CPU多核心及两张多CPU多核心结构简图***

多级缓存与内存.png

![多级缓存与内存](./多级缓存与内存.png)多CPU多核心缓存架构图.png

![多核心CPU内部结构简图](./多核心CPU内部结构简图.png)

多CPU多核心缓存架构图.png

![多CPU多核心缓存架构图](./多CPU多核心缓存架构图.png)

CPU的缓存具体情况 可以使用CPU-Z或者也可以直接在任务管理器(可以使用快捷键:CTRL+SHIFT+ESC打开任务管理器)来查看:

CPU-Z查看CPU缓存.png

![CPU-Z查看CPU缓存](./CPU-Z查看CPU缓存.png)

任务管理器查看CPU缓存.png

![任务管理器查看CPU缓存](./任务管理器查看CPU缓存.png)


CPU选取内存中读取命令 将命令解析翻译成自己能够对应上的操作步骤 控制硬件执行


但是由于CPU内部的ALU访问Register(寄存器)的速度极快极快 比ALU访问RAM(内存)的速度快得多


但是由于造价成本太高且发热量大 所以不能被大量采用 并且ALU访问RAM的速度"慢"也会带来很多问题


于是就在CPU内部设计了高速缓存(CPU Cache) 这样的话 每次ALU取数据的时候速度就会快很多


缓存级数是多有多的好处 少有少的优势 而常见的3级缓存的设计 则是在获取数据和更新数据之间寻找的平衡点


随着技术的发展 多核心的CPU越来越常见、普及 这是因为当单个CPU主频超过一定范围后


CPU成本和散热成了很大的问题 主频很难突破10GHz 为了获得更快的计算速度和更好的性能


芯片设计者决定绕过主频 采用人海战术 在一块CPU中增加多个核心(Core)


一个核心是一个可以运行指令的独立单元 它包含了ALU和寄存器 并配备L1和L2 Cache 多个核心共享L3 Cache

#### 缓存行

缓存行:Cache Line

CPU高速缓存中存取数据的基本单位叫做Cache Line(缓存行)

实际上 cache分成了多个组 每个组分成多个CacheLine行 大致如下:

缓存行示意图.png

![缓存行示意图](./缓存行示意图.png)

Cache中的数据是按块读取的 当CPU访问某个数据时

计算机将数据从主存读入Cache 是把要读取数据附近的一部分数据都读取进来

这样一次读取的一组数据就叫做Cache Line 每一级缓存中都能放很多的CacheLine

***附:一张图便于理解这种优化模式***

缓存行理解.png

![缓存行理解](缓存行理解.png)

~~~

目前应用最多的缓存行长度是64Byte


还是那句话:大有大的好处 小有小的优势:

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

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

~~~

*附:访问存储速度金字塔模型图*

存储金字塔模型图.png

![存储金字塔模型图](./存储金字塔模型图.png)

***如何写出让CPU跑的更快的代码***

~~~JAVA

//JAVA代码优先之前:

publicclass T01_CacheLinePadding {

   privatestaticclass T {

       publicvolatilelong x =0L;

   }


   publicstaticT[] arr =newT[2];


   static {

       arr[0] =newT();

       arr[1] =newT();

   }


   publicstaticvoidmain(String[] args) throwsException {

       Thread t1 =newThread(()->{

           for (long i =0; i <1000_0000L; i++) {

               arr[0].x= i;

           }

       });


       Thread t2 =newThread(()->{

           for (long i =0; i <1000_0000L; i++) {

               arr[1].x= i;

           }

       });


       finallong start =System.nanoTime();

       t1.start();

       t2.start();

       t1.join();

       t2.join();

       System.out.println((System.nanoTime() - start)/100_0000);

   }

   //执行结果 :200

~~~

~~~JAVA

//JAVA代码优先之后:

publicclass T02_CacheLinePadding {

   privatestaticclass Padding {

       //请注意下面这一行代码:

       publicvolatilelong p1, p2, p3, p4, p5, p6, p7;

   }


   privatestaticclass T extends Padding {

       publicvolatilelong x =0L;

   }


   publicstaticT[] arr =newT[2];


   static {

       arr[0] =newT();

       arr[1] =newT();

   }


   publicstaticvoidmain(String[] args) throwsException {

       Thread t1 =newThread(()->{

           for (long i =0; i <1000_0000L; i++) {

               arr[0].x= i;

           }

       });


       Thread t2 =newThread(()->{

           for (long i =0; i <1000_0000L; i++) {

               arr[1].x= i;

           }

       });


       finallong start =System.nanoTime();

       t1.start();

       t2.start();

       t1.join();

       t2.join();

       System.out.println((System.nanoTime() - start)/100_0000);

   }

}

//执行结果 :83

~~~

~~~

们发现同样是处理1000_0000L次 后面的代码执行效率明显比前面的快 这是为什么呢?

其实这也是大厂必问的一道关于缓存行(Cache Line)的一道面试题 我下面我们来仔细分析下:

前面我们提到了缓存行的概念 缓存行的大小为64个字节 一个long值在内存中占用8个字节 那么我们后一段代码中通过父子类定义了8个long类型的变量 正好占用内存64个字节大小 根据空间局部性原理 从主存是按块读取数据进缓存 这一块就叫缓存行 一个缓存行是64字节 根据缓存一致性协议 如果两个线程修改的内容存在于一个缓存行的话 会互相干扰 影响效率 所以可以前后各填充一定的空来保证有效数据一定在独立的缓存行来提升效率 也就是说 因为插入的7个long(每个Long占8Bytes 加上x 则一共占64Bytes)导致线程修改的两个数据被分隔开 使得它们不可能位于同一个Cache Line中 这样就可以避免线程操作因缓存一致性协议导致的影响和干扰 从而优化了处理的效率

~~~

请记住这样的一句话:不要在构造方法中 启动任何线程! (出自《Effective Java》)

***Padding的魔法***

为了解决上面缓存行出现的问题 采用了Padding的方式 这是一种用空间来换时间的优化策略

~~~JAVA

class LhsPadding

{

   protectedlong p1, p2, p3, p4, p5, p6, p7;

}


class Value extends LhsPadding

{

   protectedvolatilelong value;

}


class RhsPadding extends Value

{

   protectedlong p9, p10, p11, p12, p13, p14, p15;

}

~~~

这里不得不提到一款JAVA的并发编程框架:Disruptor

~~~

Disruptor是英国外汇交易公司LMAX开发的一个高性能队列 研发的初衷是解决内存队列的延迟问题 与Kafka、RabbitMQ用于服务间的消息队列不同 disruptor一般用于线程间消息的传递 基于Disruptor开发的系统单线程能支撑每秒600万订单

disruptor是用于一个JVM中多个线程之间的消息队列 作用与ArrayBlockingQueue有相似之处 但是disruptor从功能、性能都远好于ArrayBlockingQueue 当多个线程之间传递大量数据或对性能要求较高时 可以考虑使用disruptor作为ArrayBlockingQueue的替代者

官方也对disruptor和ArrayBlockingQueue的性能在不同的应用场景下做了对比 目测性能只有有5~10倍左右的提升

~~~

***那么Disruptor为什么这么牛逼?***

- CAS

- 消除伪共享

- RingBuffer


相关链接:[Disruptor项目开源链接](https://github.com/LMAX-Exchange/disruptor)[简书:Disruptor详解](https://www.jianshu.com/p/bad7b4b44e48)[知乎:一起聊聊Disruptor](https://zhuanlan.zhihu.com/p/21355046)

#### 局部性原理

**局部性原理**:在CPU访问存储设备时 无论是存取数据亦或存取指令 都趋于聚集在一片连续的区域中 这就是局部性原理

**时间局部性(Temporal Locality)**:如果一个信息项正在被访问 那么在近期它很可能还会被再次访问 比如循环、递归、方法的反复调用等

**空间局部性(Spatial Locality)**:如果一个存储器的位置被引用 那么将来他附近的位置也会被引用 比如顺序执行的代码、连续创建的两个对象、数组等

### 存储器

储存器的种类有很多 包括寄存器(Register)、高速缓存器(Cache)、内存(RAM)、硬盘(SSD/HDD)、磁带、光盘等介质

存储器层次结构示意图.png

![存储器层次结构示意图](./存储器层次结构示意图.png)


~~~

bit:字位(比特) 是信息量的最小单位

我们常说的64位 32位指的就是CPU的字长

如果是64位 那么CPU每次能处理64位二进制数据

二进制数的一位所包含的信息就是一比特 如二进制数0100就是4比特


Byte:字节

1字节(Byte)=8字位(比特)

1汉字=2字节=2Bytes=16字位=16bits


存储器的相关单位的转换关系:

8bits=1Byte ;1024Bytes=1KB;1024KB=1MB;1024MB=1GB;1024GB=1TB;1024TB=1PB


在Java语言中 指针的长度是4bytes 8种基本类型的长度(单位:bytes):

byte:1

short:2

int:4

long:8

float:4

double:8

char:2

boolean:单独声明时 一个boolean的长度为4个字节;但是boolean数组中的每个boolean的长度为1个字节

~~~

~~~

1.计算机处理字长分为32位和64位

2.计算机指令集分为简单指令集(RISC)和复杂指令集(CISC)两种

3.乱序:在单线程中可以提高CPU的效率 在多线程中 可能会出现意想不到的结果

4.CPU能直接访问的存储器是有三种 分别为内部寄存器Register、高速缓冲存储器Cache、内存储器RAM 并且访问速度依次降低

5.CPU向下兼容 所谓的兼容性是说 64位的CPU可以完美的兼容64位的应用程序软件和32位的应用程序软件 相反来说 32位的CPU只能运行32位的应用程序软件 否则会因为处理字长不够而导致程序软件的崩溃

~~~

资料均来源于互联网 由@Admin丶武林高手整理发布 侵权联系QQ:1513358596

相关文章
|
6月前
|
JavaScript
计算机底层基础知识
计算机底层基础知识
65 0
|
29天前
|
存储 缓存 数据处理
简述计算机X86架构
【10月更文挑战第3天】本文介绍了计算机的基本工作原理,重点阐述了CPU(中央处理器)及其组成部分:运算单元、数据单元和控制单元的功能。文中解释了CPU通过总线与内存等设备通信的过程,并详细描述了指令执行的步骤,包括指令获取、数据处理和结果存储。此外,还介绍了地址总线和数据总线的作用,以及段寄存器在内存管理中的应用。最后,提供了一些基本的CPU指令示例。文中配有多幅插图帮助理解。
|
3月前
|
存储 算法 安全
【第二章】软件设计师 之 操作系统基本原理
这篇文章是软件设计师备考资料的第二章,讲解了操作系统的基本原理,包括操作系统概述、进程状态转换、同步与互斥问题、PV操作、死锁问题与银行家算法、存储管理、文件系统和设备管理等关键知识点。
【第二章】软件设计师 之 操作系统基本原理
|
6月前
|
运维 网络协议 安全
第一节-网络的基本概念
第一节-网络的基本概念
69 0
|
算法 Unix 程序员
C++简介 C语言编程原理
C++简介 C语言编程原理
|
安全 编译器 程序员
「1」程序的基本概念
🐰基本数据类型和内存映像 🏡前言 🌸基本数据类型 ✈️void类型 🤔提示 🐰类型转换 🏡前言 🌸隐式转换 ✈️定义 ✈️基本数据类型的兼容关系 🤔提示 🌸强制类型转换 ✈️引入 🤔提示
#计算机组成原理# (学第四章先看!!)第四章 存储器简述
#计算机组成原理# (学第四章先看!!)第四章 存储器简述
73 1
#计算机组成原理# (学第四章先看!!)第四章 存储器简述
|
数据安全/隐私保护 网络架构
二十二、局域网基本概念和体系结构
二十二、局域网基本概念和体系结构
二十二、局域网基本概念和体系结构
|
存储
为什么计算机只能理解0和1这两个二进制数字?底层原理是什么?
为什么计算机只能理解0和1这两个二进制数字?底层原理是什么?
1358 0
|
监控 网络协议 安全
计算机的网络原理是什么?底层原理是什么?
计算机的网络原理是什么?底层原理是什么?
229 0