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

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

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

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

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

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

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

使用方法如下:

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

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

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

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

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

代码如下:

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

    #include<bits/stdc++.h> using namespace std; int s[3]={1,5,19}; void shellsort(int *a,int n){ ...

  2. 浅谈javascript的运行机制

    积累一下这几天学的,记录一下: 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程 ...

  3. easyui-combogrid必填为空时无法通过表单验证的问题

    在使用easyui-combogrid时,由于html解析出的格式是如下三层: <td> <input id="txcombo" class="easy ...

  4. 谈一谈Tomcat中webSocket,Jetty WebSocket 和Spring WebSocket以及github中Java-WebSocket.jar分别对Socket协议的角色定位以及效果的不同点;

    开局先上一张图:(http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html)   当前截图来自于apache的tomcat官网(问:为 ...

  5. luogu3224 [HNOI2012]永无乡

    线段树合并好写好调,隔壁老王的treap+启发式合并难写难调 #include <iostream> #include <cstdio> using namespace std ...

  6. ogre3D学习基础17 --- 如何手动创建ogre程序

    建立自己的Ogre程序 一直以来都是使用ExampleApplication.h来写程序,现在来看看它到底有什么神奇的地方. 首先,我们新建一个win32空项目 然后配置环境 最后新建define.c ...

  7. Django中前端界面实现级联查询

    Django前端界面实现级联查询 一.前端界面中 <span scope="col" colspan="6"> 院系:<select id=& ...

  8. 贪吃蛇—C—基于easyx图形库(下):从画图程序到贪吃蛇【自带穿墙术】

    上节我们用方向控制函数写了个小画图程序,它虽然简单好玩,但我们不应该止步于此.革命尚未成功,同志还需努力. 开始撸代码之前,我们先理清一下思路.和前面画图程序不同,贪吃蛇可以有很多节,可以用一个足够大 ...

  9. unity c# 代码示例

    1. using UnityEngine; using System.Collections; public class AnimatorMove : MonoBehaviour { public f ...

  10. 根据窗口尺寸onresize判断窗口的大小

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...