写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率(单核)。有以下几种情况:
1.CPU占用率固定在50%,为一条直线
2.CPU的占用率为一条直线,具体占用率由命令行参数决定(范围1~100)
3.CPU的占用率状态为一条正弦曲线
4.多核处理器情况下上述问题怎么解决
loop; mov dx i ;将i置入dx寄存器 inc dx ;将dx寄存器加1 mov dx i ;将dx中的值赋回i cmp i n ;比较i和n j1 loop ;i小于n时则重复循环
我的cpu是 I5 2410M 2.30GHZ(双核四线程,如图) 因为目前的cpu每个时钟周期可执行两条以上的代码,取平均值2,于是(2300000000*2)/5=920000000(循环/秒) 每秒可以执行循环920000000次。
不能简单的取n=920000000然后sleep(1000),如果让cpu工作1s,休息1s很可能是锯齿,先达到一个峰值然后跌入一个很低的占有率;所以我们睡眠时间改为100ms,100ms比较接近windows的调度时间,n=92000000。如果sleep时间选的太小,会造成线程频繁的唤醒和挂起,无形中增加了内核时间的不确定性因此代码如下:
#include <windows.h>
int main(void)
{
<span style="white-space:pre"> </span>//Run on CPU 0(0x00000001)(00000001)
<span style="white-space:pre"> </span>//Run on CPU 1(0x00000002)(00000010)
<span style="white-space:pre"> </span>//Run on CPU 0 AND CPU 1(0x00000003)(00000101)
<span style="white-space:pre"> </span>//Run on CPU 2(0x00000004)(00000100)
<span style="white-space:pre"> </span>//......
<span style="white-space:pre"> </span>//SetProcessAffinityMask(GetCurrentProcess(),0x1);//进程与指定cpu绑定
<span style="white-space:pre"> </span>SetThreadAffinityMask(GetCurrentThread(), 0x1);//线程与指定cpu绑定
<span style="white-space:pre"> </span>while(true)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>for(int i=0;i<92000000;i++)
<span style="white-space:pre"> </span>;
<span style="white-space:pre"> </span>Sleep(100);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return 0;
}
使用SetProcessAffinityMask函数,进程与CPU绑定,得到如下图。
使用SetThreadAffinityMask函数,进程与CPU绑定,得到如下图。
#include <windows.h>
const int busyTime=100;
const int idleTime=busyTime;
int main(void)
{
double startTime;
SetProcessAffinityMask(GetCurrentProcess(), 0x1);
while(true)
{
startTime=GetTickCount();
while((GetTickCount() - startTime) <= busyTime)
{
;
}
Sleep(idleTime);
}
return 0;
} 效果如下图所示,与第一种解法效果差不多,因为都假设当前系统只有当前程序在运行,但实际上,操作系统有很多程序会同时调试执行各种任务,如果此刻进程使用20%的cpu,那我们的程序只有使用30%的cpu才能达到50%的效果。
using System;
using System.Diagnostics;
namespace CPU
{
class Program
{
static void Main(string[] args)
{
cpu(1000);
}
static void cpu(double level)
{
PerformanceCounter p = new PerformanceCounter("Processor", "% Processor Time", "_Total");
if (p == null)
{
return;
}
while (true)
{
if (p.NextValue() > level)
System.Threading.Thread.Sleep(1000);
}
}
}
}#include <windows.h>
#include <math.h>
int main(void)
{
SetProcessAffinityMask(GetCurrentProcess(), 0x1);
const double SPLIT=0.01;
const int COUNT=200;
const double PI=3.14159265;
const int INTERVAL=300;
DWORD busySpan[COUNT]; //array of busy time
DWORD idleSpan[COUNT]; //array of idle time
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;
}
DWORD startTime=0;
int j=0;
while(true)
{
j=j%COUNT;
startTime=GetTickCount();
while((GetTickCount()-startTime)<=busySpan[j])
;
Sleep(idleSpan[j]);
j++;
}
return 0;
} 如果不考虑其它程序的CPU占用情况,可以在每个核上开一个线程,运行指定的函数,实现每个核的CPU占用率相同。如果CPU占用率曲线不是周期性变化,就要对每个t值都要计算一次,否则,可以只计算第一个周期内的各个t值,其它周期的直接取缓存计算结果。
#include<iostream>
#include<cmath>
#include<windows.h>
static int PERIOD = 60 * 1000; //周期ms
const int COUNT = 300; //一个周期计算次数
const double GAP_LINEAR = 100; //线性函数时间间隔100ms
const double PI = 3.1415926535898; //PI
const double GAP = (double)PERIOD / COUNT; //周期函数时间间隔
const double FACTOR = 2 * PI / PERIOD; //周期函数的系数
static double Ratio = 0.5; //线性函数的值 0.5即50%
static double Max=0.9; //方波函数的最大值
static double Min=0.1; //方波函数的最小值
typedef double Func(double); //定义一个函数类型 Func*为函数指针
typedef void Solve(Func *calc);//定义函数类型,参数为函数指针Func*
inline DWORD get_time()
{
return GetTickCount(); //操作系统启动到现在所经过的时间ms
}
double calc_sin(double x) //调用周期函数solve_period的参数
{
return (1 + sin(FACTOR * x)) / 2; //y=1/2(1+sin(a*x))
}
double calc_fangbo(double x) //调用周期函数solve_period的参数
{
//方波函数
if(x<=PERIOD/2) return Max;
else return Min;
}
void solve_period(Func *calc) //线程函数为周期函数
{
double x = 0.0;
double cache[COUNT];
for (int i = 0; i < COUNT; ++i, x += GAP)
cache[i] = calc(x);
int count = 0;
while(1)
{
unsigned ta = get_time();
if (count >= COUNT) count = 0;
double r = cache[count++];
DWORD busy = r * GAP;
while(get_time() - ta < busy) {}
Sleep(GAP - busy);
}
}
void solve_linear(Func*) //线程函数为线性函数,参数为空 NULL
{
const unsigned BUSY = Ratio * GAP_LINEAR;
const unsigned IDLE = (1 - Ratio) * GAP_LINEAR;
while(1)
{
unsigned ta = get_time();
while(get_time() - ta < BUSY) {}
Sleep(IDLE);
}
}
void run(int i=1,double R=0.5,double T=60000,double max=0.9,double min=0.1)
//i为输出状态,R为直线函数的值,T为周期函数的周期,max方波最大值,min方波最小值
{
Ratio=R; PERIOD=T; Max=max; Min=min;
Func *func[] = {NULL ,calc_sin,calc_fangbo}; //传给Solve的参数,函数指针数组
Solve *solve_func[] = { solve_linear, solve_period}; //Solve函数指针数组
SYSTEM_INFO info;
GetSystemInfo(&info); //得到cpu数目
int NUM_CPUS = info.dwNumberOfProcessors;
HANDLE *handle = new HANDLE[NUM_CPUS];
DWORD *thread_id = new DWORD[NUM_CPUS]; //线程id
switch(i)
{
case 1: //cpu0 ,cpu1都输出直线
{
for (int i = 0; i < NUM_CPUS; ++i)
{
Func *calc = func[0];
Solve *solve = solve_func[0];
if ((handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,
(VOID*)calc, 0, &thread_id[i])) != NULL) //创建新线程
SetThreadAffinityMask(handle[i], i); //限定线程运行在哪个cpu上
}
WaitForSingleObject(handle[0],INFINITE); //等待线程结束
break;
}
case 2: //cpu0直线,cpu1正弦
{
if ((handle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve_func[0],
(VOID*)func[0], 0, &thread_id[1])) != NULL) //创建新线程
SetThreadAffinityMask(handle[1], 1); //限定线程运行在哪个cpu上
Func *calc = func[1];
Solve *solve = solve_func[1];
if ((handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,
(VOID*)calc, 0, &thread_id[0])) != NULL) //创建新线程
SetThreadAffinityMask(handle[0], 2); //限定线程运行在哪个cpu上
WaitForSingleObject(handle[0],INFINITE); //等待线程结束
break;
}
case 3: //cpu0直线,cpu1方波
{
if ((handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve_func[0],
(VOID*)func[0], 0, &thread_id[0])) != NULL) //创建新线程
SetThreadAffinityMask(handle[0], 1); //限定线程运行在哪个cpu上
Func *calc = func[2];
Solve *solve = solve_func[1];
if ((handle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,
(VOID*)calc, 0, &thread_id[1])) != NULL) //创建新线程
SetThreadAffinityMask(handle[1], 2); //限定线程运行在哪个cpu上
WaitForSingleObject(handle[0],INFINITE); //等待线程结束
break;
}
case 4: //cpu0正弦,cpu1方波
{
if ((handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve_func[1],
(VOID*)func[1], 0, &thread_id[0])) != NULL) //创建新线程
SetThreadAffinityMask(handle[0], 1); //限定线程运行在哪个cpu上
Func *calc = func[2];
Solve *solve = solve_func[1];
if ((handle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,
(VOID*)calc, 0, &thread_id[1])) != NULL) //创建新线程
SetThreadAffinityMask(handle[1], 2); //限定线程运行在哪个cpu上
WaitForSingleObject(handle[0],INFINITE); //等待线程结束
break;
}
default: break;
}
}
void main()
{
//run(1,0.5); //cpu1 ,cpu2都输出50%的直线
run(2,0.5,30000); //cpu1 0.5直线,cpu2正弦周期30000
//run(3); //cpu1直线,cpu2方波
//run(4,0.8,30000,0.95,0.5); //cpu1正弦,cpu2 0.95-0.5的方波
}
这是是第一次CPU跑直线,第二个CPU跑正弦函数~~~~~~~~·
原文地址:http://blog.csdn.net/sin_geek/article/details/39636509