4. x86 拓扑结构¶
本文档记录并阐明了内核中 x86 拓扑建模和表示的主要方面。当对相关代码进行更改时,请更新/修改。
架构无关的拓扑定义在 如何通过 sysfs 导出 CPU 拓扑信息 中。此文件保存了 x86 特定的差异/特殊性,这些差异/特殊性不一定适用于通用定义。因此,在 x86 上读取 Linux 拓扑的方法是从通用定义开始,并同时查看此文件以了解 x86 的具体细节。
不用说,代码应该使用通用函数 - 此文件仅用于记录 x86 拓扑的内部工作原理。
由 Thomas Gleixner <tglx@linutronix.de> 和 Borislav Petkov <bp@alien8.de> 发起。
拓扑设施的主要目的是为需要知道/查询/使用正在运行的系统关于线程、核心、封装等结构的的代码提供适当的接口。
内核并不关心物理插槽的概念,因为插槽与软件无关。它是一个机电组件。过去,一个插槽总是包含一个封装(见下文),但是随着多芯片模块 (MCM) 的出现,一个插槽可以容纳多个封装。因此,代码中可能仍然有对插槽的引用,但它们具有历史性质,应该被清理掉。
系统的拓扑结构以以下单元描述:
封装
核心
线程
4.1. 封装¶
封装包含多个核心以及共享资源,例如 DRAM 控制器、共享缓存等。
现代系统也可能使用术语“Die”来表示封装。
AMD 的封装术语是“节点”。
内核中与封装相关的拓扑信息
topology_num_threads_per_package()
一个封装中的线程数。
topology_num_cores_per_package()
一个封装中的核心数。
topology_max_dies_per_package()
一个封装中的最大 die 数量。
cpuinfo_x86.topo.die_id
die 的物理 ID。
cpuinfo_x86.topo.pkg_id
封装的物理 ID。此信息通过 CPUID 检索,并从封装中核心的 APIC ID 推导得出。
现代系统使用此值作为插槽。一个插槽内可能存在多个封装。此值可能与 topo.die_id 不同。
cpuinfo_x86.topo.logical_pkg_id
封装的逻辑 ID。由于我们不信任 BIOS 以一致的方式枚举封装,因此我们引入了逻辑封装 ID 的概念,以便我们可以合理地计算系统中最大可能的封装数量,并线性地枚举封装。
topology_max_packages()
系统中最大可能的封装数量。有助于每个封装设施预先分配每个封装的信息。
cpuinfo_x86.topo.llc_id
在英特尔上,共享末级缓存的 CPU 列表中的第一个 APIC ID
在 AMD 上,包含末级缓存的节点 ID 或核心复合体 ID。通常,它是一个在系统上唯一标识 LLC 的数字。
4.2. 核心¶
一个核心由 1 个或多个线程组成。线程是 SMT 型线程还是 CMT 型线程无关紧要。
AMD 对 CMT 核心的术语是“计算单元”。内核始终使用“核心”。
4.3. 线程¶
线程是单个调度单元。它等同于逻辑 Linux CPU。
AMD 对 CMT 线程的术语是“计算单元核心”。内核始终使用“线程”。
内核中与线程相关的拓扑信息
topology_core_cpumask()
cpumask 包含一个线程所属封装中的所有在线线程。
在线线程的数量也打印在 /proc/cpuinfo 的 “siblings” 中。
topology_sibling_cpumask()
cpumask 包含一个线程所属核心中的所有在线线程。
topology_logical_package_id()
线程所属的逻辑封装 ID。
topology_physical_package_id()
线程所属的物理封装 ID。
topology_core_id();
线程所属的核心的 ID。它也打印在 /proc/cpuinfo 的 “core_id” 中。
4.4. 系统拓扑示例¶
注意
备选的 Linux CPU 枚举取决于 BIOS 如何枚举线程。许多 BIOS 首先枚举所有线程 0,然后枚举所有线程 1。这样做的好处是,无论是否启用线程,线程 0 的逻辑 Linux CPU 编号都保持不变。这仅仅是一个实现细节,没有实际影响。
单封装,单核
[package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
单封装,双核
每个核心一个线程
[package 0] -> [core 0] -> [thread 0] -> Linux CPU 0 -> [core 1] -> [thread 0] -> Linux CPU 1
每个核心两个线程
[package 0] -> [core 0] -> [thread 0] -> Linux CPU 0 -> [thread 1] -> Linux CPU 1 -> [core 1] -> [thread 0] -> Linux CPU 2 -> [thread 1] -> Linux CPU 3
备选枚举
[package 0] -> [core 0] -> [thread 0] -> Linux CPU 0 -> [thread 1] -> Linux CPU 2 -> [core 1] -> [thread 0] -> Linux CPU 1 -> [thread 1] -> Linux CPU 3
AMD 对 CMT 系统的术语
[node 0] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 0 -> [Compute Unit Core 1] -> Linux CPU 1 -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 2 -> [Compute Unit Core 1] -> Linux CPU 3
双封装,双核
每个核心一个线程
[package 0] -> [core 0] -> [thread 0] -> Linux CPU 0 -> [core 1] -> [thread 0] -> Linux CPU 1 [package 1] -> [core 0] -> [thread 0] -> Linux CPU 2 -> [core 1] -> [thread 0] -> Linux CPU 3
每个核心两个线程
[package 0] -> [core 0] -> [thread 0] -> Linux CPU 0 -> [thread 1] -> Linux CPU 1 -> [core 1] -> [thread 0] -> Linux CPU 2 -> [thread 1] -> Linux CPU 3 [package 1] -> [core 0] -> [thread 0] -> Linux CPU 4 -> [thread 1] -> Linux CPU 5 -> [core 1] -> [thread 0] -> Linux CPU 6 -> [thread 1] -> Linux CPU 7
备选枚举
[package 0] -> [core 0] -> [thread 0] -> Linux CPU 0 -> [thread 1] -> Linux CPU 4 -> [core 1] -> [thread 0] -> Linux CPU 1 -> [thread 1] -> Linux CPU 5 [package 1] -> [core 0] -> [thread 0] -> Linux CPU 2 -> [thread 1] -> Linux CPU 6 -> [core 1] -> [thread 0] -> Linux CPU 3 -> [thread 1] -> Linux CPU 7
AMD 对 CMT 系统的术语
[node 0] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 0 -> [Compute Unit Core 1] -> Linux CPU 1 -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 2 -> [Compute Unit Core 1] -> Linux CPU 3 [node 1] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 4 -> [Compute Unit Core 1] -> Linux CPU 5 -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 6 -> [Compute Unit Core 1] -> Linux CPU 7