Chinaunix首页 | 论坛 | 博客
  • 博客访问: 48596
  • 博文数量: 28
  • 博客积分: 1446
  • 博客等级: 上尉
  • 技术积分: 165
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-18 20:52
文章分类

全部博文(28)

文章存档

2012年(1)

2011年(23)

2010年(4)

我的朋友

分类:

2010-06-21 09:26:14

1、us级计时说明:

使用C语言进行计时,在用户空间中可以使用C语言函数gettimeofday 得到时间,它的调用格式是:

#include
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv , const struct timezone *tz);
结构timeval的定义为:
strut timeval {long tv_sec; /* 秒数 */long tv_usec; /* 微秒数 */};

可以看出,使用这种方式计时,精度可达微秒,也就是10-6秒。进行计时的时候,我们需要前后调用两次gettimeofday,然后计算中间的差值:

gettimeofday( &start, NULL );
foo();
gettimeofday( &end, NULL );
timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;
timeuse /= 1000000;

2、自己写的在linux基于qt4.6的us级的计时程序:

#include
#include
#include

#include

void caculate()
{
    for(int i=0;i<32323;i++)
    {
        for(int j=0;j<32323;j++)
            ;
    }
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget *w = new QWidget;
    QLabel *label1,*label2,*label3;

    struct timeval start;
    struct timeval end;
    quint64 timestart,timeend,timeuse;


    //获得CPU计时器的时钟频率
    gettimeofday(&start,NULL);//开始计时

    caculate(); //待测试的计算函数等

    gettimeofday(&end,NULL); //终止计时

    timestart = 1000000*start.tv_sec+start.tv_usec;
    timeend = 1000000*end.tv_sec+end.tv_usec;
    timeuse = timeend-timestart;

    label1 = new QLabel("Start Time:"+QString::number(timestart,10)+" us",w);
    label1->setGeometry(10,10,400,30);
    label2 = new QLabel("End   Time:"+QString::number(timeend,10)+" us",w);
    label2->setGeometry(10,50,400,30);
    label3 = new QLabel("Use    Time:"+QString::number(timeuse,10)+" us",w);
    label3->setGeometry(10,90,400,30);

    w->setMinimumSize(400,200);
    w->setMaximumSize(400,200);
    w->show();

    return a.exec();
}

3、另外附上其它的基本知识:

最小到秒的时间的获取

int time(char cnt)
{

time_t t; //实例化time_t结构

struct tm *timenow1; //实例化tm结构指针
struct tm *timenow2; //实例化tm结构指针   

time(&t);//time函数读取现在的时间(国际标准时间非北京时间),然后传值给t
timenow1=localtime(&t); //localtime函数把从time取得的时间t换算成你电脑中的时间(就是你设置的地区)
printf("the current time1 is: %02d:%02d:%02d\n",timenow1->tm_hour,timenow1->tm_min,timenow1- >tm_sec);
printf("Local time1 is %s\n",asctime(timenow1)); //上句中asctime函数把时间转换成字符,通过printf()函数输出

time(&t);

timenow2=localtime(&t);
printf("the current time2 is: %02d:%02d:%02d\n",timenow2->tm_hour,timenow2->tm_min,timenow1->tm_sec);
printf("Local time2 is %s\n",asctime(timenow2));

if((timenow2->tm_hour==timenow1->tm_hour) && (timenow2->tm_min==timenow1->tm_min))
{
    n=timenow2->tm_sec-timenow2->tm_sec;
    printf("n is %d\n",n);//秒
   }

//注:如果想获得国际标准时间,将localtime换成gmtime函数
//注:time_t是一个在time.h中定义好的结构体。而tm结构体的原形如下:

/*
struct tm //最小到秒,#include
{
   int tm_sec;//seconds 0-61
   int tm_min;//minutes 1-59
   int tm_hour;//hours 0-23
   int tm_mday;//day of the month 1-31
   int tm_mon;//months since jan 0-11
   int tm_year;//years from 1900
   int tm_wday;//days since Sunday, 0-6
   int tm_yday;//days since Jan 1, 0-365
   int tm_isdst;//Daylight Saving time indicator
};
*/
}

纳秒级计时

函数原型:int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)

其中参数timespec定义是:

struct timespec
{
         time_t tv_sec; /* seconds * /
         long tv_nsec; /* nanoseconds * /
}

实际应用(部分,不完整):

struct timesepc req;
struct timespec rem;

int ret;

req.tv_sec = 2;   //这就表示2秒
req.tv_nsec = 0;

ret = nanosleep(&req, &rem);
  
if (ret < 0)
{
//....
}

用rdrtc实现linux下的精确计时

在linux开发版最长问到的问题之一就是在linux下如何得到更精确的计时。其实有很多办法,比如以前就有人用select。不过现在有更精确 的实时时钟可以用,这就是用CLOCK_PROCESS_CPUTIME_ID做参数通过timer_create来创建timer。通过 clock_getres可以得到系统的精度。

实际上,上述方法底层用的就是CPU的rdtsc指令。 在linux下,可以用到CPU的rdtsc指令(当然,windows下也是这样。现在的CPU一般都支持这个指令)来得到一个CPU的时间戳 (Time   Stamp),这个值是每个指令周期都增加的,再根据CPU的频率就可以计算出时间来。用这种方式,对于频率高的CPU,甚至可以实现纳秒级的时间控制。 不过据说因为精度太高,这种方式数据抖动比较厉害,每次结果都不一样,经常有几百甚至上千的差距。不过在我的实验中误差并没有这么大,上下在1%左右,不 过如果你的要求高的话,这1%也是很厉害的。不过sleep调用也是会有误差的,这里就不去研究了。

下面是源码:

#include

int get_rdtsc() {
asm("rdtsc");
}

int main() {
int i;
for(i=0;i<10;i++) {
    int t1 = get_rdtsc();
    sleep(1);
    int t2 = get_rdtsc();
    printf("t2 - t1 = %ld (%ldMHZ) ", t2 - t1, (t2-t1)/1000000);
}
}

我的实验环境:Intel E6320/2G,使用VMWare虚拟机,系统是centos5-x86。下面是输出结果。

t2 - t1 = 1865320163 (1865MHZ)
t2 - t1 = 1865996702 (1865MHZ)
t2 - t1 = 1862758710 (1862MHZ)
t2 - t1 = 1865247214 (1865MHZ)
t2 - t1 = 1863456686 (1863MHZ)
t2 - t1 = 1865427930 (1865MHZ)
t2 - t1 = 1865423429 (1865MHZ)
t2 - t1 = 1863616999 (1863MHZ)
t2 - t1 = 1865105795 (1865MHZ)
t2 - t1 = 1867224090 (1867MHZ)

阅读(2746) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~