CPU电源管理——基本概念和topology
Posted hellokitty2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CPU电源管理——基本概念和topology相关的知识,希望对你有一定的参考价值。
1. 相关名词解释
SMP:(Symmetric Multi-Processing)对称多处理,一个chip上集成多个核心
SMT:(Simultaneous multithreading)同时多线程,一个核心上实现多个hardware context,以支持多线程。通过复制硬件寄存器状态等手段,同时执行多个线程。
Node:某些Core之间,独享总线和memory,称作Node。Core只访问Node内的memory,因此可以减轻对总线和memory的带宽需求。但是有些场景下,Core会不可避免的访问其它Node的memory,这会造成很大的访问延迟。
NUMA: (Non-uniform Memory Access)不一致内存访问,以内存访问的不一致性为代价,减轻对总线和memory的带宽需求。这种结构对进程调度算法的要求较高,尽量减少跨Node的内存访问次数,以提升系统性能。
HMP:(Heterogeneous Multi-Processing)异构多处理,ARM的一种架构,在乎功耗的存在。HMP架构在一个chip中,封装两类ARM Core,一类为高性能Core(如Cortex-A15,也称作big core),一类为低性能Core(如Cortex-A7,也称作little core),因此HMP也称作big·little架构。
还有big-middle-little架构。
2. CPU topology除了描述CPU的组成之外,其主要功能是向kernel调度器提供必要的信息,以便让它合理地分配任务,最终达到性能和功耗之间的平衡。
CPU topology:Cluster-->Core-->Threads
3.CPU拓扑框架
------------------------- ---------------------------- | CPU topology driver | | Task Scheduler etc. | ------------------------- ---------------------------- ------------------------------------------------------- | Kernel general CPU topology | ---------------------------------------------------------- ---------------------------------------------------------- | arch-dependent CPU topology | ----------------------------------------------------------
Kernel general CPU topology位于"include/linux/topology.h”中,定义了获取系统CPU topology信息的标准接口。底层的arch-dependent CPU topology会根据平台的特性,实现kernel定义的那些接口。
CPU topology信息有两个重要的使用场景:一是向用户提供当前的CPU信息(eg:lscpu),这是由CPU topology driver实现的;二是向调度器提供CPU core的信息,以便合理的调度任务。
3.1 Kernel general CPU topology
Kernel general CPU topology位于 include/linux/topology.h 中,主要以“#ifndef ... #define”类型的宏定义的形式提供API,其目的是:底层的arch-dependent CPU topology可以重新定义这些宏,只要底层有定义,则优先使用底层的,否则就使用Kernel general CPU topology中的默认API,主要包括:
/* include/linux/topology.h */ #ifndef topology_physical_package_id #define topology_physical_package_id(cpu) ((void)(cpu), -1) #endif #ifndef topology_core_id #define topology_core_id(cpu) ((void)(cpu), 0) #endif #ifndef topology_thread_cpumask #define topology_thread_cpumask(cpu) cpumask_of(cpu) #endif #ifndef topology_core_cpumask #define topology_core_cpumask(cpu) cpumask_of(cpu) #endif #ifdef CONFIG_SCHED_SMT static inline const struct cpumask *cpu_smt_mask(int cpu) { return topology_thread_cpumask(cpu); } #endif static inline const struct cpumask *cpu_cpu_mask(int cpu) { return cpumask_of_node(cpu_to_node(cpu)); }
topology_physical_package_id:用于获取某个CPU的package ID,即socket(X86)或者cluster(ARM),具体意义依赖于具体平台的实现;
topology_core_id:某个CPU的core ID。即第二章所描述的core,具体意义依赖于具体的平台实现;
topology_thread_cpumask:获取和该CPU属于同一个core的所有CPU,通俗的讲,就是姐妹Thread;
topology_core_cpumask:获取和该CPU属于同一个cluster的所有CPU;
cpu_cpu_mask: 获取该CPU属于同一个Node的所有CPU;
cpu_smt_mask: 用于SMT调度(CONFIG_SCHED_SMT)的一个封装,意义同topology_thread_cpumask。
3.2 arch-dependent CPU topology
位于“arch/arm64/include/asm/topology.h”和“arch/arm64/kernel/topology.c”中,主要负责ARM64平台相关的topology转换,包括:
(1) 定义一个数据结构,以及基于该数据结构的变量,用于存储系统的CPU topology
/* arch/arm64/include/asm/topology.h */ struct cpu_topology { int thread_id; int core_id; int cluster_id; cpumask_t thread_sibling; cpumask_t core_sibling; }; extern struct cpu_topology cpu_topology[NR_CPUS];
cluster_id、core_id、thead_id描述了拓扑结构的三个层次,thread_sibling和core_sibling,保存了和该CPU位于相同级别(同一个core和同一个cluster)的所有姐妹CPU。系统中每个CPU(个数由NR_CPUS指定,是从OS的角度看的)都有一个struct cpu_topology变量,用于描述该CPU在整个topology中的地位。以数组的形式维护。
(2)重定义CPU topology有关的宏定义
/* arch/arm64/include/asm/topology.h */ #define topology_physical_package_id(cpu) (cpu_topology[cpu].cluster_id) #define topology_core_id(cpu) (cpu_topology[cpu].core_id) #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) #define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
实现比较简单,从该CPU对应的struct cpu_topology变量中取出指定的字段即可。
(3)提供初始化并构建CPU topology的方法,以便在系统启动时调用
/* arch/arm64/include/asm/topology.h */ void init_cpu_topology(void); void store_cpu_topology(unsigned int cpuid);
init_cpu_topology的调用路径是:kernel_init-->smp_prepare_cpus-->init_cpu_topology,主要完成如下任务:
store_cpu_topology的调用路径是:kernel_init-->smp_prepare_cpus-->store_cpu_topology,在没有从DTS中成功获取CPU topology的情况下,从ARM64的MPIDR寄存器中读取topology信息。
设备树中的cpu-map和clusterX描述了CPU的拓扑结构,具体可参考“Documentation/devicetree/bindings/arm/topology.txt”中的描述。
3.3 CPU topology driver
CPU topology driver位于“driversase opology.c”中,基于“include/linux/topology.h”所提供的API,以sysfs的形式,向用户空间提供获取CPU topology信息的接口,lscpu应用,就是基于该接口实现的。sysfs的格式可参考“Documentation/cputopology.txt”。
/sys/devices/system/cpu/cpuX/topology/下
physical_package_id: //就是此CPU位于的Cluster编号 core_id: //在一个Cluster内此CPU的编号 thread_siblings: //每个CPU核的位掩码,CPU0 CPU1 CPU2分别为0x1 0x2 0x4 thread_siblings_list: //CPU是几这个就是几,CPU0就是0,CPU7就是7 core_siblings: //每个Cluster内的CPU组成的位掩码,若四小核Cluster0就是0x0f,3中核就是0x70 core_siblings_list: //每个Cluster内的CPU组成的数字加中画线显示,若4小核,3中核,1大核,小核的是0-3,中核就是4-6,大核就是7
/sys/devices/system/cpu/下
kernel_max 一共有多少个核,7 kernel_max: 31 offline: 2,4-31,32-63 online: 0-1,3 possible: 0-31 present: 0-31
4. CPU一共有4种状态需要表示:
cpu_possible_bits,系统中包含的所有的可能的CPU core,在系统初始化的时候就已经确定。对于ARM64来说,DTS中所有格式正确的CPU core,都属于possible的core;
cpu_present_bits,系统中所有可用的CPU core(具备online的条件,具体由底层代码决定),并不是所有possible的core都是present的。对于支持CPU hotplug的形态,present core可以动态改变;
cpu_online_bits,系统中所有运行状态的CPU core(后面会详细说明这个状态的意义);
cpu_active_bits,有active的进程正在运行的CPU core。
参考:
Linux CPU core的电源管理(1)_概述: http://www.wowotech.net/pm_subsystem/cpu_core_pm_overview.html
Linux CPU core的电源管理(2)_cpu topology:http://www.wowotech.net/pm_subsystem/cpu_topology.html
以上是关于CPU电源管理——基本概念和topology的主要内容,如果未能解决你的问题,请参考以下文章