CPU的主频,即CPU内核工作的时钟频率(CPU Clock Speed)。CPU的主频表示在CPU内数字脉冲信号震荡的速度。主频和实际的运算速度存在一定的关系,但目前还没有一个确定的公式能够定量两者的数值关系,因为CPU的运算速度还要看CPU的流水线的各方面的性能指标(缓存、指令集,CPU的位数等等)。由于主频并不直接代表运算速度,所以在一定情况下,很可能会出现主频较高的CPU实际运算速度较低的现象。

在windows操作系统中,可以使用右键点击“我的电脑”,查看属性来获取CPU的主频信息,然而该信息是存在于注册表之中的。也就是说可以通过修改注册表来伪造CPU主频信息。那能不能用其它方法获得该信息呢?

检测CPU的速度,一般是测试在单位时间内运算的指令条数,但用这种方法有太大的局限性,由于受到很多因素的影响,准确度比较低,因为你不知道在你的程序外别的程序占用了多少的时间片。其实在586及之后处理器中,已经有了一条专用的指令来测试主频,那就是 RDTSC指令,意思是读取时间标记计数器(Read Time-Stamp Counter),Time-stamp counter 是处理器内部的一个64位的MSR (model specific register),处理器每时钟周期递增时间标签计数器 MSR 一次,在处理器复位时将它重设为 0。RDTSC 指令把 TSC的值低32位装入EAX中,高32位装入EDX中。如果CPU的主频是200MHz,那么在一秒钟内,TSC的值增加 200,000,000 次。所以在计算的时候,把两次的TSC差值除以两次的时间差值就是CPU的主频。

从上面的资料得到了一个思路:首先使用RDTSC指令获取1个TSC的值,将其存储起来,再延时1秒,使用RDTSC指令获取1个新的TSC值,并用其减去第一次获得的TSC值,即可得到该CPU的主频。用C和汇编混合的代码如下:

#include <windows.h>
#include <stdio.h> int main(int argc,char* argv[])
{
static int time[2];
int quotient = 0; //商
int remainder = 0; //余数 __asm{
rdtsc // read time-stamp count
mov ebx,offset time //将time的偏移地址存入ebx
mov [ebx+0],edx //把TSC的值的高32位存入[ebx+0]中
mov [ebx+4],eax //把TSC的值的低32位存入[ebx+4]中
}
Sleep(1000);
__asm{
rdtsc // read time-stamp count
mov ecx,offset time //将time的偏移地址存入ecx
sub eax,[ecx+4] //把延时1秒后的TSC值的低32位减去1秒前的TSC值的低32位
sbb edx,[ecx+0] //把延时1秒后的TSC值的高32位减去1秒前的TSC值的高32位 mov ecx,1000000000 //转换成GHz
div ecx
mov quotient,eax //将结果中的商赋值于quotiend
mov remainder,edx //将结果中的余数赋值于remainder
}
remainder = remainder / 10000000; //余数仅保留两位
printf("该机主频为:%d.%d",quotient,remainder);
return 0;
}

注意:寄存器 CR4 中的时间标签禁用 (TSD) 标志限制 RDTSC 的使用。清除 TSD 标志时,RDTSC 指令可以在任何特权级别执行;设置此标志时,指令只能在特权级别 0 执行。在特权级别 0 执行时,时间标签计数器还可以使用 RDMSR 指令读取。

但是在多核时代,RDTSC 指令的准确度大大削弱了,原因有如下几点:

1. 不能保证同一块主板上每个核的 CPU 时钟周期数(Time Stamp Counter)是同步的;

2. CPU 的时钟频率可能变化,例如笔记本电脑的节能功能;

3. 乱序执行导致 RDTSC 测得的周期数不准。 虽然 RDTSC 废掉了,高精度计时还是有办法的,在 Windows 上用 QueryPerformanceCounter 和 QueryPerformanceFrequency,Linux 上用 POSIX 的 clock_gettime 函数,以 CLOCK_MONOTONIC 参数调用。

在接下来的几篇文章章中,我会继续介绍相关内容。

参考文章:

1、多核时代不宜再用 x86 的 RDTSC 指令测试指令周期和时间

http://blog.csdn.net/solstice/article/details/5196544

2、RDTSC命令详解

http://blog.csdn.net/tbwood/article/details/5536597

编程获得CPU的主频的更多相关文章

  1. java多线程并发编程与CPU时钟分配小议

    我们先来研究下JAVA的多线程的并发编程和CPU时钟振荡的关系吧 老规矩,先科普 我们的操作系统在DOS以前都是单任务的 什么是单任务呢?就是一次只能做一件事 你复制文件的时候,就不能重命名了 那么现 ...

  2. 为什么CPU的主频止步于4GHz?

    你对CPU的认识大概还停留在奔腾4年代吧……奔腾4最终止步于3.8GHz,原计划推出的4GHz奔腾4处理器也被胎死腹中.英特尔意识到处理器研发道路上走入了“唯主频论”的误区,2004年10月,英特尔总 ...

  3. CPU的主频

    CPU的主频,即CPU内核工作的时钟频率(CPU Clock Speed).通常所说的某某CPU是多少兆赫的(MHZ),而这个多少兆赫就是“CPU的主频”.很多人认为CPU的主频就是其运行速度,其实不 ...

  4. 多线程编程,CPU是如何解决多线程内存访问问题的

    CPU对内存变量的修改是先读取内存数据到CPU Cache中,然后再由CPU做运算,运算完成后继续写入到内存中 在单核CPU中,这完全没有问题,然而在多核CPU中,每一个CPU核心都拥有自己独立的Ca ...

  5. X86架构CPU常识(主频,外频,FSB,cpu位和字长,倍频系数,缓存,CPU扩展指令集,CPU内核和I/O工作电压,制造工艺,指令集,超流水线与超标量)

    1.主频 主频也叫时钟频率,单位是MHz,用来表示CPU的运算速度. CPU的主频=外频×倍频系数.很多人认为主频就决定着CPU的运行速度,这不仅是个片面的,而且对于服务器来讲,这个认识也出现了偏差. ...

  6. Python 爬取 中关村CPU名字和主频

    0.准备工作   1.相关教程         Python 爬虫系列教程:http://cuiqingcai.com/1052.html         Python Web课程:http://ww ...

  7. 【UEFI】---关于BIOS,EIST和PState&CState和CPU主频变化得关系

    Intel处理器都支持Turbo和EIST,且一般情况下,各家厂商在BIOS中都会设置EIST和PState的开关,那么这些开关与CPU的频率的关系是什么呢?今天对此做个总结: 按照国际惯例,本次梳理 ...

  8. 手机CPU架构体系分类及各大厂商

    手机cpu相关知识,这对于开发Android应用程序适应各个机型有一定的辅助作用 . 手机cpu架构体系分类 指令集可分为复杂指令集(CISC)和精简指令集(RISC)两部分,代表架构分别是x86.A ...

  9. CUDA显卡运算编程菜鸟入门指南1——Hello world - yfszzx的专栏 - 博客频道 - CSDN.NET

    第一次知道有显卡(GPU)编程这个东西,是去年比特币最热门的时候,看了几篇关于比特币的文章,说比特币挖矿要靠显卡,CPU的速度与GPU根本就没法比,于是就非常好奇,显卡是什么神奇的东西?为什么运算速度 ...

随机推荐

  1. 基于busybox和LFS的linux系统定制

    自从在大学知道了Linux这玩意是可以定制的之后,一直想做出一版属于自己的Linux系统.最近工作比较闲,终于塌下心来好好学习了一下.   目前来说,我接触的定制Linux的方法主要有两种:   1. ...

  2. 25-React事件处理及条件渲染

    Handling Events React元素的事件处理非常类似于对DOM元素添加事件处理,但有一部分的语法不同: 1.React事件使用camelCase(驼峰命名法)来进行命名,而不是小写字母 2 ...

  3. ruby学习总结05

    1.数值类(Numeric) 有理数:Rational(分子,分母) 复数:Complex(实数,虚数) 随机数:Rnadom   rand()  返回比1小的浮点数,rand(种子数)  返回0到该 ...

  4. jQuery函数attr()和prop()的区别,val()

    [自己总结,详情见下面转录的文章]: attr()用于操作html属性,prop()属性用于操作DOM属性 ①: 很多情况下可以互用 ②:attr()独自适用的情况,自定义的html属性,html属性 ...

  5. 从原理上搞定编码-- Base64编码

    BASE64是一种编码方式,通常用于把二进制数据编码为可写的字符形式的数据.这是一种可逆的编码方式.编码后的数据是一个字符串,其中包含的字符为:A-Z.a-z.0-9.+./共64个字符:26 + 2 ...

  6. 正则表达式(/[^0-9]/g,'')中的"/g"是什么意思 ?

    正则表达式(/[^0-9]/g,'')中的"/g"是什么意思 ?     表达式加上参数g之后,表明可以进行全局匹配,注意这里“可以”的含义.我们详细叙述: 1)对于表达式对象的e ...

  7. SQL函数学习(十九):CAST()函数和CONVERT()函数

    19.CAST()函数和CONVERT()函数 CAST()函数可以将某种数据类型的表达式转化为另一种数据类型 CONVERT()函数 也 可以将指定的数据类型转换为另一种数据类型 19.1 CAST ...

  8. SpringMVC 模拟登陆

    新建BackgroundController类: package cn.bdqn.mvc.controller; import org.springframework.stereotype.Contr ...

  9. jdk安装环境变量设置

    设置JAVA_HOME,点击新建,变量名:JAVA_HOME,变量值:D:\java\jdk1.7.0,即刚才jdk安装的路径.   设置CLASSPATH属性,变量名:CLASSPATH,变量值:. ...

  10. js中两个对象的比较

    代码取自于underscore.js 1.8.3的isEqual函数. 做了一些小小的修改,主要是Function的比较修改. 自己也加了一些代码解读. <!DOCTYPE html> & ...