解説
アセンブラの「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;
}
