Linux核心概念详解
  • 0. Linux核心概念详解
  • 1. 调试环境
  • 2. Linux 调度器
    • 2.1 任务
    • 2.2 核心概念
      • 2.2.1 核心概念 - 调度实体
      • 2.2.2 核心概念 - 调度类
      • 2.2.3 核心概念 - 调度策略
      • 2.2.4 核心概念 - 运行队列
      • 2.2.5 核心概念 - 优先级
    • 2.3 演进历史
      • 2.3.1 O(n)调度器 - 调度逻辑
      • 2.3.2 O(n)调度器 - 时间分配
      • 2.3.3 O(n)调度器 - 调度时机
      • 2.3.4 O(1)调度器 - 简介
      • 2.3.5 O(1)调度器 - 调度逻辑
      • 2.3.6 O(1)调度器 - 时间分配
      • 2.3.7 RSDL
      • 2.3.8 CFS
    • 2.4 DL调度器
      • 2.4.1 DL调度器 - 调度算法
      • 2.4.2 DL调度器 -核心代码
    • 2.5 RT调度器
    • 2.6 CFS
      • 2.6.1 公平性
      • 2.6.2 调度逻辑
      • 2.6.2.1 调度逻辑 - 数据结构
      • 2.6.2.2 调度逻辑 - vruntime
      • 2.6.2.3 调度逻辑 - 调度周期
      • 2.6.2.4 调度逻辑 - 调度节拍
      • 2.6.2.5 调度逻辑 - 任务抢占
      • 2.6.2.6 调度逻辑 - 调度时机
      • 2.6.3 组调度
      • 2.6.3.1 组调度 - 数据结构
      • 2.6.3.2 组调度 - 调度逻辑
      • 2.6.3.3 组调度 - 时间分配
      • 2.6.3.4 组调度 - 任务组权重
      • 2.6.4 带宽控制
      • 2.6.4.1 带宽控制 - 数据结构
      • 2.6.4.2 带宽控制 - 带宽时间
      • 2.6.4.3 带宽控制 - 挂起与解挂
      • 2.6.4.3 带宽控制 - 定时器
    • 2.7 负载追踪
      • 2.7.1 负载追踪 - 简介
      • 2.7.2 负载追踪 - 数据结构
      • 2.7.3 负载追踪 - 计算负载
      • 2.7.4 负载追踪 - 更新负载
    • 2.8 负载均衡
      • 2.8.1 简介
      • 2.8.2 CPU的拓扑结构
      • 2.8.3 数据结构
      • 2.8.4 算法思路
      • 2.8.5 触发时机
      • 2.8.6 总结
  • 3. LINUX 内存管理
    • 3.1 寻址模式
      • 3.1.1 地址
      • 3.1.2 地址转换
      • 3.1.3 Linux的地址空间
    • 3.2 物理内存
      • 3.2.1 数据结构
      • 3.2.2 初始化
      • 3.2.3 物理内存模型
      • 3.2.4 Buddy System(伙伴系统)
      • 3.2.5 SLAB/SLUB/SLOB
Powered by GitBook
On this page

Was this helpful?

  1. 2. Linux 调度器
  2. 2.8 负载均衡

2.8.2 CPU的拓扑结构

Previous2.8.1 简介Next2.8.3 数据结构

Last updated 3 years ago

Was this helpful?

CPU的拓扑结构可以理解为在硬件层面上多个CPU的排列方式, 对于运行的任务而言,拓扑结构决定了其从一个CPU迁移到另一个CPU将要付出的代价。在详细讨论拓扑结构之前,我们先介绍几个与CPU相关的概念:

  • Socket: 对应主板上CPU插槽

  • Core: 独立的一个执行单元,硬件上实现真正并行计算的组件,例如我们说一个CPU是“四核八线程”,其中每个核就对应一个Core

  • Hyper-Threading: 逻辑上的一个执行单元,多个超线程共享一个核,例如“四核八线程”,就是每两个线程共享一个核。由于多个超线程共享一个物理执行单元,因此超线程并不是硬件层面上独立的并行计算单元,只是在OS级别的并发单元。

例如本人机器的CPU 型号是 Intel i5-8265U, 一个物理处理器,4核8线程,其拓扑结果如下:

Linux 中通过命令 lstopo 即可查看CPU 的拓扑结构,通过命令 hardinfo 可以查看系统的各类硬件信息。

这里我们并没有提及CPU, CPU是最早出现的概念,早期与Socket是1:1的对应关系,但发展到现在基本已经是一个泛化和抽象的概念了,严格地说已经变成了一个日常用语。但在OS层面,CPU依然表示系统的一个执行单位,每个线程都会对应一个系统CPU. 例如上图中,系统会显示有8个CPU.

Note: 系统CPU 的信息记录在 /proc/cpuinfo 中,可以通过 cat 命令查看。

通过该图可以发现:P#0与P#4就是两个超线程,并且共享Core L#0. 还可以看出同一个Core中的所有超线程共享所有的CPU缓存(L1, L2, L3),而不同的Core 只共享L3。

对多核CPU而言,如何访问主存(RAM)也是一个重要议题,主要涉及到两种拓扑结构:

在图一中,所有的CPU 都处在一个NUMA节点中。

当CPU访问数据时,只有当所有的缓存(L1, L2, L3)都没有命中时才会访问主存(RAM),如果主存也没有数据则会发生缺页中断(page fault)并从磁盘加载数据。通过上面的介绍我们知道:从缓存到主存,不同的CPU能够共享的层级是不一样的。也就是说,当迁移任务时,选择不同的目标CPU 就意味着要付出不同的代价。通常而言我们认为:

  1. 同一个超线程集(Hyperthreaded Set)中的CPU能够共享所有的缓存、主存,所以将任务在不同线程之间迁移可以认为没有性能损耗

  2. SMP架构或者同一个NUMA节点内,不同的Core 可能只会共享部分缓存,但访问主存的时间都是一样的。因此如果对任务进行跨核迁移的话,新CPU的缓存将需要重新warm up

  3. NUMA架构下,不同节点(Node)会有自己的本地主存(Local RAM),CPU访问其他节点的主存比访问本地主存需要更多时间。因此不到万不得已,调度器不会跨节点地进行任务迁移。

从同一个超线程集合,到NUMA中跨节点的CPU,我们可以认为CPU之间的“物理距离”在不断增加,这种“物理距离”形成了一种层级结构。根据上述分析可以知道,当调度器做任务迁移时,所选择的目标CPU越“近”则性能损耗就越小。因此内核需要某种方式来有效地组织CPU,这种组织方式能够根据“距离”将CPU分组,并形成合理的层级结构,使得调度器能够高效调整各个CPU的负载。

SMP(Symmetric Multiprocessing) 被译为, 简单说就是每个CPU在访问主存时的代价都是一样的,主存作为全局的一个资源被所有CPU所共享。示意图如下:

NUMA(Non-uniform Memory Access) 被译为, 系统将CPU分为不同的集群,每个集群叫着一个节点(Node),每个节点都有自己的本地内存(Local RAM),CPU 可以访问任何节点的内存,但访问本地内存的速度要远高于访问非本地内存的速度。示意图如下:

对称多处理
非均匀访存模型
图一:Intel i5-8265U 拓扑结构
图二:SMP
图三:NUMA