CPU使用率是如何计算的?

Posted

技术标签:

【中文标题】CPU使用率是如何计算的?【英文标题】:How is CPU usage calculated? 【发布时间】:2011-04-14 11:18:21 【问题描述】:

在我的桌面上,我有一个小部件可以告诉我当前的 CPU 使用率。它还显示了我的两个核心中的每一个的使用情况。

我一直想知道,CPU 是如何计算其使用了多少处理能力的?此外,如果 CPU 在执行一些密集计算时挂起,它(或处理此活动的任何东西)如何检查使用情况而不会挂起?

【问题讨论】:

你问的是CPU的电源管理,比如CPU检测它是否耗电和发热?例如,Skylake 在芯片上有一个微控制器来进行电源管理(与 CPU 内核分开),输入来自温度/功率传感器和一些工作负载信息。 (例如,当运行具有大量缓存/TLB 未命中的代码时,它甚至会降频,即使在操作系统方面它正在使用 100% 的 CPU)... ... 这回答了第 2 部分,与第 1 部分(操作系统级负载平均)无关。有关链接,请参阅Why does this delay-loop start to run faster after several iterations with no sleep?。您问的是 CPU 如何检查 它自己的 使用情况,而不是操作系统跟踪 CPU 使用情况。也许这不是你的意思,但这就是对问题的解释的答案:P 【参考方案1】:

CPU 不会自己进行使用率计算。它可能具有使该任务更容易的硬件功能,但这主要是操作系统的工作。所以显然实现的细节会有所不同(尤其是在多核系统的情况下)。

一般的想法是查看 CPU 需要做的事情的队列有多长。操作系统可能会定期查看调度程序以确定它必须做的事情的数量。

This is a function Linux in (ripped from Wikipedia) that performs said calculation:

#define FSHIFT   11  /* nr of bits of precision */
#define FIXED_1  (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals */
#define EXP_1  1884  /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5  2014  /* 1/exp(5sec/5min) */
#define EXP_15 2037  /* 1/exp(5sec/15min) */

#define CALC_LOAD(load,exp,n) \
    load *= exp; \
    load += n*(FIXED_1-exp); \
    load >>= FSHIFT;

unsigned long avenrun[3];

static inline void calc_load(unsigned long ticks)

    unsigned long active_tasks; /* fixed-point */
    static int count = LOAD_FREQ;

    count -= ticks;
    if (count < 0) 
        count += LOAD_FREQ;
        active_tasks = count_active_tasks();
        CALC_LOAD(avenrun[0], EXP_1, active_tasks);
        CALC_LOAD(avenrun[1], EXP_5, active_tasks);
        CALC_LOAD(avenrun[2], EXP_15, active_tasks);
    

至于您问题的第二部分,大多数现代操作系统都是multi-tasked。这意味着操作系统不会让程序占用所有的处理时间并且没有任何自己的时间(unless you make it do that)。换句话说,即使应用程序出现挂起,操作系统仍然可以为自己的工作偷走一些时间。

【讨论】:

"CPU 本身实际上并没有做任何 CPU 使用率计算。" - 对处理器上的工作负载进行采样的操作系统代码在哪里执行? :) @Ani:好吧,没有代码,CPU 不能自己做任何事情,不是吗? :-) 我的意思是没有操作码或机器指令可以告诉你 CPU 使用情况,AFAIK。 @aaa carp:啊,这很有趣,我已经纠正了。虽然我很确定操作系统仍然必须根据性能计数器计算(整体)CPU 使用率。 当然,您仍然需要处理它们,它们只是寄存器中的数字。性能计数器提供了操作系统可能无法提供的非常好的信息,例如缓存未命中等。 @Vatine:我将 OP 的问题解释为与 CPU 负载有关,因为该问题提到了性能。如果 CPU A 有 2 个待处理任务,而 CPU B 有 20 个待处理任务(都执行类似的操作),则两者都可能使用 100% 的 CPU 时间,但 CPU A 的性能更好。【参考方案2】:

    CPU 不会“挂起”,它只是以峰值容量运行,这意味着它每秒处理的指令数量与它的物理能力一样多。 计算 CPU 使用率的进程是其中的一些指令。如果应用程序试图以比 CPU 能力更快的速度执行操作,那么它们只会被延迟,因此会“挂起”。

    CPU 利用率的计算基于总可用利用率。所以如果一个CPU有两个核心,一个核心有30%的使用率,另一个是60%,那么整体的利用率就是45%。您还可以查看每个内核的使用情况。

【讨论】:

【参考方案3】:

一种方法如下:

选择一个采样间隔,比如每 5 分钟(300 秒)的实际经过时间。您可以从gettimeofday 获得此信息。

获取您在这 300 秒内使用的处理时间。您可以使用times() 调用来获取此信息。那将是new_process_time - old_process_time,其中old_process_time 是您从上一个时间间隔保存的处理时间。

那么你的 cpu 百分比就是(process_time/elapsed_time)*100.0 您可以设置一个警报,每 300 秒向您发出信号以进行这些计算。

我不想使用超过某个目标 cpu 百分比的进程。这种方法效果很好,与我的系统监视器非常吻合。如果我们使用过多的 cpu,我们会睡一会儿。

【讨论】:

【参考方案4】:

有很多方法可以做到:

处理器维护几个衡量性能的计数器,您可以使用 Papi 接口访问它们。比如这里简单介绍一下:http://blogs.oracle.com/jonh/entry/performance_counter_generic_events

还有:http://www.drdobbs.com/tools/184406109

您可能需要的计数器是 PAPI_TOT_CYC,它是繁忙周期数(如果我没记错的话)

【讨论】:

【参考方案5】:

有一个特殊的任务叫做空闲任务,当没有其他任务可以运行时运行。 % 使用率只是我们没有运行空闲任务的时间百分比。操作系统将保持运行空闲任务所花费的总时间:

当我们切换到空闲任务时,设置 t = 当前时间 当我们从空闲任务切换时,将(当前时间 - t)添加到运行总数中

如果我们将运行总数中的两个样本相隔 n 秒,我们可以计算这 n 秒运行空闲任务的百分比为(第二个样本 - 第一个样本)/n

请注意,这是操作系统所做的,而不是 CPU。任务的概念在 CPU 层面是不存在的! (实际上,空闲任务会通过 HLT 指令使处理器进入睡眠状态,因此 CPU 确实知道何时不使用)

关于第二个问题,现代操作系统是抢先式多任务的,这意味着操作系统可以随时切换离开您的任务。操作系统实际上是如何从您的任务中窃取 CPU 的?中断:http://en.wikipedia.org/wiki/Interrupt

【讨论】:

++ 很好的答案。我还发现自己告诉人们程序正在运行或等待,并且分别使用 100% 或 0% 的内核。他们看到的“百分比利用率”只是一个短期的平均水平。你会认为这很明显,但有时并非如此。 +1 这简洁地解释了一切,谢谢!很高兴知道CPU实际上可以通过使用HLT指令和中断来“什么都不做”。 @tjklemz:有趣的事实:现代 x86 使用 monitor / mwait 指令的特殊参数进入睡眠状态。 hlt saves some power, but only the shallowest sleep state (C1)。相关:software.intel.com/en-us/blogs/2008/03/27/…/software.intel.com/en-us/blogs/2008/04/29/…。请注意,Skylake 最终让操作系统将完全控制权交给了硬件,至少在活动时进行频率缩放,但也许操作系统仍然决定睡眠状态。【参考方案6】:

要获取 CPU 使用率,请定期对进程时间进行采样,并找出差异。

例如,如果这些是进程 1 的 CPU 时间:

kernel: 1:00:00.0000
user:   9:00:00.0000

然后你在两秒钟后再次获得它们,它们是:

kernel: 1:00:00.0300
user:   9:00:00.6100

减去内核时间(差为0.03)和用户时间(0.61),将它们加在一起(0.64),然后除以 2 秒的采样时间(0.32) .

所以在过去两秒内,该进程平均使用了 32% 的 CPU 时间。

获取此信息所需的特定系统调用(显然)在每个平台上都不同。在 Windows 上,您可以使用 GetProcessTimes 或 GetSystemTimes,如果您想要查看已用或空闲 CPU 时间的快捷方式。

【讨论】:

【参考方案7】:

这是我对类似代码的一点接触的基本理解。任务管理器之类的程序或您的小部件访问系统调用(例如 NtQuerySystemInformation())并使用从操作系统收集的信息来简单计算 CPU 空闲或被使用的时间百分比(在标准时间内)。 CPU 知道它什么时候是空闲的,因此它可以确定它什么时候不是空闲的。这些程序确实会被阻塞……当我的笔记本电脑的任务管理器在计算 CPU 使用率达到 100% 时,它会一直冻结。

可以在 MSDN 网站上找到一段很酷的示例代码,其中显示了用于计算一组指令的 CPU 使用率的函数调用:http://msdn.microsoft.com/en-us/library/aa364157(VS.85).aspx

这些系统调用的作用是访问我认为的内核代码……这超出了我的理解范围。

【讨论】:

【参考方案8】:

嗯,据我所知,有一个巨人

while(true)

操作系统启动的循环。您的流程是从该循环中管理的。它允许外部代码以块的形式直接在处理器上执行。毫不夸张地说,这是对实际情况的超级简化。

【讨论】:

以上是关于CPU使用率是如何计算的?的主要内容,如果未能解决你的问题,请参考以下文章

嵌入式软件开发杂谈(10):CPU的使用率是如何计算的

嵌入式软件开发杂谈(10):CPU的使用率是如何计算的

嵌入式软件开发杂谈(10):CPU的使用率是如何计算的

嵌入式软件开发杂谈(10):CPU的使用率是如何计算的

Kubernetes pod cpu 使用率计算方法 HPA

prometheus作为监控,如何计算kubernetes中容器的cpu使用率?