【AICon】 如何构建高效的 RAG 系统?RAG 技术在实际应用中遇到的挑战及应对策略?>>> 了解详情
写点什么

CPU 隔离:Full Dynticks 深探

  • 2022-04-02
  • 本文字数:3399 字

    阅读完需:约 11 分钟

CPU 隔离:Full Dynticks 深探

SUSE Labs 团队探索了 Kernel CPU 隔离及其核心组件之一:Full Dynticks(或 Nohz Full),并撰写了本系列文章:

 

1. CPU 隔离 – 简介

2. CPU 隔离 – Full Dynticks 深探

3. CPU 隔离 – Nohz_full

4. CPU 隔离 – 管理和权衡

5. CPU 隔离 – 实践

 

本文是第二篇。

 

我们之前介绍了 linux kernel 定时器中断,以及它在 kernel 内部状态和服务维护中扮演的角色。抖动敏感型工作负载的用户可能希望消除这种高速率事件导致的 CPU 周期盗用和 CPU 缓存清除。

 

然而,停止定时器中断并非易事,因为许多 kernel 组件依赖周期性事件,主要是定时器、定时和调度程序。但有一个例外:当 CPU 空闲时,不需要这种 100~1000 Hz 频率的中断。事实上,当 CPU 无需工作时,就没有任务调度器需要维护,没有定时器排队,也没有定时用户。

 

因此,“节能”自然成为打破周期性定时器的第一个诱因,因为它是专门针对 CPU 空闲状态的优化。CONFIG_NO_HZ_IDLE (https://lwn.net/Articles/223185/)内核选项带来了一种停止周期性中断的机制,并在 CPU 空闲状态时实现。这一重大进展为满足抖动敏感型工作负载的需求铺平了道路,并提供了一个动态中断的基础架构。接下来就是扩展这个功能,以便在 CPU 忙碌的时候,也可以停止时钟中断。然而,目前的技术水平并不能达到人们预期的目标,下一节中介绍的每一个问题都花了几年时间来解决。


时钟中断服务的替代方案


如前文所述,定时的一次性事件(计时器回调)或周期性事件(调度程序、计时、RCU 等)的几个子系统需要时钟中断 。因此,如果我们想在 CPU 运行实际任务时停止时钟中断,则不能忽略那些请求事件。我们必须使用替代方案为它们提供服务,或者在最坏的情况下限制我们的服务。也就是说,对于这些子系统对周期性时钟中断的依赖性,我们必须从以下各种方式中选择哪些是可能且相关的:

 

1.绑定到另一个 CPU


有些工作碰巧在当前 CPU Tick 时执行,但它也可以在另一个 CPU 上执行,而不会出现任何问题。未绑定的计时器就是这样的情况,即未固定到任何 CPU 的计时器。这也间接适用于未绑定的延迟工作队列(https://www.kernel.org/doc/html/v4.10/core-api/workqueue.html),因为它们依赖未绑定的计时器。这些计时器很容易绑定到其他地方,但这是以运行这些未绑定工作的 CPU 投入一些额外开销为代价的。


2.负载到另一个 CPU


Some tick work related to the current CPU is not initially designed to be executed on another CPU but we can manage to do it, usually at some cost. This is the case for RCU callbacks processing and regular scheduler tick.有些与当前 CPU 相关的时钟中断,其最初设计并非是在另一个 CPU 上执行的,但我们可以设法做到这一点,这通常需要付出一定的成本。RCU 回调处理和常规调度程序就是这种情况。


2.1 RCU 回调处理


RCU (https://lwn.net/Articles/262464/)是一种无锁同步机制,一旦保证所有 CPU 都能看到指定的更新,写入程序就可以执行回调。这些回调通常在其排队的 CPU 上执行,即可以来自 softirq 上下文,也可以来自名为“rcuc”的固定内核线程。跟踪和执行这些回调需要时钟中断以轮询它们的队列和内部状态。


为了解决这个问题,一项名为 RCU NOCB 的功能,通过配置内核参数 CONFIG_RCU_NOCB_CPU=y 得以实现。它允许将整个工作从依赖始终中断转移到一组名为“rcuog, rcuop or rcuos”的未绑定的 CPU 的内核线程。

 

这当然会给运行 rcuo[gps] kthreads 和锁定竞争的 CPU 带来特定的开销。


2.2 调度程序时的时钟中断


调度器需要持续收集关于本地和全局任务负载的多项统计信息,从而使其内部状态保持最新。在相当长的时间内,忙碌的 CPU 在进入完全 nohz 模式之前可能有残余的 1 Hz Tick。最终,这些残余的 1 Hz Tick 会转移到未绑定的工作队列中。

 

这也会给运行这些工作队列的 CPU 带来更多开销。


3. 用上下文更改事件替换轮询事件


计时器中断从中断的上下文和频率推导信息。这是“CPU 记账”和“RCU 静态状态报告”两个重要组件的基础。为了在没有中断的情况下处理这些特性,我们需要从上下文变化和时间戳(通常需要一定代价)中推导出这些信息。这读起来可能很抽象,因此,最好在实践中多了解一下。


3.1 Cputime 记账


当在 procfs 文件系统中检查指定进程的 stat 文件时(/proc/$PID/stat : https://man7.org/linux/man-pages/man5/procfs.5.html),可以检索多个上下文的 cputime 统计信息,例如线程在用户空间、内核空间、客户机等中花费的时间。

 

这些数字由调度程序 cputime 记账功能来维护。 Tick 会触发并检查它中断了哪个上下文。如果中断了用户上下文,则一个 jiffy(两次 Tick 之间的时间)将计入用户时间。如果中断了内核上下文,则 jiffy 将被计入内核时间。这种行为如下图所示:


图 3:Dynticks-空闲 Cputime 记账

 

在上例中,我们记录了 2 次用户 Tick 和 6 次内核 Tick。对于 1000 Hz 的 Tick,一个 jiffy 等于 1 毫秒。因此,用户时间记录为 2ms,内核时间记录为 6ms。最终结果总是与在每种环境中的实际时间相近,但通常已经足够好了。Tick 频率越高,cputime 越精确。

 

现在检查一下闲置记账。这种方式不同,因为空闲时间内没有 Tick,因此,我们所能做的就是计算退出空闲状态和进入空闲状态的时间戳之间的差。


为了能够在运行非空闲任务并且 Tick 停止时对用户和内核 CPU 使用时间进行记账,我们必须将空闲记账逻辑扩展到用户/内核记账中。如下所示:


图 4:Full dynticks Cputime 记账


在这里,内核时间可以通过用户进入空闲状态的时间戳减去提出空闲状态的时间戳来检索。同时,在 idle_enter 之前和 user_exit 之后发生的任何事情都要加在其中。用户时间是用户进入和用户退出空闲状态之间的差,它的计算非常简单,甚至比基于 Tick 的记账更加精确。

 

但这带来了一个问题:为什么不在 Tick 运行时一直使用这种解决方案呢?


因为每次在我们跨越用户/内核边界时,需要读取精确但可能提取很慢的硬件时钟。通用工作负载经常遇到这种情况,从而产生性能损失。因此,这种无 Tick 的记账必须保留给将其条目在内核的工作负载。


3.2 RCU 静止状态报告


当 RCU 写者程序发布更新并将回调排队等待执行时,它必须等待所有 CPU 报告新的“RCU 静止状态”。这意味着 CPU 已经通过了不属于受保护 RCU 读者程序的代码,称为“RCU 读取端临界区”。

 

实际上,rcu_read_lock() 和 rcu_read_unlock()之间的任何代码(或任何不可抢占的代码)都是“RCU 读取端临界区”;其他剩下的都是“RCU 静止状态”。

 

要追踪静止状态,RCU 依赖 Tick 并检查它中断了哪个上下文。如果中断了不在 rcu_read_lock()/rcu_read_unlock()对保护部分内的代码,它报告静止状态。如果中断了用户空间,它也被认为是静止状态,因为用户空间不能使用内核 RCU 子系统。


图 5:Dynticks-空闲 RCU 静止状态报告

 

上图还说明了 tick-deprived idle 任务如何从特殊处理方式中再次受益。空闲 CPU 不是主动报告静止状态,而是通过进入“RCU 扩展静止状态”被动报告。它在进入和退出空闲状态时递增一个具有完整内存屏障的原子变量。

 

然后,等待所有 CPU 报告静态状态的 RCU 最终会扫描未响应的 CPU,以找出扩展的静态状态,并代表这些 CPU 报告静态状态。

 

这种模式之所以有效,是因为我们知道空闲上下文不使用 RCU。我们知道用户空间具有相同的属性,因此,当运行非空闲任务的时候停止 Tick 时,这种被动报告方案可以扩展到用户空间中:


图 6:Full-dynticks RCU 静止状态报告

 

由于 CPU 很少在内核中花费太多时间,因此,上述提议将取代基于 Tick 的静止状态报告。RCU 扩展的静止状态要么在其间出现短暂的延迟,要么就持续很长时间。

 

与 cputime 记账类似,这同样有一个问题:为什么即使在 Tick 运行时也不采用这种模式?

 

因为这将在每个用户/内核往返过程中产生一个代价高昂的原子操作,并且会有一个完整的内存屏障。此外,报告静态状态的责任最终由其他 CPU 承担。

 

4. 如果没有其他选择,则继续使用 Tick


如果没有周期性事件或者频繁事件,有些情况根本无法解决。例如,调度程序任务抢占就是如此。为了保证本地公平性,调度程序必须能够在多个任务之间共享 CPU,并定期检查是否需要抢占。因此,在 CPU 上运行单个任务是在空闲上下文中进一步停止 Tick 的要求。其他子系统也可能会请求定期 Tick,从而在某些情况下保持运行:posix cpu 计时器、perf 事件等。我们将进一步探讨这些细节。

 

您可以看到,在运行实际任务时,完全停止 Tick 是可能的,但会出现很多陷阱,用户必须准备做好一些权衡。我们将在下一篇文章中详细解释。

2022-04-02 18:073574

评论

发布
暂无评论
发现更多内容

关于数据导入,教你几招

Simon

MySQL

BAT同系列公司面试总结,哪些你所不知道的,学习android的好书

android 程序员 移动开发

(完整版)直播回顾:2021 MAXP 无服务器赛题讲解

亚马逊云科技 (Amazon Web Services)

人工智能 云计算 创新大赛

ButterKnife被弃用,ViewBinding才是findView的未来?,秀出天际

android 程序员 移动开发

Android高阶:了解这些知识点,学习Binder就不成问题(1)

android 程序员 移动开发

基线模型开源分享及深度讲解 | 2021 MAXP 直播第二讲:基于DGL的图机器学习任务

亚马逊云科技 (Amazon Web Services)

人工智能 图神经网络 创新大赛

APP瘦身大法--AndResGuard的使用,android地图开发框架

android 程序员 移动开发

App黑白化实现扩展,一键护眼模式,给App,安卓事件分发机制面试

android 程序员 移动开发

Android:手把手教你实现在XML中配置网易云歌手详情滑动效果

android 程序员 移动开发

Android:金九银十怎么从中小企业挤进一线大厂?大厂面试题问的深度

android 程序员 移动开发

AsyncTask相关知识,安卓工程师面试题及答案

android 程序员 移动开发

Butterknife源码分析,android开发环境搭建实验报告

android 程序员 移动开发

BAT资深面试官-带你破解Android高级面试,渣本逆袭大厂面经分享

android 程序员 移动开发

Android高级面试题大全(持续更新中),字节跳动厂内部超高质量Flutter+Kotlin笔记

android 程序员 移动开发

Android:怎么看待大厂面试门槛越来越高,,让你明明白白的使用RecyclerView

android 程序员 移动开发

一个递归调用引发的 “血案”

神策技术社区

App怎么做才能永不崩溃,一文详解

android 程序员 移动开发

BAT面试有关散列(哈希)表的面试题详解,flutter图片压缩上传

android 程序员 移动开发

BroadcastReceiver官方概览,【面试总结

android 程序员 移动开发

BroadcastReceiver源码分析,一线互联网大厂中高级Android面试真题收录

android 程序员 移动开发

Android高阶:了解这些知识点,学习Binder就不成问题,androidapp开发教程推荐

android 程序员 移动开发

Android:年过35岁的程序员还有出路吗?面试了一个-46-岁程序员后

android 程序员 移动开发

深入剖析Redis客户端Jedis的特性和原理

vivo互联网技术

数据库 redis Jedis 集群

App 竟然是这样跑起来的 —— Android App_Activity 启动流程分析

android 程序员 移动开发

这个深秋,StarRocks喊你一起来撸码 | StarRocks Hacker Meetup 报名开启

StarRocks

数据库 Meetup StarRocks

APP瘦身大法--AndResGuard的使用(1),为什么阿里的程序员成长如此之快

android 程序员 移动开发

Base64 的原理、实现及应用,面试字节跳动Android工程师该怎么准备

android 程序员 移动开发

Android:三四十岁的大龄程序员如何对后辈评价“太水技术低

android 程序员 移动开发

Android:让你明明白白的使用RecyclerView—,retrofit优点

android 程序员 移动开发

App基于手机壳颜色换肤?先尝试一下用 KMeans 来提取图像中的主色

android 程序员 移动开发

BAT常见Android面试20题详解,985研究生入职电网6个月

android 程序员 移动开发

CPU 隔离:Full Dynticks 深探_硬件_Frederic Weisbecker_InfoQ精选文章