【本文鏈接】
http://www.cnblogs.com/hellogiser/p/cpu-manager.html
【題目】
寫一個程序,讓用戶來決定Windows任務管理器(Task Manager)的CPU占用率。程序越精簡越好,計算機語言不限。例如,可以實現下面三種情況:
1. CPU的占用率固定在50%,為一條直線;
2. CPU的占用率為一條直線,但是具體占用率由命令行參數決定(參數范圍1~ 100);
3. CPU的占用率狀態是一個正弦曲線。
【分析】
如果不考慮其它程序的CPU占用情況,可以在每個核上開一個線程,運行指定的函數,實現每個核的CPU占用率相同。
要讓CPU的占用率,呈函數 y = calc(t) (0 <= y <= 1, t為時間,單位為ms )分布,只要取間隔很短的一系列點,認為在某個間隔內,y值近似不變。
設間隔值為GAP,顯然在指定t值附近的GAP這段時間內,
CPU占用時間為:busy = GAP * calc(t),
CPU空閒時間為:idle = GAP – busy
(1)對於CPU的占用率固定在50%,cacl(t)返回一個常數值0.5;
(2)對於CPU的占用率固定在p%,cacl(t)返回一個常數值p/100;
(3) CPU的占用率狀態是一個正弦曲線,則y = 0.5 * (1 + sin(a * t + b))
其周期T = 2 * PI / a (PI = 3.1415927),可以指定T值為60s即60000ms,則可以確定a值為 2 * PI / T, 若在這60000ms內我們計算200次(c = 200),則GAP值為 T / c = 300ms.也就是說,只要確定了周期和計算次數,其它幾個參數也都確定下來。
可以創建一個線程,然後在指定的處理器上運行。具體可以通過CreateThread,SetThreadAffinityMask和WaitForSingleObject函數來實現。
【代碼】
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// 01_CPUManager.cpp : Defines the entry point for the console application.
//
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/6/24
*/
#include "stdafx.h"
#include <cmath>
#include <iostream>
#include <Windows.h>
using namespace std;
#define GAP_LINEAR 100
#define RATIO 0.5
typedef double Func(double);
double cacl_linear(double ratio)
{
return ratio;
}
void Solve_Linear(Func *cacl)
{
unsigned BUSY_TIME = GAP_LINEAR * cacl(RATIO); //ms
unsigned IDLE_TIME = GAP_LINEAR - BUSY_TIME; //ms
INT64 startTime = 0;
while(true)
{
//busy loop
startTime = GetTickCount();
while(GetTickCount() - startTime < BUSY_TIME)
;
// idle loop
Sleep(IDLE_TIME);
}
}
void Run_Linear()
{
// run on processor 1
HANDLE handle;
DWORD thread_id;
handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Solve_Linear,
(VOID *)cacl_linear, 0, &thread_id);
if (handle != NULL)
SetThreadAffinityMask(handle, 1);// run on process #1
WaitForSingleObject(handle, INFINITE);
}
/*
y = calc(t) (0 <= y <= 1)
GAP
busy: GAP*calc(t)
idle: GAP-busy
y = 0.5 * (1 + sin(a * t + b))
*/
const int PERIOD = 60 * 1000; // ms
const int COUNT = 200;
const double GAP = (double)PERIOD / COUNT;
const double PI = 3.1415926;
const double A = (2 * PI) / PERIOD;
double cacl_sin(double t)
{
// t = 0,1*gap,2*gap,...,200*gap
return (1 + sin(A * t)) / 2;
}
void Solve_Sin(Func *cacl)
{
double BUSY_TIME[COUNT] ; //ms
double t = 0.0;
for (int i = 0; i < COUNT; ++i)
{
t = i * GAP;
BUSY_TIME[i] = GAP * cacl(t);
}
int i = 0;
INT64 startTime = 0;
unsigned busyTime, idleTime;
while(true)
{
if(i >= COUNT)
i = 0;
busyTime = BUSY_TIME[i];
idleTime = GAP - busyTime;
//busy loop
startTime = GetTickCount();
while(GetTickCount() - startTime < busyTime)
;
// idle loop
Sleep(idleTime);
}
}
void Run_Sin()
{
// run on processor 2
HANDLE handle;
DWORD thread_id;
handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Solve_Sin,
(VOID *)cacl_sin, 0, &thread_id);
if (handle != NULL)
SetThreadAffinityMask(handle, 2);// run on process #2
WaitForSingleObject(handle, INFINITE);
}
void test_main()
{
Run_Linear();
Run_Sin();
}
int _tmain(int argc, _TCHAR *argv[])
{
test_main();
return 0;
}
【本文鏈接】
http://www.cnblogs.com/hellogiser/p/cpu-manager.html