在我的桌面上,我有一个小部件,可以告诉我当前的CPU使用率。它还显示了我两个内核中每个内核的用法。
我一直想知道,CPU如何计算正在使用多少处理能力?此外,如果CPU挂断了一些密集的计算,那么它(或处理此活动的任何对象)如何检查使用情况而又不挂断?
在我的桌面上,我有一个小部件,可以告诉我当前的CPU使用率。它还显示了我两个内核中每个内核的用法。
我一直想知道,CPU如何计算正在使用多少处理能力?此外,如果CPU挂断了一些密集的计算,那么它(或处理此活动的任何对象)如何检查使用情况而又不挂断?
Answers:
The CPU doesn't do the usage calculations by itself. It may have hardware features to make that task easier, but it's mostly the job of the operating system. So obviously the details of implementations will vary (especially in the case of multicore systems).
总体思路是查看CPU需要完成的工作队列有多长时间。操作系统可能会定期查看调度程序,以确定其必须执行的操作数量。
这是Linux中的一个功能(从Wikipedia摘录),用于执行上述计算:
#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);
}
}
至于问题的第二部分,大多数现代操作系统是多任务的。这意味着OS不会让程序占用所有处理时间,而不会自己占用任何处理时间(除非您让它这样做)。换句话说,即使应用程序似乎挂起,操作系统仍可以占用一些时间来完成自己的工作。
当没有其他任务可以运行时,有一个特殊的任务称为空闲任务。使用百分比只是我们不运行空闲任务的时间的百分比。操作系统将保持运行空闲任务所花费的总时间:
如果我们将运行总时间间隔为n秒的两个样本分开,我们可以将运行空闲任务所花费的n秒的百分比计算为(第二个样本-第一个样本)/ n
请注意,这是操作系统执行的操作,而不是CPU。任务的概念在CPU级别不存在!(实际上,空闲任务将使处理器通过HLT指令进入睡眠状态,因此CPU会知道何时不使用处理器)。
关于第二个问题,现代操作系统具有抢先性的多任务功能,这意味着操作系统可以随时退出您的任务。操作系统实际上是如何从任务中窃取CPU的?中断:http : //en.wikipedia.org/wiki/Interrupt
monitor
/mwait
指令进入睡眠状态。 hlt
节省了一些功率,但仅节省了最浅的睡眠状态(C1)。相关阅读:software.intel.com/en-us/blogs/2008/03/27/... / software.intel.com/en-us/blogs/2008/04/29/...。请注意,Skylake最终让OS完全控制硬件,至少在活动时进行频率缩放,但OS仍可以决定睡眠状态。
要获取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总时间。
一种方法如下:
选择一个采样间隔,例如每5分钟(300秒)实际经过的时间。你可以从这里得到gettimeofday
。
获取您在那300秒内使用的处理时间。您可以使用该times()
呼叫获取此信息。这将是new_process_time - old_process_time
,其中old_process_time
是您从上一个时间间隔保存的处理时间。
然后,(process_time/elapsed_time)*100.0
您的cpu百分比就是您可以设置一个警报,使其每300秒发出一次信号来进行这些计算。
我有一个过程,我不想使用超过特定目标cpu百分比的过程。这种方法效果很好,并且与我的系统监视器非常吻合。如果我们使用过多的cpu,我们会睡一会儿。
这是我基本了解类似代码后的基本理解。诸如任务管理器之类的程序或诸如NtQuerySystemInformation()之类的窗口小部件访问系统调用,并使用从OS收集的信息来简单计算CPU空闲或被使用的时间百分比(以标准时间)。CPU知道何时空闲,因此可以确定何时不空闲。这些程序确实可能被阻塞...我的笨拙笔记本电脑的任务管理器在计算CPU使用率时一直冻结,直到达到100%。
可以在MSDN网站上找到很多很酷的示例代码,其中显示了用于计算一组指令的CPU使用率的函数调用:http : //msdn.microsoft.com/zh-cn/library/aa364157( VS.85) .aspx
这些系统调用的作用是访问内核代码,我相信...这超出了我的理解范围。
有多种方法可以做到:
处理器维护着几个衡量性能的计数器,您可以使用Papi界面访问它们。例如,这里是一个简短的介绍:http : //blogs.oracle.com/jonh/entry/performance_counter_generic_events
还:http : //www.drdobbs.com/tools/184406109
您可能想要的计数器是PAPI_TOT_CYC,它是繁忙周期的数量(如果我没记错的话)
CPU不会“挂起”,它只是在峰值容量下运行,这意味着它每秒处理的指令数量与其物理能力一样。其中一些指令是计算CPU使用率的过程。如果应用程序尝试执行的操作速度超过CPU的能力,那么它们只会被延迟,从而“挂断”。
CPU利用率的计算基于总可用利用率。因此,如果一个CPU有两个内核,一个内核使用率是30%,另一个是60%,则总体利用率是45%。您还可以查看每个单独核心的用法。