题目:让CPU占用率曲线听你指挥
代码:
// 面试题1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h> //Sleep
#include <math.h>
#include <stdlib.h>
#ifndef _HEADERFILENAME_H_
#define _HEADERFILENAME_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <PowrProf.h>
#ifdef __cplusplus
}
#endif
#endif
#pragma comment(lib,"PowrProf.lib")
typedef struct _PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION , *PPROCESSOR_POWER_INFORMATION;
//对机器的适应性差,一旦换CUP,需要重新估计n
int n = 9600000;
void Solution_1()
{
for(; ;)
{
for(int i=0; i<n; i++)
;
Sleep(10);
}
}
void Solution_2()
{
const DWORD busyTime = 10; //10ms unsigned long DWORD;
const DWORD idleTime = busyTime;
//DWORD startTime = 0;
while(true)
{
DWORD startTime = GetTickCount(); //系统启动到现在所经历时间的毫秒值
// busy loop
while((GetTickCount() - startTime) <= busyTime)
;
// idle loop
Sleep(idleTime); //主动进入睡眠状态,10毫秒
}
}
//
const int SAMPLING_COUNT = 200; //抽样点数量
const double PI = 3.1415926535;
const int TOTAL_AMPLITUDE = 300; //每个抽样点对应的时间片
void Solution_3()
{
DWORD 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] = (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]);
}
}
inline unsigned __int64 GetCPUTickCount()
{
__asm
{
rdtsc;
}
}
void Solution_4()
{
_PROCESSOR_POWER_INFORMATION info;
CallNtPowerInformation(ProcessorInformation ,NULL, 0,&info,sizeof(info));
unsigned __int64 t_begin = GetCPUTickCount();
// do something
unsigned __int64 t_end = GetCPUTickCount();
double millisec = (double)(t_end - t_begin)/(double)info.CurrentMhz;
}
int Soluiton_5()
{
HANDLE curhandle = GetCurrentThread(); //获取当前线程句柄
DWORD_PTR dwThreadAffinityMask = 2;
if(!SetThreadAffinityMask(curhandle, dwThreadAffinityMask))
{
return 0;
}
int busytime = 10; // 10ms;
int idletime = busytime;
//DWORD starttime = 0;
//获取当前cpu的周期
_PROCESSOR_POWER_INFORMATION IpOutputBuffer;
CallNtPowerInformation(
ProcessorInformation, //获取处理器信息
NULL,
0,
&IpOutputBuffer,
sizeof(IpOutputBuffer)
);
printf("%lld", IpOutputBuffer.CurrentMhz);
unsigned __int64 starttime = 0;
unsigned __int64 endtime;
//while(1)
//{
//starttime = GetCPUTickCount();
//endtime = GetCPUTickCount();
//注意:这个地方要再除以一个1000,因为想要求的是ms单位,__rdtsc()得到的cpu周期数,
//CurrentMhz为cpu频率,单位为MHZ=周期/秒=周期*1000/毫秒
//while((((double)endtime - (double)starttime)/1000/(double)IpOutputBuffer.CurrentMhz) <= busytime);
//Sleep(idletime);
DWORD 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] = (DWORD)(amplitude + (sin(PI * radian) * amplitude));
radian += radianIncrement;
}
for (int j = 0;;j = (j + 1) % SAMPLING_COUNT)
{
starttime = GetCPUTickCount();
endtime = GetCPUTickCount();
double millisec = (double)((double)endtime - (double)starttime)/1000/(double)IpOutputBuffer.CurrentMhz;
//printf("[%j]=%d\n",j,busySpan[j]);
while ( millisec <= busySpan[j])
;
Sleep(TOTAL_AMPLITUDE - busySpan[j]);
}
// }
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
Soluiton_5();
//Solution_3();
return 0;
}
参考
http://bbs.pediy.com/showthread.php?t=96926
http://msdn.microsoft.com/zh-cn/subscriptions/aa372675
http://www.cnblogs.com/growup/archive/2012/03/13/2394783.html
http://blog.csdn.net/jia_xiaoxin/article/details/2919455