zoukankan      html  css  js  c++  java
  • 让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截图如下:

  • 相关阅读:
    3524: [Poi2014]Couriers -- 主席树
    bzoj 2190: [SDOI2008]仪仗队 -- 欧拉函数
    模板 -- 树链剖分
    bzoj 1823: [JSOI2010]满汉全席 -- 2-sat
    bzoj 1704: [Usaco2007 Mar]Face The Right Way 自动转身机 -- 贪心
    bzoj 1231: [Usaco2008 Nov]mixup2 混乱的奶牛 -- 状压DP
    redis 主从复制
    redis 事务
    redis持久化——AOF
    redis 持久化 ——RDB
  • 原文地址:https://www.cnblogs.com/huyourongmonkey/p/7517794.html
Copyright © 2011-2022 走看看