让多核CPU占用率曲线听你指挥——《编程之美》1.1学习笔记
Problem:
写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率。有以下几种情况: 1.CPU占用率固定在50%,为一条直线; 2.CPU的占用率为一条直线,具体占用率由命令行参数决定(范围1~100); 3.CPU的占用率状态为一条正弦曲线。
分析与解法:
(1)通过观察任务管理器,它大约1s更新一次。当CPU使用率为0时,System Idle Process占用了CPU的空闲时间。
System Idle Process在CPU空闲的的时候,发出一个IDLE命令,使CPU挂起(暂时停止工作),可有效的降低CPU内核的温度,无法终止。在这个进程里出现的CPU占用数值并不是真正的占用而是体现的CPU的空闲率,也就说这个数值越大CPU的空闲率就越高,反之就是CPU的占用率越高。Linux中对应的进程为init,PID为1。
当系统中的进程或者在等待用户输入,或者在等待某些事件的发生(发出I/O请求等待I/O响应),或者主动进入休眠状态(比如Sleep())。
在任务管理器中的一个刷新周期内,CPU忙(执行应用程序)的时间和刷新周期总时间的比率就是CPU的占用率。其显示的是每个刷新周期内CPU占用率的统计平均值。我们可以写一个程序让它在任务管理器的刷新时间内一会儿忙,一会儿闲,通过调节忙/闲的比例,来控制任务管理器中显示的CPU占用率。
书上的代码以单核CPU为前提,但对于多核CPU来说,同一个进程可能被CPU的任务分配器分配到不同的核心上执行,所以造成无法让任务管理器达到预想的效果。其实打开任务管理器,可以看到多个CPU使用记录。本人电脑CPU是Core i5 450M,双核4线程。在OS看来就如同有四个CPU工作一样。我的任务管理器中就有四个CPU使用记录。
所谓超线程技术就是利用特殊的硬件指令,把多线程处理器内部的两个逻辑内核模拟成两个物理芯片,从而使单个处理器就能“享用”线程级的并行计算的处理器技术。多线程技术可以在支持多线程的操作系统和软件上,有效的增强处理器在多任务、多线程处理上的处理能力。
可以使用SetProcessAffinityMask()函数可以使特定的处理器运行指定进程。
BOOL SetProcessAffinityMask(HANDLE hProcess, DWORD_PTR dwProcessAffinityMask);
第一个参数用来指定指定哪个进程,传入它的句柄。第二个进程用来指定哪个CPU核心来执行此进程。
DWORD_PTR,其实就是unsigned long*.Unsigned long type for pointer precision.Use when casting a pointer to a long type to perform pointer arithmetic.(Also commonly used for general 32-bit parameters that have been extended to 64 bits in 64-bit windows.)
DWORD 其实就是unsigned long。Windows下常用来保存地址或存放指针。
比如这样调用函数:
::SetProcessAffinityMask(::GetCurrentProcess(),0x00000001);可以指定当前执行的进程在第一个CPU上运行。对于双核CPU,
::SetProcessAffinityMask(::GetCurrentProcess(),0x00000002);可以指定在第二个CPU上运行。
::SetProcessAffinityMask(::GetCurrentProcess(),0x00000003);可以允许在两个CPU上任意运行。
HANDLE GetCurrentProcess(void);
可以获得当前进程的句柄。注意,这个句柄为一个伪句柄。只能在我们的进程中才能代表当前进程的句柄,事实上这个函数目前只是简单的返回-1这个值。也就是说在我们的程序中-1便能表示本进程的句柄。
(2)那么对于绘制50%直线,程序代码为:
#include <Windows.h>
- #include<stdlib.h>
- #include<tchar.h>
- int _tmain(int argc,_TCHAR* argv[])
- {
- int busyTime = 10;
- int idleTime = busyTime*5;
- __int64startTime = 0;
- ::SetThreadAffinityMask(::GetCurrentProcess(),0x00000001);
- while(true)
- {
- startTime = GetTickCount();
- //busy loop
- while((GetTickCount() - startTime) <= busyTime);
- //idle loop
- Sleep(idleTime);
- }
- return 0;
- }
GetTickCount()可以得到系统从启动到运行到现在所经历时间的毫秒值。最多能统计到49.7天。我们利用它判断busy loop要持续多久。
其中idleTime为busyTime的五倍,可以修改其值使其更逼近50%。不同机子的情况不同。
__int64是VC++的64位扩展。范围为[-2^63,2^63)。当64位与32位混合运算时,32位整数会隐式转换成64位整数。输入输出它时使用cin、cout会造成错误。需要使用scanf("%I64d",&a);和printf("%I64d",a);
还有unsigned __int64,其范围为[0,2^64)。
对应g++中的64位扩展为long long和unsigned long long。范围与运算与上相仿。输入输出使用scanf("%lld",&a);和printf("%lld",a);
int _tmain(int argc, _TCHAR* argv[])。
_tmain这个符号多见于VC++创建的控制台工程中,这个是为了保证移植unicode而加入的(一般_t、_T、T()这些东西都和unicode有关系)。定义在头文件tchar.h中。
(3)对于绘制正弦曲线:
#include <Windows.h>
- #include<stdlib.h>
- #include<math.h>
- #include<tchar.h>
- const double SPLIT = 0.01;
- const int COUNT = 200;
- const double PI = 3.14159265;
- const int INTERVAL = 300;
- int _tmain(int argc, _TCHAR* argv[] )
- {
- DWORDbusySpan[COUNT]; //array of busy times
- DWORDidleSpan[COUNT]; //array of idle times
- int half = INTERVAL/2;
- double radian = 0.0;
- //如何近似趋近一条正弦曲线?这样!
- for(int i = 0; i < COUNT; ++i)
- {
- busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));
- idleSpan[i] = INTERVAL - busySpan[i];
- radian += SPLIT;
- }
- DWORDstartTime = 0;
- int j = 0;
- ::SetProcessAffinityMask(::GetCurrentProcess(),0x00000002);
- while(true)
- {
- j = j % COUNT;
- startTime = GetTickCount();
- while((GetTickCount() - startTime) <= busySpan[j]);
- Sleep(idleSpan[j]);
- j++;
- }
- return 0;
- }
通过在一个周期2*PI中等分200份,将每一个间隔点的half + (sin( PI * radian) * half))的值存入busySpan[i],将其补植存入idleSpan[i]。half是整个值域INTERVAL的一半。这样可以近似趋近一条正弦曲线。
运行效果为:
(4)可以通过RDTSC指令获得当前CPU核心运行周期数。
在x86平台上定义函数:
- inline __int64GetCPUTickCount()
- {
- __asm
- {
- rdtsc;
- }
- }
在x64平台上定义:
#define GetCPUTickCount() __rdtsc()
使用CallNtPowerInformation API得到CPU频率,从而将周期数转化为毫秒数,例如如下:
- _PROCESSOR_POWER_INFORMATIONinfo;
- CallNTPowerInformation(11, //query processor power information
- NULL, //no input buffer
- 0, //input buffer size is zero
- &info, //output buffer
- sizeof(info) //outbuf size
- );
- __int64t_begin = GetCPUTickCount();
- //do something
- __int64t_end = GetCPUTickCount();
- millisec = ((double)t_end - (double)t_begin)/(double)info.CurrentMhz;
RDTSC指令读取当前CPU的周期数,在多CPU系统中这个周期数在不同的CPU间基数不同,频率也不同。用从两个不同的CPU得到的周期数来计算会得出没有意义的值。所以需要用SetProcessAffinityMask避免进程迁移。另外,CPU的频率也会随系统供电及负荷情况有所调整。
相关推荐
在C#编程环境中,获取CPU利用率是通过操作系统提供的性能计数器来实现的。性能计数器是一种系统级别的数据采集工具,它允许程序实时监控系统的各种性能指标,如CPU使用率、内存使用情况等。下面将详细介绍如何使用C#...
本文将深入探讨如何通过编程来获取电脑的CPU利用率,并提供详细解释,以便于理解和应用。 CPU利用率是指CPU在一段时间内处于忙碌状态的百分比,反映了CPU工作负荷的强度。它通常分为用户空间利用率和内核空间利用率...
在编程层面,可以使用各种编程语言的库来实现动态显示CPU利用率。例如,Python有psutil库,Java有Java Management Extensions (JMX),C#有System.Diagnostics.Process类,它们都能提供获取CPU利用率的API。这些库...
2. GUI编程:使用MFC(Microsoft Foundation Classes)或其他图形库创建用户界面,展示CPU利用率曲线。 3. 动态链接库(DLL):CpuDll.dll可能封装了操作系统调用,提供了跨进程共享代码的能力。 总结,CpuUsage是...
除了PerMon_WinCE,还可以考虑使用其他第三方工具或编程接口(API)来实现CPU利用率的测量。例如,WinCE支持WM_PerfCounter类,这是一个可以访问性能计数器的API,可以用来自定义监控解决方案。 在WinCE环境中,...
CPU利用率组件源码是用于监控和分析系统CPU使用情况的软件模块,通常由程序员使用编程语言如C语言来编写。本篇将深入探讨CPU利用率组件源码的相关知识点,并结合C语言的特点进行详细阐述。 首先,CPU利用率是通过...
标题“Java通过JNI查看Windows的CPU利用率的问题”涉及到的是Java编程语言如何利用Java Native Interface (JNI) 这一技术来获取Windows操作系统的CPU使用情况。JNI是Java平台标准的一部分,它允许Java代码和其他语言...
"模拟CPU利用率的曲线"这个项目提供了一个直观的工具,其效果与Windows系统内置的性能监视器相似,允许用户自定义显示样式,以满足不同的监控需求。 首先,我们需要理解CPU利用率的概念。CPU利用率是指CPU在一段...
在NT系列的操作系统下,可以使用ntdll.dll中的未公开API NtQuerySystemInformation 来获取CPU利用率。这个API可以获取系统的基本信息、系统时间信息以及性能信息。通过查询系统的基本信息,可以得知系统中的处理器...
3. **计算CPU利用率**:通过比较两次读取之间的时间差,以及CPU在这段时间内的总运行时间,可以计算出CPU利用率。公式大致为:(总运行时间 / (第二次读取 - 第一次读取)) * 100%。 4. **处理内存利用率**:内存利用...
然而,在示例代码中,具体实现细节未完全展示,但可以推测其通过某种方式读取了系统性能数据,然后基于这些数据计算出CPU的利用率。 #### 3. **Linux平台下的CPU占用率计算** 对于Linux系统,CPU占用率的计算通常...
在IT行业中,了解如何通过编程方式获取系统的CPU利用率是一项实用的技能。VB(Visual Basic)是一种流行的编程语言,尤其在Windows环境下,它提供了丰富的API函数和控件来处理各种系统信息,包括CPU的使用情况。在这...
本文将深入探讨如何在Windows操作系统下,利用C++编程语言,通过Visual C++ 6.0(VC6.0)开发环境来实现CPU利用率的实时监测和输出。 首先,CPU利用率的计算通常基于操作系统的系统调用或API,如Windows API中的`...
本项目是利用Qt实现的一个功能,即实时显示CPU使用率,对于系统监控或者性能分析的软件来说,这是一个非常实用的功能。 首先,我们要理解如何在Qt中获取系统资源信息。在Qt库中,并没有直接提供获取CPU使用率的API...
在C++编程中,获取CPU使用率是一项常见的需求,无论是为了监控系统性能,还是分析某个特定进程的资源消耗。本文将详细讲解如何使用C++来获取系统整体的CPU使用率以及单个进程的CPU使用率。 首先,我们需要理解CPU...
在Linux和OpenWRT系统中,CPU使用率是衡量系统性能和资源利用率的重要指标。本文将探讨如何通过编程计算Linux和OpenWRT系统的CPU使用率,以帮助管理员监控和优化系统性能。 首先,CPU使用率是指CPU在一段时间内执行...
标题中的“编个小探钻机芯实时检测CPU利用率”指的是创建一个小型的监控工具,能够实时监测计算机CPU的使用情况。这个工具可以被形象地比喻为一个“小探”,能够深入到系统的“芯”脏,获取CPU利用率的信息,并以...
例如,通过比较进程的用户时间和系统时间与总的CPU时间,可以计算出当前进程的CPU利用率。 除了使用API,还可以利用第三方库如JCL (Jedi Code Library) 或者 embarcadero 自己的VCL组件,这些库提供了封装好的接口...
这需要根据sin函数的值来动态调整繁忙和空闲时间的比例,实现周期性的CPU利用率变化。 9. **程序实现**: 提供的两个程序代码中,程序1通过一个简单的循环来维持50%的CPU占用率,而程序2则更复杂,使用sin函数来...
通过编程方式获取CPU使用率,可以帮助开发者了解程序运行时对系统资源的占用情况,从而优化程序性能。以下是一些关于如何使用VC++(MFC库)和其他相关工具来获取CPU使用率的知识点。 首先,VC++中的MFC库并没有直接...