日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

CPU C-state & cpuidle driver[通俗易懂]

發布時間:2023/12/19 综合教程 39 生活家
生活随笔 收集整理的這篇文章主要介紹了 CPU C-state & cpuidle driver[通俗易懂] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 什么是C-states、C-mode?

為了在CPU空閑時節約能源,可以命令CPU進入低功耗模式。C-state是intel CPU處于空閑時的一種狀態,CPU有幾種電源模式,它們統稱為“c狀態”或“c模式”

低功耗模式最初是在486DX4處理器中引入的。到目前為止,已經引入了更多的功耗模式,并且對每種模式進行了增強,以使CPU在這些低功耗模式下消耗更少的功率。

CPU的每個狀態都使用不同的電量,并且對應用程序性能的影響也不同。
每當CPU內核處于空閑狀態時,內置的節能邏輯就會啟動,并嘗試將內核從當前的C狀態轉換為更高的C狀態,從而關閉各種處理器組件以節省功耗

但是你還需要了解,每次應用程序嘗試在一個CPU來執行某些任務時,相應的CPU必須從其“更深的睡眠狀態”返回到“運行狀態”,這需要更多時間來喚醒計算機。 CPU并再次100%啟動并運行。這個過程還必須在原子環境中完成,以便在啟動CP U核心時沒有任何人嘗試使用cpu核心。

因此,CPU過渡到的各種C模式稱為C-state。
它們通常從C0開始,但C0比較特殊,它正常的CPU工作模式,即CPU已100%的開啟。
隨著C-state級別的增加,CPU睡眠模式會更深,即,更多的電路和信號將被關閉,并且CPU需要更多的時間才能返回到C0模式(即喚醒)。
每種模式也有一個名稱,其中每個c-state具有不同的省電策略,有些c級別還有不同的子模式。

下面鏈接有各級別cstate說明,intel手冊上也有詳細描述。

https://access.redhat.com/solutions/202743

mode	Name	What id does	CPUs
C0	Operating State	CPU fully turned on	All CPUs
C1	Halt	Stops CPU main internal clocks via software; bus interface unit and APIC are kept running at full speed	486DX4 and above
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	All socket 775 CPUs
C1E	--	Stops all CPU internal clocks	Turion 64, 65-nm Athlon X2 and Phenom CPUs
C2	Stop Grant	Stops CPU main internal clocks via hardware; bus interface unit and APIC are kept running at full speed	486DX4 and above
C2	Stop Clock	Stops CPU internal and external clocks via hardware	Only 486DX4, Pentium, Pentium MMX, K5, K6, K6-2, K6-III
C2E	Extended Stop Grant	Stops CPU main internal clocks via hardware and reduces CPU voltage; bus interface unit and APIC are kept running at full speed	Core 2 Duo and above (Intel only)
C3	Sleep	Stops all CPU internal clocks	Pentium II, Athlon and above, but not on Core 2 Duo E4000 and E6000
C3	Deep Sleep	Stops all CPU internal and external clocks	Pentium II and above, but not on Core 2 Duo E4000 and E6000; Turion 64
C3	AltVID	Stops all CPU internal clocks and reduces CPU voltage	AMD Turion 64
C4	Deeper Sleep	Reduces CPU voltage	Pentium M and above, but not on Core 2 Duo E4000 and E6000 series; AMD Turion 64
C4E/C5	Enhanced Deeper Sleep	Reduces CPU voltage even more and turns off the memory cache	Core Solo, Core Duo and 45-nm mobile Core 2 Duo only
C6	Deep Power Down	Reduces the CPU internal voltage to any value, including 0 V	45-nm mobile Core 2 Duo only
C7	Deep Energy Saving	The CPU tries to flush its L3 cache. If the L3 cache is able to be entirely cleared, the CPU cuts its power to save energy. The power from the system agent is removed too.	—
C7s	—	When an MWAIT(C7) command is issued with a C7s sub-state hint, the entire L3 cache is flushed in one step as opposed to flushing the L3 cache in multiple steps. This also allows the system to send I/O devices to low power mode to reduce unnecessary power consumption when the system idles down.	—
C8	—	The L3 cache is flushed in a single step. The power to the PLL is cut.	—
C9	—	The VCCIN (VCC Input Voltage) gets lowered to a minimum.	—
C10	—	The single phase core management system, VR12.6, goes into a low-power state. The CPU is almost shut down.	—

Jetbrains全家桶1年46,售后保障穩定

2. 如何禁用處理器睡眠狀態?

對延遲敏感的應用程序不希望處理器進入到更深的C狀態,因為從C狀態返回到C0會引起延遲。這些延遲的范圍可以從數百微秒到毫秒。

有幾種方法可以實現此目的。

方法1

通過使用內核命令行參數processor.max_cstate = 0、intel_idle.max_cstate=0進行引導,讓系統不進入深度的C狀態。可以在grub2文件中添加這些變量。

**為什么要設置2個參數,分別代表什么? **

具體作用:
1)intel_idle.max_cstate=0
在intel平臺上,模式會使用intel cpuidle drviver,intel_idle.max_cstate=0 意味著禁用intel cpuidle driver,讓其退化使用acpi driver。

2)processor.max_cstate=0
processor.max_cstate=0用描述acpi driver中cpu cstate的最大級別,但是實際max_cstate=0并不能真的讓CPU保持在C0態,只能讓CPU保持在C1狀態。如下代碼:

Note that intel_idle.max_state = 0 disables intel_idle and lets acpi_idle (processor.max_state) take over.

vim /usr/src/debug/kernel-3.10.0-693.19.1.el7/linux-3.10.0-693.19.1.el7.x86_64/drivers/idle/intel_idle.c
(... set number ...)
 889 /*
 890  * intel_idle_probe()
 891  */
 892 static int __init intel_idle_probe(void)
 893 {
 894         unsigned int eax, ebx, ecx;
 895         const struct x86_cpu_id *id;
 896 
 897         if (max_cstate == 0) {
 898                 pr_debug(PREFIX "disabled\n");
 899                 return -EPERM;
 900         }
(...)

looking at the acpi processor_idle code:

Raw
vim /usr/src/debug/kernel-3.10.0-693.19.1.el7/linux-3.10.0-693.19.1.el7.x86_64/drivers/acpi/processor_idle.c
(... set number ...)
 915         if (max_cstate == 0)
 916                 max_cstate = 1;
(...)

the acpi_idle driver doesn’t allow locking to C0, i.e. the effect of the following two boot command lines is the same:

processor.max_cstate=0 intel_idle.max_cstate=0
processor.max_cstate=1 intel_idle.max_cstate=0 (與上面等效)

方法2

第二種方法是使用電源管理服務質量接口(PM QOS)。

文件**/dev/cpu_dma_latency**是一個字符設備,當打開該接口時,它會注冊一個服務質量請求以請求操作系統的延遲。

程序應打開**/dev/cpu_dma_latency**,向其寫入一個32位數字,該數字表示最大響應時間(以微秒為單位),寫入零表示您想要最快的響應時間。
通常cpu_dma_latency被系統tuned服務使用,通過配置文件來修改cpu _dma_latency的值,下面是是tuned配置文件中的一部分:

[cpu]  
force_latency = 1

通常只要調整latency后,cpu_dma_latency文件處于激活狀態,該文件描述符將始終處于打開狀態

[root@localhost ~]# lsof | grep cpu_dma
tuned    1709   root   11w     CHR   10,61   0t0   2219  /dev/cpu_dma_latency

tuned的配置文件將force_latency寫為1,作用:以確保CPU C-state不會進入除C1之外的更深的C狀態。

3. 如何讀取及解釋/dev/cpu_dma_latency?

我們可以使用hexdump工具來讀此文件,如下示例:

[root@localhost ~]# cat /dev/cpu_dma_latency 
?5w[root@localhost ~]#
[root@localhost ~]# hexdump /dev/cpu_dma_latency 
0000000 9400 7735                              
0000004
[root@localhost ~]# echo $((0x77359400))
2000000000
[root@localhost ~]#

cpu_dma_latency反饋的數值,表示當前等待時間值為2000秒,這是CPU從較深的C狀態變為C0所需或需要的時間。

在RedHat 7上,默認設置為2000秒。我們使用force_latency = 1設置調整cpu_dma_latency時,可以用tuned-adm命令來調整。

例如,我們設置tuned模式為latency-performance:

[root@localhost ~]# tuned-adm active
Current active profile: balanced
[root@localhost ~]# tuned-adm list
Available profiles:
- balanced
- desktop
- latency-performance
- network-latency
- network-throughput
- powersave
- test
- throughput-performance
- virtual-guest
- virtual-host
Current active profile: balanced
[root@localhost ~]# 
[root@localhost ~]# head /lib/tuned/latency-performance/tuned.conf | grep latency -a1
[cpu]
force_latency=1
governor=performance
[root@localhost ~]# 
[root@localhost ~]# tuned-adm profile latency-performance
[root@localhost ~]#
[root@localhost ~]# hexdump /dev/cpu_dma_latency
0000000 0001 0000                              
0000004
[root@localhost ~]#

可以看到,等待時間值已更改為1微秒。

由于cpu_dma_latency(PM qos)會影響到cpuidle driver的governor的處理邏輯,所以會影響不同C-state的進入。

cpuidle有2種governor:laddermenu,分別代表按順序計入C-state,和選擇進入

cpu在進入idle時,會通過cpuidle governor的策略選擇合適的C-state進入。

static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
{
        struct menu_device *data = &__get_cpu_var(menu_devices);
        int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); //讀取cpu_dma_latency
        int i;
        int multiplier;
        struct timespec t;

        if (data->needs_update) {
                menu_update(drv, dev);
                data->needs_update = 0;
        }

        data->exit_us = 0;

        /* Special case when user has set very strict latency requirement */
        if (unlikely(latency_req == 0)) 
                return 0;

        /* determine the expected residency time, round up */
        t = ktime_to_timespec(tick_nohz_get_sleep_length());
        data->expected_us =
                t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;


        data->bucket = which_bucket(data->expected_us);

        multiplier = performance_multiplier();

        /*
         * if the correction factor is 0 (eg first time init or cpu hotplug
         * etc), we actually want to start out with a unity factor.
         */
        if (data->correction_factor[data->bucket] == 0)
                data->correction_factor[data->bucket] = RESOLUTION * DECAY;

        /* Make sure to round up for half microseconds */
        data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
                                         RESOLUTION * DECAY);

        get_typical_interval(data);

        if (CPUIDLE_DRIVER_STATE_START > 0) {
                data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1;
                /*
                 * We want to default to C1 (hlt), not to busy polling
                 * unless the timer is happening really really soon.
                 */
                if (data->expected_us > 5 &&
                    !drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
                        dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
                        data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
        } else {
                data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
        }

        /*
         * Find the idle state with the lowest power while satisfying
         * our constraints.
         */
        for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
                struct cpuidle_state *s = &drv->states[i];
                struct cpuidle_state_usage *su = &dev->states_usage[i];

                if (s->disabled || su->disable)
                        continue;
                if (s->target_residency > data->predicted_us)
                        continue;
                if (s->exit_latency > latency_req) //與cpu_dma_latency對比,小于才會選下一個C-state
                        continue;
                if (s->exit_latency * multiplier > data->predicted_us)
                        continue;

                data->last_state_idx = i;
                data->exit_us = s->exit_latency;
        }

        return data->last_state_idx;
}

4. CPU允許的最大C-state是多少?

intel CPU一般會有多個CPU c-state,但實際也要根據cmdline的中提供的max_cstate設定值,具體來說不同型號的處理器所允許的最大c狀態會有所不同

比如:在我的筆記本上查看,共有9個C-state級別,移動設備會更注重功耗

root@ThinkPad-T450:/work/kernel # cat /sys/module/intel_idle/parameters/max_cstate
9

5. 如何檢查不同C-state的喚醒延遲值?

延遲時間值可能會根據各種C-state以及從更深的C-state到C0的過渡時間而變化。

sysfs中查看CPU每個C-state的exit_latency延遲值: (exit_latency由驅動指定

root@ThinkPad-T450:/sys/devices/system/cpu/cpu2/cpuidle # for state in state{0..8};do echo c-$state `cat $state/name` `cat $state/latency`;done
c-state0 POLL 0
c-state1 C1 2
c-state2 C1E 10
c-state3 C3 40
c-state4 C6 133
c-state5 C7s 166
c-state6 C8 300
c-state7 C9 600
c-state8 C10 2600
root@ThinkPad-T450:/sys/devices/system/cpu/cpu2/cpuidle #

6. 如何檢查和監視Linux中每個CPU和內核的CPU c狀態使用情況?

intel平臺可以使用turbostat工具,該工具
可以查所有可用CPU核心的c-state使用量及占用百分比。

root@ThinkPad-T450:/work/kernel # turbostat -q
^CCore	CPU	Avg_MHz	Busy%	Bzy_MHz	TSC_MHz	IRQ	SMI	POLL	C1	C1E	C3	C6	C7s	C8	C9	C10	POLL%	C1%	C1E%	C3%	C6%	C7s%	C8%	C9%	C10%	CPU%c1	CPU%c3	CPU%c6	CPU%c7	CoreTmp	PkgTmp	Pkg%pc2	Pkg%pc8	Pkg%pc9	Pk%pc10	PkgWatt	CorWatt	GFXWatt
-	-	267	18.28	1463	2194	10021	0	23	220	1256	3391	1215	3465	1724	875	25	0.00	0.17	1.24	10.16	6.61	25.43	20.23	17.59	0.32	15.69	13.53	8.55	43.94	46	47	0.00	0.00	0.00	0.00	4.20	1.58	0.33
0	0	249	18.09	1377	2195	2460	0	7	45	305	849	295	817	451	222	0	0.00	0.14	1.20	9.88	6.54	24.14	21.03	19.08	0.00	13.70	14.46	8.62	45.13	46	47	0.00	0.00	0.00	0.00	4.20	1.58	0.33
0	1	215	15.70	1374	2194	2573	0	2	57	372	933	317	895	437	230	5	0.00	0.21	1.31	11.59	6.57	25.82	19.51	18.87	0.53	16.08
1	2	291	18.92	1543	2194	2678	0	8	67	337	866	318	940	408	185	11	0.00	0.27	1.58	10.29	6.77	27.23	20.14	14.34	0.45	17.24	12.60	8.47	42.76	46
1	3	312	20.43	1533	2195	2310	0	6	51	242	743	285	813	428	238	9	0.00	0.06	0.88	8.90	6.57	24.54	20.22	18.06	0.31	15.75
root@ThinkPad-T450:/work/kernel #

在設置max_cstate=0的情況下,CPU最深的C-state為C1

[root@localhost ~]# cat /proc/cmdline 
BOOT_IMAGE=/vmlinuz-3.10.0-693.11.1.el7.es.10.x86_64 root=/dev/mapper/os-root ro console=ttyS0,9600 console=tty0 rootdelay=90 nomodeset 
crashkernel=auto rd.lvm.lv=os/root rd.lvm.lv=os/swap biosdevname=1 net.ifnames=1 rhgb quiet LANG=en_US.UTF-8
processor.max_cstate=0 intel_idle.max_cstate=0
[root@localhost ~]#
[root@localhost ~]# turbostat 
	Core	CPU	Avg_MHz	Busy%	Bzy_MHz	TSC_MHz	IRQ	SMI	CPU%c1	CPU%c3	CPU%c6	CoreTmp	Pkg%pc3	Pkg%pc6
	-	-	8	0.52	1600	2394	2219	176	99.48	0.00	0.00	34	0.00	0.00
	0	1	1	0.08	1600	2394	300	11	99.92	0.00	0.00	32	0.00	0.00
	0	9	0	0.03	1600	2394	24	11	99.97
	1	3	1	0.06	1600	2394	73	11	99.94	0.00	0.00	29
	1	11	117	7.33	1600	2394	411	11	92.67
	9	5	1	0.07	1600	2394	89	11	99.93	0.00	0.00	26
	9	13	1	0.04	1600	2394	47	11	99.96
	10	7	1	0.05	1600	2394	61	11	99.95	0.00	0.00	28
	10	15	1	0.05	1600	2394	39	11	99.95
	0	0	1	0.09	1600	2394	264	11	99.91	0.00	0.00	29	0.00	0.00
	0	8	0	0.03	1600	2394	46	11	99.97
	1	2	1	0.08	1600	2394	177	11	99.92	0.00	0.00	32
	1	10	1	0.08	1600	2394	59	11	99.92
	9	4	2	0.12	1600	2394	237	11	99.88	0.00	0.00	33
	9	12	1	0.04	1600	2394	27	11	99.96
	10	6	2	0.10	1600	2394	287	11	99.90	0.00	0.00	34
	10	14	2	0.13	1600	2394	78	11	99.87
^C
[root@localhost ~]#

7. 什么叫POLL idle狀態?

前面看到的結果,都不能讓CPU完全不進入C-state,因為cpu idle enter代碼進入了C1狀態,cmdlind添加idle=poll參數可以讓CPU完全處于C0狀態,當CPU空閑時其實是執行busy-loop,但是TOP并看不出來。

POLL idle狀態不是真正的空閑狀態,它不節省任何功率。取而代之的是,執行busy-waiting。如果足夠了解你的應用程序,對延遲很敏感,讓內核知道必須盡快處理工作,因為進入任何實際的硬件空閑狀態可能會導致輕微的性能損失,則可以使用此狀態。

X86體系結構平臺上存在兩種不同的cpuidle驅動程序:

“ acpi_idle” cpuidle驅動程序
acpi_idle cpuidle驅動程序從ACPI BIOS表(從最新平臺上的_CST ACPI函數或從較舊平臺上的FADT BIOS表)檢索可用的睡眠狀態(C狀態)。不會從ACPI表中檢索C1狀態。如果進入C1狀態,內核將調用hlt指令(或Intel上的mwait)。

“ intel_idle” cpuidle驅動程序
在內核2.6.36中引入了intel_idle驅動程序。它僅服務于最近的Intel CPU(Nehalem,Westmere,Sandybridge,Atoms或更高版本)。在較舊的Intel CPU上,仍使用acpi_idle驅動程序(如果BIOS提供C狀態ACPI表)。intel_idle驅動程序知道處理器的睡眠狀態功能,并忽略ACPI BIOS導出的處理器睡眠狀態表。

8. 為什么操作系統可能會忽略BIOS設置?

https://access.redhat.com/solutions/202743
紅帽鏈接中表示,操作系統可能會基于正在使用的cpidle驅動程序忽略BIOS設置,這刷新了我之前對BIOS C-state設定的認知。

針對不同的硬件廠商,BIOS中的實現也不一樣,有些服務器BIOS中沒有關閉C-state選項,我曾經在一臺dell服務器上進入BIOS設置,并沒有發現有選項可以關閉C-state,或C-state的相關配置。

如果使用intel_idle(intel計算機上的默認設置),則OS可以忽略ACPI和BIOS設置,即驅動程序可以重新啟用C狀態
如果禁用intel_idle并使用較舊的acpi_idle驅動程序,則操作系統應遵循BIOS設置。
可以通過以下方式禁用intel_idle驅動程序:

將intel_idle.max_cstate = 0傳遞到內核命令行或傳遞idle = xxx (其中*可以例如是poll,即idle = poll)

目前來看,關于C-state,使用OS來控制C-state的進出是最穩妥的做法。
比如:添加“idle=poll”內核參數,可以讓CPU完全不進入C-state。

9. 如何查看當前加載的驅動程序?

intel_idle驅動程序是支持現代Intel處理器的CPU idle驅動程序。
intel_idle驅動程序為內核提供目標駐留時間和每個受支持的英特爾處理器的退出延遲時間。
cpu_idle memu governor用此數據來預測CPU空閑多長時間

root@ThinkPad-T450:/work/kernel # cat /sys/devices/system/cpu/cpuidle/current_driver 
intel_idle
root@ThinkPad-T450:/work/kernel # cat /sys/devices/system/cpu/cpuidle/current_governor_ro 
menu
root@ThinkPad-T450:/work/kernel #

總結

以上是生活随笔為你收集整理的CPU C-state &amp; cpuidle driver[通俗易懂]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。