CPU動作周波数取得

解説

   アセンブラの「rdtsc」命令を使うことで取得。「cpuid」が使えるCPUが載っているマシンでのみ動作する(最近のPentium以降は対応)。

   GetCPUFreq() : 動作周波数取得
   IsEnableCPUID() :  「cpuid」が使えるかどうか判別
   IsEnableRDTSC() :  「rdtsc」が使えるかどうか判別

 ・使い方
    GetCPUFreq();を実行すれば2秒後に整数形式で周波数が取得できる。単位はMHz。
   結果に数MHzの誤差があるがこれは勘弁してください。

 ・コード


#include "Mmsystem.h"
#pragma comment(lib,"Winmm.lib")

bool IsEnableCPUID(void)
{  
	 bool bRet;
	DWORD dwTemp1;
	DWORD dwTemp2; 
	_asm
	{
		pushfd
		pop eax
		mov dwTemp1,eax
		xor eax,00200000h
		push eax
		popfd
		pushfd
		pop eax
		mov dwTemp2,eax
	}
	if(dwTemp1 != dwTemp2)
		bRet = true;
	else
		bRet = false;

	return bRet;
} 

bool IsEnableRDTSC(void)
{  
	 bool bRet;
	DWORD dwTemp; 

	bRet = IsEnableCPUID();
	if(bRet == true)
	{
		_asm
		{
			mov EAX, 1
			cpuid
			mov dwTemp, EDX
		}
		if(dwTemp & 0x00000010)
			bRet = true; // RDTSC命令が使用できる
	}

	return bRet;
}

int GetCPUFreq(void)
{  
	int nRet; 
	nRet = 0;
	if(IsEnableRDTSC() == true)
	{
		DWORD dwEAX1;
		DWORD dwEAX2;
		DWORD dwEDX1;
		DWORD dwEDX2;
		DWORD dwTime;

		dwTime = ::timeGetTime();
		__asm
		{
			rdtsc
			mov dwEAX1,eax
			mov dwEDX1,edx
		}
		/////////////////////////////////
		while(1) //2秒アイドル用の無限ループ
		{
			if(::timeGetTime() - dwTime > 2000)
				break;
		}
		/////////////////////////////////
		dwTime = ::timeGetTime() - dwTime;
		__asm
		{
			rdtsc
			mov dwEAX2,eax
			mov dwEDX2,edx
		}
		dwEDX2 -= dwEDX1;
		dwEAX2 -= dwEAX1;
		nRet = (dwEDX2 << 32) + dwEAX2; //Clock数
		nRet /= dwTime; //Hz msecで除算
		nRet /= 1000; //MHz
	}

	return nRet;
}

カテゴリー「VC++ TIPS」 のエントリー