编程之美面试题1

题目:让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

    原文作者:紫荆飘香V
    原文地址: https://blog.csdn.net/ahuang1900/article/details/33359603
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞