【编程之美】CPU
今天开始看编程之美 。第一个问题是CPU的使用率控制,微软的问题果然高大上,我一看就傻了,啥也不知道。没追求直接看答案试了一下。发现自己电脑太好了,4核8线程,程序乱飘。加了一个进程绑定,可以控制一个CPU的占有率。
代码结果如下:
#include"stdio.h" #include <Windows.h> void main() { //前三行可以不要 SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); int CpuNum=SystemInfo.dwNumberOfProcessors; //获取cpu数目 SetThreadAffinityMask(GetCurrentThread(), 1); //线程与cpu绑定 while(1) { for(int i=0;i<3400000000;i++); Sleep(10); } }
现在的疑问是,不知道如何指定具体的某一个CPU. SetThreadAffinityMask的第二个参数改了后和自己想要的不一样。也不知道如何实现所有CPU占有率的同时控制。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
第二个版本 按照书中给的可以根据不同的CPU精确计算时间的代码 效果好很多
//比初始最简单的版本好很多 CPU使用中可以得到非常漂亮的直线 不像之前有锯齿 #include<stdio.h> #include<Windows.h> void main() { const int busyTime=10; //10ms const int idleTime=busyTime; //50% cpu useage int startTime=0; SetThreadAffinityMask(GetCurrentThread(), 1); //cpu绑定 while(1) { int startTime=GetTickCount(); //busy loop while(GetTickCount()-startTime<=busyTime); //idle loop Sleep(idleTime); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
第三个版本 正弦曲线 可以调周期和赋值等参数
开始脑子晕了 总是搞不清楚关系 后来看了答案 发现答案的思路很清晰 自己又静下心来分析了一下正弦函数的表达式修改一下自己的代码 也实现了功能 不过曲线上个抖动比较大。
计算公式:
一次取样的时间 busytime+idletime=常数 单位毫秒
忙的时间占得百分比就是正弦函数计算的结果:
busytime/(busytime+idletime)=middle+amplitude*sin(x)
每一次的x值与周期有关
x=n*(busytime+idletime)/1000T 周期单位是秒 n每循环一次加1
代码:
#include<stdio.h> #include<Windows.h> #include<math.h> #include<stdlib.h> #define Mine 1 #define Answer 0 #if Mine void main() { SetThreadAffinityMask(GetCurrentThread(), 1); //cpu绑定 double busyTime; double idleTime; double onceTime=200; //一次抽样300ms busyTime+idleTime=300 float up=0.8; //正弦曲线波峰值 float down=0.2; //正弦曲线波谷值 int T=60; //正弦曲线周期s int startTime=0; int n=0; float amplitude=(up-down)/2; //振幅 float middle=(up+down)/2; //正弦曲线中心点 while(1) { busyTime=onceTime*(middle+amplitude*sin(2*3.1415*n*onceTime/(1000*T))); idleTime=onceTime-busyTime; int startTime=GetTickCount(); //busy loop while(GetTickCount()-startTime<=busyTime); //idle loop Sleep(idleTime); n=n+1; } } #endif #if Answer const int SAMPLING_COUNT=200; //抽样点数量 const double PI=3.1415926535; const int TOTAL_AMPLITUDE=300; //每个抽样点对应的时间片 int main() { SetThreadAffinityMask(GetCurrentThread(), 1); long busySpan[SAMPLING_COUNT]; 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]=(long)(amplitude+(sin(PI*radian)*amplitude)); radian+=radianIncrement; } int startTime=0; for(int j=0;;j=(j+1)%SAMPLING_COUNT) { startTime=GetTickCount(); while((GetTickCount()-startTime)<=busySpan[j]); Sleep(30+TOTAL_AMPLITUDE-busySpan[j]); } return 0; } #endif
书上代码结果:
自己写得代码结果:
抖动很大 而且onceTime变小后抖动更大了 在onceTime很小的时候 busytime/onceTime=0.5 时曲线都会饱和截至,不知道原因。
注:所有的图都是第一个cpu的结果有效。