CPU 就和皮鞋廠的工人一樣, 無可奈何之時也得躺平。歷代CPU的架構(gòu)師都有一顆仁慈的心——給自己的產(chǎn)品留下了躺平的功能,而且是一代更比一代強。相關(guān)的指令有HLT/PAUSE/MWAIT/UMWAT/TPAUSE,其中我最喜愛的是UMWAIT,它的妙處我們后面再說。
當(dāng)然經(jīng)理并不會輕易讓CPU工人去摸魚, 必須滿足一定的條件。Linux 內(nèi)核中那么嚴(yán)格說來是由Scheduler 來判斷目前的工作量是否飽滿。如果工作量實在不夠,也只好讓CPU劃劃水, 睜只眼閉只眼, 好歹省點電費不是。雖然在CPU層面摸魚的手段花樣百出, 但是在OS層面只有一個抽象的概念就是IDLE。在這個時候經(jīng)理表面上放任CPU工人劃水, 其實打的是省電的小九九,這也算是Win-Win的帕累托改進。那么問題就來了, Scheduler 到底是如何判斷當(dāng)前工作量不飽滿呢?
調(diào)度器中idle 觸發(fā)條件
Linux Scheduler 為每一個CPU工人都維護了一個RunQueue 可以認(rèn)為是一個任務(wù)列表, 當(dāng)且僅當(dāng)這個列表里所有的任務(wù)都不是runnable的狀態(tài)時, Scheduler 才會切換到idle process。也就是說這個時候CPU工人完全無所事事, 必須休息節(jié)省體力以及節(jié)省電費! 同時還要注意可以通過nohz/nohz_full啟動參數(shù)減少tick 中斷對正在休息的CPU工人的干擾!
身世顯赫
那么首先我們要考慮得是idle進程從何而來,在描述細(xì)節(jié)之前我先劇透一下, idle進程雖然名字聽起來不怎么樣, 但是出身顯赫。首個idle進程實際上轉(zhuǎn)化自0號進程!內(nèi)核成為了生活的真相帝, 躺平并不是人人都能擁有的選項!
具體的過程則是說來話長. 在開辟鴻蒙之初, kernel 所有的進程之始祖是一個靜態(tài)的結(jié)構(gòu)體:
struct task_struct init_task
init_task 并非由任何kernel API所創(chuàng)建, 是所有進程的祖先, 名副其實的the one。
它肩負(fù)了非常重要的職責(zé), 例如創(chuàng)建首個內(nèi)核線程kernel_init。從而達(dá)到 一生二,二生三,三生萬物 的效果。不過今天這些不是本文的重點, 重點在于大功告成之際, init_task 并未事了拂衣去而是默默的轉(zhuǎn)化成了idle 進程。它繼續(xù)無言的守護著整個系統(tǒng), 俯首甘當(dāng)孺子牛啊。
這里參見代碼 init/main.c line 451,這里是函數(shù)rest_init 的最后階段大家可以發(fā)現(xiàn)調(diào)用了 cpu_startup_entry 這個函數(shù)。
我們可以跳轉(zhuǎn)到 kernel/sched/idle.c 來一窺細(xì)節(jié). 這里第一個arch_cpu_idle_entry 是可選接口,x86并沒有實現(xiàn),核心中的核心還是函數(shù) do_idle()-- just 躺平.
如果沒有在啟動時強制idle 模式為poll, 則我們將在這里進入真正的躺平函數(shù) cpuidle_idle_call.
在smp系統(tǒng)中 core0 以外的其它core 也會通過 start_secondary 函數(shù)最終產(chǎn)生0號進程且調(diào)用cpu_startup_entry 來進入idle loop之中。
CPU各種“躺平”的姿勢
各個廠子出產(chǎn)的CPU工人的idle 姿勢也是慢慢演化的, 從簡入繁, 花樣百出。下面我們一起來浮光掠影的看一下這些"超能力"。
X86
HLT
這是初代的idle 指令, 于486DX時代引入. 首先只有在ring0的特權(quán)級別才能執(zhí)行HLT指令, 同時執(zhí) 行的效果是 CPU 進入了C1/C1E state(參考ACPI標(biāo)準(zhǔn))。嚴(yán)格說起來只能算是摸魚0.1v。APIC/BUS /CACHE 都是照常運轉(zhuǎn), 只要中斷發(fā)生, CPU工人立即就要回到產(chǎn)線繼續(xù)搬磚。C1E 稍微又優(yōu)待了CPU點, 停止內(nèi)部時鐘又降了壓, 比較體貼。
PAUSE
這個也是非常早期的指令(Pentium 4)許可CPU 工人打個盹,大概從幾個到幾十個cycles吧(各代CPU有差異)。為什么要打盹呢?其實主要是要降低CPU工人在特定情況下(spin-lock)給內(nèi)存控制器帶來的壓力,與其讓CPU工人阻塞了內(nèi)存控器, 不如讓他打個盹吧。在最近的幾代Xeon之上還附帶了降低功耗的buff。
MWAIT/MONITOR
新一代CPU架構(gòu)師回顧了前輩的設(shè)計, 覺得CPU工人的權(quán)力完全沒有得到充分的照顧, 應(yīng)該給予更進一步的休息機會乃至真正的躺平!而且喚醒的條件又多了一個, 除了中斷這種強喚醒模式以外, 又加了內(nèi)存的CacheLine Invalidate喚醒。你的鄰居CPU 除了敲門以外還多了拿橡皮筋彈窗戶玻璃的渠道。首先這兩條指令也只能在ring0 級別執(zhí)行, 首先是調(diào)用MONITOR 地址范圍, 其次是MWAIT 進入休眠,一旦該地址的內(nèi)存被任何其它的主體修改, 則喚醒CPU工人起來繼續(xù)搬磚。同時這次最大的改進是可以通過MWAIT 進入各種不同的Cstate。其中C6 是我心目中真正的躺平 CPU 電壓可以歸0同時cache 也停, 實至名歸啊。
最常見的C State 狀態(tài)詳細(xì)描述,引自[2]
Cstate | Name | Description |
---|---|---|
C0 | Operating State | CPU fully turned on |
C1E | Enhanced Halt | Stops CPU main internal clocks via software and reduces CPU voltage; bus interface unit and APIC are kept running at full speed |
C3 | Deep Sleep | Stops all CPU internal and external clocks |
C6 | Deep Power Down | Reduces the CPU internal voltage to any value, including 0 Volts |
UMWAIT/UMONITOR
MWAIT雖好, 但是奈何必須在ring0特權(quán)級下執(zhí)行, 如果是一些特定的用戶級應(yīng)用例如DPDK, Linux的 idle driver 是很難得到執(zhí)行的機會,所以CPU架構(gòu)師又生憐憫之心, 允許CPU在用戶級也能進入躺平的模式, 不過作為妥協(xié)連C1 state都不行,只能進入 C0.1/C0.2 等神秘模式。效果還有待觀察,不過話說回來SPR這代Xeon才開始支持....距離上市少說還得1年之久。
TPAUSE
UMWAIT 指令的升級加強版, 附帶了一個timer。TPAUSE 可以讓CPU工人根據(jù)規(guī)定好的時間進行休息, 時間一到, 立刻繼續(xù)搬磚。當(dāng)然這也是一個簇新簇新的指令,大家還要等待SPR。
ARM的Idle-state 級別情況比較復(fù)雜一些, 更多的是和具體的芯片實現(xiàn)相關(guān). 但是總體上也是把握幾個大的類別:
只是停止CPU內(nèi)部時鐘
CPU降頻
停止給Cache供電
停止給CPU供電
和X86 相比 Arm的喚醒機制沒有和MESI協(xié)議連接有些遺憾(也就是沒有實現(xiàn)通過MEM 地址監(jiān)控的方式達(dá)成喚醒).
YEILD
這條頗為類似 PAUSE基本功能接近,使用場景也接近(spin lock).
WFE/WFI
這兩條指令顧名思義 wait for event/ wait for interrupt,中斷這條大家都可以理解類似HLT,那么event這條就值得看看了。ARM架構(gòu)可以從一個CPU向所有其它CPU 發(fā)送event(sev 指令),我的理解類似IPI廣播,收到了此event的CPU如果處于idle狀態(tài), 則需要立即喚醒。(注:和宋老師討論以后發(fā)現(xiàn) event 和IPI的一個區(qū)別是不需要ISR來響應(yīng),同時event并不能喚醒由于WFI指令進入的idle,這個有點囧,反過來中斷可以喚醒由于WFE進入的idle。這兩個躺平姿勢水很深啊)
軟件實現(xiàn)
除了硬件的各種花式躺平技術(shù)之外還有兩類“偽躺平”技術(shù)。
idle polling
通過啟動參數(shù), 我們可以指定cpu的idle 進程并不調(diào)用硬件提供的idle功能而僅僅是polling, 這種情況主要用于需要極低的CPU從idle狀態(tài)返回時延的場景。那么如果壓根沒有進入實際的idle狀態(tài),當(dāng)然時延是極低的,同時也能融入到idle整體的框架,不至于破壞規(guī)矩開特例。
halt-polling
在打開虛擬化的場景下, 事情就變得更加有趣了。大多數(shù)情況下, qemu 會缺省的只對guest 提供HLT指令作為idle的唯一機制,但是 HLT 指令毫無懸念的會觸發(fā)VMEXIT。雖然說大多數(shù)情況下kvm看到exit reason 是HLT 也只是執(zhí)行poll而已, 但是VMEXIT/VM_RESUME 還是如此的痛,畢竟幾千個cycles已經(jīng)無謂流逝, 追求極致的我們怎么能放任資源浪費。于是Redhat在Guest端引入了halt poll 機制, 也就是說如果matrix中的CPU工人首先開始假摸魚(poll), 如果假摸魚時間超過了閾值才真的去觸發(fā)HLT指令。如果很快就被從假模魚狀態(tài)拉回去搬磚, 則省去了出入matrix的費用(經(jīng)理得意的笑了)。
最后軟件硬件各路躺平姿勢花樣繁多, 內(nèi)核無奈又祭出了抽象大法把idle的時長與返回時延的選擇與具體執(zhí)行idle的機制分離開來。
idle governor 就負(fù)責(zé)做時長與時延的選擇,也可以稱為 idle -select。
idle driver 則是負(fù)責(zé)通過我們上面描述的各種軟硬件機制來實現(xiàn)governor指定的目標(biāo)。同時向governor menu 經(jīng)理提供各種不同機制的性能參數(shù),以供menu經(jīng)理選擇,就是所謂的idle-enter。
idle governor 缺省的算法只有一個就是menu, 還有3個候選的ladder/TEO/haltpoll 算法但是一般需要重新編譯內(nèi)核來激活。
ladder 算法故名意思, 是首先從能耗較高/返回時延較小的狀態(tài)開始,當(dāng)系統(tǒng)idle超過了閾值再進入更深的節(jié)能狀態(tài),從而逐步升級節(jié)能狀態(tài)。俗稱添油戰(zhàn)術(shù)也可以美其名曰“快速迭代”。
menu 算法單從名字看則有點讓人摸不到頭腦,其內(nèi)部機制也確實頗為復(fù)雜,menu算法主要是要在節(jié)能狀態(tài)的停留時間與系統(tǒng)能容忍的返回時延之間做權(quán)衡以達(dá)到最佳效果。
請原諒我非常不精確地描述一下menu。menu仿佛一個非常敬業(yè)的經(jīng)理凡事都要精算做出最優(yōu)選擇,CPU工人一旦休息再想打起精神干活這個轉(zhuǎn)換是有一個代價的, 往往需要口頭鼓勵(畫餅)+物質(zhì)鼓勵(肉夾饃)。那么經(jīng)理就要考慮如果工人休息時間太短,休息的好處遠(yuǎn)低于讓CPU工人重新振作的代價,那么這個休息就是不合理的(無情啊)。而且休息也有好些種類, 從假休息到完全躺平, 到底哪一種休息狀態(tài)才是收益比最佳的? menu會無情的選擇那個休息帶來好處大于重新振作代價的方案。同時menu經(jīng)理還會受到來自客戶的壓力, 時延也是要滿足的??蛻舻哪托拇蟮稚隙际遣缓玫? menu經(jīng)理會瘋狂試探客戶的底線。它選擇的方案是滿足客戶耐心上限的情況下CPU工人消耗能耗最少的方案。同時做到以上兩點 menu經(jīng)理大約才能有希望完成OKR/KPI。
結(jié)語
今天我們一起浮光掠影的討論了一下Linux的各種躺平姿勢,從中能領(lǐng)略到一代代CPU架構(gòu)師對CPU打工人的關(guān)愛。最后我衷心的祝愿CPU打工人在層出不窮的各類躺平技術(shù)加持下,最終能同各位經(jīng)理一起實現(xiàn)碳中和的OKR/KPI。
原文標(biāo)題:漫話Linux之“躺平”: IDLE 子系統(tǒng)
文章出處:【微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
責(zé)任編輯:haq
-
cpu
+關(guān)注
關(guān)注
68文章
11080瀏覽量
217089 -
Linux
+關(guān)注
關(guān)注
87文章
11511瀏覽量
213814
原文標(biāo)題:漫話Linux之“躺平”: IDLE 子系統(tǒng)
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
“碰一下”支付終端應(yīng)用在酒店:智能無卡入住與客房控制

上電時GPIO控制的LED偶爾詭異地亮了一下

碰一下終端,讓自助售貨機秒變 “家里的冰箱”

人形機靈巧手求推薦
在Linux下安裝軟件有哪些方法
初始化AFE4400的時候,哪些控制字是必須最先寫的?
“碰一下”支付背后的4G技術(shù)
支付寶發(fā)布新一代AI視覺搜索“探一下”
干貨來嘍!實用樹莓派Linux編譯指南

Linux文件壓縮打包的各種姿勢
觸摸屏驅(qū)動板無法燒寫程序的相關(guān)原因
自感線圈斷電時燈泡為啥會閃亮一下
Linux內(nèi)核測試技術(shù)

評論