编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器)

【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3242910.html 

【目录】

不考虑其他进程,cpu画正弦曲线

获取总体cpu利用率

获取多核处理器单个cpu利用率

考虑其他进程,cpu画正弦曲线


下面的程序针对多核处理器,可以设置让任何一个cpu显示相应的曲线(本文以正弦曲线为例)

代码编译环境:windows 7 64位 酷睿 i5 处理器,vs2010.

可以修改CpuSin函数的计算 busySpan 和 idleSpan的部分以显示不同的曲线。

下面的代码没有考虑cpu中其他进程的占用情况,这种情况详见第二部分

 1 #include <windows.h>
2 #include <stdio.h>
3 #include <math.h>
4
5 //把一条正弦曲线0~2pi 之间的弧度等分200份抽样,计算每个点的振幅
6 //然后每隔300ms设置下一个抽样点,并让cpu工作对应振幅时间
7 const int samplingCount = 200; //抽样点数目
8 const double pi = 3.1415926;
9 const int totalAmplitude = 300; //每个抽样点对应时间片
10 const double delta = 2.0/samplingCount; //抽样弧度的增量
11
12 int busySpan[samplingCount];//每个抽样点对应的busy时间
13 int idleSpan[samplingCount];//每个抽样点对应的idle时间
14
15 //一个线程调用MakeUsageSin,并把该线程绑定到一个cpu,那么该cpu呈现正弦曲线
16 DWORD WINAPI MakeUsageSin(LPVOID lpParameter)
17 {
18 DWORD startTime = 0;
19 for(int j = 0; ; j = (j + 1) % samplingCount)
20 {
21 startTime = GetTickCount();
22 while ((GetTickCount() - startTime) < busySpan[j]);
23 Sleep(idleSpan[j]);
24 }
25 }
26
27 //如果cpuindex < 0 则所有cpu都显示正弦曲线
28 //否则只有第 cpuindex个cpu显示正弦曲线
29 //cpuindex 从 0 开始计数
30 void CpuSin(int cpuIndex)
31 {
32 //计算 busySpan 和 idleSpan
33 double radian = 0;
34 int amplitude = totalAmplitude / 2;
35 for (int i = 0; i < samplingCount; i++)
36 {
37 busySpan[i] = (DWORD)(amplitude + sin(pi*radian)*amplitude);
38 idleSpan[i] = totalAmplitude - busySpan[i];
39 radian += delta;
40 }
41
42 //获取系统cup数量
43 SYSTEM_INFO SysInfo;
44 GetSystemInfo(&SysInfo);
45 int num_processors = SysInfo.dwNumberOfProcessors;
46 if(cpuIndex + 1 > num_processors)
47 {
48 printf("error: the index of cpu is out of boundary\n");
49 printf("cpu number: %d\n", num_processors);
50 printf("your index: %d\n", cpuIndex);
51 printf("** tip: the index of cpu start from 0 **\n");
52 return;
53 }
54
55 if(cpuIndex < 0)
56 {
57 HANDLE* threads = new HANDLE[num_processors];
58 for (int i = 0;i < num_processors;i++)
59 {
60 DWORD mask = 1<<i;
61 threads[i] = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL);
62 SetThreadAffinityMask(threads[i], 1<<i);//线程指定在某个cpu运行
63 }
64 WaitForMultipleObjects(num_processors, threads, TRUE, INFINITE);
65 }
66 else
67 {
68 HANDLE thread;
69 DWORD mask = 1;
70 thread = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL);
71 SetThreadAffinityMask(thread, 1<<cpuIndex);
72 WaitForSingleObject(thread,INFINITE);
73 }
74
75 }
76 int main()
77 {
78
79 CpuSin(0);
80 return 0;
81 }

运行结果:


下面我们考虑其他进程对cpu的影响,即需要检测出某个cpu当前的使用率。

首先对于单核处理器获取cpu利用率,或者多核处理器获取总的cpu利用率,可以通过windows api “GetSystemTimes” 来实现

该函数声明如下:BOOL GetSystemTimes(LPFILETIME  IdleTime,LPFILETIME   KernelTime,LPFILETIME   UserTime),具体可以参考msdn接口介绍

cpu利用率计算公式为:CPURate=100.0-(NowIdleTime-LastIdleTime)/(NowKernelTime-LastKernelTime+NowUserTime-LastUserTime)*100.0

计算总的cpu利用率或者单核处理器cpu利用率的类实现如下:

 1 class CCPUUseRate
2 {
3 public:
4 BOOL Initialize()
5 {
6 FILETIME ftIdle, ftKernel, ftUser;
7 BOOL flag = FALSE;
8 if (flag = GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
9 {
10 m_fOldCPUIdleTime = FileTimeToDouble(ftIdle);
11 m_fOldCPUKernelTime = FileTimeToDouble(ftKernel);
12 m_fOldCPUUserTime = FileTimeToDouble(ftUser);
13
14 }
15 return flag;
16 }
17 //调用Initialize后要等待1左右秒再调用此函数
18 int GetCPUUseRate()
19 {
20 int nCPUUseRate = -1;
21 FILETIME ftIdle, ftKernel, ftUser;
22 if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
23 {
24 double fCPUIdleTime = FileTimeToDouble(ftIdle);
25 double fCPUKernelTime = FileTimeToDouble(ftKernel);
26 double fCPUUserTime = FileTimeToDouble(ftUser);
27 nCPUUseRate= (int)(100.0 - (fCPUIdleTime - m_fOldCPUIdleTime)
28 / (fCPUKernelTime - m_fOldCPUKernelTime + fCPUUserTime - m_fOldCPUUserTime)
29 *100.0);
30 m_fOldCPUIdleTime = fCPUIdleTime;
31 m_fOldCPUKernelTime = fCPUKernelTime;
32 m_fOldCPUUserTime = fCPUUserTime;
33 }
34 return nCPUUseRate;
35 }
36 private:
37 double FileTimeToDouble(FILETIME &filetime)
38 {
39 return (double)(filetime.dwHighDateTime * 4.294967296E9) + (double)filetime.dwLowDateTime;
40 }
41 private:
42 double m_fOldCPUIdleTime;
43 double m_fOldCPUKernelTime;
44 double m_fOldCPUUserTime;
45 };

注意:前后两次调用GetSystemTimes之间要间隔一定时间,使用方法如下:

 1 int main()
2 {
3 CCPUUseRate cpuUseRate;
4 if (!cpuUseRate.Initialize())
5 {
6 printf("Error! %d\n", GetLastError());
7 getch();
8 return -1;
9 }
10 else
11 {
12 while (true)
13 {
14 Sleep(1000);
15 printf("\r当前CPU使用率为:%4d%%", cpuUseRate.GetCPUUseRate());
16 }
17 }
18 return 0;
19 }

对于计算多核处理器中单个cpu的使用率,可以使用pdh.h头文件中的接口,该头文件是visual studio自带的,包含该头文件时,还需要引入相关的lib库:

 1 #include <TCHAR.h>
2 #include <windows.h>
3 #include <pdh.h>
4 #include <cstdio>
5 #include <cmath>
6 #pragma comment(lib, "pdh.lib")
7
8 //---------------------------------------------------comput the cpu usage rate
9 static PDH_HQUERY cpuQuery;
10 static PDH_HCOUNTER cpuTotal;
11
12 //cpuindex 为指定的cpu id ,从0开始
13 void init(int cpuIndex)
14 {
15 PDH_STATUS Status = PdhOpenQuery(NULL, NULL, &cpuQuery);
16 if (Status != ERROR_SUCCESS)
17 {
18 printf("\nPdhOpenQuery failed with status 0x%x.", Status);
19 exit(-1);
20 }
21 char buf[50];
22 sprintf(buf, "\\Processor(%d)\\%% Processor Time", cpuIndex);
23 PdhAddCounter(cpuQuery, LPCSTR(buf), NULL, &cpuTotal);
24 PdhCollectQueryData(cpuQuery);
25 }
26
27
28 double getCpuUsageRate()
29 {
30 PDH_FMT_COUNTERVALUE counterVal;
31 PdhCollectQueryData(cpuQuery);
32 PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
33 return counterVal.doubleValue;
34 }

注:该方法也可以计算总的cpu利用率,只要把PdhAddCounter的第二个字符串参数改为"\\Processor(_Total)\\%% Processor Time"

前后两次调用PdhCollectQueryData之间也需要间隔一定时间

使用方法如下:

1 int main()
2 {
3 init(0);
4 while(1)
5 {
6 Sleep(800);
7 printf("\n%f\n", getCpuUsageRate());
8 }
9 }

利用上述方法获取cpu当前利用率后,再画正弦曲线,只需要改变进程的busy时间和idle时间,如果当前点曲线需要的cpu利用率是a%,cpu实际利用率是b%

若a>b, 那么进程的busy时间为该点时间片的(a-b)%

若a<=b,那么进程busy时间为0(实际情况中由于cpu使用率采集的不精确以及使用率的不断变化,busy时间设置为0效果不一定最好,本文中是设置为原来时间的3/4)

实际上除了当前进程外,如果cpu一直占用某个使用率,会影响曲线的形状,特别是曲线的下部分.

代码如下:

  1 #include <TCHAR.h>
2 #include <windows.h>
3 #include <pdh.h>
4 #include <cstdio>
5 #include <cmath>
6 #pragma comment(lib, "pdh.lib")
7
8 //---------------------------------------------------comput the cpu usage rate
9 static PDH_HQUERY cpuQuery;
10 static PDH_HCOUNTER cpuTotal;
11
12 //cpuindex 为指定的cpu id ,从0开始
13 void init(int cpuIndex)
14 {
15 PDH_STATUS Status = PdhOpenQuery(NULL, NULL, &cpuQuery);
16 if (Status != ERROR_SUCCESS)
17 {
18 printf("\nPdhOpenQuery failed with status 0x%x.", Status);
19 exit(-1);
20 }
21 char buf[50];
22 sprintf(buf, "\\Processor(%d)\\%% Processor Time",cpuIndex);
23 PdhAddCounter(cpuQuery, LPCSTR(buf), NULL, &cpuTotal);
24 PdhCollectQueryData(cpuQuery);
25 }
26
27
28 double getCpuUsageRate()
29 {
30 PDH_FMT_COUNTERVALUE counterVal;
31 PdhCollectQueryData(cpuQuery);
32 PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
33 return counterVal.doubleValue;
34 }
35
36 //--------------------------------------------------------------------cpu sin
37 //把一条正弦曲线0~2pi 之间的弧度等分200份抽样,计算每个点的振幅
38 //然后每隔300ms设置下一个抽样点,并让cpu工作对应振幅时间
39 const int samplingCount = 200; //抽样点数目
40 const double pi = 3.1415926;
41 const int totalAmplitude = 300; //每个抽样点对应时间片
42 const double delta = 2.0/samplingCount; //抽样弧度的增量
43
44 DWORD busySpan[samplingCount];//每个抽样点对应的busy时间
45 int idleSpan[samplingCount];//每个抽样点对应的idle时间
46
47 //一个线程调用MakeUsageSin,并把该线程绑定到一个cpu,那么该cpu呈现正弦曲线
48 DWORD WINAPI MakeUsageSin(LPVOID lpParameter)
49 {
50 DWORD startTime = 0;
51 for(int j = 0; ; j = (j + 1) % samplingCount)
52 {
53 startTime = GetTickCount();
54 DWORD realBusy = busySpan[j];
55
56 double currentCpuUsageRate = getCpuUsageRate();
57 if(currentCpuUsageRate < busySpan[j]*1.0/totalAmplitude)
58 realBusy = (busySpan[j]*1.0/totalAmplitude - currentCpuUsageRate)*totalAmplitude;
59 else
60 realBusy *= 0.75;
61
62 while ((GetTickCount() - startTime) < realBusy);
63 Sleep(idleSpan[j]);
64 }
65 }
66
67 //如果cpuindex < 0 则所有cpu都显示正弦曲线
68 //否则只有第 cpuindex个cpu显示正弦曲线
69 //cpuindex 从 0 开始计数
70 void CpuSin(int cpuIndex)
71 {
72 //计算 busySpan 和 idleSpan
73 double radian = 0;
74 int amplitude = totalAmplitude / 2;
75 for (int i = 0; i < samplingCount; i++)
76 {
77 busySpan[i] = (DWORD)(amplitude + sin(pi*radian)*amplitude);
78 idleSpan[i] = totalAmplitude - busySpan[i];
79 radian += delta;
80 }
81
82 //获取系统cup数量
83 SYSTEM_INFO SysInfo;
84 GetSystemInfo(&SysInfo);
85 int num_processors = SysInfo.dwNumberOfProcessors;
86 if(cpuIndex + 1 > num_processors)
87 {
88 printf("error: the index of cpu is out of boundary\n");
89 printf("cpu number: %d\n", num_processors);
90 printf("your index: %d\n", cpuIndex);
91 printf("** tip: the index of cpu start from 0 **\n");
92 return;
93 }
94
95 if(cpuIndex < 0)
96 {
97 HANDLE* threads = new HANDLE[num_processors];
98 for (int i = 0;i < num_processors;i++)
99 {
100 DWORD mask = 1<<i;
101 threads[i] = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL);
102 SetThreadAffinityMask(threads[i], 1<<i);//线程指定在某个cpu运行
103 }
104 WaitForMultipleObjects(num_processors, threads, TRUE, INFINITE);
105 }
106 else
107 {
108 init(cpuIndex);
109 HANDLE thread;
110 DWORD mask = 1;
111 thread = CreateThread(NULL, 0, MakeUsageSin, &mask, 0, NULL);
112 SetThreadAffinityMask(thread, 1<<cpuIndex);
113 WaitForSingleObject(thread,INFINITE);
114 }
115
116 }
117 //-------------------------------------
118
119 int main()
120 {
121 CpuSin(0);
122 }

主要改动在MakeUsageSin函数,初始化在上面代码108行

结果如下:

【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3242910.html

让cpu占用率曲线听你指挥(多核处理器)的更多相关文章

  1. 第1章 游戏之乐——让CPU占用率曲线听你指挥

    让CPU占用率曲线听你指挥 写一个程序,让用于来决定Windows任务管理器(Task Manager)的CPU占用率.程序越精简越好,计算机语言不限.例如,可以实现下面三种情况: CPU的占用率固定 ...

  2. 编程之美_1.1 让CPU占用率曲线听你指挥

    听到有人说让要写一个程序,让用户来决定Windows任务管理器的CPU占用率. 觉得很好奇.但第一个想法就是写个死循环.哈哈.不知道具体的占用率是多少,但至少能保证在程序运行时,CPU的占用率终会稳定 ...

  3. 1.1 让CPU占用率曲线听你指挥[cpu manager]

    [本文链接] http://www.cnblogs.com/hellogiser/p/cpu-manager.html [题目] 写一个程序,让用户来决定Windows任务管理器(Task Manag ...

  4. 编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器)

    [目录] 不考虑其他进程,cpu画正弦曲线 获取总体cpu利用率 获取多核处理器单个cpu利用率 考虑其他进程,cpu画正弦曲线 下面的程序针对多核处理器,可以设置让任何一个cpu显示相应的曲线(本文 ...

  5. 让CPU占用率曲线听你指挥

    使用GetTickCount()和Sleep(): Code#include <stdio.h> #include <unistd.h> #include <time.h ...

  6. 编程之美读书笔记1.1——让CPU占用率曲线听你的指挥

    http://blog.csdn.net/pipisorry/article/details/36189155 <strong><span style="font-size ...

  7. 让CPU的占有率曲线听我指挥

    最近我要在公司的一个study group负责AWS的AutoScaling功能的介绍.AWS可以根据instance(虚拟机)的CPU使用量进行scaling. 为了做demo,于是就有这样一个需求 ...

  8. 控制CPU占用率曲线

    编程之美的第一个问题,我的机器是双核的,用文中的代码,得到的曲线波动比较大额,受其他进程的影响比较大.文中提到10ms接近windows的调度时间片,如果选得太小,会造成线程被频繁唤醒和挂起,造成内核 ...

  9. 编程之美 之 让CPU占用率听你指挥

    昨天在bbs上淘到了这本编程之美.顺手刷了第一章,很有意思.第一章的要求是要控制CPU曲线,绘制出对应的形状. 拿到这个问题,我的第一反应是, 是不是有这么一个API,能在任务管理器上的对应区域直接绘 ...

随机推荐

  1. 使用tensorflow设计的网络模型看不到数据流向怎么办

    首先tensorflow的设计思想就是先把需要用的变量已张量的形式保存, 实际上并没有实质的数值填充. 然后设计网络架构,也仅仅是架构而已, 只能说明数据关系和层与层之间的关系. 真正的数据输入是在主 ...

  2. oracle 迭代查询

    Oracle 迭代查询, 以后台菜单作为示例 这是要准备的sql create table tbl_menu( id number primary key, parent_id , name ) no ...

  3. MySQL时间字段究竟使用INT还是DateTime

    今天解析DEDECMS时发现deder的MYSQL时间字段,都是用 `senddata` ) unsigned '; 随后又在网上找到这篇文章,看来如果时间字段有参与运算,用int更好,一来检索时不用 ...

  4. 安装 Windows Server 2012 Active Directory 只读域控制器 (RODC)(级别 200)

    安装 Windows Server 2012 Active Directory 只读域控制器 (RODC)(级别 200) 适用对象:Windows Server 2012 本主题介绍如何创建分步的 ...

  5. OpenStack之虚机热迁移

    OpenStack之虚机热迁移 最近要搞虚机的热迁移,所以也就看了看虚机迁移部分的内容.我的系统是CentOS6.5,此处为基于NFS共享平台的虚机迁移.有关NFS共享服务器的搭建可以看这里. Yak ...

  6. SDRAM学习(二)之初始化

    目录 1.SDRAM初始化的内容(结合英文数据手册) 2.SDRAM初始化的时序 3.代码的编写 4.modesim的仿真 SDRAM初始化的内容 SDRAMs must be powered up ...

  7. Leetcode 540.有序数组中的单一元素

    有序数组中的单一元素 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数. 示例 1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例 2: 输入 ...

  8. centos 7 配置ip

    1.动态获取ip(前提是你的路由器已经开启了DHCP) 修改网卡配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens32    (最后一个为网卡名称) 动态 ...

  9. 配置kubectl客户端通过token方式访问kube-apiserver

    使用的变量 本文档用到的变量定义如下: $ export MASTER_IP=XX.XX.XX.XX # 替换为 kubernetes master VIP $ export KUBE_APISERV ...

  10. python函数之五马分析

    Python 函数 函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段. 函数能提高应用的模块性和代码的重复利用率.Python提供了许多内建函数,比如print().也可以自己创建函数, ...