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

【本文链接】

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(
NULL0, (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(
NULL0, (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