让CPU占用率曲线听你指挥

题目:

写一个程序,让用户来决定Windows任务管理器(task manager)的CPU占用率。程序越精简越好。计算机语言不限。

例如:可以实现下面三种情况:

1.CPU的占用率固定在50%,为一条直线;

2.CPU的占用率为一条直接,具体占用率由命令行参数决定(参数范围1~100);

3.CPU的占用率状态是一条正弦曲线。

首先解释一下什么是“CPU占有率”?

      在任务管理器的一个刷新周期内,CPU忙(执行应用程序)的时间和刷新周期总时间的比率,就是CPU的占用率。也就是说,任务管理器中显示的是每个刷新周期内CPU占用率的统计平均值。

      要操纵CPU的使用率曲线,就需要使CPU在一段时间在一段时间内(根据task manager的采样率)跑busy和idle两个不同的循环(loop),从而通过不同的时间比例,来调节CPU使用率。

     Busy loop可以通过执行空循环来实现Busy用可循环来实现,for(i=0;i<n;i++) ,并且可以利用GetTickCount()判断busy loop要循环多久;idle可以通过Sleep()来实现。  sleep(睡眠)函数,功能:执行挂起一段时间,头文件#include <windows.h>。

     因此,可以写个程序,在一个刷新周期中,一会忙,一会闲,调节忙闲比例,来控制CPU占用率。

     一个刷新时间到底是多久?且鼠标移动,后台程序等都会对曲线造成影响。单核多核条件下CPU占用率又会情况不同。

    我的电脑CPU型号

对于问题:CPU的占用率固定在50%,为一条直线。

解法一:简单的解法

实现代码如下:

#include<stdio.h>
#include<unistd.h>
#include<windows.h> 
int main(){
	for(;;){
		for(int i=0;i<9600000;i++)
		;
		Sleep(10);
	}
	return 0;
} 

 运行出来CPU截图:

在不断的调整参数后,有锯齿,近似一条直线。

在选取参数中,不能选的太小,如果选得太小,会造成线程频繁地被唤醒和挂起,无形中又增加了内核时间的不确定性。

这种方法要注意两种影响:

(1)尽量减少sleep/awake的频率,以减少操作系统内核调度程序的干扰。

(2)尽量不要调用system call(比如I/O这些privilege instruction),因为它也会导致很多不可控的内核运行时间。

这方法的缺点很明显:不能适应机器差异性。一旦换了CPU,就得重新估算n值。

解法二:使用GetTickCount()和Sleep()

实现代码如下:

#include<windows.h>
#include<stdio.h>

int main(){
	int busyTime=10;
	int idleTime=busyTime;
	int startTime=0;
	while(true){
		 startTime=GetTickCount();
		 //busy loop
		 while((GetTickCount()-startTime)<=busyTime)
		 ;
		 //idle loop
		 Sleep(idleTime);
		
	}
	return 0;
	
}

 运行出来的CPU截图:

截图结果与图一相似。

这两种解放都是假设目前系统上只有当前程序在运行,但实际上,操作系统中有很多程序会同时执行各种各样的任务,如果此刻其他进程使用了10%的CPU,那我们程序就只能使用40%的CPU,这样才能达到50%的效果。

解法三:能动态适应的解法

Perform是从Windows NT开始就包含在Windows管理工具组中的专业检测工具之一。Perform可获取有关操作系统,应用程序和硬件的各种效能技术器(perf counter)。

Microsoft.NET Framework提供了performanceCounter这一对象,可以方便地得到当前各种性能数据。包括CPU的使用率。

这种还没有弄出来

解法四:正弦曲线

把一条正弦曲线0~2n之间的弧度等分成200份进行抽样,计算每个抽样点的振幅

然后每隔300ms的时间取下一个抽样点,并让CPU工作对应振幅的时间。

#include<windows.h>
#include<stdlib.h>
#include<math.h>

const int SAMPLING_COUNT=200;//抽样点数量
const double PI=3.1415926535;//pi值
const int TOTAL_AMPLITUDE=300;// 每个抽样点对应的时间片

int main()
{
     SetThreadAffinityMask(GetCurrentProcess(), 0x00000001);
	DWORD busySpan[SAMPLING_COUNT]; //array of busy time
	DWORD idleSpan[SAMPLING_COUNT]; //array of idle time
	int amplitude=TOTAL_AMPLITUDE/2;
	double radian=0.0;
	double radianIncrement=2.0/(double)SAMPLING_COUNT;//抽样弧度的增量,也可以自己设置固定的增量大小
	for(int i=0;i<SAMPLING_COUNT;i++)
	{
		busySpan[i]=(DWORD)(amplitude+(sin(PI*radian)*amplitude));
		idleSpan[i]=TOTAL_AMPLITUDE-busySpan[i];
		radian+=radianIncrement;
		//printf("%d	%d
",busySpan[i],TOTAL_AMPLITUDE-busySpan[i]);
	}
	DWORD startTime=0;
	//for(int j=0;;j=(j+1)%SAMPLING_COUNT){
	//	startTime=GetTickCount();
	//	while((GetTickCount()-startTime)<=busySpan[j])
	//	;
	//	Sleep(TOTAL_AMPLITUDE-busySpan[j]);
//	}
	int j=0;
	while(true)
	{
		j=j%SAMPLING_COUNT;
		startTime=GetTickCount();
	while((GetTickCount()-startTime)<=busySpan[j])
		;
		Sleep(idleSpan[j]);
		j++;
	}
	return 0;
}

 运行出的CPU截图如下:

原文地址:https://www.cnblogs.com/huyourongmonkey/p/7517794.html