最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一文解析Menu Governor

2023-05-12 16:07 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

在現(xiàn)代操作系統(tǒng)中,往往很多時(shí)候并不需要去執(zhí)行cpu密集型的任務(wù),而每當(dāng)這個(gè)時(shí)候,如果去持續(xù)的執(zhí)行循環(huán)去等待新的任務(wù)發(fā)過來,那需要消耗巨大的能量。所以設(shè)計(jì)人員設(shè)計(jì)出一種空閑狀態(tài)以此CPU進(jìn)入低功耗模式。在Linux系統(tǒng)中,系統(tǒng)中的程序在CPU上運(yùn)行,當(dāng)執(zhí)行完成后便讓出CPU,而這個(gè)時(shí)候CPU無需執(zhí)行任何程序,并且也沒有任何中斷、異常信號(hào)發(fā)過來,CPU便會(huì)進(jìn)入一種空閑的狀態(tài),一般稱這種狀態(tài)為cpu idle狀態(tài)。

一、 CPU idle 框架概述

CPU idle框架主要分為cpu idle governor,cpu idle driver,cpu idle core。

cpu idle governor,cpu idle driver,cpu idle core三者的關(guān)系如下圖所示:



CPU調(diào)度器發(fā)現(xiàn)沒有任務(wù)在運(yùn)行時(shí),會(huì)切換到idle進(jìn)程,通過cpuidle_idle_call接口調(diào)到cpuidle framework中,cpuidle framework內(nèi)部會(huì)選擇適當(dāng)?shù)牟呗栽跊Q定進(jìn)入哪種狀態(tài),然后回調(diào)到driver端實(shí)現(xiàn)。

當(dāng)CPU進(jìn)入idle狀態(tài)后,CPU將停止時(shí)鐘并且部分硬件將會(huì)停止使用,以此來減少CPU所消耗的能量。但是在這種情況下,該CPU的性能會(huì)受到很大限制。控制好CPU如何進(jìn)入/退出CPU idle深度(即C state)是CPU idle子系統(tǒng)中一個(gè)關(guān)鍵點(diǎn)。

C state根據(jù)不同的深度會(huì)存在不同的退出延遲和功耗,如下圖所示


本文主要是對(duì)CPU idle governor的一個(gè)粗略介紹。本文所有代碼選自Linux Kernel5.0.7。

二、 CPU idle 進(jìn)入/退出流程簡述

Linux系統(tǒng)啟動(dòng)的時(shí)候,會(huì)在每一個(gè)CPU上創(chuàng)建對(duì)應(yīng)的cpu idle線程。系統(tǒng)初始化完成后,將init線程轉(zhuǎn)化為idle線程。在init/main.c中start_cpu()函數(shù)最后會(huì)調(diào)用 arch_call_rest_init()將init進(jìn)程轉(zhuǎn)化為idle進(jìn)程,最終進(jìn)入到cpu_startup_entry()中進(jìn)入到無限的idle loop中。


在do_idle()中,代碼會(huì)不斷地輪詢,判斷當(dāng)前系統(tǒng)是否需要調(diào)度,如果系統(tǒng)當(dāng)前不需要調(diào)度,則進(jìn)入到idle狀態(tài)。

do_idle()->cpuidle_idle_call()->cpuidle_select()

進(jìn)入cpuidle流程后,會(huì)根據(jù)系統(tǒng)中對(duì)應(yīng)governor策略進(jìn)而選擇不同的idle state。



系統(tǒng)在選擇完idle state后,還會(huì)調(diào)用cpuidle_reflect()將選取過程中一些信息和結(jié)果保留下來,以備下一次選取使用。

在進(jìn)入idle狀態(tài)后,CPU會(huì)調(diào)用WFI指令(wait for interrupt),直到有中斷到來,系統(tǒng)就會(huì)退出idle狀態(tài)。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??



三、CPU idle governor

1.綜述

在實(shí)際CPU運(yùn)行環(huán)境中,不同的CPU他們對(duì)idle狀態(tài)的需求和進(jìn)入/退出方法會(huì)存在差別,而這其中功耗和退出延遲成為了在idle調(diào)度過程一組不可調(diào)和的矛盾,如何保證在滿足性能需求的前提下盡可能的節(jié)省功耗成了CPU idle子系統(tǒng)的一個(gè)重要組成部分。CPU idle governor在整個(gè)CPU idle子系統(tǒng)中負(fù)責(zé)提供如何使用CPU idle的策略。

內(nèi)核中提供了兩種策略:Menu和Ladder。選擇哪種調(diào)度器,取決于內(nèi)核的配置,其中關(guān)鍵點(diǎn)是系統(tǒng)調(diào)度的tick是否可以被空閑循環(huán)停止。在系統(tǒng)初始化過程中,menu和ladder分別通過cpuidle_register_governor()注冊(cè)到系統(tǒng)中。

ladder governor會(huì)首先進(jìn)入最淺的idle state,然后如果待的時(shí)間足夠長,則會(huì)進(jìn)入到更深一級(jí)的idle state,以此類推,直到到達(dá)最深的idle state。當(dāng)被喚醒時(shí),會(huì)盡可能快地重新啟動(dòng)CPU;等到下次空閑,則又會(huì)從idle state1開始進(jìn)入。它往往用于periodic timer tick system。

而在tickless system中,ladder可能會(huì)存在沒有機(jī)會(huì)進(jìn)入到更深一級(jí)的idle狀態(tài)中,引起功耗損失,所以這個(gè)時(shí)候往往會(huì)使用menu調(diào)度器。menu調(diào)度器則不一定遵守由淺入深的規(guī)則,如果深度的idle state更好,那么就會(huì)直接進(jìn)入到深度的idle state。

由于主流系統(tǒng)中常采用tickless system,本文重點(diǎn)介紹menu governor。

對(duì)于menu調(diào)度器,存在兩種決定idle深度(下稱C state)的因素

(1)能量平衡點(diǎn)(停留時(shí)間)

在進(jìn)入/退出C state時(shí),系統(tǒng)會(huì)消耗一定的能量,所以頻繁進(jìn)出C state不是一件能帶來收益的事情,調(diào)度器在考慮進(jìn)入C state的時(shí)候,會(huì)考慮進(jìn)入該C state的預(yù)計(jì)持續(xù)時(shí)間。

(2)性能影響(系統(tǒng)延遲容忍度)

對(duì)于C state來說,退出C state會(huì)存在巨大的延遲,這會(huì)極大影響性能。因此對(duì)于調(diào)度器來說,系統(tǒng)越忙,C state就越不能被接受,系統(tǒng)的工作負(fù)載也被納入決策因素中。

而以上兩個(gè)因素,menu governor的職責(zé)具體到實(shí)際情況中,便轉(zhuǎn)換為了兩個(gè)任務(wù):1.預(yù)測(cè)C state的停留時(shí)間。2.計(jì)算系統(tǒng)延遲容忍度

在struct cpuidle_state中使用target_residency來記錄該C state下的停留時(shí)間閾值。在選擇過程中,會(huì)計(jì)算出預(yù)計(jì)停留時(shí)間(predicted_us)和備選的C state中的target_residency進(jìn)行比較,選取其中滿足停留時(shí)間大于target_residency的C state。

選取時(shí),先通過pm qos計(jì)算出系統(tǒng)此時(shí)的系統(tǒng)容忍度(latency_req),接著在所有exit_latency小于latency_req的C state中選擇power_usage最小的那個(gè)state。

2.核心結(jié)構(gòu)體

C state的結(jié)構(gòu)體如下:



  • name:該state 的名稱

  • desc:該state的簡介

  • exit_latency:表示退出該state的延遲,單位us

  • power_usage:表示該state下的功耗

  • target_residency:期望停留時(shí)間,單位us

  • enter:進(jìn)入該state的回調(diào)函數(shù)

menu governor的結(jié)構(gòu)體如下:



  • last_state_idx:記錄上一次進(jìn)入的idle深度

  • need_update:在系統(tǒng)每次從C state返回時(shí),會(huì)調(diào)用reflect接口,用于考慮這次state切換的結(jié)果,menu governor的reflect接口會(huì)將need_update設(shè)置為1,在下次進(jìn)入select時(shí)對(duì)idle信息進(jìn)行更新

  • tick_wakeup:記錄上次退出C狀態(tài)是否是被tick喚醒

  • next_timer_us:記錄距離下一個(gè)tick到來的時(shí)間

  • bucket:記錄在當(dāng)前的校正因子的位置

  • correction factor:保存校正因子的數(shù)組

  • intervals、interval_ptr:計(jì)算標(biāo)準(zhǔn)差時(shí)所采用的停留時(shí)間

3.核心函數(shù)

menu governor的menu_select()的核心部分如下:



在計(jì)算predict的過程中,menu governor會(huì)將下一個(gè)tick到來的時(shí)間點(diǎn)距離此刻的時(shí)間(next_timer_us)作為一個(gè)基礎(chǔ)的predicted_us,并在這個(gè)基礎(chǔ)上調(diào)整。

首先,因?yàn)閜redicted_us并不總是與next_timer_us直接相等,在等待下一個(gè)tick的過程很有可能被其他時(shí)間所喚醒,所以需要引入校正因子(correction factor)矯正predicted_us。此校正因子從對(duì)應(yīng)的bucket索引中選取。

menu governor使用了一組12組校正因子來預(yù)測(cè)空閑時(shí)間,校正因子的值基于過去predicted_us和next_timer_us的比率,并且采用動(dòng)態(tài)平均算法。另外對(duì)于不同的next_timers_us,校正因子的影響程度是不一樣的;對(duì)于不同的io wait場(chǎng)景,系統(tǒng)對(duì)校正因子也有著不同的敏感程度 。

隨后嘗試通過最近的8個(gè)過去的停留時(shí)間來查找重復(fù)間隔,如果他們的標(biāo)準(zhǔn)差小于一定閾值,則將這8個(gè)時(shí)間的平均值作為predicted_us。

最后取以上兩個(gè)流程中的最小值。

對(duì)于系統(tǒng)容忍度,menu governor使用性能乘數(shù)(performance multiplier)、預(yù)計(jì)停留時(shí)間(predicted)和系統(tǒng)延遲需求(latency requirement)來找出最大退出延遲。系統(tǒng)延遲需求作為第一個(gè)系統(tǒng)延遲容忍度;通過公式(1)計(jì)算出另外一個(gè)系統(tǒng)容忍度:predicted_us / (1 +10 * iowaiters)

*iowaiters指當(dāng)前cpu上iowait的任務(wù)數(shù)

取前面兩個(gè)系統(tǒng)容忍度中最小值作為最小的系統(tǒng)容忍度。

最后根據(jù)前面計(jì)算出來的兩個(gè)因素來選取具體的idle state,將計(jì)算出的predicted_us與所有idle狀態(tài)的停留時(shí)間進(jìn)行比較,選擇特定idle狀態(tài)的條件是相應(yīng)的停留時(shí)間應(yīng)小于predicted_us。另外,將狀態(tài)的exit_latency與系統(tǒng)的交互性要求進(jìn)行比較。基于兩個(gè)等待時(shí)間因素,選擇適當(dāng)?shù)目臻e狀態(tài)。

在cpu退出idle狀態(tài)后,menu governor會(huì)將將上一輪的進(jìn)入idle狀態(tài)的數(shù)據(jù)更新到menu driver中,作為下一次select的參數(shù)。



下一次進(jìn)入選擇流程時(shí),會(huì)先觸發(fā)更新需求,即進(jìn)入到menu_update()中



在更新信息時(shí),會(huì)嘗試算出進(jìn)入idle狀態(tài)到被喚醒經(jīng)歷了多長時(shí)間。

①如果cpu被tick喚醒,而且上次記錄的next_timer_us大于了一個(gè)tick的時(shí)間,那么governor就假定cpu已經(jīng)空閑了很長時(shí)間,則measured_us為9 * MAX_INTERESTING / 10(INTERESTING=50000)

②如果cpu退出了輪詢狀態(tài),會(huì)導(dǎo)致選擇該狀態(tài)的空閑持續(xù)時(shí)間不準(zhǔn)確,故將next_timer_us作為measured_us

③除此之外,measured_us將使用驅(qū)動(dòng)中記錄的上次idle狀態(tài)中停留時(shí)間

算出來之后再減去退出延遲,然后與next_timer_us取最小值,便得出了最終的measured_us。

接下來是計(jì)算下一次選擇校正因子(correction factor)的值

將上一次的校正因子先衰減一次,然后加上一個(gè)predicted_us和next_timer_us的比值

new_factor += RESOLUTION * measured_us / data->next_timer_us;

(RESOLUTION=1024)

最后就可以將這兩個(gè)值更新到governor的驅(qū)動(dòng)中。


原文作者:內(nèi)核工匠


一文解析Menu Governor的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
密云县| 阿拉善右旗| 夏邑县| 双峰县| 本溪| 百色市| 固安县| 涪陵区| 湖州市| 南澳县| 繁昌县| 齐河县| 濮阳市| 如东县| 磐石市| 静海县| 平度市| 泸州市| 盐边县| 武汉市| 福州市| 喀什市| 伊金霍洛旗| 满洲里市| 汶上县| 永定县| 巍山| 佛坪县| 北流市| 平南县| 满洲里市| 绥德县| 巴东县| 双鸭山市| 六枝特区| 新巴尔虎右旗| 沽源县| 开平市| 南靖县| 沙湾县| 正定县|