淺析 linux 電源配置
一、背景
近期,我們收到用戶反饋,在使用 deepin 系統(tǒng)過程中遇到了 CPU 功耗過高導(dǎo)致的設(shè)備發(fā)熱、續(xù)航較差情況,而用戶在這些負(fù)載場景下,CPU 的占用往往不高。為了解決這個痛點,統(tǒng)信軟件開源社區(qū)中心特別成立專項計劃,對于 deepin 的電源進行專項優(yōu)化,本文旨在針對此問題根因進行分析與說明。
在對電源進行專項優(yōu)化之前,我們首先對 deepin 系統(tǒng)進行了深入的調(diào)查和分析,以了解其在負(fù)載場景下的實際運行情況。經(jīng)過對 CPU 使用率和功耗的監(jiān)測,我們發(fā)現(xiàn)了一個令人驚訝的事實:盡管在高負(fù)載場景下 CPU 的占用率不高,但其功耗卻持續(xù)升高,最終導(dǎo)致設(shè)備發(fā)熱并影響續(xù)航。也就是說,我們前期做的省電優(yōu)化工作,不僅無效,還起了反作用(具體情況作者將在下文作出仔細(xì)說明)。
二、問題
1. 內(nèi)核
最開始發(fā)現(xiàn)問題的地方在內(nèi)核。有用戶將我們的內(nèi)核和 ubuntu 的內(nèi)核進行對比后發(fā)現(xiàn),雖然我們的系統(tǒng)和 ubuntu 系統(tǒng)的性能差不多,但是在發(fā)熱和續(xù)航上,我們較 ubuntu 落后較多。有用戶在 deepin 系統(tǒng)上使用 ubuntu 和其他開源 linux 發(fā)行版的配置文件分別編譯內(nèi)核,發(fā)現(xiàn) deepin 的主要問題存在于發(fā)熱控制之上。我們的測試同事高度重視這一社區(qū)反饋,遂對社區(qū)用戶反饋的問題進行復(fù)現(xiàn),佐證了這一現(xiàn)象。
對于這種問題,我們立即聯(lián)系了內(nèi)核研發(fā)部的同事,并邀請部分對內(nèi)核配置有一定研究的社區(qū)用戶共同參與。在大家的合力排查下,我們發(fā)現(xiàn),deepin v23 中提供的HWE內(nèi)核存在部分 debug 和無用的內(nèi)核選項被開啟的情況,并且部分節(jié)電功能實際未能獲得啟用,這些都在一定程度上導(dǎo)致了 deepin v23 的續(xù)航表現(xiàn)不佳。
2. 系統(tǒng)
在系統(tǒng)層面,我重新審視了 dde-daemon 提供的電源調(diào)度模塊,并且對比內(nèi)核文檔提供的文件接口,分析我們用戶使用的電源模式,發(fā)現(xiàn)其中存在可以優(yōu)化的空間。這將是本文著重講解的內(nèi)容之一。
3. 前置知識:ACPI
ACPI 是 Advanced Configuration and Power Interface 的縮寫,是一種計算機硬件和操作系統(tǒng)之間交換能源相關(guān)信息的接口規(guī)范。它定義了計算機硬件的能源相關(guān)信息,如電源供應(yīng)器狀態(tài)、設(shè)備功耗、設(shè)備功率因數(shù)等。ACPI 是操作系統(tǒng)控制計算機硬件能源管理的標(biāo)準(zhǔn),同時也是硬件廠商和操作系統(tǒng)之間通信的標(biāo)準(zhǔn)。
在 deepin 系統(tǒng)中,ACPI 負(fù)責(zé)處理計算機硬件的能源管理,它與 deepin 系統(tǒng)的電源管理模塊進行交互,以實現(xiàn)對計算機硬件的能源管理。
在分析系統(tǒng)層面的問題時,我們需要了解 ACPI 和電源管理模塊的作用和功能,以及它們是如何協(xié)同工作的。在本文中,我們將會詳細(xì)講解 ACPI 的工作原理以及deepin系統(tǒng)中的電源調(diào)度模塊工作模式,并提出可行優(yōu)化建議。
首先,讓我們了解一下 ACPI 的工作原理。當(dāng)計算機硬件發(fā)生電源變化時,ACPI 會收集硬件信息,并向操作系統(tǒng)發(fā)送電源請求。操作系統(tǒng)收到電源請求后,會根據(jù)用戶配置自動調(diào)整各個硬件的電源策略。而 deepin 系統(tǒng)的電源模塊則是幫助用戶生成配置來調(diào)整 ACPI 的行為。所以在這一方面,我們能做的就是向 ACPI 提供合理的電源策略,在保證性能的同時,降低設(shè)備溫度并提升續(xù)航表現(xiàn)。
4. 平臺電源配置
相關(guān)內(nèi)核文檔<https://docs.kernel.org/userspace-api/sysfs-platform_profile.html>
UEFI ACPI 文檔<https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/index.html>
平臺電源配置是電源管理模塊的一個重要組成部分,它用于管理計算機平臺硬件(指所有支持 ACPI 的設(shè)備)的電源狀態(tài),而 CPU 也是屬于 ACPI 設(shè)備的一部分。不過 CPU 是計算機的核心發(fā)熱大戶,對于其使用平臺電源管理可能粒度較粗,所以 APCI 引入了一些 CPU 獨有的性能管理方式,在下一小節(jié)將詳細(xì)說明。
平臺電源配置提供了三種可選模式:performance (性能模式),balance (平衡模式),low-power (節(jié)能模式)。一般情況下,用戶使用平衡模式就可以。在臺式機和 mini 主機類(對于功耗和發(fā)熱沒有任何要求)設(shè)備上默認(rèn)提供性能模式,在筆記本等移動設(shè)備上默認(rèn)提供平衡模式。默認(rèn)不提供節(jié)能模式,因為某些 ACPI 設(shè)備在節(jié)能模式工作過程中可能出現(xiàn)“睡死現(xiàn)象”,所以為了避免此問題,默認(rèn)不提供 low-power 節(jié)電模式。
5. CPU電源配置
?傳統(tǒng)電源模式(SCalling)內(nèi)核文檔<https://www.kernel.org/doc/html/v6.1/admin-guide/pm/cpufreq.html>
?Intel PState 內(nèi)核文檔<https://www.kernel.org/doc/html/v6.1/admin-guide/pm/intel_pstate.html>
AMD PState 內(nèi)核文檔<https://docs.kernel.org/admin-guide/pm/amd-pstate.html>
如果有時間,可以自行研讀上述電源文檔,就很容易理解 CPU 電源配置相關(guān)內(nèi)容。作者在這里的講述將忽略大量技術(shù)細(xì)節(jié)和實現(xiàn)方式,僅表述如何調(diào)整 CPU 的電源模式。
在/sys/devices/system/cpu/cpufreq 目錄下有許多文件名為 policy<x>(x 代表核心編號),這些文件對應(yīng)著你電腦上的 CPU 核心,而 CPU 的電源調(diào)度細(xì)節(jié)就在這些文件夾里面。在 policy<x>目錄下有一個文件 scaling_driver,使用 cat 或其他方式訪問它,得到的結(jié)果就是我們當(dāng)前使用的調(diào)度器:
intel_cpufreq / acpi_cpufreq : 使用 scaling freq 調(diào)度
intel_pastate : 使用 Intel Pstate 調(diào)度
amd-pstate : 使用 AMD Pstate 調(diào)度
6. scalling freq 調(diào)度
這是最傳統(tǒng)的 CPU 調(diào)度方式,你可以在 policy<x>文件夾下的 scaling_available_governors 獲取可選電源模式:

你可能好奇,為啥這里有這么多平衡模式,其實這些平衡模式的作用都是是一樣的:平衡性能和續(xù)航,不過使用的算法可能不同,這里我不做詳細(xì)說明,我在網(wǎng)絡(luò)上找到一些詳細(xì)資料可以參考,有興趣的朋友可自行查閱:
oppo 內(nèi)核團隊:schedutil governor 情景分析:http://www.wowotech.net/process_management/schedutil_governor.html
linux 內(nèi)核文檔:schedutil governor:https://www.kernel.org/doc/html/next/translations/zh_CN/scheduler/schedutil.html
Arch wiki:https://wiki.archlinux.org/title/CPU_frequency_scaling
我們可以更改 scaling_governors 來更改此核心的電源調(diào)度(注意:只能更改為 scaling_available_governors 文件中列出的電源調(diào)度,不同電腦可能存在差異)。
7. Intel Pstate
這是 Intel 近幾代 CPU 獨享的 moment,內(nèi)核開啟 intel pstate 后(V23 內(nèi)核默認(rèn)開啟)你會發(fā)現(xiàn)在 policy<x>文件夾下多了幾個文件:
我們只需要關(guān)注:
energy_performance_available_perference : 可用的 pstate 電源調(diào)度
energy_performance_perference : 當(dāng)前選定的 pstate 電源調(diào)度,可以更改此文件內(nèi)容來更改電源調(diào)度
在 Intel Pstate 中出現(xiàn)了兩個新的調(diào)度方案:
balance_performance : 平衡偏性能,平時工作頻率不高,在負(fù)載增大時能快速響應(yīng)
balance_power : 平衡偏節(jié)能,電源策略較為保守
在部分電腦上還有 default 方案,此方案就是經(jīng)過 pstate 優(yōu)化過的 balance 策略。具體PState 使用的黑魔法以及主動模式和被動模式的調(diào)度策略,可以參照內(nèi)核文檔進行分析。
8. AMD PState
這是 AMD ZEN2 以上用戶,以及支持 kernel 6.4.x 用戶獨享的 moment。其實 AMD 在6.1 內(nèi)核已經(jīng)做了 PState 的支持,不過是被動模式。
9. (Actvie Mode)主動模式
Active Mode 僅在內(nèi)核版本大于 6.4 以上,且內(nèi)核選項打開 AMD PState 時可用。可能需要在 grub 內(nèi)加入啟動參數(shù)以打開此功能:amd_pstate=active,也可以修改文件實現(xiàn) Active Mode 的電源策略和 Intel PStatewi 類似。
10. (Passive Mode)被動模式
Passtive Mode 僅在內(nèi)核大于 6.1 以上,且內(nèi)核選項打開 AMD PState 時可用??赡苄枰?grub 加入啟動參數(shù)開啟此功能:amd_pstate=passive,也可修改文件實現(xiàn)。
Passive Mode 提供兩種電源模式,在/sys/device/system/cpu/cpufreq/scaling_governor文件進行調(diào)整:
performance 使用 platform_profile 進行配置,調(diào)度積極性較高
scheutils 在/sys/device/system/cpu/cpufreq/schedutil/rate_limit_us 文件中調(diào)整調(diào)度粒度(兩次調(diào)度的間隔時間)和 ACPI 的 scheutils 類/sys/device/system/cpu/cpufreq/scaling_governor
11. (Guided Mode)引導(dǎo)模式
Guided Mode 僅在內(nèi)核大于 6.1 以上,且內(nèi)核選項打開 AMD PState 時可用??赡苄枰?grub 加入啟動參數(shù)開啟此功能:amd_pstate=guided,也可修改文件實現(xiàn)。這就類似汽車的自動擋,驅(qū)動程序請求最低和最大性能級別,平臺自動選擇此范圍內(nèi)適合當(dāng)前工作負(fù)荷的性能級別。
三、GPU 電源管理部分
1. AMD GPU
如果是 AMD GPU 則需要更改兩個文件(使用 tee 命令進行寫入):
/sys/class/drm/card0/device/power_dpm_state(這是一個遺留接口,目的是向后兼容)
performance 高性能模式
balance 平衡模式
battery 節(jié)能模式
/sys/class/drm/card0/device/power_dpm_force_performance_level
以下設(shè)置來自AMD官方驅(qū)動文檔:
https://dri.freedesktop.org/docs/drm/gpu/amdgpu.html#power-dpm-force-performance-level 書簽:drm/amdgpu AMDgpu driver — The Linux Kernel documentation
2. power_dpm_force_performance_level
AMD GPU 驅(qū)動程序提供了一個 sysfs API,用于調(diào)整某些與功率相關(guān)的參數(shù)。文件 power-dpm-force-performance-level 將用于執(zhí)行此操作。它接受以下參數(shù):
auto:當(dāng)選擇 auto 時,設(shè)備將嘗試針對驅(qū)動中的當(dāng)前條件動態(tài)選擇最佳功率曲線
low:當(dāng)選擇低時,GPU 被強制到最低功率狀態(tài)
high:當(dāng)選擇高時,GPU 被強制到最高功率狀態(tài)
manual:當(dāng)選擇手動時,用戶可以通過 sysfs pp_dpm_mclk、pp_dpm_sclk和pp_dpm_pcie 文件手動調(diào)整每個時鐘域啟用的電源狀態(tài),并通過 pp_power_profile_mode sysfs 文件調(diào)整電源狀態(tài)轉(zhuǎn)換方式。
profile_standard 固定時鐘級別分析模式。此模式將時鐘設(shè)置為固定級別,該級別因ASIC 而異。這對于分析特定工作負(fù)載很有用(不常用)。
profile_min_sclk 最小 sclk 分析模式。此模式將 sclk 強制設(shè)置為最低級別。這對于分析最小功耗的場景很有用(不常用)。
profile_min_mclk 最小 mclk 分析模式。此模式將 mclk 強制設(shè)置為最低級別。這對于分析最小功耗的場景很有用(不常用)。
profile_peak 峰值分析模式。此模式將所有時鐘(mclk、sclk、pcie)設(shè)置為最高級別。這對于分析最大性能的場景很有用(不常用)。
3. 測試
LOW 模式的跑分

auto 模式的跑分

high 模式的跑分

4. Intel GPU
intel GPU 使用的 i915 驅(qū)動,并不希望你對其做出調(diào)整,因為其驅(qū)動自帶的電源策略已經(jīng)足夠聰明。不過你也可以通過 intel 提供的 intel-gpu-tools 進行調(diào)整和獲取信息。
sudo apt install intel-gpu-tools
然后使用
sudo intel_gpu_frequency
來獲取當(dāng)前頻率(當(dāng)前使用的是 Intel A750)

可以看到 intel 的顯卡驅(qū)動是在 600 MHz 到 2400 MHz 之間動態(tài)調(diào)整
測試筆記本下 intel 核顯跑分如下

5. Nvidia
由于 nvidia 驅(qū)動不開源,所以在系統(tǒng)層面無法對其做控制。
四、應(yīng)用
應(yīng)用級別的省電,應(yīng)該就是在保證用戶使用流暢度的前提下節(jié)省性能。之前也有用戶提出過,是否能參照 vivo 的 origin3 os 的不公平調(diào)度算法來實現(xiàn)優(yōu)化。畢竟安卓系統(tǒng)的底層也是 linux,理論上實現(xiàn)難度不大。
Cgroups,全稱 Control Groups,是 Linux 內(nèi)核提供的一種資源管理機制,用于對進程分組并對其資源進行限制和隔離。Cgroups 可以用于限制進程的 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)等資源,也可以用于限制進程的優(yōu)先級和 IO 權(quán)限。利用其提供的能力,我們很容易實現(xiàn)類似不公平調(diào)度算法(我們新的 AM 天然支持 Cgroups 的操作),但是我還有一些顧慮:
不同于手機操作系統(tǒng),計算機操作系統(tǒng)是多任務(wù)并行的,在多數(shù)窗口管理器下,我們并沒有一個明顯的前臺應(yīng)用,此時使用不公平調(diào)度可能存在隱患;
容易引發(fā)人機對抗。在我的觀念里面,計算機是為人服務(wù)的,那么用戶的意志必定是第一優(yōu)先級,所以我們不應(yīng)改變用戶的行為,如果使用不平衡調(diào)度和用戶預(yù)期不一致,會極大降低用戶體驗;
使用前后臺區(qū)分應(yīng)用,可能導(dǎo)致開銷和收益比下降,性價比不高。linux桌面不像安卓設(shè)備有明顯前后臺,那么用戶頻繁切換應(yīng)用的操作將導(dǎo)致我們的調(diào)度器頻繁切換調(diào)度,使得開銷過大。
我認(rèn)為最佳的解決方案是:提供能力,但不提供方案。我們可以提供基于 Cgroups 方式修改應(yīng)用組的優(yōu)先級,然后讓用戶自己選擇什么應(yīng)用優(yōu)先級更高,什么應(yīng)用優(yōu)先級低,以實現(xiàn)調(diào)度(比如在 dock 上右鍵選擇優(yōu)先級)或提供一套配置以供用戶自由選擇。
如果一個電腦需要使用不平衡調(diào)度來保證使用流暢性,可能這并不是一個操作系統(tǒng)能解決的問題,而更應(yīng)該考慮硬件是否需要更換,以保證多任務(wù)使用的流暢性。
?
附錄——常用的調(diào)試測試工具
1. S-tui
可以看到 CPU 頻率變化,配合 stress 可以對 cpu 進行壓力測試。

2. intel-gpu-tools
可以使用 intel_gpu_frequency 來獲取和調(diào)整 i965 的驅(qū)動頻率。
3. glmark2
GPU 跑分軟件。

——圖/文∣項澤龍?產(chǎn)研平臺/開源社區(qū)中心/研發(fā)部