计算机底层原理概述

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

# 计算机底层原理

## 计算机的组成

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

控制器(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

相关文章
|
运维 监控 Java
研发规范第十三讲:阿里 - 如何进行项目稳定性建设
研发规范第十三讲:阿里 - 如何进行项目稳定性建设
843 1
|
2月前
|
缓存 监控 JavaScript
《Electron应用性能深耕:资源加载与内存治理的进阶路径》
本文围绕Electron桌面应用的性能优化展开,深入剖析了资源加载与内存治理的进阶路径。从底层机制出发,分析了Electron在主进程预加载、渲染进程解析、跨进程共享等环节的资源加载瓶颈,提出了包含动态加载、多级缓存、格式优化等在内的突破策略;针对内存占用问题,从渲染进程、主进程、GPU内存管理及垃圾回收机制等方面,构建了系统性优化方案。同时,结合实战案例探讨了优化中的辩证关系与跨平台适配经验,强调以数据驱动实现动态调节,为提升Electron应用性能提供了全面且深入的技术指引。
139 0
|
Kubernetes 负载均衡 API
Kubernetes通俗讲解
Kubernetes(K8s)是自动部署、扩展和管理容器化应用的开源平台,源自Google的Borg系统。它简化了大规模容器应用的部署和维护,支持自动部署、扩展、高可用性、服务发现与负载均衡及存储管理。K8s具有Master和Node节点架构,涵盖API Server、Scheduler等组件,其核心概念包括Pod、Service、Deployment和Namespace。使用时需安装集群、定义资源配置文件并应用配置。K8s具备可移植性、可扩展性、自动化及强大的社区支持等优势。
251 2
|
人工智能 关系型数据库 BI
算术逻辑单元ALU
算术逻辑单元ALU
2645 0
|
9月前
|
自动驾驶 vr&ar 开发者
把Waymo玩成GTA游戏!全生成式的车辆行驶轨迹视频合成器来了
FreeVS(Free View Synthesis)是一种创新技术,能够在真实驾驶场景中合成车辆的摄像头视角视频,不仅限于已知轨迹,还能生成全新轨迹上的视频。它采用伪图像表示和视角变换模拟技术,突破了传统方法对已知轨迹的依赖,提升了自动驾驶技术的测试和验证能力。实验结果显示,FreeVS在Waymo Open Dataset上表现出色,具有广泛的应用前景。论文链接:https://arxiv.org/abs/2410.18079
278 16
|
数据可视化 数据处理 开发者
构建高效的数据流图:Python与PyGraphviz的实践
【9月更文挑战第13天】在本文中,我们将探索如何利用Python和PyGraphviz库来创建和操作数据流图。我们将通过一个具体示例,展示如何从零开始构建一张数据流图,并讨论如何优化图表以提高可读性。文章旨在为初学者提供一个清晰的入门指南,同时为有经验的开发者提供一些高级技巧。
|
编解码 监控 网络协议
【绝密技巧】揭秘!如何用魔法般的步骤实现RTSP推送H.264与H.265(HEVC),打造震撼视听盛宴,让每一帧都充满魔力!
【8月更文挑战第15天】本文详述了如何使用RTSP流媒体服务推送H.264及H.265编码视频,适用于视频监控和直播平台。首先需确保环境支持这两种编码格式,可通过FFmpeg实现。在Ubuntu上安装FFmpeg后,可配置从摄像头捕获视频并推流至RTSP服务器。针对H.265编码,只需更改视频编码器为`libx265`。客户端可使用VLC播放器接收流。此外,还提供了C++示例代码用于自定义服务器实现,包括初始化上下文、打开编码器和循环编码视频帧。此教程旨在助力实现RTSP推送目标。
439 0
|
存储 程序员 C语言
堆和栈之间有什么区别
【9月更文挑战第1天】堆和栈之间有什么区别
2286 0
|
自然语言处理 物联网 算法框架/工具
开源大语言模型(LLM)汇总
随着ChatGPT的火爆,越来越多人希望在本地运行一个大语言模型。为此我维护了这个开源大语言模型汇总,跟踪每天不发的大语言模型和精调语言模型。
3359 0
开源大语言模型(LLM)汇总