如何读取CPU频率?

光宇广贞 2009-04-29 06:49:48
如题
...全文
776 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
光宇广贞 2009-04-30
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 sbtdkj1017 的回复:]
不是很明白问此问题的目的。
如果想知道CPU频率(如题),用QueryPerformanceFrequency就够了,而且已经很精确了。
如果想计时,用我刚才发的两函数就可以了。
如果想定时(18楼),用Timer就可以了
[/Quote]
QueryPerformanceFrequency 做不到,它有它自己的计时精度,不能配合 __rdtsc()函数。而rdtsc才是真正的CPU时钟频率,通过两个rdtsc在一定时段内的值差便可以精确计算出CPU的频率。
sbtdkj1017 2009-04-30
  • 打赏
  • 举报
回复
不是很明白问此问题的目的。
如果想知道CPU频率(如题),用QueryPerformanceFrequency就够了,而且已经很精确了。
如果想计时,用我刚才发的两函数就可以了。
如果想定时(18楼),用Timer就可以了
光宇广贞 2009-04-30
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 sbtdkj1017 的回复:]
C/C++ code

void CDemoDoc::tic()
{
QueryPerformanceCounter(&m_start);
}

void CDemoDoc::toc()
{
LARGE_INTEGER stop,freq;
QueryPerformanceCounter(&stop);
if(!QueryPerformanceFrequency(&freq))
{
TRACE("high-resolution performance counter not supported by the hardware\n");
return;
}
if (freq.LowPart==0 && freq.HighPart==0)
{
m_etime = -1;

[/Quote]

谢谢。
然后呢?
怎么样计算出一秒钟?

一种方式是进入循环读取QueryPerformanceCounter使两次QueryPerformanceCounter的差值满足QueryPerformanceFrequency,除此之外还有没有更高效的方法?
或者根本不用去知道1秒的时长仅可以凭命令本身就去计算出频率来?

rdtsc指令周期大约在60左右。
sbtdkj1017 2009-04-30
  • 打赏
  • 举报
回复

void CDemoDoc::tic()
{
QueryPerformanceCounter(&m_start);
}

void CDemoDoc::toc()
{
LARGE_INTEGER stop,freq;
QueryPerformanceCounter(&stop);
if(!QueryPerformanceFrequency(&freq))
{
TRACE("high-resolution performance counter not supported by the hardware\n");
return;
}
if (freq.LowPart==0 && freq.HighPart==0)
{
m_etime = -1;
return;
}
m_etime = (stop.QuadPart-m_start.QuadPart)/(float)freq.QuadPart;
}

chenchangxiong 2009-04-30
  • 打赏
  • 举报
回复
学习ing
Jalien 2009-04-30
  • 打赏
  • 举报
回复
学习了~
jackzhhuang 2009-04-30
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 hikaliv 的回复:]
引用 13 楼 jackzhhuang 的回复:
QueryPerformance函数


它里面是怎么实现的?说是牺牲了精度却保证了稳定性的函数方法,它能较精确地计算出一秒的tickcounts ,问题是它是怎么知道那是一秒?
[/Quote]
这个我也不知道他是如何实现的。
光宇广贞 2009-04-30
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 jackzhhuang 的回复:]
QueryPerformance函数
[/Quote]

它里面是怎么实现的?说是牺牲了精度却保证了稳定性的函数方法,它能较精确地计算出一秒的tickcounts ,问题是它是怎么知道那是一秒?
jackzhhuang 2009-04-30
  • 打赏
  • 举报
回复
QueryPerformance函数
yeungqi 2009-04-30
  • 打赏
  • 举报
回复
up
光宇广贞 2009-04-30
  • 打赏
  • 举报
回复
cpuid 无法取得 CPU 的实际频率。有关通过 CPUID 和没有其它方法配合的 rdtsc 函数都是不正确的。

问题改成这样问吧:

实模式下可以直接读 BIOS 来实时检测CPU的频率,而WINDOWS下怎么样读?
注册表的方式不好,而且在RELEASE模式下结果是不正确的。

有没有其它的方式?
Sou2012 2009-04-29
  • 打赏
  • 举报
回复
MARK!!!
tangshuiling 2009-04-29
  • 打赏
  • 举报
回复
mark!
xghuzd 2009-04-29
  • 打赏
  • 举报
回复
不会,只能帮顶了。
lingyin55 2009-04-29
  • 打赏
  • 举报
回复

可以参考 __cpuid 这个在MSDN里的例子,贴在下面,可能新CPU会不好用,老Demo了,其中有获取CPU时钟频率的部分,自己可以找找MSDN看看返回值中的一些参数:



#include <stdio.h>
#include <string.h>
#include <intrin.h>

const char* szFeatures[] =
{
"x87 FPU On Chip",
"Virtual-8086 Mode Enhancement",
"Debugging Extensions",
"Page Size Extensions",
"Time Stamp Counter",
"RDMSR and WRMSR Support",
"Physical Address Extensions",
"Machine Check Exception",
"CMPXCHG8B Instruction",
"APIC On Chip",
"Unknown1",
"SYSENTER and SYSEXIT",
"Memory Type Range Registers",
"PTE Global Bit",
"Machine Check Architecture",
"Conditional Move/Compare Instruction",
"Page Attribute Table",
"Page Size Extension",
"Processor Serial Number",
"CFLUSH Extension",
"Unknown2",
"Debug Store",
"Thermal Monitor and Clock Ctrl",
"MMX Technology",
"FXSAVE/FXRSTOR",
"SSE Extensions",
"SSE2 Extensions",
"Self Snoop",
"Hyper-threading Technology",
"Thermal Monitor",
"Unknown4",
"Pend. Brk. EN."
};

int main(int argc, char* argv[])
{
char CPUString[0x20];
char CPUBrandString[0x40];
int CPUInfo[4] = {-1};
int nSteppingID = 0;
int nModel = 0;
int nFamily = 0;
int nProcessorType = 0;
int nExtendedmodel = 0;
int nExtendedfamily = 0;
int nBrandIndex = 0;
int nCLFLUSHcachelinesize = 0;
int nAPICPhysicalID = 0;
int nFeatureInfo = 0;
int nCacheLineSize = 0;
int nL2Associativity = 0;
int nCacheSizeK = 0;
int nRet = 0;
unsigned nIds, nExIds, i;
bool bSSE3NewInstructions = false;
bool bMONITOR_MWAIT = false;
bool bCPLQualifiedDebugStore = false;
bool bThermalMonitor2 = false;


// __cpuid with an InfoType argument of 0 returns the number of
// valid Ids in CPUInfo[0] and the CPU identification string in
// the other three array elements. The CPU identification string is
// not in linear order. The code below arranges the information
// in a human readable form.
__cpuid(CPUInfo, 0);
nIds = CPUInfo[0];
memset(CPUString, 0, sizeof(CPUString));
*((int*)CPUString) = CPUInfo[1];
*((int*)(CPUString+4)) = CPUInfo[3];
*((int*)(CPUString+8)) = CPUInfo[2];

// Get the information associated with each valid Id
for (i=0; i<=nIds; ++i)
{
__cpuid(CPUInfo, i);
printf_s("\nFor InfoType %d\n", i);
printf_s("CPUInfo[0] = 0x%x\n", CPUInfo[0]);
printf_s("CPUInfo[1] = 0x%x\n", CPUInfo[1]);
printf_s("CPUInfo[2] = 0x%x\n", CPUInfo[2]);
printf_s("CPUInfo[3] = 0x%x\n", CPUInfo[3]);

// Interpret CPU feature information.
if (i == 1)
{
nSteppingID = CPUInfo[0] & 0xf;
nModel = (CPUInfo[0] >> 4) & 0xf;
nFamily = (CPUInfo[0] >> 8) & 0xf;
nProcessorType = (CPUInfo[0] >> 12) & 0x3;
nExtendedmodel = (CPUInfo[0] >> 16) & 0xf;
nExtendedfamily = (CPUInfo[0] >> 20) & 0xff;
nBrandIndex = CPUInfo[1] & 0xff;
nCLFLUSHcachelinesize = ((CPUInfo[1] >> 8) & 0xff) * 8;
nAPICPhysicalID = (CPUInfo[1] >> 24) & 0xff;
bSSE3NewInstructions = (CPUInfo[2] & 0x1) || false;
bMONITOR_MWAIT = (CPUInfo[2] & 0x8) || false;
bCPLQualifiedDebugStore = (CPUInfo[2] & 0x10) || false;
bThermalMonitor2 = (CPUInfo[2] & 0x100) || false;
nFeatureInfo = CPUInfo[3];
}
}

// Calling __cpuid with 0x80000000 as the InfoType argument
// gets the number of valid extended IDs.
__cpuid(CPUInfo, 0x80000000);
nExIds = CPUInfo[0];
memset(CPUBrandString, 0, sizeof(CPUBrandString));

// Get the information associated with each extended ID.
for (i=0x80000000; i<=nExIds; ++i)
{
__cpuid(CPUInfo, i);
printf_s("\nFor InfoType %x\n", i);
printf_s("CPUInfo[0] = 0x%x\n", CPUInfo[0]);
printf_s("CPUInfo[1] = 0x%x\n", CPUInfo[1]);
printf_s("CPUInfo[2] = 0x%x\n", CPUInfo[2]);
printf_s("CPUInfo[3] = 0x%x\n", CPUInfo[3]);

// Interpret CPU brand string and cache information.
if (i == 0x80000002)
memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
else if (i == 0x80000003)
memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
else if (i == 0x80000004)
memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
else if (i == 0x80000006)
{
nCacheLineSize = CPUInfo[2] & 0xff;
nL2Associativity = (CPUInfo[2] >> 12) & 0xf;
nCacheSizeK = (CPUInfo[2] >> 16) & 0xffff;
}
}

// Display all the information in user-friendly format.

printf_s("\n\nCPU String: %s\n", CPUString);

if (nIds >= 1)
{
if (nSteppingID)
printf_s("Stepping ID = %d\n", nSteppingID);
if (nModel)
printf_s("Model = %d\n", nModel);
if (nFamily)
printf_s("Family = %d\n", nFamily);
if (nProcessorType)
printf_s("Processor Type = %d\n", nProcessorType);
if (nExtendedmodel)
printf_s("Extended model = %d\n", nExtendedmodel);
if (nExtendedfamily)
printf_s("Extended family = %d\n", nExtendedfamily);
if (nBrandIndex)
printf_s("Brand Index = %d\n", nBrandIndex);
if (nCLFLUSHcachelinesize)
printf_s("CLFLUSH cache line size = %d\n",
nCLFLUSHcachelinesize);
if (nAPICPhysicalID)
printf_s("APIC Physical ID = %d\n", nAPICPhysicalID);

if (nFeatureInfo || bSSE3NewInstructions ||
bMONITOR_MWAIT || bCPLQualifiedDebugStore ||
bThermalMonitor2)
{
printf_s("\nThe following features are supported:\n");

if (bSSE3NewInstructions)
printf_s("\tSSE3 New Instructions\n");
if (bMONITOR_MWAIT)
printf_s("\tMONITOR/MWAIT\n");
if (bCPLQualifiedDebugStore)
printf_s("\tCPL Qualified Debug Store\n");
if (bThermalMonitor2)
printf_s("\tThermal Monitor 2\n");

i = 0;
nIds = 1;
while (i < (sizeof(szFeatures)/sizeof(const char*)))
{
if (nFeatureInfo & nIds)
{
printf_s("\t");
printf_s(szFeatures);
printf_s("\n");
}

nIds <<= 1;
++i;
}
}
}

if (nExIds >= 0x80000004)
printf_s("\nCPU Brand String: %s\n", CPUBrandString);

if (nExIds >= 0x80000006)
{
printf_s("Cache Line Size = %d\n", nCacheLineSize);
printf_s("L2 Associativity = %d\n", nL2Associativity);
printf_s("Cache Size = %dK\n", nCacheSizeK);
}

return nRet;
}

lingyin55 2009-04-29
  • 打赏
  • 举报
回复
参考


#include <windows.h>
#include <stdio.h>
#include <iostream.h>

void main()
{
int tick1,tick2;
_asm rdtsc
_asm mov tick1,eax
Sleep(50);
_asm rdtsc
_asm mov tick2,eax
int freq=(tick2-tick1)/50000;
printf("CPU:%d MHz",freq);

SYSTEM_INFO siSysInfo;
GetSystemInfo(&siSysInfo);


printf("\nHardware information: \n");
printf(" OEM ID: %u\n", siSysInfo.dwOemId);
printf(" Number of processors: %u\n", siSysInfo.dwNumberOfProcessors);
printf(" Page size: %u\n", siSysInfo.dwPageSize);
printf(" Processor type: %u\n", siSysInfo.dwProcessorType);
printf(" Minimum application address: %lx\n", siSysInfo.lpMinimumApplicationAddress);
printf(" Maximum application address: %lx\n", siSysInfo.lpMaximumApplicationAddress);
printf(" Active processor mask: %u\n", siSysInfo.dwActiveProcessorMask);

MEMORYSTATUS memstatus;
memset(&memstatus,0,sizeof(MEMORYSTATUS));
memstatus.dwLength =sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&memstatus);
DWORD mem=memstatus.dwAvailPhys;
DWORD res=memstatus.dwAvailVirtual;
DWORD totalphy=memstatus.dwTotalPhys;
DWORD totalvir=memstatus.dwTotalVirtual;
cout << "Total:" << totalphy << " ";
cout << "Free:" << mem <<endl;
cout << "Physical memory in use:" << memstatus.dwMemoryLoad << "%" <<endl;

}

jixingzhong 2009-04-29
  • 打赏
  • 举报
回复
VC知识库文章:

利用利用CPUID 汇编指令(机器码:0FH A2H, 如果你的编译器不支持CPUID 指 令,只有emit 机器码了), 该指令可以被如下CPU识别:

Intel 486 以上的CPU,
Cyrix M1 以上的CPU,
AMD Am486 以上的CPU

  (1) 取CPU OEM 字符串, 判断CPU 厂商
  先让EAX=0, 再调用CPUID
   Inel的CPU将返回:

EBX:756E6547H 'Genu'
EDX:49656E69H 'ineI'
ECX:6C65746EH 'ntel'
EBX,EDX,ECX 将连成"GenuineIntel", 真正的Intel。

Cyrix 的CPU 将返回:

EBX:43797269H
EDX:78496E73H
ECX:74656164H
"CyrixInstead","Cyrix 来代替"。

AMD 的CPU 将返回:

EBX:41757468H
EDX:656E7469H
ECX:63414D44H
"AuthenticAMD", 可信的AMD。

  在Windows98中,用右键单击"我的电脑",选择" 属性- 常规"在计算机描述 处就可看见CPU OEM 字符串。

  (2)CPU 到底是几86, 是否支持MMX
  先让EAX=1,再调用CPUID
  EAX的8到11位就表明是几86

3 - 386
4 - i486
5 - Pentium
6 - Pentium Pro Pentium II
2 - Dual Processors

  EDX 的第0位:有无FPU

  EDX的第23位:CPU是否支持IA MMX,很重要啊 !如果你想用那57条新增的指 令,先检查这一位吧,否则就等着看Windows 的"该程序执行了非法指令,将被关 闭" 吧。

  (3) 专门检测是否P6架构
  先让EAX=1,再调用CPUID
  如果AL=1,就是Pentium Pro 或Pentium II
  (4) 专门检测AMD的CPU信息
  先让EAX=80000001H,再调用CPUID
  如果EAX=51H, 是AMD K5
  如 果EAX=66H, 是K6
  EDX第0 位: 是否有FPU( 多余的 !谁用过没FPU的K5,K6?)
  EDX 第23 位,CPU是否支持MMX,

  程序如下:

//------CPUID Instruction Demo Program------------
#include
#include
#pragma hdrstop
//------------------------------------------------
#pragma inline
#pragma argsused
int main(int argc, char **argv)
{
char OEMString[13];
int iEAXValue,iEBXValue,iECXValue,iEDXValue;
_asm {
mov eax,0
cpuid
mov DWORD PTR OEMString,ebx
mov DWORD PTR OEMString+4,edx
mov DWORD PTR OEMString+8,ecx
mov BYTE PTR OEMString+12,0
}
cout< < "This CPU 's OEM String is:"< < OEMString< < endl;
_asm {
mov eax,1
cpuid
mov iEAXValue,eax
mov iEBXValue,ebx
mov iECXValue,ecx
mov iEDXValue,edx
}
if(iEDXValue&0x800000)
cout < < "This is MMX CPU"< < endl;
else
cout < < "None MMX Support."< < endl;
int iCPUFamily=(0xf00 & iEAXValue) > >8;
cout < < "CPU Family is:"< < iCPUFamily< < endl;
_asm{
mov eax,2
CPUID
}
if(_AL==1)
cout < < "Pentium Pro or Pentium II Found";

return 0;
}
jixingzhong 2009-04-29
  • 打赏
  • 举报
回复
VC知识库文章:

利用利用CPUID 汇编指令(机器码:0FH A2H, 如果你的编译器不支持CPUID 指 令,只有emit 机器码了), 该指令可以被如下CPU识别:

Intel 486 以上的CPU,
Cyrix M1 以上的CPU,
AMD Am486 以上的CPU

  (1) 取CPU OEM 字符串, 判断CPU 厂商
  先让EAX=0, 再调用CPUID
   Inel的CPU将返回:

EBX:756E6547H 'Genu'
EDX:49656E69H 'ineI'
ECX:6C65746EH 'ntel'
EBX,EDX,ECX 将连成"GenuineIntel", 真正的Intel。

Cyrix 的CPU 将返回:

EBX:43797269H
EDX:78496E73H
ECX:74656164H
"CyrixInstead","Cyrix 来代替"。

AMD 的CPU 将返回:

EBX:41757468H
EDX:656E7469H
ECX:63414D44H
"AuthenticAMD", 可信的AMD。

  在Windows98中,用右键单击"我的电脑",选择" 属性- 常规"在计算机描述 处就可看见CPU OEM 字符串。

  (2)CPU 到底是几86, 是否支持MMX
  先让EAX=1,再调用CPUID
  EAX的8到11位就表明是几86

3 - 386
4 - i486
5 - Pentium
6 - Pentium Pro Pentium II
2 - Dual Processors

  EDX 的第0位:有无FPU

  EDX的第23位:CPU是否支持IA MMX,很重要啊 !如果你想用那57条新增的指 令,先检查这一位吧,否则就等着看Windows 的"该程序执行了非法指令,将被关 闭" 吧。

  (3) 专门检测是否P6架构
  先让EAX=1,再调用CPUID
  如果AL=1,就是Pentium Pro 或Pentium II
  (4) 专门检测AMD的CPU信息
  先让EAX=80000001H,再调用CPUID
  如果EAX=51H, 是AMD K5
  如 果EAX=66H, 是K6
  EDX第0 位: 是否有FPU( 多余的 !谁用过没FPU的K5,K6?)
  EDX 第23 位,CPU是否支持MMX,

  程序如下:

//------CPUID Instruction Demo Program------------
#include
#include
#pragma hdrstop
//------------------------------------------------
#pragma inline
#pragma argsused
int main(int argc, char **argv)
{
char OEMString[13];
int iEAXValue,iEBXValue,iECXValue,iEDXValue;
_asm {
mov eax,0
cpuid
mov DWORD PTR OEMString,ebx
mov DWORD PTR OEMString+4,edx
mov DWORD PTR OEMString+8,ecx
mov BYTE PTR OEMString+12,0
}
cout< < "This CPU 's OEM String is:"< < OEMString< < endl;
_asm {
mov eax,1
cpuid
mov iEAXValue,eax
mov iEBXValue,ebx
mov iECXValue,ecx
mov iEDXValue,edx
}
if(iEDXValue&0x800000)
cout < < "This is MMX CPU"< < endl;
else
cout < < "None MMX Support."< < endl;
int iCPUFamily=(0xf00 & iEAXValue) > >8;
cout < < "CPU Family is:"< < iCPUFamily< < endl;
_asm{
mov eax,2
CPUID
}
if(_AL==1)
cout < < "Pentium Pro or Pentium II Found";

return 0;
}
jixingzhong 2009-04-29
  • 打赏
  • 举报
回复
一个CPU信息获取类 http://www.codefans.net/soft/2594.shtml
liliangbao 2009-04-29
  • 打赏
  • 举报
回复
http://topic.csdn.net/t/20050114/23/3727239.html

64,636

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧