cpu

217 阅读14分钟

cpu相关的概念

  • cpu位数
  • cpu架构
  • cpu组成
  • cpu工作方式
  • cpu频率

cpu 与 时钟 (clock)

cpu是如何被驱动的

其实可以换个问法,如同人的心脏的跳动驱使着人的存活,那么计算机之中扮演心脏一样的角色是谁呢?

cpu 内部的石英晶振(扮演着计时器的角色),通电后,以固定的频率触发 cpu 执行一个基本操作。 石英晶振扮演着 类似心脏一样的角色。

周期

时钟周期 指令周期 机器周期

  • 时钟周期
    时钟周期是时钟晶振频率的倒数。时钟周期是计算机之中 最基本,最小的时间单位。

  • 指令周期
    cpu执行一条指令所耗费的时间。

  • 机器周期
    一条指令的执行 需要分为多个阶段,每个阶段执行完成所需的时间,被称为是机器周期。

三者之间的关系

一个 指令周期 包含 若干个 机器周期;
一个 机器周期 包含 若干个 时钟周期。

cpu频率

cpu频率的含义是什么?

是指 处理器的时钟频率 ,是指 cpu每秒钟 所能 执行指令的次数。

cpu频率与cpu性能的关系

比较简单地说,cpu频率越高,cpu的性能就越好,可以简单地这样理解。

cpu的频率越高越好嘛

但是实际上并不是,cpu频率越高,可能导致cpu出现过热现象,导致cpu出现问题。

Linux 与 cpu频率

Linux下 如何查看cpu的频率

cat /proc/cpuinfo | grep  MHz|uniq

cpu 组成

cpu 由哪些 部件构成?

  • 寄存器
  • 控制器
  • 运算器
  • 高速缓存
  • 内存转换 (MMU)
  • 快表 (TLB)

等......

寄存器

寄存器的作用是什么?

用来暂存 指令、数据 等处理对象。

控制器

控制器的作用是什么?

负责把内存之中的指令 数据 读入寄存器,并根据指令的执行结果来控制计算器。

运算器

运算器的作用是什么?

负责运算从内存读入寄存器的数据。

cpu 高速缓存

cpu 高速缓存的容量 是 远远小于 内存的。 这是需要注意的。

cpu 高速缓存 缓存的内容是什么?

缓存的是 内存之中的值。

cpu高速缓存 与 内存 的区别

1: cpu高速缓存的存取速度 远远 超过 内存的存取速度。
2: cpu高速缓存的单价 要比 内存 昂贵
3: cpu高速缓存的容量 要 远远 小于 内存

cpu 高速缓存的作用

换个问法,高速缓存 在 cpu 执行指令的过程之中的哪个阶段发挥作用?
cpu要从内存的指定地址获取数据的时候,会首先从高速缓存之中查询是否存在。 cpu写回执行执行的执行结果的时候,会根据写入的策略来判断 是否写入高速缓存。

cpu 高速缓存 产生的原因

由于 cpu的处理速度 远超 内存 访问速度。所以cpu上增加 高速缓存 用来弥补 cpu处理速度 和 内存访问速度之间的差异。

对于使用cpu高速缓存后,会产生的几个疑惑?

cpu高速缓存的读

如果从 cpu高速缓存之中未找到内容,那么从内存之中读取数据, 顺便更新 高速缓存之中的数据。(比较简单地考虑,忽略当前cpu高速缓存的分级机制)

cpu高速缓存的写

在忽略 cpu高速缓存 的分级机制下,分为直写和回写两种。

  • 直写
    不管是否命中 cpu高速缓存,每次写操作都会写入到内存之中。
  • 回写
    在 高速缓存之中 多维护一个标志位,表示缓存是否已经修改过。会根据这个标志位来判断,是否需要写入内存。

两者的不同,在于 写入内存的机制。

对于cpu读取数据,如果高速缓存之中不存在数据,从内存之中读取数据后,如何分配到 高速缓存

如果cpu 读取 没有命中高速缓存,那么 将 内存数据 映射到 高速缓存 之中的方式有

  • 直接映射
  • 全相联映射
  • 组相联映射
    三种映射规则 可以选择(具体的规则,这里就不介绍了。)
    目前的实际采用的应该是 组相联映射。
    出现不同的映射规则的原因是为了 提高缓存的命中率,一切都是为了此目的而不断进行优化的。

由于cpu高速缓存容量远远小于内存,则cpu高速缓存满了后,具体的替换规则 是如何的?

常见的替换规则有:

  • 先进先出 (FIFO)
  • 最近最少使用 (LRU)
  • 最不经常使用 (LFU)
  • 随机替换算法 (Random)

现实实际使用的替换规则 应该是 LRU,出现不同的替换规则,主要的目的是为了 提高缓存的命中率。

对于cpu写入的问题,如何保证 cpu高速缓存 和 内存 数据的一致性

换个具体的问法:如果cpu要修改某个内存之中的数据,同时这个数据被 cpu高速缓存 进行缓存了,那么这个写入的步骤如何进行处理?
对于这个问题,cpu高速缓存 有 全写法 和 回写法两种策略。

多核cpu架构下,各个cpu之间的缓存一致性问题

例如,多核cpu架构下,操作同一个变量,多个cpu的高速缓存之中的数据一致性问题。
解决方案有:
1: 对总线加锁 2: 使用 MESI协议,来实现 各个cpu之间的缓存一致性问题。 3: 禁用缓存

感觉MESI 机制 已经解决了 可见性问题。这个其实就不是问题了呀,为什么 java之类的语言还要提供volatile之类的关键字呢?

虽然 MESI机制能够解决 多个cpu之间的缓存一致性问题,但是会带来性能的问题。所以针对性能的问题,cpu的设计者,又在cpu这个硬件层次上 增加了 store buffer 与 invalid queue 这两个硬件,是的原本的MESI机制的缓存一致性,从强一致性 转换成为了弱一致性。因此而引出了内存屏障的概念,目的是为了解决store buffer 与 invalid queue 带来的问题。

MESI

MESI机制会导致 cpu性能下降的原因

在 多核cpu的架构下,某个cpu对于高速缓存的一些操作,需要 同步 等待其他cpu的响应。同步等待这样的行为,会导致cpu性能下降。

对于MESI机制会导致 cpu性能下降,所采取的措施是什么?

cpu的设计人员,在硬件层面上增加了 store buffer 以及 invalid queue 这两个组件 来提高性能

cpu 增加了 store buffer 以及 invalid queue 组件之后,是否会带来新的问题,如果是,是什么?

cpu 增加 store buffer 以及 invalid queue 组件之后, 会导致 MESI原本的强一致性模型 变成 弱一致性模型,在程序的并发情况下,导致可见性。

对于导致 MESI从强一致性变为 弱一致性 的解决措施是什么?

硬件工程师 提供 内存屏障指令,由软件工程师在编码的时候调用,来规避 程序并发时 的可见性问题 以及 有序性问题。

对于一个程序员而言,了解cpu的高速缓存的意义是什么?

主要是了解可见性问题产生的根本原因。主要目的还是了解 cpu高速缓存在 cpu运行过程之中所扮演的角色,在更微观的层次上理解程序的执行,从而对程序的执行 建立起 更深层次 的认知。

MMU

MMU是什么?

MMU 被称为是 内存管理单元

MMU的作用是什么?

MMU的一个主要的作用就是将 虚拟内存地址 转换 成为 物理内存地址。

TLB (快表)

TLB (快表)的作用是什么

TLB 缓存 虚拟地址 与 物理地址 的映射关系。
TLB 其实本质上也是一块高速缓存。

cpu 核数

与 cpu 核数 相关的概念

  • 物理核数
  • 逻辑核数
  • cpu超线程

什么是 cpu 物理核数,什么是 cpu逻辑核数?

物理核数:cpu上的物理核数。

逻辑核数:cpu开启了超线程,一个物理核可以分成n个逻辑核,n为超线程的数量

逻辑cpu核数

逻辑cpu核数的作用

Linux下的进程调度 是以 逻辑cpu核数 为基数,进程调度的,将任务调度到某个cpu下面。

逻辑cpu核数 的计算公式

未开启超线程:
逻辑cpu数目 = 物理cpu数目 * 物理cpu核数

开启超线程:
逻辑cpu数目 = 物理cpu数目 * 物理cpu核数 * 2

Linux下 如何查看逻辑cpu核数

/proc/cpuinfo 文件之中的processor 表示的是逻辑cpu的数目。
执行以下命令 获得当前机器上的逻辑cpu的数目 cat /proc/cpuinfo | grep processor | wc -l

逻辑cpu 与 进程调度 之间的关系

搜索资料得出的结论: 1:Linux 进程调度,将进程分配给cpu,这里的cpu指的是逻辑cpu。 所以是以逻辑cpu为实体分配进程的。

cpu 超线程

注意:cpu超线程 是在硬件层面采取的优化措施。

什么是 cpu 超线程

CPU超线程就是利用特殊字符的硬件指令,把两个逻辑内核模拟成物理芯片,让单个处理器能使用线程级并行计算,从而兼容多线程并行计算,从而兼容多线程操作系统和软件,使运行性能提高。

如何判断 Linux 下 cpu开启了超线程?

查看 /proc/cpuinfo 文件的信息来判断,是否开启了超线程。

siblings 与 cpu cores 取值相同,说明 cpu支持超线程或者为开启超线程。

siblings 的取值为 cpu cores 取值的两倍,说明开启了cpu超线程。

cat /proc/cpuinfo | grep -e siblings -e cores

cpu 超线程产生的原因

为了提高cpu的利用率

cpu 超线程的优缺点

优势:1:对于并发场景,并发能力会增强,cpu的利用率会提高。
劣势:2:单核性能会有损耗。

cpu位数

cpu位数的含义是什么?

cpu的位数 表示 cpu所能够一次 存储和处理 二进制数据的位数。
cpu的位数,就是寄存器的位宽。寄存器的位宽,表示寄存器能够放入多大的数据。 cpu的位数 表示cpu能够一次能够处理的位数,如果是64位,那么表示一次最大能够处理64位的数据,就是 2^64。

cpu位数对于 作为一个程序员的意义,换个说法,其实就是 cpu位数会对程序的编程产生哪些方面的影响?

cpu位数 会影响 在程序的并发方面产生影响。

假如是64位的cpu,那么go语言之中,读取长度超过8字节的字符串,这样的操作是原子性的嘛?

golang 之中字符串类型的变量的 读取 和 赋值 并不是原子性的。
给出下列的代码,来作为表示 字符串类型的变量的读取和赋值并不是原子性的,会导致并发安全问题。


var a = "0"

func main() {

   ch := make(chan string)

   go func() {
      i := 1

      for {

         if i%2 == 0 {
            a = "0"
         } else {
            a = "aa"
         }
         time.Sleep(1 * time.Millisecond)
         i++
      }
   }()

   go func() {
      for {
         b := a
         if b != "0" && b != "aa" {
            ch <- b
         }
      }
   }()

   for i := 0; i < 10; i++ {
      fmt.Println("Got strange string: ", <-ch)
   }

}

cpu 工作方式

cpu 是怎么样工作的

cpu 以 指令为基本单位,不断地执行 一个又一个的指令。

cpu执行的指令过程分为四个步骤:

  • 1: 取指
  • 2: 译码 :将指令(二进制),转换成为所需执行的操作
  • 3: 执行
  • 4: 写回

cpu 乱序执行

乱序执行是什么意思?

程序之中的代码顺序 可能会被 编译器 或者cpu 根据某种策略 打乱执行的顺序,但是并不影响最终的结果。

有哪些 原因 导致 cpu 可能 乱序执行 程序

  • 1: 在编译器,编译器进行指令重排。
  • 2: 运行期,cpu进行指令乱序执行。

什么是 cpu的流水线技术

cpu 运行一个指令 分为 取指 译码 执行 写回,这四个步骤 分别由 cpu之中独立的组件执行。

所以如果所需执行的指令之间并没有依赖关系(即 下一个指令 依赖 上一个指令 执行的结果),那么第一个指令执行完 取指 之后,进入 译码 阶段,第二个指令就可以进入 取指 阶段。 cpu并发执行指令,提高 cpu 执行指令的速度。

所以为了效率着想,cpu 在运行时,可能会调整指令的执行顺序,来提高运行速度。

cpu流水线技术的作用是什么

尽可能地提高 cpu运行指令的速度。

为什么要了解 cpu 乱序执行这个机制? 或者换个问法,知道了cpu的乱序执行机制后,对于我们程序员而言,产生什么样的指导意义?

cpu的乱序执行机制,是 并发编程之中 有序性 问题的来源(编译优化以及cpu运行时乱序执行 导致 并发编程有序性问题)。

所以当我们进行 并发编程时,可以具备一个意识,程序的执行顺序 并非是 我们所写的代码的顺序,在这样的思考方式的指导下,尽量避免并发问题的产生。

同时,看待所写的程序时,我们所写的一行代码,背后可能代表着多个指令(在代码翻译成为机器码后),它们之间的执行顺序也可能是乱序的,具体的例子如,创建一个java对象,在背后就可能乱序执行。

一般的编程语言 如果 代码的执行 会 超过 cpu的位数,那么被翻译成为 机器码之后,一句代码 就可能对应着多个机器码,那么就可能存在指令重拍的可能性,在并发编程的时候,就可能会出问题。

cpu 架构

cpu架构是什么意思?

cpu架构就是处理器的硬件架构,又被成为称为微架构,是一堆硬件电路去实现指令集所规定的操作运算。 应该算 cpu实现了什么样的指令集,从而称呼cpu的指令集是什么。
x86架构的处理器 含义是:采用了Intel X86指令集的处理器。
cpu在设计的时候,采用了哪种类型的指令集,那么就决定了cpu的架构是什么类型。

cpu目前的架构有哪些?

其实这个问题,可以转换成为 目前到底有哪些指令集。 cpu的架构,就是由cpu所实现的指令集来决定的。
自己目前的认知,cpu的架构有两种 x86 与 arm 架构。
x86架构,又被称为amd架构。

指令集 和 cpu架构 之间的关系是什么?

应该是 先有指令集,然后根据指令集来设计cpu。 cpu所实现的指令集类型,决定了cpu的架构。

Linux 如何查看cpu的架构

执行 arch 命令来查看cpu的架构

了解cpu架构对于程序员的意义是什么?换个问法,cpu架构对于程序的运行有什么样的影响,应该如何正确选择cpu架构,从而使程序的运行维持正常的状态。

cpu 与 指令集

指令集 是什么?

指令集 其实是 一堆 二进制数据。

cpu 是如何运行执行一个指令的?换个方式问,其实可以这样问,一条指令在cpu之中的执行流程是什么?

cpu执行的指令过程分为四个步骤:

  • 1: 取指
  • 2: 译码 :将指令(二进制),转换成为所需执行的操作
  • 3: 执行
  • 4: 写回

cpu 的最小的执行单位

因为cpu的执行是会被打断的,所以想知道 cpu执行什么是一定会执行完成,不会中断的。
cpu执行一条指令 是 不会打断的,要么成功 要么失败。

为什么要建立起cpu 最小的执行单位的 认知? 换个问法来说,了解cpu的最小执行单位 对于程序员而言的意义是什么?

一般程序员 编程使用的语言是 高级编程语言,高级编程语言的代码 与 指令 并不是一一对应的, 一句高级编程语言 可能会对应多个指令。所以对于程序员而言,因为使用高级编程语言,所以可能会产生错觉,从而导致编写代码 导致并发的原子性问题的出现。

汇编语言 与 指令集 的关系

汇编语言 使用 人类所能看懂的方式来描述指令集。 指令集之中的指令,其实是一串二进制的数据,很难让人读懂。
自己目前的一点理解,一句汇编代码 其实代表这个 一个指令。

汇编语言出现的原因

单纯的指令集 难以阅读,为了方便人类理解,故而产生了 汇编语言。
汇编语言 使用 人类所能看懂的方式来描述指令集。

汇编语言的优缺点

优点:
解决了 指令集 难以阅读的问题,汇编语言更加可读。
缺点:
1: 汇编语言的可移植性很差,不能跨平台。arm的汇编语言和x86的汇编语言不同。
2: 指令集发生了修改,那么汇编语言也要发生修改。

在跨平台的需求下,更加高级的编程语言随之出现,例如c,java 等。

汇编语言 是 如何转换成为 指令 的?

汇编语言 通过 汇编过程 转换成为 指令,这里的指令也可以称为是机器码,也就是0101这样的二进制数据。

高级编程语言编程后的程序 是 如何转换成为汇编代码的?

高级编程语言编写的程序 经过 编译 这个过程,变成汇编代码。
编译这个功能,由编译器来执行,这其实也是编译器产生的原因(自己的理解)。

高级编程语言 是否能够 直接 翻译 成为 机器码(指令) ?

是可以的。

为什么 现有的逻辑 是 高级编程语言 -> 汇编语言 -> 机器码(指令), 不是 高级编程语言 -> 机器码(指令) ?是有什么特殊的原因嘛?

可能是因为 汇编语言 和 机器码十分接近,从 汇编语言 到 机器码(指令) 不需要太多的劳动力,高级编程语言 -〉 汇编语言 这个过程 比起 高级编程语言 -> 机器码(指令) 这个过程更加方便吧。

CPU 与 内存

cpu 如何与 内存 进行交互

cpu 是通过 总线 来和 内存 进行交互的。
地址总线传递地址,数据总线 传递 数据。

cpu 与 内存 交互 的发展历史

CPU与内存的简单连接:FSB时代
在历史上CPU、内存数量比较少的年代里的总线方案-FSB,FSB的全称是Front Side Bus,因此也叫前端总线。

CPU通过FSB总线连接到北桥芯片,然后再连接到内存。

内存控制器是集成在北桥里的,Cpu和内存之间的通信全部都要通过这一条FSB总线来进行。

image.png

多CPU多内存条复杂互联:NUMA时代
当CPU的主频提升到了3GHz每秒以后,硬件制造商们发现单个CPU的已经到了物理极限了。

所以就改变了性能改进的方法,改成为向多核、甚至是多CPU的方向来发展。

在这种情况下,如果仍然采用FSB总线,会导致所有的CPU和内存通信都经过总线,

这样总线就成为了瓶颈,无法充分发挥多核的优势与性能。

所以CPU制造商们把内存控制器从北桥搬到了CPU内部,这样CPU便可以直接和自己的内存进行通信了。

那么,如果CPU想要访问不和自己直连的内存条怎么办呢?
所以就诞生了新的总线类型,它就叫QPI总线。 image.png

NUMA

NUMA架构的产生原因

单个cpu的频率发展到了极致,开始使用多核并发的方式来提高性能,因此产生 多个cpu 与 多个内存条组合在一起的现状,为了提高这种情况下的性能,故而产生了NUMA架构。

NUMA 是软件层面的特点,还是硬件层面的特点

是硬件层面的特点。

CPU的 NUMA架构 是什么意思

cpu 与 内存 进行交互的 有多种方式,而其中的一种 被称为是 NUMA。
NUMA: 非统一内存访问。

简单的描述:
在多个cpu和多个内存的情况下,将一部分内存作为某个cpu的本地内存,将另一部分的内存作为另外的cpu的本地内存。

CPU NUMA架构 的形状

image.png

NUMA 所带来的影响是什么?

NUMA机制 会 对于 内存分配 产生影响。
在一个 NUMA Node 的内存即将耗尽的时候,Linux 采取的默认策略是 swap/淘汰 内存页,对于消耗大内存的应用而言(比如一个应用内存大于一个 NUMA Node 的所有内存)来说,一旦某个后续需要用到那部分内存页,就会出现明显的性能下降。

上面的描述,很容易让我们产生,是否某个程序所需要的内存过大,就容易陷入NUMA陷阱,导致无法完全利用机器的物理内存 的想法。

但是,实际上并不会,因为进程调度导致进程被分配到不同的cpu上,进程在不同的cpu上执行,自然会在cpu对应的本地内存上进行分配,所以还是能充分利用 机器的物理内存的。
除非,进程绑定了cpu 亲和性,某个进程只能在某个cpu上执行,那样,则会陷入 NUMA架构所带来的问题。

Linux 与 NUMA

对于cpu的NUMA架构,Linux在软件层面做了什么样的处理,或者换个问法,Linux 如何 抽象NUMA机制

自己目前的认知:
从 Linux 角度来看,基于这种硬件结构,一个 CPU 会被抽象成一个 NUMA Node, 并且尽可能将 CPU 所需要的内存分配在它的本地内存中。

Linux下 查看是否启用 NUMA

执行

dmesg | grep numa

如果没出现disable之类的信息,那就是支持NUMA架构了。

Linux 下 对应NUMA功能的客户端命令

numactl

numactl
查看当前机器的 NUMA 状况
numactl --hardware

cpu 与 Linux 进程调度

Linux下 进程调度 所能分配的cpu 的 最小单位是什么?

cpu逻辑核 是 Linux下 进程调度所能分配的最小单位。