首页 > 技术文章 > 编程之美 1.1让CPU占用率曲线听你指挥

Linkabox 2013-10-11 12:21 原文

问题:

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

2.问题1的进阶,占用率有参数决定。

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

此题目涉及到操作系统API的调用,及对CPU时钟周期的理解,我的电脑配置为:i5-3570k 3.40GHz

解法一:

执行一个循环n次的空循环,然后Sleep()一段时间。

这种方法的不稳定因素太多,例如:机器的差异性、系统内核调度程序的干扰。

实验结果:没有推算出n的值,随便敲了几个,CPU占用率浮动在16%上下。

解法二:

利用GetTickCount()计算busyTime同时Sleep(idleTime),由参数指定busyTime所占比例。

实验结果:虽然busyTime和idleTime相等,但观察CPU占用率还是为25%,可能我的CPU是四核。

解法三:

利用Perfmon实时查询CPU使用率动态调整idleTime

实验结果:因为PerformanceCounter这对象由.Net提供,C#的东西没去试。

正弦曲线解法:

#include <Windows.h>
#include <stdlib.h>
#include <math.h>
#include <tchar.h>
const double SPLIT=0.01;    //弧度变化率
const int COUNT=200;        //细分区间
const double PI=3.14159265;
const int INTERVAL=300;        //决定振幅

int _tmain(int argc,_TCHAR* argv[])
{
    DWORD busySpan[COUNT];
    DWORD idleSpan[COUNT];
    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;
}

总结:

Sleep()——让当前线程停下来

WaitForSingleObject()——自己停下来,等待某个事情发生

GetTickCount()——得到系统启动到现在所经历的毫秒数

timeGetSystemTime()——另一种得到高精度时间的方法

GetProcessorInfo() / SetThreadAffinityMask() ——遇到多核用这两个方法更好控制CPU

GetCPUTickCount()——获取CPU核心运行周期,要配合上面两个方法来使用,否则得到的值没什么意义

推荐阅读