控制CPU曲线变化

        网上有很多关于控制CPU曲线的文章,大部分是从《编程之美》上的题目得到的解决思路。本文从网上的文章进行了参考借鉴,对相应的程序进行了修改。主题框架是从网上借鉴的。加进了部分修改和整理,以及修改过程中的知识点。

1、解决思路

       CPU占用率=1秒内CPU执行命令的时间/1秒,想控制CPU占用率曲线即控制CPU忙时间同CPU空闲时间的比值。比如1秒内,有0.5秒(500 毫秒)为CPU忙的时间,剩下的时间0.5秒为空闲时间,则其占用率为50%。

        如何令CPU忙呢?大部分为让程序执行空语句,这里空语句转换成机器指令大概为5条语句(这个结果是通过汇编语言推断出来的结果)。

        这里补充一下关于CPU执行命令快慢的参数的知识。主频是我们判断CPU计算速度快慢的重要参数。比如本人电脑的CPU为1.9GHz,4核,它代表一秒可以执行4*1.9*10^9次运算周期(这里说的有点不专业),每个周期可以执行两条指令。也就是说每秒可以执行2*4*1.9*10^9条指令,这里的指令是指机器语言的指令。(我们用C++编写的指令需编译链接后才可转换为机器指令其条数也会发生变化,一搬会变多,比如一个空语句转换为机器指令可以转换为5条指令)。

       这一点说明我们也可以通过控制执行语句的条数来控制CPU忙的时间,本文采用控制CPU忙的时间来实现控制CPU占用率的目的。

       让CPU空闲,本文使用Sleep()函数。

      具体代码为:

while(1)
{
 
 startTime= GetTickCount();                                                //获得当前时间(单位为毫秒)
 while((GetTickCount()-startTime)<=(INTERVAL/2));    //控制程序忙时间
 Sleep(INTERVAL/2);                                                            //控制CPU空闲时间

}

以上代码为较核心代码。

具体程序代码为:

#include <windows.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#define COUNT 200        //数组个数

const double SPLIT = 0.01;     //间隔
const double PI = 3.14159265;   //常数
const double SLOPE = 200;    //锯齿幅度
const int       INTERVAL = 100;    //正选波幅度  

using namespace std;

DWORD WINAPI SineThread(LPVOID Sine)        //创建可以产生CPU曲线的线程
{
 DWORD busySpan[COUNT];                  //数组,存储空语句运算次数
 DWORD idleSpan[COUNT];                  //存储sleep语句运算次数
 int half = INTERVAL/2;                  //为sin函数找中间值
 double radian = 0.0;                    //从0-1的增长
 DWORD startTime;
 int i;
 for (i=0; i<COUNT; i++)                //构造正选型信号数组
 {
  busySpan[i] = (DWORD)(half + half*sin(2*PI*radian));
  idleSpan[i] = (DWORD)(INTERVAL - busySpan[i]);
  int a=0;
  a=radian;
  radian = radian-a;
  radian += SPLIT;
                                       //cout<<radian<<endl;//radian从0到1变化
 }
 i = 0;
 while(1)
 {
  i %= COUNT;
  startTime = GetTickCount();
    while((GetTickCount()-startTime) <= busySpan[i])
   {;
      }
  Sleep(idleSpan[i]);
  i++;
 }
 return 0;
}

DWORD WINAPI SawThread(LPVOID Saw)                    //定义产生锯齿波的线程
{
 DWORD busySpan[COUNT];                            //忙数组
 DWORD idleSpan[COUNT];                            //空闲数组
 
 double radian = 0.0;                              //斜率,或者说新的百分比
                                                   //double BUCHANG=200;
 DWORD startTime;
 int i;

 for (i=0; i<COUNT; i++)                               //COUNT=200
 {
                                                    //i %= INTERVAL;//INTERVAL=300
  int a=SLOPE*radian;
  busySpan[i] = (DWORD)(a%100);                //SLOPE=200
  idleSpan[i] = (DWORD)(INTERVAL - busySpan[i]);
  radian += SPLIT;                                  //间隔=0.075
 }
 i = 0;
 while(1)
 {
  i %= COUNT;
  startTime = GetTickCount();
  while((GetTickCount()-startTime) <= busySpan[i])
   ;
  Sleep(idleSpan[i]);
  i++;
 }
 return 0;
}
DWORD WINAPI LineThread(LPVOID Line){
 DWORD startTime;
while(1)
{
 
 startTime= GetTickCount();
 while((GetTickCount()-startTime)<=(INTERVAL/2));
 Sleep(INTERVAL/2);

}
return 0;
}

int main()
{
 HANDLE hThread1, hThread2;
 HANDLE hThread3;
 DWORD dwThreadId1, dwThreadId2;
 DWORD dwThreadId3;

 hThread1  =CreateThread(NULL, 0, SineThread, 0, CREATE_SUSPENDED, &dwThreadId1);//创建线程,在制定的CPU上运行
 //hThread2 = CreateThread(NULL, 0, SawThread, 0, CREATE_SUSPENDED, &dwThreadId2);//创建线程,在指定的CPU上运行
 hThread3 = CreateThread(NULL, 0, LineThread, 0, CREATE_SUSPENDED, &dwThreadId3);
 SetThreadAffinityMask(hThread1, 1);
                                                                                  //SetThreadAffinityMask(hThread2, 0x00000001);
 SetThreadAffinityMask(hThread3, 2);
 ResumeThread(hThread1);                                                           //激活指定线程
 //ResumeThread(hThread2);
 ResumeThread(hThread3);                                                           //激活指定线程
 SuspendThread(GetCurrentThread());
 return 0;
}

得到的结果为:

特别说明:

SetThreadAffinityMask(hThread1,1);用于指定线程1在CPU0上运行。

本文尝试性的想让仅在第3个核心上运行均为成功,查找相关资料

SetThreadAffinityMask(hThread1,0x3);可以实现,均未成功。

还需进一步学习。

关于正弦曲线的参数控制,设计到两个参数SPLIT、INTERVAL,本人推导了一下他们同正弦曲线的周期T有如下关系:

INTERVAL/(1000*SPLIT)=T

大家可以理解为:

INTERVAL越大,T越大;

SPLIT越大,T越小。

这两个参数,可以用来控制正选曲线的显示周期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值