初探Linux CPU動態調頻與實測
關於
本文主要涉及Linux CPUFreq子系統是什麼,為什麼需要,怎麼用。
並解決在實際測試中遇到的三個問題:
scaling_governor
沒有userspace
的問題。/proc/cpuinfo
與cpuinfo_cur_freq
顯示頻率不同。- 無法針對單個核心調頻並使一個CPU下的不同的核心運行在不同的頻率下。
參考資料
- Linux 2.6 內核中的最新電源管理技術綜述_CPUFreq
- Linux動態頻率調節系統CPUFreq
- Fedora社區對於問題一的討論地址
- Archlinux論壇對於問題一的討論地址
- StackExchange 問題:Why do cpuinfo_cur_freq and /proc/cpuinfo report different numbers?
- Stackoverflow 問題:Understanding cpu frequency, thread selection and more
- Intel 論壇問題:How can I scale only one cores frequency in a multi-core processor?
初探變頻技術:在Linux中查看CPU相關信息
再問為什麼之前,可以先看看到底Linux
變頻到底是什麼,可以通過什麼手段來看。
本部分使用的操作系統是Fedora27
,linux
內核版本是4.13
。本部分參考參考資料2的博客。
在Linux系統中查看與CPU相關的信息主要有兩個方法:
- 通過查看
/proc/cpuinfo
,比如當前運行頻率可以通過|grep MHz
查看。但是這個方法在413,414內核變動較大,不推薦通過此方法查看。具體的原因可以見後面的小節。 - 另外一個方法是通過
sysfs
查看與修改,目錄是/sys/devices/system/cpu/cpu*
先主要通過第二個方法進行查看:
與CPU相關的sysfs
介面均在此目錄下,可以通過查看這些文件內容查看CPU相關的信息,例如:
- online offline 文件中保存著當前在線以及下線的核心的數量。
- present 中記錄著主板上安裝的CPU的編號
進一步進入cpufreq
目錄下,該目錄下的文件記錄與頻率相關的內容。
對於fedora系統,無需安裝其它工具。如果使用ubuntu系統時,該目錄可能為空,需要手動安裝cpufrequtils
。
在cpuN
(N為具體的第幾個CPU)下有關於該CPU的具體參數文件。與頻率有關的文件在該目錄下的cpufreq
文件夾下。fedora系統該文件夾下有如下信息:
cpuinfo_xxx
開頭文件代表著cpu硬體上支持的頻率cpuinfo_max_freq cpuinfo_min_freq
最大、最小頻率cpuinfo_cur_freq
是當前運行的頻率(可能也有問題,具體見後面的小節)scaling_xxx
開頭文件代表可以通過CPUFreq系統用軟體進行調節時所支持的頻率scaling_available_governors
可供選擇的頻率調節策略scaling_governors
當前選擇的策略scaling_max_freq scaling_min_freq
調節是最大、最小頻率scaling_cur_freq
是軟體當前指定的頻率scaling_driver
調頻驅動 (當前intel_pstate
)
特別注意:可能新版的處理器,新的Linux內核中只有部分介面,且調度也只有powersave和ondemand兩種,這是由於使用了p-state driver
導致。如何修改見後面小節。
CPUFreq 子系統
根據以上觀察,可以有如下總結:
- CPU的硬體特性決定了這個CPU的最高和最低工作頻率,所有的頻率調整數值都必須在這個範圍內。
- 可以在這個範圍內再次定義出一個軟體的調節範圍,它們用scaling_xxx_freq來表示
- CPUFreq系統把一些公共的邏輯和介面代碼抽象出來,這些代碼與平台無關,也與具體的調頻策略無關
- 另外一部分,與實際的調頻策略相關的部分被稱作cpufreq_policy
- cpufreq_policy又是由頻率信息和具體的governor組成,governor才是具體策略的實現者
- governor的實現最好能做到平台無關,與平台相關的代碼用cpufreq_driver表述
關於CPUFreq的具體理論,主要參考參考文獻1,該參考文獻使用的linux內核位2.6版本,該部分以2.6版本為主。
為什麼會出現變頻技術
簡要來說,變頻技術的主要目的是節約功耗。變頻技術作為電源管理技術以節能為目的加入linux內核。與之前看的大小核類似,變頻技術都是為了 energy efficient computing
,為了提高performance per watt
。
變頻與超頻
變頻與超頻不同的是,超頻是指通過提高核心電壓等手段讓處理器工作在非標準頻率下的行為,這往往會造成 CPU 使用壽命縮短以及系統穩定性下降等嚴重後果。而變頻技術是指CPU硬體本身支持在不同的頻率下運行,系統在運行過程中可以根據隨時可能發生變化的系統負載情況動態在這些不同的運行頻率之間進行切換,從而達到對性能和功耗做到二者兼顧的目的。
為什麼需要 CPUFreq子系統
由於每一個各家實現變頻技術的使用方法都不同,故需要按照其實現方法向內核中添加代碼,才能支持處理的變頻使用。為了兼容各種類型的處理器並最大程度復用代碼,故linux中開發了CPUFreq子系統用於實現變頻的功能。
CPUFreq需要實現哪些部分
所以大思路是要兼容各種處理器,再根據工作負載動態調整處理器的運行的頻率。所以可以將這個部分分為兩個部分:
- 根據系統負載的動態變化挑選出 CPU 合適的運行頻率。
- 按照選定的運行頻率在選定的時間對 CPU 進行設置,使之真正工作在這一頻率上。
從設計角度來說,應該保證二者是清晰的隔離開的並通過規範定義的介面進行通信
CPUFreq的設計
CPUFreq內核子系統的設計框架如下圖所示:
故cpufreq
作為中間層,向上抽象了處理器變頻的具體實現,向下分離了變頻的策略。將具體的策略和變頻的物理上實現進行分離。
這種設計帶來的好處是使得 governor 和 CPU 相關的變頻驅動程序的開發可以相互獨立進行,並在最大限度上實現代碼重用,內核開發人員在編寫和試驗新的 governor 時不會再陷入到某款特定 CPU 的變頻技術的硬體實現細節中去,而 CPU 生產廠商在向 Linux 內核中添加支持其特定的 CPU 變頻技術的代碼時只需提供一個相對來說簡單了很多的驅動程序,而不必考慮在各種不同的應用場景中如何選擇合適的運行頻率這些複雜的問題。
CPUFreq的使用
第一部分在實際機器上看的實際sysfs
中的文件就是CPUFreq
留的介面,可以通過cat
對文件進行讀取,同時可以用echo
向文件寫入。在2.6內核中,在選擇使用userspace
的策略時,向scaling_setspeed
中寫入指定的頻率,可以修改CPU的運行頻率。
除了可以使用sysfs
中提供的介面,還可以用上文提到的cpufrequtils
工具包。
用戶如何根據實際負載變頻
所以,當選擇userspace
時,可以每固定時鐘間隔根據任務負載對CPU頻率進行調節。但是直接在用戶態實現這些調節演算法有以下兩種問題:
- 當性能需求徒然提升時,需要等待下一次調節周期時才能更新實際運行頻率,故有一段時間的慢速運行時間。
- 在用戶空間對系統負載情況採樣分析是否合理:
由於一個用戶態程序很難完整的收集到所有需要的信息,因為這些信息大部分都保存在內核空間,如果想要收集這些系統信息,必然需要進行用戶態與內核態之間的數據交互,而頻繁的用戶態與內核態之間的數據交互又會給系統性能帶來負面影響。
所以在2.6內核中提出了ondemand
,其是一個在運行在內核態,細粒度時間間隔對系統負載情況採樣分析的策略。那麼這個表明系統負載的百分比數值是如何得到的呢?
在支持 Intel 最新的 Enhanced Speedstep 技術的 CPU 中,在處理器硬體中直接提供了兩個 MSR 寄存器(Model Specific Register)供 ondemand governor 採樣分析系統負載情況使用。這兩個 MSR 寄存器的名字分別為 IA32_MPERF 和 IA32_APERF,
- IA32_MPERF MSR 中的 MPERF 代表 Maximum Performance ,該寄存器是一個當 CPU 處在 ACPI C0 狀態下時按照 CPU 硬體支持的最高運行頻率每隔一個時鐘周期加一的計數器
- IA32_APERF MSR 中的 APERF 代表 Actual Performance ,該寄存器是一個當 CPU 處在 ACPI C0 狀態下時按照 CPU 硬體當前的實際運行頻率每隔一個時鐘周期加一的計數器
有了這兩個寄存器的存在,再考慮上 CPU 處於 ACPI C0 和處於 ACPI C1、C2、C3 三種狀態下的時間比例,也就是 CPU 處於工作狀態和休眠狀態的時間比例, ondemand governor 就可以準確的計算出 CPU 的負載情況了
具體CPU驅動相關部分
實際上支持 Intel Enhanced Speedstep 技術的處理器為用戶提供了非常簡單的編程介面,對 CPU 運行頻率進行設置是通過一個名為 IA32_PERF_CTL 的 MSR 寄存器進行的,另外還有一個名為 IA32_PERF_STATUS 的 MSR 寄存器可供檢查 CPU 當前所處的運行頻率。當用戶需要對 CPU 運行頻率進行設置時只需按照 Intel 開發手冊的說明向 IA32_PERF_CTL MSR 寄存器中寫入規定的數值即可。
所以,來調頻吧
這一部分,本來想就是測試一下修改不同核心的頻率,然後使其運行在不同的頻率下。最後書寫測試程序,使線程綁定具體的核心,跑下測試。然而沒想到又遇到了很多問題。
- 首先,是
governor
沒有userspace
的問題。 - 再,到底誰才真正顯示了當前頻率。
- 最後,CPU的核心真的能運行在不同頻率下嗎????
問題一:解決intel_pstate driver
解決思路
在兩台Macbook Pro和Macbook Air上安裝Fedora後並沒有看到上面所說的ondemand
的調度方法,也沒有發現可以通過用戶態調整核心運行頻率的介面,爬了各種帖子後發現其根本原因出在intel_pstate driver
上。(在/sys/devices/system/cpu/cpuX/cpufreq
下查看scaling_driver
顯示為intel_pstate
。)
fedora社區討論地址、archlinux論壇討論地址,查看之後找到了archlinux裡面的一個描述文檔
- 對於現代 Intel CPU,將使用
pstate
功率驅動程序,而非下列其他驅動程序。此驅動程序的優先順序高於其他驅動程序,並編入內核(而非編譯為模塊)。此驅動程序將自動用於 Sandy Bridge(以及更新的 CPU)。如果在使用這個驅動的時候遇到問題,建議您在 Grub 的內核參數中將其禁用(即修改 /etc/default/grub 文件,在 GRUB_CMDLINE_LINUX_DEFAULT= 後添加intel_pstate=disable
)。您可以使用與此驅動程序配套的用戶空間工具,但這些工具不受您的控制。 - 儘管上述 P State 行為會受到
/sys/devices/system/cpu/intel_pstate
影響,例如:可以通過# echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo
關閉 Intel 睿頻加速,從而降低 CPU 的溫度。 - 對於現代 Intel CPU,Linux Thermal Daemon 也提供了一些其他的控制方法(例如 thermald),它們可以通過 P-state、T-state 或 Intel 節能驅動程序來主動控制系統溫度。thermald 也適用於較老的 Intel CPU。如果最新版本的驅動程序不可用,那麼守護進程會還原為 x86 MSR (Model Specific Register),由 Linux「cpufreq 子系統」來控制系統冷卻。
Linux kernel中關於intel_pstate
的描述文檔:鏈接 。Intel官方關於此驅動給的Slide:鏈接。
簡單來說,pstat
又回去了,結合了變頻策略和具體的硬體驅動,為了更好的性能和功耗……可能吧。有機會再詳細學習一下pstat
。
在Fedora中將驅動改回acpi-cpufreq
- 按照官方說明,在/etc/default/grub 文件,在 GRUB_CMDLINE_LINUX_DEFAULT= 後添加
intel_pstate=disable
- 對於ubuntu系統,提供了update-grub的工具,而對於Fedora,需要利用grub2-mkconfig工具,輸入以下命令:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg #Traditionalsudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg #EFI
重新查看/sys/devices/system/cpu/cpuX/cpufreq/scaling_driver已經變為acpi-cpufreq。
本以為大功告成,可以愉快的測試了。結果又出現了更多的問題:
問題二:誰到底正真顯示了CPU
的當前頻率!!
問題現象
按照道理來說,第一部分介紹的兩種方式查出來的當前頻率應該相同。然而,事實並非如此:
/proc/cpuinfo 與 cpuinfo_cur_freq 居然不相符!!!!
發現問題時,我的內核已經更新到Linux4.14
了。當然發現與內核版本有關時,已是後話了。
/proc/cpuinfo
與cpuinfo_cur_freq
中反應的當前的CPU的頻率有比較大的出入,下面是在設置調度策略為ondemand
時分別監視/proc/cpuinfo
中的頻率信息與sysfs
的cpuinfo_cur_freq
中的頻率信息。可以發現其中的差異非常大。
當設置調頻策略為userspace
且設置四個核心為cpuinfo_cur_freq
中所示頻率時,/proc/cpuinfo
中並沒有相似的變動。
寫了一個創建4個線程並平均分配到四個核心的相同計算任務的測試程序,並設置調頻策略為ondemand
。可以看到在計算任務重時,雖然兩個地方都顯示跑到了最高頻率,但是最高頻率並不相同。
解決思路
爬了很多帖子,最後在Stack Exchange的這個問題 Why do cpuinfo_cur_freq and /proc/cpuinfo report different numbers? 下找到了線索。其中的一個老哥的回復非常有用,回復內容如下:
Note: Since Kernel 4.13, cat /proc/cpuinfo | grep MHz no longer returns the current clock speed. At the Kernel Bugzilla, they say its intentional. See /proc/cpuinfo does not update frequency. Its also mentioned here: Power Management Updates Touch Intel P-State & More For Linux 4.13 – Marc Ranolfi Oct 11 17 at 3:14
在第一個鏈接描述的現象正是現在我面臨的情況:
The 4.13 kernel with intel_pstate=passive (or active) does not appear to correctly update the CPU frequency in /proc/cpuinfo
在該問題的討論中,提及到4.13之後不再以/proc/cpuinfo
讀取cpu
頻率信息,且cpuinfo_cur_freq
才是正確的。這也導致一些依賴於/proc/cpuinfo
的軟體出現一些問題。
在第二個鏈接裡面提到了在Kernel 4.13
的更新中有這樣一條新的特性:
x86 systems will no longer try to export their current CPU frequency to /proc/cpuinfo. Theres also a way to rework how the CPU frequency is exported via sysfs too, using the registers for computing the current frequency rather than relying upon the CPUFreq driver
好吧,總的來說,就是和Linux內核版本相關,新的內核版本可能取消了向CPUinfo
輸出實時頻率的feature。
實際測試
而實際測試發現情況並沒有這麼簡單。測試平台CPU信號為Intel haswell架構i5-4258U。
由於Fedora更新比較勤快,我的Fedora系統有三個內核:兩個是4.14的,一個是4.13的。
下面測試均開了四個watch窗口,分別監視:/proc/cpuinfo
, cpuinfo_cur_freq
, scaling_cur_freq
, scaling_governor
。
4.14內核
首先測試在4.14內核中的情況:
當書寫腳本將四個核心均調到性能模式(從按需模式調過來的),可以發現兩個現象
- 目前來說沒有問題,均到了最大頻率。
- 但是和上面帖子不同的是,
/proc/cpuinfo
中展現的可能是正確的頻率。
然後測試的是powersave
模式,如下圖所示,有以下發現
- 依然沒有問題,所有頻率都降到了最低
- 同樣,
/proc/cpuinfo
中展現的可能是正確的頻率
然後跑自己設置的實驗環境,兩個900000,兩個2401000。這次結果就比較有趣了
- 確實是用戶設置的頻率,但是只有設置的
cpu0
有用,其他的都按照cpu0
的頻率跑 cpuinfo_cur_freq
倒是按照了設置來走的,可惜不是實際評論。
在測試一下設置不同的,可以斷定所有的cpu
均按照cpu0
的頻率來走了。
再設置回performance
時,發現其並沒有全部升到最高,可能performance
策略不管用了……
總結一下414內核的特點:
/proc/cpuinfo
是顯示正確頻率的地方cpuinfo_cur_freq
顯示的是錯誤的,雖然是最接近設置目標的。userspace
只能設置統一頻率performance
不管用
4.13內核
切換回4.13
內核進行測試,配置測試環境依舊如上相同。這裡不單一分析了,直接在最後進行總結。
用戶配置模式,這裡配置的是2300000, 2300000,1800000,1500000
。依舊只按照cpu0
進行設置。
powersaving
模式:
performance
模式:
特意為了檢測governor
是否也只能統一設置,做了如下實驗,得出結論,governor
也是統一設置的。
所以4.13
內核的總結如下:
/proc/cpuinfo
總是顯示最高頻率,cpuinfo_cur_freq
中顯示的亦不是正確頻率scaling_cur_freq
中顯示的是當前頻率。userspace
可以統一設置頻率,不能單獨設置。performance
沒有用。
總結
- 412 413 414 內核關於CPU變頻這塊變動明顯
- 無論是413還是414內核,均以
scaling_cur_freq
為準。 - 貌似核心頻率只能全部修改,不能當個修改。
問題三:到底能不能單獨配置每個核心運行頻率?
上面的測試可以發現,核心頻率可以全部修改,不能單獨修改?所以到底能不能單獨配置每個核心的運行頻率呢?
第一條線索
為了找這個問題的答案,爬了很多帖子,在stackoverflow的這個問題下找到了線索:Understanding cpu frequency, thread selection and more,取答案中比較關鍵的部分翻譯如下:
大體來說,cpufreq
提供的很多功能並不被Hardware或者Kernel所支持,所以通過cpufreq
設置的功能不一定會按照預期運行。例如,如果利用cpufreq
為每個cpu
設置單獨的運行的頻率,現實中在超線程的系統,兩個CPUs
可能會綁定在一起,所以必須有相同的頻率。
Intel P-states
實際上是提供了一個frequency-voltage
對,通過降低cpu
運行的電壓來降低cpu
的運行頻率。這些frequency-voltage
對是離散的,可能與cpufreq
提供的可選頻率有出入。
所以從這個答案可以知道第一個原因:
- 可能由於超線程技術導致兩個虛擬CPU其實是一個核心,所以兩個綁定在一起。
第二條線索
轉到Intel的論壇,發現類似的一個帖子:How can I scale only one cores frequency in a multi-core processor? 在這個問題中,McCalpin, John給出了另一個比較詳細的解釋,原答案可以找原貼看。
首先要了解什麼是uncore
,其實uncore
就是intel用來描述其微處理器上不是un
處理器核心core
的部分,包括例如L1 L2 cache
,ALU
之類一堆。處理器運行的頻率/電壓與uncore
有關。
回答的主要內容總結如下
- 首先第一個問題是當前消費級別的
uncore
(如i系),只支持設置唯一一個時鐘頻率。 - 然後是伺服器級的
uncore
(如E系),雖然支持每個核心不同頻率,但是你一旦指定他們運行在不同的頻率,uncore中功耗控制單元(PCU)可能會再次改寫你的請求,因為PCU可能認為你的設定不合理…… - 所以討論一下運行在不同的頻率的可能性:
- 能否直接要求每個核心運行在不同頻率:設置是可以的,通過修改
MSR IA32_PERF_CTL
寄存器,但是這並不意味著硬體會響應你的請求。 - 能否通過設置不同核的電壓,間接改變核心的運行頻率:
- 首先很少系統是有與核數量相同的電源來提供運行在不同電壓上。
- 再則,在Haswell架構之前,頻率和電壓是綁定的,一起寫入
MSR IA32_PERF_CTL
。 Haswell
提供了 on-chip voltage regulators ,其允許給不同的核心不同的頻率。- 這也不意味著硬體會響應你的請求(因為PCU的存在)
- 所以到底他們有可能會響應嗎
- 首先要清楚,PCU有最終的決定權
- 該答案的作者也沒能在Haswell之前的處理器中實現運行不同頻率。
- 這個部分詳細可以去看 Uncore Performance Monitoring Manuals for the various Xeon E5 products
So… Conclusion
所以在我的當前的筆記本環境下跑出不同頻率的CPU可能性不大了。本來想著p-state
和具體uncore
對於變頻的處理細節可以暫時不管,可能現在需要繼續填坑,詳細了解了。
推薦閱讀:
※Linux下的開源軟體有哪些有趣的玩法?
※雲伺服器jdk tomcat安裝配置測試詳細的步驟
※Linux堆內存管理深入分析(下)
※怎樣才算有自主知識產權的操作系統?研發「自主知識產權」的操作系統對中國的社會和經濟有何意義?
※做linux kernel相關研究的如何創(zhuan)業(qian)?