Linux中怎么精确获取cpu主频和cpu周期

likeyiyy 2014-06-24 06:29:15
首先我当然知道用cat /proc/cpuinfo
我的机器得到的结果是1600Mhz
然而在用程序进行测试时,我发现不是这样。
----------------------------------------------------------------------
当然我最初的需求是想获取cpu的周期,我要根据cpu周期做一个相对精确的延时,比如说几十个ns。
我在网上找到一段程序。
static inline uint64_t get_cycle_count()
{
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32) | lo;
}
这个函数使用rdtsc指令。
-----------------------------------------------------------------------
当然很明显,我的目的是要延时指定的ns数,所以我要在cpu周期数和ns数之间做一个转换。

要延时的cpu周期数 = 要延时的ns数 * (CPU主频(MHz) / 1000)

我想上面的公式是没有错的。(不会有错吧。)

然后我发现程序并没有延时我指定的ns数,我很奇怪,然后写了一段程序验证。

uint64_t old,new;
int i = 0;
int delayms = 700;
for(i = 0; i < 100; i++)
{
old = get_cycle_count();
usleep(delayms* 1000);
new = get_cycle_count();

printf("%d\n",(new-old)/delayms*1000);
}

上面的程序(new-old)/delayms将得到一个固定的比值,这个比值应该代表当前的CPU的主频,以Mhz为单位,没问题吧。

我以为我会得到1600,然而事实上我的到的是,2667,真是一个奇葩的数字。

我不知道到底是因为cat /proc/cpuinfo无法得到正真的频率。
还是get_cycle_count无法得到真正的时钟周期
但是无论如何,我想问一下:Linux中怎么精确获取cpu主频和cpu周期呢?

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>

#define NS 1000000000


// Linux/GCC

static inline uint64_t get_cycle_count()
{
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32) | lo;
}

int main(int argc,char ** argv)
{

int i = 0;
uint64_t old,new;
int delayms = 700;
for(i = 0; i < 100; i++)
{
old = get_cycle_count();
usleep(delayms * 1000);
new = get_cycle_count();
printf("%u\n",(new-old)/(delayms*1000));

}
}
...全文
6236 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
imliuda 2014-06-27
  • 打赏
  • 举报
回复
用户空间不可能会精确到ns,你还是用usleep吧,实在需要,做驱动吧
likeyiyy 2014-06-26
  • 打赏
  • 举报
回复
引用 5 楼 colddown 的回复:
如果内核使用了CPU Frequency scaling,有可能主频是会动态改变的。
我猜测也是。
likeyiyy 2014-06-26
  • 打赏
  • 举报
回复
引用 4 楼 senioryzc 的回复:
对于多核的cpu usleep 之后可能你的程序被迁移到另外一个cpu核心 你或许看看是否可以把你的程序绑定某个cpu核心 或者多比较几次,如果前后2次不在一个核上,就重新计算 cat /proc/cpuinfo 得到的肯定是正确的,延时直接用usleep 应该比你自己实现的好
usleep精确到微秒级,不够啊。 clock_gettime还可以考虑一下。
colddown 2014-06-25
  • 打赏
  • 举报
回复
如果内核使用了CPU Frequency scaling,有可能主频是会动态改变的。
senioryzc 2014-06-25
  • 打赏
  • 举报
回复
对于多核的cpu usleep 之后可能你的程序被迁移到另外一个cpu核心 你或许看看是否可以把你的程序绑定某个cpu核心 或者多比较几次,如果前后2次不在一个核上,就重新计算 cat /proc/cpuinfo 得到的肯定是正确的,延时直接用usleep 应该比你自己实现的好
likeyiyy 2014-06-24
  • 打赏
  • 举报
回复
在另外一台1600Mhz的机器上不正常 主频1600,输出3411 ------------------- 这个世界让我疯了。
likeyiyy 2014-06-24
  • 打赏
  • 举报
回复
在另外一台2800Mhz主频的机器测试正常。 主频是2800,输出是2800
likeyiyy 2014-06-24
  • 打赏
  • 举报
回复
在虚拟机里,测试正常 主频是2600,输出也是2600

1,025

社区成员

发帖
与我相关
我的任务
社区描述
Linux /Unix kernel支持不同的硬件体系,X86, ARM, MIPS, 等等
社区管理员
  • CPU和硬件区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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