算法的优雅(四):让CPU曲线听你的指挥

来源:互联网 发布:linux root密码忘记 编辑:程序博客网 时间:2024/05/12 12:49

内容同样来自《编程之美》的第一节《让CPU曲线听你的指挥》,感觉我写的不清楚的可以移步《编程之美》这本书,CSDN书库里面有,淘宝上有正版的,24元不过邮费10块,有一家淘宝包邮,也是正版的,不过书是书店图书馆下架的展示书.....


这一章里,总共有三个问题:

1.CPU的占用率固定在50%。

2.CPU的占用率为一条直线,具体占用率由命令行参数决定。

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


下面的东西只涉及到1,3问,第2问我也不会......


首先,我们先思考一个问题,CPU的占用率代表着什么?这个问题我们要在正在学习的操作系统里面寻找答案,在任务管理器的一个刷新周期内,CPU的执行应用程序事件和刷新周期总时间比就是CPU的占用率,知道了这个,我们就可以写一个程序,控制CPU在一个刷新周期内一会儿忙,一会儿闲,之后调节这个比例,保持在50%。


首先,我们将这个问题简化一下,让CPU是单核的,并且已近知道了CPU的频率,可以估算出一秒内CPU可以执行多少条指令,之后取一半,再考虑一下时间间隔,如果我们让CPU工作1秒,休息1秒,很容易出现一个起伏很大的波形,所以,回想一下windows系统课上老师说的windows调度时间片时间,10毫秒。

代码:

int main(){for (;;){for (int i = 0; i < time; i++);Sleep(10);}return 0;}

这样,一个CPU直线出现了。

但是,有个问题,就是不同电脑怎么办,双核又怎么办。


还记得windows下有个函数么?GetTickCount(),这个是显示从系统启动到现在经历的时间,毫秒单位,有了它,我们就能判断我们的空循环需要多久了。

const DWORD busyTime = 10;const DWORD int idleTime = busyTime;Int64 startTime = 0;while (true){DWORD startTime = GetTickCount();while (GetTickCount() - startTime <= busyTime);Sleep(idleTime);}



这样,我们解决了不同电脑的问题。

这样,画正弦曲线也不难了。

我们把正弦曲线0~2π之间的弧度等分200份,计算每个点振幅,然后每隔300ms的时间抽取下个点,并让CPU工作对应振幅的时间。

#include "windows.h"#include "stdio.h"#include "math.h"const int SAMPLING_COUNT = 200;const double PI = 3.1415926535;const int TOTAL_AMPLITUDE = 300;int _tmain(int argc, _TCHAR* argv[]){DWORD buySpan[SAMPLING_COUNT];int amplintude = 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));radian += radianIncrement;}DWORD startTime = 0;for (int j = 0;; j = (j + 1) % SAMPLING_COUNT){startTime = GetTickCount();while ((GetTickCount() - startTime) <= busySpan[j]);Sleep(TOTAL_AMPLITUDE - busySpan[j]);}return 0;}

显然,双核的情况下还是不尽人意的。

想到windows下API中有GetCurrentProcessSetProcessAffinityMask,更改之:

#include "windows.h"#include "stdio.h"#include "math.h"const int SAMPLING_COUNT = 200;const double PI = 3.1415926535;const int TOTAL_AMPLITUDE = 300;int _tmain(int argc, _TCHAR* argv[]){SetProcessAffinityMask(GetCurrentProcess(),0x00000001);DWORD buySpan[SAMPLING_COUNT];int amplintude = 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));radian += radianIncrement;}DWORD startTime = 0;for (int j = 0;; j = (j + 1) % SAMPLING_COUNT){startTime = GetTickCount();while ((GetTickCount() - startTime) <= busySpan[j]);Sleep(TOTAL_AMPLITUDE - busySpan[j]);}return 0;}
暂时CSDN不知道怎么上传不了图了...以后补上吧.....
大体是想就是控制一个周期内的CPU工作情况,而至于图像的生成,和win32课程上的生成方式类似的,算法设计的不多,主要是对API的一种了解,《编程之美》上说,如果你对上面的几个API了解并能应用了,你可以在简历上写“精通windows”了.....
PS中秋节快乐。

原创粉丝点击