CPU性能调节【ChatGPT】

CPU性能调节

概念

现代处理器大多具有多种不同的时钟频率和电压配置,通常称为操作性能点或 P 状态(在 ACPI 术语中)。一般来说,时钟频率和电压越高,CPU 在单位时间内可以执行的指令数量就越多,但同时能耗也会随之增加。因此,在 CPU 容量(单位时间内可以执行的指令数量)和 CPU 消耗的功率之间存在自然的权衡关系。

在某些情况下,希望或甚至需要尽可能快地运行程序,这时就没有理由使用低于最高性能频率/电压配置的 P 状态。然而,在其他情况下,可能并不需要那么快地执行指令,并且在相对长时间内保持最高的 CPU 容量而没有完全利用它可能被视为浪费。出于热量或电源供应能力等原因,长时间保持最大 CPU 容量可能并不可行。为了应对这些情况,处理器提供了硬件接口,允许在不同的频率/电压配置之间切换,或者(在 ACPI 术语中)进入不同的 P 状态。

通常,这些接口与估算所需 CPU 容量的算法一起使用,以决定将 CPU 放入哪些 P 状态。当然,由于系统利用率通常会随时间变化,因此需要定期重复执行这一过程。这种活动被称为 CPU 性能调整或 CPU 频率调整(因为它涉及调整 CPU 时钟频率)。

Linux中的CPU性能调节

Linux内核通过CPUFreq(CPU频率调整)子系统支持CPU性能调整,它由三层代码组成:核心、调频调度器和调频驱动程序。

CPUFreq核心提供了支持CPU性能调整的所有平台的通用代码基础设施和用户空间接口。它定义了其他组件操作的基本框架。

调频调度器实现了估算所需CPU容量的算法。一般来说,每个调频调度器实现了一个(可能是带参数的)调频算法。

调频驱动程序与硬件进行通信。它们向调频调度器提供有关可用P状态(或在某些情况下是P状态范围)的信息,并访问特定于平台的硬件接口,以根据调频调度器的请求更改CPU的P状态。

原则上,所有可用的调频调度器都可以与每个调频驱动程序一起使用。这种设计基于这样的观察:在大多数情况下,用于P状态选择的性能调整算法所使用的信息可以以平台无关的形式表示,因此应该可以使用完全相同的性能调整算法,而不管使用哪个调频驱动程序。因此,相同的调频调度器集应适用于每个支持的平台。

然而,对于基于硬件本身提供的信息的性能调整算法,这种观察可能不成立,例如通过反馈寄存器提供的信息,因为该信息通常特定于它来自的硬件接口,并且可能不容易以抽象的、平台无关的方式表示。因此,CPUFreq允许调频驱动程序绕过调频调度器层,并实现自己的性能调整算法。这就是intel_pstate调频驱动程序所做的事情。

CPUFreq策略对象

在某些情况下,用于控制 P 状态的硬件接口是由多个 CPU 共享的。也就是说,例如,同一个寄存器(或一组寄存器)被用于同时控制多个 CPU 的 P 状态,对其进行写操作会同时影响所有这些 CPU。

共享硬件 P 状态控制接口的 CPU 集合在 CPUFreq 中被表示为 struct cpufreq_policy 对象。为了保持一致性,当给定集合中只有一个 CPU 时,也会使用 struct cpufreq_policy。

CPUFreq 核心为系统中的每个 CPU 维护一个指向 struct cpufreq_policy 对象的指针,包括当前处于离线状态的 CPU。如果多个 CPU 共享相同的硬件 P 状态控制接口,那么与它们对应的所有指针都指向同一个 struct cpufreq_policy 对象。

CPUFreq 使用 struct cpufreq_policy 作为其基本数据类型,并且其用户空间接口的设计是基于策略概念的。

CPU初始化

首先,要使 CPUFreq 正常工作,必须注册一个调频驱动程序。一次只能注册一个调频驱动程序,因此期望调频驱动程序能够处理系统中的所有 CPU。

调频驱动程序可以在 CPU 注册之前或之后进行注册。如果 CPU 较早注册,那么在注册调频驱动程序时,驱动程序核心会调用 CPUFreq 核心,以记录所有已注册的 CPU。反之,如果有任何 CPU 在调频驱动程序注册之后注册,CPUFreq 核心将在它们注册时被调用以记录它们。

无论如何,一旦准备好处理某个 CPU,CPUFreq 核心就会被调用以记录它之前尚未见过的逻辑 CPU。[请注意,逻辑 CPU 可能是物理单核处理器,或者是多核处理器中的单个核心,或者是物理处理器或处理器核心中的硬件线程。在下文中,“CPU”除非另有说明,否则始终指“逻辑 CPU”,而“处理器”用于指代可能包含多个逻辑 CPU 的物理部分。]

一旦被调用,CPUFreq 核心会检查给定 CPU 的策略指针是否已经设置,如果已经设置,则跳过策略对象的创建。否则,将创建并初始化一个新的策略对象,这涉及在 sysfs 中创建一个新的策略目录,并将与给定 CPU 对应的策略指针设置为新策略对象在内存中的地址。

接下来,调频驱动程序的 ->init() 回调将以新 CPU 的策略指针作为参数被调用。该回调应该初始化给定 CPU(或者更准确地说,表示其所属硬件接口的一组 CPU)的性能调整硬件接口,并且如果它被调用的策略对象是新的,还应该设置策略的参数,比如硬件支持的最小和最大频率、可用频率表(如果支持的 P 状态不是一个连续的范围),以及属于同一策略的 CPU 掩码(包括在线和离线的 CPU)。然后,核心会使用该掩码为其中的所有 CPU 填充策略指针。

对于新策略对象的下一个重要初始化步骤是将一个调频调度器附加到它上面(首先是由内核命令行或配置确定的默认调频调度器,但可以通过 sysfs 后续更改)。首先,将新策略对象的指针传递给调频调度器的 ->init() 回调,该回调应该初始化处理给定策略所需的所有数据结构,并可能向其添加一个调频调度器的 sysfs 接口。接下来,通过调用其 ->start() 回调来启动调频调度器。

该回调应该为给定策略中所有在线 CPU 向 CPU 调度器注册每个 CPU 利用率更新回调。利用率更新回调将由 CPU 调度器在重要事件(如任务入队和出队)发生时、在每次调度器滴答迭代时,或者通常在 CPU 利用率可能发生变化时(从调度器的角度来看)被调用。它们应该执行所需的计算,以确定未来使用的 P 状态,并调用调频驱动程序根据 P 状态选择进行硬件更改。根据调频驱动程序和调频调度器的配置和能力,调频驱动程序可以直接从调度器上下文中调用,也可以通过内核线程或工作队列进行异步调用。

对于以前处于“非活动”状态的策略对象,也会采取类似的步骤,这意味着它们之前的所有 CPU 都是离线的。在这种情况下,唯一的实际区别是 CPUFreq 核心将尝试使用先前与变为“非活动”状态的策略相关联的调频调度器(现在重新初始化)而不是默认调频调度器。

另外,如果以前处于离线状态的 CPU 正在重新上线,但与之共享策略对象的其他 CPU 已经在线,那么根本不需要重新初始化策略对象。在这种情况下,只需要重新启动调频调度器,以便它可以考虑新上线的 CPU。这是通过按照这个顺序调用调频调度器的 ->stop 和 ->start() 回调来实现的。

如前所述,intel_pstate 调频驱动程序绕过 CPUFreq 的调频调度器层,并提供自己的 P 状态选择算法。因此,如果使用 intel_pstate,新策略对象不会附加调频调度器。相反,将调用驱动程序的 ->setpolicy() 回调,为每个策略注册每个 CPU 的利用率更新回调。这些回调将由 CPU 调度器以与调频调度器相同的方式调用,但在 intel_pstate 的情况下,它们既确定要使用的 P 状态,又从调度器上下文中一次性地相应地更改硬件配置。

在调频驱动程序注销时(例如,当包含它的内核模块被卸载时)或者当最后一个属于给定策略的 CPU 被注销时,与 CPU 初始化时创建的策略对象和其他相关数据结构都会被清除。

策略接口在sysfs中

在内核初始化期间,CPUFreq 核心会在 /sys/devices/system/cpu/ 下创建一个名为 cpufreq 的 sysfs 目录(kobject)。

该目录包含一个名为 policyX 的子目录(其中 X 代表一个整数) ,对应 CPUFreq 核心维护的每个策略对象。对于与给定策略相关联(或属于)的所有 CPU,/sys/devices/system/cpu/cpuY/(其中 Y 代表一个可能与 X 不同的整数)下的 cpufreq 符号链接指向每个 policyX 目录。在 /sys/devices/system/cpu/cpufreq 中的每个 policyX 目录都包含特定于策略的属性(文件),用于控制相应策略对象(即与它们相关联的所有 CPU)的 CPUFreq 行为。

其中一些属性是通用的。它们由 CPUFreq 核心创建,它们的行为通常不依赖于使用的调频驱动程序以及附加到给定策略的调频调度器。一些调频驱动程序还会在 sysfs 中的策略目录中添加特定于驱动程序的属性,以控制驱动程序行为的特定方面。

/sys/devices/system/cpu/cpufreq/policyX/目录下的通用属性如下:

  • affected_cpus:属于该策略的在线CPU列表(即共享由policyX策略对象表示的硬件性能调节接口)。
  • bios_limit:如果平台固件(BIOS)告诉操作系统对CPU频率施加了上限,该限制将通过此属性报告(如果存在)。
    • 该限制的存在可能是由于一些(通常是无意的)BIOS设置、来自服务处理器或其他基于BIOS/HW的机制的限制。
    • 这不包括可以通过通用热管理驱动程序发现的ACPI热限制。
    • 如果使用的缩放驱动程序不支持此属性,则该属性不存在。
  • cpuinfo_cur_freq:从硬件获取的属于该策略的CPU当前频率(以千赫为单位)。
    • 预期这是硬件实际运行的频率。如果无法确定该频率,则该属性不应存在。
  • cpuinfo_max_freq:属于该策略的CPU可以运行的最大可能操作频率(以千赫为单位)。
  • cpuinfo_min_freq:属于该策略的CPU可以运行的最小可能操作频率(以千赫为单位)。
  • cpuinfo_transition_latency:将属于该策略的CPU从一个P状态切换到另一个P状态所需的时间,以纳秒为单位。
    • 如果未知,或者已知为非常高,以至于缩放驱动程序无法与ondemand调节器一起工作,则从该属性读取将返回-1(CPUFREQ_ETERNAL)。
  • related_cpus:属于该策略的所有(在线和离线)CPU的列表。
  • scaling_available_governors:内核中存在的可以附加到该策略的CPUFreq调节器或(如果使用intel_pstate缩放驱动程序)可以应用于该策略的驱动程序提供的缩放算法的列表。
    • [注意:某些调节器是模块化的,可能需要加载一个内核模块,以使其持有的调节器可用并被列在此属性中。]
  • scaling_cur_freq:属于该策略的所有CPU的当前频率(以千赫为单位)。
    • 在大多数情况下,这是缩放驱动程序通过其提供的缩放接口从硬件请求的最后一个P状态的频率,这可能反映或者不反映CPU实际运行的频率(由于硬件设计和其他限制)。
  • scaling_driver:当前使用的缩放驱动程序。
  • scaling_governor:当前附加到该策略的缩放调节器或(如果使用intel_pstate缩放驱动程序)当前应用于该策略的驱动程序提供的缩放算法。
    • 该属性是可读写的,对其进行写操作将导致一个新的缩放调节器被附加到该策略,或者一个新的由缩放驱动程序提供的缩放算法被应用于该策略(在intel_pstate情况下),写入该属性的字符串必须是scaling_available_governors属性中描述的名称之一。
  • scaling_max_freq:属于该策略的CPU被允许运行的最大频率(以千赫为单位)。
    • 该属性是可读写的,向其写入表示整数的字符串将导致设置一个新的限制(它不能低于scaling_min_freq属性的值)。
  • scaling_min_freq:属于该策略的CPU被允许运行的最小频率(以千赫为单位)。
    • 该属性是可读写的,向其写入表示非负整数的字符串将导致设置一个新的限制(它不能高于scaling_max_freq属性的值)。
  • scaling_setspeed:仅当用户空间缩放调节器附加到给定策略时,此属性才可用。
    • 它返回调节器请求的最后一个频率(以千赫为单位),或者可以写入以设置策略的新频率。

通用的频率调节器

CPUFreq提供了通用的频率调节器,可以与所有调节驱动程序一起使用。正如前面所述,每个调节器实现了一个单一的、可能是带参数的性能调节算法。

调节器附加到策略对象上,不同的策略对象可以同时由不同的调节器处理(尽管在某些情况下可能会导致次优的结果)。

给定策略对象的调节器可以随时通过sysfs中的scaling_governor策略属性来更改。

一些调节器公开了sysfs属性,用于控制或微调它们实现的调节算法。这些属性被称为调节器可调参数,可以是全局的(系统范围)或每个策略的,这取决于所使用的调节驱动程序。如果驱动程序要求调节器可调参数是每个策略的,它们位于每个策略目录的子目录中。否则,它们位于/sys/devices/system/cpu/cpufreq/的子目录中。在任何一种情况下,包含调节器可调参数的子目录的名称是提供它们的调节器的名称。

performance

当附加到策略对象时,此调节器会导致在该策略中请求最高频率,不超过scaling_max_freq策略限制。

请求是在设置策略的调节器为performance时进行一次,并且在此之后,scaling_max_freq或scaling_min_freq策略限制发生变化时进行。

powersave

当附加到策略对象时,此调节器会导致在该策略中请求最低频率,不低于scaling_min_freq策略限制。

请求是在设置策略的调节器为powersave时进行一次,并且在此之后,scaling_max_freq或scaling_min_freq策略限制发生变化时进行。

userspace

此调节器本身不执行任何操作。相反,它允许用户空间通过写入该策略的scaling_setspeed属性来设置其所附加的CPU频率。

schedutil

此调节器使用CPU调度器中可用的CPU利用率数据。它通常被视为CPU调度器的一部分,因此可以直接访问调度器的内部数据结构。

它完全在调度器上下文中运行,尽管在某些情况下,当它决定应该为给定策略更改CPU频率时,它可能需要异步调用调节驱动程序(这取决于驱动程序是否能够从调度器上下文中更改CPU频率)。

此调节器对于特定CPU的操作取决于调用其利用率更新回调的调度类。如果它是由RT或deadline调度类调用的,调节器将增加频率到允许的最大值(即scaling_max_freq策略限制)。反之,如果它是由CFS调度类调用的,调节器将使用给定CPU的根控制组的Per-Entity Load Tracking (PELT)指标作为CPU利用率估计(有关PELT机制的描述,请参阅Per-entity load tracking LWN.net文章)。然后,根据以下公式计算要应用的新CPU频率:

f = 1.25 * f_0 * util / max

其中,util是PELT数,max是util的理论最大值,f_0要么是给定策略的最大可能CPU频率(如果PELT数是频率不变的),要么是当前CPU频率(否则)。

此调节器还采用一种机制,允许它临时提高最近等待I/O的任务的CPU频率,称为"IO-wait boosting"。当调度器将SCHED_CPUFREQ_IOWAIT标志传递给调节器回调时,会导致频率立即提高到允许的最大值,然后随着时间的推移,频率会回到上述公式返回的值。

此调节器仅公开一个可调参数:

  • rate_limit_us

    两次调节器计算之间必须经过的最短时间(以微秒为单位)(默认值:scaling驱动程序的过渡延迟的1000倍)。

    此可调参数的目的是减少调节器的调度器上下文开销,否则可能过大。

一般认为,此调节器是对旧的ondemand和conservative调节器(下文有描述)的替代,因为它更简单,与CPU调度器集成更紧密,其在CPU上下文切换方面的开销不太显著,并且它使用调度器自己的CPU利用率指标,因此原则上其决策不应与调度器的其他部分的决策相矛盾。

ondemand

此调节器使用CPU负载作为CPU频率选择指标。

为了估算当前CPU负载,它测量了连续调用其工作例程之间经过的时间,并计算了给定CPU非空闲时间的时间比。将非空闲(活动)时间与总CPU时间的比率作为负载的估计。

如果此调节器附加到多个CPU共享的策略上,则对所有CPU估计负载,并将最大结果作为整个策略的负载估计。

此调节器的工作例程必须在进程上下文中运行,因此它是异步调用的(通过工作队列),并且如果需要,CPU P状态会从那里更新。因此,此调节器的调度器上下文开销最小,但它会相对频繁地导致额外的CPU上下文切换,并且由它触发的CPU P状态更新可能相对不规则。此外,它通过运行减少CPU空闲时间的代码来影响自己的CPU负载指标(尽管它只会轻微地减少CPU空闲时间)。

它通常选择与估计负载成比例的CPU频率,以便cpuinfo_max_freq策略属性的值对应于负载为1(或100%),而cpuinfo_min_freq策略属性的值对应于负载为0,除非负载超过(可配置的)加速阈值,在这种情况下,它将直接使用其允许使用的最高频率(scaling_max_freq策略限制)。

此调节器公开以下可调参数:

  • sampling_rate

    这是调节器工作例程应该运行的频率,以微秒为单位。

    通常,它设置为大约10000(10毫秒)的值。其默认值等于每个此调节器附加的策略的cpuinfo_transition_latency的值(但由于这里的单位大于1000,这意味着sampling_rate所代表的时间默认情况下比过渡延迟大1000倍)。

    如果此可调参数是每个策略的,以下shell命令将设置其代表的时间为过渡延迟的750倍:

    # echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) > ondemand/sampling_rate
    
  • up_threshold

    如果估计的CPU负载高于此值(以百分比表示),调节器将将频率设置为策略允许的最大值。否则,所选频率将与估计的CPU负载成比例。

  • ignore_nice_load

    如果设置为1(默认为0),它将导致CPU负载估算代码将执行"nice"级别大于0的任务的CPU时间视为CPU空闲时间。

    如果系统中有不应在决定在何种频率运行CPU时考虑的任务,则这可能很有用。然后,只需将这些任务的"nice"级别增加到大于0,并将此属性设置为1即可。

  • sampling_down_factor

    临时乘数,介于1(默认值)和100(包括)之间,应用于sampling_rate值,如果CPU负载超过up_threshold。

    这会导致调节器的工作例程的下一次执行(在将频率设置为允许的最大值后)被延迟,因此频率会在最大水平上保持更长时间。

    这样可以避免某些突发工作负载中的频率波动,但会以维持最大CPU容量的额外能量消耗为代价。

  • powersave_bias

    应用于调节器的原始频率目标(包括当估计的CPU负载超过up_threshold值时使用的最大值)的减少因子,或者适用于AMD频率敏感性powersave bias驱动程序(drivers/cpufreq/amd_freq_sensitivity.c)的灵敏度阈值,介于0和1000之间。

    如果未加载AMD频率敏感性powersave bias驱动程序,则应用的有效频率由以下公式给出:

      f * (1 - powersave_bias / 1000)
    

    其中,f是调节器的原始频率目标。在这种情况下,此属性的默认值为0。

    如果加载了 AMD 频率敏感性节能偏置驱动程序,则该属性的默认值为 400,并且它的使用方式有所不同。

    在 Family 16h(及更高版本)的 AMD 处理器上,存在一种机制可以从硬件中获取一个介于 0 和 100%(包括边界值)之间的测得工作负载敏感性值。该值可用于估计运行在 CPU 上的工作负载在响应频率变化时性能的变化情况。

    具有 0 敏感性(内存绑定或 IO 绑定)的工作负载的性能预计不会因增加 CPU 频率而有所提高,而具有 100% 敏感性(CPU 绑定)的工作负载预计在增加 CPU 频率时将表现得更好。

    如果工作负载的敏感性低于 powersave_bias 值所代表的阈值,敏感性节能偏置驱动程序将导致调频调度器选择比其原始目标更低的频率,以避免为那些不会受益于以更高 CPU 频率运行的工作负载进行过度配置。

conservative

此调节器使用CPU负载作为CPU频率选择指标。

它以与上述ondemand调节器相同的方式估算CPU负载,但它实现的CPU频率选择算法不同。

即它避免在短时间间隔内显著改变频率,这可能不适合供电能力有限的系统(例如,使用电池供电的系统)。为了实现这一点,它以相对较小的步长逐步改变频率,一次一步,向上或向下 - 取决于估计的CPU负载是否超过了(可配置的)阈值。

此调节器公开以下可调参数:

  • freq_step

    频率步长,作为调节器允许设置的最大频率(scaling_max_freq策略限制)的百分比,介于0和100之间(默认值为5)。

    这是频率允许一次性改变的量。将其设置为0将导致使用默认频率步长(5%),将其设置为100实际上会导致调节器周期性地在scaling_min_freq和scaling_max_freq策略限制之间切换频率。

  • down_threshold

    阈值(以百分比表示,默认为20),用于确定频率变化的方向。

    如果估计的CPU负载大于此值,频率将增加(按freq_step)。如果负载小于此值(且sampling_down_factor机制未生效),频率将降低。否则,频率将不会改变。

  • sampling_down_factor

    频率降低延迟因子,介于1(默认值)和10之间。

    它实际上导致频率下降sampling_down_factor倍慢于上升。

频率提升支持

背景

一些处理器支持一种机制,可以在特定条件下临时提高多核处理器中某些核心的运行频率(甚至超过整个处理器包的可持续频率阈值),例如,如果整个芯片未完全利用并且低于其预期的热量或功率预算。

不同的供应商使用不同的名称来指代这种功能。对于英特尔处理器,它被称为"Turbo Boost",AMD 称之为"Turbo-Core"或(在技术文档中)"Core Performance Boost"等等。一般来说,不同的供应商实现方式也不同。这里简称为"频率提升"以便简洁地指代所有这些实现。

频率提升机制可以是基于硬件或基于软件的。如果是基于硬件的(例如在 x86 上),触发提升的决定是由硬件做出的(尽管一般需要将硬件置于特殊状态,以便在一定范围内控制 CPU 频率)。如果是基于软件的(例如在 ARM 上),则是由缩放驱动程序决定是否触发提升以及何时触发。

sysfs 中的 boost 文件

该文件位于 /sys/devices/system/cpu/cpufreq/,用于控制整个系统的"boost"设置。如果底层的缩放驱动程序不支持频率提升机制(或支持但提供了特定于驱动程序的接口来控制它,比如 intel_pstate),则该文件不存在。

如果该文件中的值为 1,则表示启用了频率提升机制。这意味着硬件可以被置于能够触发提升的状态(在基于硬件的情况下),或者允许软件触发提升(在基于软件的情况下)。这并不意味着当前系统中的任何 CPU 实际上正在使用提升。它只表示允许使用频率提升机制(由于其他原因,可能永远不会使用)。

如果该文件中的值为 0,则表示禁用了频率提升机制,根本无法使用。

可以向该文件写入的唯一值是 0 和 1。

控制提升的原因

频率提升机制通常旨在帮助在软件分辨率下(例如在调度器滴答间隔以下)实现最佳 CPU 性能,并且已经证明适用于许多工作负载,但在某些情况下可能会导致问题。

因此,许多系统允许在平台固件(BIOS)设置中禁用频率提升机制,但这需要重新启动系统才能调整设置,这在某些情况下可能并不实际。例如:

  • 提升意味着超频处理器,尽管在受控条件下。通常,提高频率和电压会导致处理器的能耗增加,即使是暂时的。这在切换到电池等容量有限的电源的系统上可能是不希望看到的,因此在系统运行时禁用提升机制可能有所帮助(但这也取决于工作负载)。
  • 在某些情况下,确定性行为比性能或能耗更重要,因此在系统运行时禁用提升可能会有用。
  • 为了检查频率提升机制本身的影响,可以在运行基准测试之前后能够运行带有和不带有提升的测试,最好是在此期间无需重新启动系统。
  • 在运行基准测试时,重现结果很重要。由于提升功能取决于整个处理器包的负载,因此单线程性能可能会因此而变化,有时可能导致无法重现的结果。通过在运行对此敏感的基准测试之前禁用频率提升机制,可以避免这种情况。

Legacy AMD cpb 开关

AMD powernow-k8 缩放驱动程序支持一个与全局提升开关非常相似的 sysfs 开关。它用于禁用/启用某些 AMD 处理器的"Core Performance Boost"功能。

如果存在该开关,则它位于 sysfs 中的每个 CPUFreq 策略目录(/sys/devices/system/cpu/cpufreq/policyX/)中,并称为 cpb,这表明这是一个更精细的控制接口。然而,实际的实现是基于系统范围的,为一个策略设置该开关会导致所有其他策略同时设置相同的值。

该开关仍然支持支持其底层硬件功能的 AMD 处理器,但它可能已经被配置在内核之外(通过 CONFIG_X86_ACPI_CPUFREQ_CPB 配置选项),而全局提升开关始终存在。因此,始终可以使用全局提升开关来代替 cpb 开关,这是非常推荐的,因为这更符合所有其他系统的做法(而且 cpb 开关将来可能不再受支持)。

对于不具备底层硬件功能的处理器(例如所有英特尔处理器),即使设置了 CONFIG_X86_ACPI_CPUFREQ_CPB 配置选项,cpb 开关也永远不存在。

参考资料

  1. Jonathan Corbet, Per-entity load tracking, 链接
posted @ 2023-12-12 11:00  摩斯电码  阅读(288)  评论(0编辑  收藏  举报