目录
目录README.md

决赛项目:位于分支v8

项目文档:分支v8 ——ARM-NUMA项目说明书.docx

演示视频:分支v8 ——演示视频.mp4

sched-ext调度器:分支v8 ——/scx_simple.bpf.c

/scx_simple.c

LD挂钩程序: 分支v8——/read_test1/LDcode/log_read.cpp

1. 问题概述

1.1 赛题说明

ARM 处理器(譬如鲲鹏 920)相较于常见的 x86 处理器,其 CPU 拓扑结构与 NUMA 层级相对复杂。在程序启动和运行过程中,需要在调度和内存管理上充分做到 NUMA 亲和,才能发挥处理器的最大性能。

举例来说,鲲鹏 920 处理器一个 CPU 上有 2 个 DIE,每个 DIE 上有若干个物理 core,构成一个 NUMA 域。在每个 NUMA 域当中,若干个物理 core 又进一步组成一个 cluster,进一步增强 cache 亲和性。此外,不同 NUMA 域之间访问时延也不同。再考虑到多 CPU 系统,会进一步加剧这种复杂性。

当前较新的 Linux 内核(6.12+)支持用户态调度(sched_ext),在 openEuler 24.03 SP1+ 上也实现了类似的功能。通过用户态调度机制,允许用户在用户空间动态加载自定义的调度策略,结合 NUMA 亲和的内存管理(分配、迁移、缓存等),可以对运行的应用实现最佳 NUMA 亲和的调度与内存管理,提升应用性能。

1.1.1 问题要求

  • 基于较新的 Linux 内核(6.12+)或者 openEuler 24.03 LTS SP1 系统(6.6 内核,已实现类似 sched_ext 的可编程调度机制)和某一款 ARM 处理器平台作为执行与验收环境。
  • 对典型多进程/多线程业务场景,如 MySQL,PostgreSQL,Nginx,Redis(6.x+),Spark,Hadoop 等,进行性能优化。不对应用进行修改,只能对 OS 系统进行优化(如果确实涉及到对 GCC、JDK 等编译器/运行时的合理配置,可酌情适当进行调整)。
  • 通过上游 Linux 内核提供的 sched_ext 接口或者 openEuler 提供的可编程调度接口实现用户态自定义调度器,实现业务亲和的自适应调度调优能力。
  • 改进系统自带的 numa balance 工具或者实现新的 numa 调优工具,结合上述用户态调度机制实现对应用的性能优化。
  • 可根据需要对内存管理库进行调优。例如在 glibc 自带的内存管理库(ptmalloc)或者 tcmalloc、jemalloc 上进行改进,进一步提升内存分配、释放、缓存等管理能力。
  • 用例要包含物理机、裸机容器,虚机容器场景,要支持测试自动化执行。
  • 需要提供完整的测试报告,包含测试用例、测试方法、调优前后数据对比等内容。

1.1.2 本项目的特色之处

(1) 采用两层调度,确保了高速 I/O 介质上的忙等待不会过度抢占计算密集型进程的 CPU

  • 当应用同时存在以下两类进程时:

    1. I/O 密集型进程 (I/O-Bound):高频轮询设备(如 100Gb 网卡 / NVMe SSD)
    2. 计算密集型进程 (CPU-Bound):需要持续占用 CPU 进行数值计算

    传统 CFS 调度器会导致 I/O 线程因忙等待频繁抢占计算线程,被抢占线程可能被迁移到非最优 NUMA 节点,跨 NUMA 内存访问激增,有效内存带宽下降 40% 以上。

  • 针对这种现象,提出了双层调度方法:

    1. I/O 线程隔离调度:将 NVMe 轮询 / 网络收包等 I/O 线程放入专用调度队列,分配专用核心运行,不与计算型线程争用核心。
    2. 计算线程保证 NUMA 亲和性:为计算线程分配充足运行资源,避免跨 NUMA 干扰。

(2) I/O 映射 CPU 自适应硬件线程分配

  • 传统 I/O 绑定存在两大局限:

    1. NUMA 本地性困境:固定绑定无法适应动态负载变化,NUMA 位置不匹配时延迟激增。
    2. 资源利用率瓶颈:静态分配浪费 CPU 资源,I/O 线程效率不会随 CPU 数量线性提升,甚至会下降。
  • 提出的改进方法:

    1. 自动识别 I/O 线程设备物理位置,动态 NUMA 绑定。
    2. “慢启动 + 吞吐量监控”方式分配核心,逐步增加分配并实时探测性能瓶颈,实现弹性扩缩容。

(3) 基于有效执行时间的完全公平调度 + NUMA 本地性

  • 传统 CFS 在复杂 NUMA 系统中的问题:

    1. 公平性陷阱:只按 vruntime 分配 CPU 时间,忽略跨 NUMA 成本。
    2. 本地性困境:NUMA 优化破坏公平性,本地进程可能独占 CPU,远端进程饥饿。
  • 改进方法:

    • 按 NUMA 节点建立调度队列(DSQ),根据线程亲和性分配到对应 DSQ,DSQ 内部继续采用 CFS 保证公平性。

(4) 基于 LD_PRELOAD 的系统调用挂钩

  • 传统 I/O 模式:应用直接调用 glibc 发起系统调用,缺乏优化机会。
  • 改进方法:
    • 利用 LD_PRELOAD 动态链接挂钩透明拦截 libc I/O 调用,将其封装为 request 对象,统一交由用户态调度框架处理。
    • 支持 futex、共享内存、用户级中断等多种调度模式。
    • 支持函数符号劫持、请求对象化、可扩展的调度策略(批量、延迟、合并)。

1.1.3 当前指标达成情况

评分项 评分细则 现有指标 分值
基本调度功能 完成基本功能,包括自定义调度器以及 NUMA 调优服务 实现了自定义调度器,保证 NUMA 本地性,并提供 baseline Sched_ext_RR 参照 40
性能提升 >10% 基本,>15% 优秀,>20% 杰出,占 30%,额外加分可达 5%~10% I/O 吞吐量提升 40%~50%,CPU 占用率减少 75%;计算负载吞吐量提升 27% 30
调度管理优化 调度管理优化 实现基于 LD_PRELOAD 的透明异步 I/O 拦截与调度框架,统一管理与调度应用 I/O 请求 10

1.1.4 相较于初赛的改进

(1) 基于 LD_PRELOAD 的系统调用挂钩

  • 透明拦截 pread/pwrite 等系统调用,封装为 request 对象并队列化调度。
  • 缓解高并发下系统调用频繁、上下文切换和锁竞争问题。
  • 改进点:
    1. 降低系统调用频率(批量调度)
    2. 减少锁竞争与抖动(延迟/批量处理)
    3. 提升缓存与 TLB 局部性
    4. 优化 IO/计算线程分离调度,避免相互干扰

(2) 基于 LD 挂钩负载与 CPU 利用率的动态核心分配算法

  • LD 挂钩程序在初始化时自命名,调度器识别后加入 special 队列,运行在专用核心上。
  • 挂钩程序统计 IO 负载信息并写入共享内存,调度器实时监控并动态调整分配核心数。
  • 其余 NUMA 队列按平均 CPU 利用率负载均衡,保证资源最大化利用。
关于
2.9 GB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

©Copyright 2023 CCF 开源发展委员会
Powered by Trustie& IntelliDE 京ICP备13000930号