当前位置: 首页 > news >正文

sched-domain

CPU拓扑

调度域和cpu的拓扑结构密切相关,cpu拓扑结构的相关代码位于:

  • kernel/sched/topology.c
  • include/linux/sched/topology.h
  • drivers/base/arch_topology.c
  • include/linux/arch_topology.h

For RISC-V & ARM64 systems, the CPU topology is generated by reading the “cpu-map” node from the device tree.

cpu_topology数据结构

//include/linux/arch_topology.h

struct cpu_topology {

    int thread_id; //CONFIG_SCHED_SMT

    int core_id;

    int package_id; //packages (clusters)

    int llc_id; //last level cache, Currently only supported on ARM64 using ACPI

    cpumask_t thread_sibling;

    cpumask_t core_sibling; //用于表示一个cluster内的所有兄弟cpu的bit mask

    cpumask_t llc_sibling; //A bit mask of packages that share the last level cache

};

内核中有一个全局数组来保存cpu topology table:

drivers/base/arch_topology.c

/*

 * cpu topology table

 */

struct cpu_topology cpu_topology[NR_CPUS];

EXPORT_SYMBOL_GPL(cpu_topology);

CPU Capacity

The following values ​​are read and calculated through the device tree.

  • capacity-dmips-mhz” property value
    • Save in raw_capacity[].
    • The maximum value is stored in capacity_scale.
  • It is simply calculated as follows:
    • cpu_scale[] = raw_capacity[] / capacity_scale

系统以所有cpu core中最大的capacity作为capacity_scale,所有cpu以该值来作为归一化处理

cpu_topology初始化

下图以4个cpu为例,0、1核属于little cluster,2、3核属于big cluster:

注意:上图中,cpu_topology数据结构的初始化,只进行了红框中成员的初始化。如右下角表中thread_siblingcore_sibling等都属于未初始化状态!

如果cpu topology没能从device tree中获取,则还可以通过mpidr寄存器获取,如下图:

注意:store_cpu_topology()有从mpidr获取cpu topology的功能(如果已经从dts中获取,则跳过相关逻辑),更重要的是获取sibling信息(update_siblings_masks()! 每一个booted cpu都要调用该函数!

调度域和调度组

:本节中load balance的“scheduling group”和cgroup中的“group scheduling”是完全不相关的两种技术!

scheduling domain topology

ARM64 架构一般按照以下顺序创建一个调度域topology:

  • SMT
    • Gives more priority to CPUs that share the L1 cache (virtual core)
    • It is the cheapest because it does not require flushing the cache.
    • arm64 is not utilized yet.
    • Using the CONFIG_SCHED_SMT kernel option
  • MC
    • Next, we give priority to CPUs within the cluster that share the L2 cache.
    • If there are clusters such as big/little, use this option to manage them by cluster unit.
    • Using the CONFIG_SCHED_MC kernel option
  • DIE
    • Next, it gives priority to CPUs that use the same die (sharing the L3 cache).
    • Most systems with less than a few cores, but not multi-clusters, typically only use this step.
  • NUMA
    • NUMA levels can use multiple levels depending on the NUMA distance.
    • Gives priority to the CPU using the shortest path across NUMA nodes.
    • Using the CONFIG_SCHED_NUMA kernel option

下面是几种常见的cpu拓扑结构:

如下是内核中定义的default topology:

/*

 * Topology list, bottom-up.

 */

static struct sched_domain_topology_level default_topology[] = {

#ifdef CONFIG_SCHED_SMT

    { cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },

#endif

#ifdef CONFIG_SCHED_MC

    { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },

#endif

    { cpu_cpu_mask, SD_INIT_NAME(DIE) },

    { NULL, },

};

如下是内核中定义的arm topology

static struct sched_domain_topology_level arm_topology[] = {

#ifdef CONFIG_SCHED_MC

    { cpu_corepower_mask, cpu_corepower_flags, SD_INIT_NAME(GMC) },

    { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },

#endif

    { cpu_cpu_mask, SD_INIT_NAME(DIE) },

    { NULL, },

};

Initialize scheduling domains

kernel_init() -> kernel_init_freeable() -> sched_init_smp() ->sched_init_domains(cpu_active_mask)

构建调度域,主要分为以下几步:

  1. __visit_domain_allocation_hell:分配和初始化调度域拓扑结构(根据cpu_mapcpu topology),包括root domain
  2. build_sched_domain:构建调度域(for_each_cpu<for_each_sd_topology>
  3. build_sched_groups:构建调度组(for_each_cpu
  4. init_sched_groups_capacity:初始化调度组的capacity
  5. cpu_attach_domainattach调度域(for_each_cpu

分配和初始化调度拓扑

__visit_domain_allocation_hell——》__sdt_alloc

该函数会根据具体CPU架构的调度域拓扑(比如,arm架构一般只有两级——MCDIE,来分配percpu的sched_domain, sched_group, and sched_group_capacity等结构。下图是以DIE level来呈现,初始化后的数据结构关系:

如上图中sched_domain_topology_level的data结构的子成员都是percpu属性的二级指针,会为该level调度域中的每个cpu分配sd、sg以及sgc等结构空间。

下图是描述如何分配和初始化root domain:

上图中,init_dl_bw、cpudl_init和cpupri_init是初始化deadline调度器的相关成员。

构建调度域

为每个cpu自下而上构建调度域结构:

for_each_cpu

for_each_sd_topology

如下是3 level的调度域结构图,其中的span成员表示该调度域管辖的cpu bitmap最底层sched_domain结构指针(这里是SMTarm结构是MC)保存在percpurunqueuesd成员中(参见cpu_attach_domain())。

sd_init()是具体负责初始化sched_domain结构的函数,下图展示了sched_domain初始化后的数据结构:

下图是sd_init() 初始化后,各level的sched_domain的sd_flags值:

构建sched_groups

构建sched groups主要在build_sched_groups() 函数中进行,其会percpu、per_sched_domain_level进行初始化。下图是一个2 clusters * 2 cores = 4 cpus的一个示例,展示了sched_group的构建过程和数据结构关系。

需要注意的是,在一个sched_domain_topology_level级别内(span),所有的sched_group双向链接成环,并被该level的所有sched_domain共享(span)!

下图则展示了2 clusters * 2 cores * 2 hw-threads = 8 cpus架构的sched domain和group的关系:

下图是一个2 clusters * 2 cores = 4 cpus架构get_group()函数执行的一个示例(看看就行^^):

初始化调度组的cpu_capacity

sched_group_capacity用于指示一个调度组的所有cpu的容量和(参照前面cpu capacity章节),在负载均衡场景,作为均衡一个调度域中不同调度组负载的一个依据。

下图中cluster0包含两个cpu,capacity分别为1535、1535;而cluster1包含的两个cpu的capacity分别为430、430。所以在DIE级别的sgc[0]的sched_group_capacity即为1535+1535=3070;而sgc[1]的sched_group_capacity则为860。

关联cpu和调度域

这个步骤非常简单,由cpu_attach_domain()函数完成,主要是将sched_domain_topology_level最底层的domain以及root domain与cpu的runqueue关联。

这里还做了一个逻辑,就是将sched domain tree中不参与调度或者在调度中没有贡献的域删除,具体参见

sd_parent_degenerate()和sd_degenerate()函数。

example

下面给出一个示例:共有3个cluster

cluster-0: cpu0-cpu2,小核

cluster-1: cpu3-cpu6,中核

cluster-2: cpu7,大核

其sched_domain/sched_group情况如下图:

注意:

  1. 每个cpu rq的sd指向的最低层次的sched domain, 这里指向的是MC domain
  2. 每个cpu 都有自己的sched domain实例,即sd地址不一样,cpu-0 MC和cpu-1/2 MC的sd地址不一样
  3. 每个相同level、相同sched domain中sg是共享的;即cpu-0/1/2 MC domain共享一个sg0, sg1, sg2双向链表;cpu-3/4/5/6 MC domain共享一个sg3, sg4, sg5, sg6双向链表;而cpu-0/1/2/3/4/5/6/7 DIE domain共享一个sg012, sg3456, sg7双向链表。参见前面构建sched groups章节。
  4. cpu7比较特别,由于cluster2中只有一个cpu7,所以MC domain没必要存在,退化了,只有一个DIE domain了
  5. 每个cpu sched_domain groups指向比较有意思,指向包含该cpu的sg,后续load balance相关逻辑会依赖这个
http://www.dtcms.com/a/423966.html

相关文章:

  • 企业网站建设中企动力免费的网页游戏
  • python(77) python脚本与jenkins pipeline交互的5种方式
  • 网站多久备案一次百度灰色关键词排名
  • 内江建设局网站注册网站刀具与钢材范围
  • 如何将安卓应用迁移到鸿蒙?
  • wordpress商业网站wordpress虚拟
  • dede 网站名称 空的团员建设网站
  • C++(Qt)软件调试---Linux动态库链接异常排查(38)
  • 记录 Qt 跨线程 信号无法触发槽函数问题
  • wireshark 01——安装
  • 网上最好购物网站邯郸网上销售公司
  • 使用top域名做网站seo职位是什么意思
  • CUDIS 健康协议在 Sui 上打造更健康的未来
  • 装修网站排行榜前十名有哪些南昌网站建设哪家最好
  • Golang学习笔记:context的使用场景
  • 带有客户案例的网站广州专业网站建设报价
  • 昆明微信网站建设软件开发模型有几种并简述其特点
  • 高效实现实体删除的宏解决方案:使用Rust宏优化删除操作
  • Rust泛型详解
  • 官方手表网站网站专题分类
  • 新乡网站建设方案搜狗网址大全下载安装
  • 关于可视化卷积核和特征图的深度理解
  • 【mysql】Mybatisplus BINARY {0} LIKE CONCAT(‘%‘, {1}, ‘%‘)写这句话是什么意思
  • 开发避坑指南(59):Vue3中高效删除数组元素的方法
  • wordpress建站要用模板吗wordpress搜索筛选
  • 安卓 WPS Office v18.21.0 国际版
  • 衡阳网站推广优化公司行业网站开发运营方案
  • 临海房产中介网站如何制作网站平台管理
  • 做网站多少人建e室内设计网官网平面图
  • git mere 错误后的回滚处理