4. x86 拓扑结构¶
本文档记录并阐明了内核中 x86 拓扑建模和表示的主要方面。在对相关代码进行更改时,请更新/修改。
架构无关的拓扑定义位于 CPU 拓扑信息如何通过 sysfs 导出。 此文件包含 x86 特定的差异/特殊性,这些差异/特殊性不一定适用于通用定义。 因此,阅读 Linux 上 x86 拓扑结构的方式是从通用拓扑结构开始,并并行查看此文件,了解 x86 的具体细节。
毋庸置疑,代码应该使用通用函数 - 此文件仅用于记录 x86 拓扑结构的内部工作原理。
由 Thomas Gleixner <tglx@linutronix.de> 和 Borislav Petkov <bp@alien8.de> 发起。
拓扑结构设施的主要目标是为需要了解/查询/使用运行系统结构的线程、核心、包等代码提供足够的接口。
内核不关心物理插槽的概念,因为插槽与软件无关。它是一个机电设备组件。过去,一个插槽总是包含一个包(见下文),但随着多芯片模块 (MCM) 的出现,一个插槽可以容纳多个包。因此,代码中可能仍然存在对插槽的引用,但它们具有历史性质,应该进行清理。
系统的拓扑结构以以下单位描述:
包
核心
线程
4.1. 包¶
包包含多个核心以及共享资源,例如 DRAM 控制器、共享缓存等。
现代系统也可以使用术语 “Die” 来表示包。
AMD 用于包的命名法是 “Node”。
内核中与包相关的拓扑信息
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 上,包含末级缓存的 Node ID 或 Core Complex ID。 通常,它是一个唯一标识系统上 LLC 的数字。
4.2. 核心¶
一个核心由 1 个或多个线程组成。线程是 SMT 类型还是 CMT 类型并不重要。
AMD 用于 CMT 核心的命名法是 “Compute Unit”。内核始终使用 “core”。
4.3. 线程¶
线程是单个调度单元。它相当于一个逻辑 Linux CPU。
AMD 用于 CMT 线程的命名法是 “Compute Unit Core”。内核始终使用 “thread”。
内核中与线程相关的拓扑信息
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” 中。
topology_logical_core_id();
线程所属的逻辑核心 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