在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 3727|回复: 3

Linux系统下获取代码运行时间的方法

[复制链接]
发表于 2014-6-13 20:54:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 vvzvv 于 2014-6-13 21:22 编辑

看了这次比赛项目题目的设置,有一些需要通过计算代码花费的时间来对比PS程序和PL程序的速度,突出ARM+FPGA结合的优势,今天学习并试验了几种在Linux系统下获取程序运行时间的方法,拿出来和大家分享一下,可能显得很小白,前辈们不要笑哈。之所以选择在linux下来试验这些方法是因为:

1. Linux系统下提供了多项获取运行时间的方法,使用简便
2.在Linux系统下运行软件更符合我们实际项目使用环境,更贴近实际


如果不在板子上运行操作系统,我可能会使用定时器/计数器或者使用示波器监测引脚状态等方法进行时间测量,我试验成功之后会贴出来和大家探讨。


第一种:使用time命令

Linux系统下统计程序运行实践最简单直接的方法就是使用time命令。此命令的用途在于测量特定指令执行时所需消耗的时间及系统资源等资讯,在统计的时间结果中包含以下数据:

       (1) 实际时间(real time):从命令行执行到运行终止的消逝时间;

       (2) 用户CPU时间(user CPU time):命令执行完成花费的系统CPU时间,即命令在用户态中执行时间的总和;

       (3) 系统CPU时间(system CPU time):命令执行完成花费的系统CPU时间,即命令在核心态中执行时间的总和。

       其中,用户CPU时间和系统CPU时间之和为CPU时间,即命令占用CPU执行的时间总和。实际时间要大于CPU时间,因为Linux是多任务操作系统,往往在执行一条命令时,系统还要处理其他任务。另一个需要注意的问题是即使每次执行相同的命令,所花费的时间也不一定相同,因为其花费的时间与系统运行相关。

time命令.png time命令2.png

在嵌入了Linux系统的ZedBoard板上进行测试,以上第一条使用time命令测试一条ls指令,结果发现获取的几个参数都是0,这是因为这条指令所能获取的时间精度有限导致的,ls指令执行很快,所以time指令无法得到精确的时间,第二张图片使用time指令测量复制一个文件所花费的时间,由于复制所花费的时间比较长,因此time指令能够显示出时间分别是10ms,30ms,150ms,反复运行几次获得的时间都不一致。

以上的测试表明:time指令所得到的结果精度无法满足要求,应该寻求精度更高的方法。


第二种:gettimeofday()函数

gettimeofday()可以获得当前系统的时间,是一个绝对值

原型如下:





  1. int
  2. gettimeofday ( struct timeval * tv , struct timezone * tz )


复制代码

timeval结型体的原型如下:






  1. struct
  2. timeval {              
  3. time_t      tv_sec;     /* seconds
  4. */              
  5. suseconds_t tv_usec;    /* microseconds */         
  6. };


复制代码


所以它可以精确到微秒,使用以下程序进行测试:


#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>

#define Nanosecond 1000000000

int main(){
        struct timeval tvs,tve;
        long int span;

        //10000个循环所花时间
        int i=10000;
        gettimeofday(&tvs,NULL);
        while (--i);
        gettimeofday(&tve,NULL);
        span = (tve.tv_sec-tvs.tv_sec)*Nanosecond + (tve.tv_usec-tvs.tv_usec)/1000000.0;
        printf("it took %ld Nanosecond to run 10000 loops\n", span);

        //1000个循环所花时间
        i=1000;
        gettimeofday(&tvs,NULL);
        while (--i);
        gettimeofday(&tve,NULL);
        span = (tve.tv_sec-tvs.tv_sec)*Nanosecond + (tve.tv_usec-tvs.tv_usec)/1000000.0;
        printf("it took %ld Nanosecond to run 1000 loops\n", span);

        //100个循环所花时间
        i=100;
        gettimeofday(&tvs,NULL);
        while (--i);
        gettimeofday(&tve,NULL);
        span = (tve.tv_sec-tvs.tv_sec)*Nanosecond + (tve.tv_usec-tvs.tv_usec)/1000000.0;
        printf("it took %ld Nanosecond to run 100 loops\n", span);

        //10个循环所花时间
        i=10;
        gettimeofday(&tvs,NULL);
        while (--i);
        gettimeofday(&tve,NULL);
        span = (tve.tv_sec-tvs.tv_sec)*Nanosecond + (tve.tv_usec-tvs.tv_usec)/1000000.0;
        printf("it took %ld Nanosecond to run 10 loops\n", span);

        return 0;

}


这个程序运行效果如下:

gettimeofday.png


第三种:clock_gettime()函数

实时函数clock_gettime()函数的函数原型为:





  1. int clock_gettime(clockid_t clk_id, struct timespec *tp);


复制代码

两个传递的参数分别为

1)时间结构体:timespec,timespec计算时间次数的单位是十亿分之一秒.






  1. strace timespec{ time_t tv_sec; long tv_nsec;}


复制代码

2)时钟类型:clockid_t

CLOCK_REALTIME:标准POSIX实时时钟

CLOCK_MONOTONICOSIX时钟,以恒定速率运行;不会复位和调整,它的取值和CLOCK_REALTIME是一样的.

CLOCK_PROCESS_CPUTIME_IDCLOCK_THREAD_CPUTIME_IDCPU中的硬件计时器中实现的.


该函数可以实现ns级的精度,其测试程序为:



#include<time.h>
#include<stdio.h>
#include<stdlib.h>

#define Nanosecond 1000000000


int main(void)
{
        struct timespec tpstart;
        struct timespec tpend;
        long int timedif;

        //10000个循环所用时间
        int i=10000;
        clock_gettime(CLOCK_MONOTONIC, &tpstart);

        while(--i);

        clock_gettime(CLOCK_MONOTONIC, &tpend);
        timedif = Nanosecond*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec);
        printf("it took %ld Nanosecond to run 10000 loops\n", timedif);

        //1000个循环所用时间
        i=1000;
        clock_gettime(CLOCK_MONOTONIC, &tpstart);

        while(--i);

        clock_gettime(CLOCK_MONOTONIC, &tpend);
        timedif = Nanosecond*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec);
        printf("it took %ld Nanosecond to run 1000 loops\n", timedif);

        //100个循环所用时间
        i=100;
        clock_gettime(CLOCK_MONOTONIC, &tpstart);

        while(--i);

        clock_gettime(CLOCK_MONOTONIC, &tpend);
        timedif = Nanosecond*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec);
        printf("it took %ld Nanosecond to run 100 loops\n", timedif);

        //10个循环所用时间
        i=10;
        clock_gettime(CLOCK_MONOTONIC, &tpstart);

        while(--i);

        clock_gettime(CLOCK_MONOTONIC, &tpend);
        timedif = Nanosecond*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec);
        printf("it took %ld Nanosecond to run 10 loops\n", timedif);


        return 0;
}



运行该程序得到结果如下:
clock_gettime.png


clock_gettime函数和gettimeofday函数得出的结果差不多,但有意思的是连续运行几次gettimeofday的测试程序得到的结果会有较大的差别,甚至有可能在测试循环1000次的时间的时候给出0ns的结果,这可能与它的精度相关,知道原因的朋友请多多指教。
多次运行.png

多次运行测试程序的结果,可以看出gettimeofday函数输出结果差异较大

结论
非常抱歉写了这么多又臭又长的东西,不过相信各位看官看到这里应该有一个判断了,在Linux系统下,要想完成比较精确的代码运行时间测量应该还是要用clock_gettime函数……(又是一句废话,哈哈哈)

个人觉得,对于项目二(CRC校验速度比较),以以太网帧为例,最小64字节的CRC32校验可能花费的时间并不会很长,这时候有ns级的时间精度还是非常重要,当然,这个结论还是要与实际的硬件测试做比较才能确定。大家在比赛过程中的收获多讨论讨论嘛,我对这个不是很熟,希望大家共同进步!

唉,这代码直接从SDK复制过来之后帖子上代码显示就没有换行了,又重新编辑了两次,彻底阵亡了,我直接当成文本贴出来吧
time命令.png
time命令2.png
time命令.png
发表于 2014-6-22 16:05:39 | 显示全部楼层
请问你没有jtag,最后怎么解决的啊?用zedboard测试?然后移植到microZed?
发表于 2014-6-23 10:48:13 | 显示全部楼层
搞点钱。
发表于 2014-8-8 22:26:12 | 显示全部楼层
哈哈,我做完挑战三之后,还有一种办法,就是用PL的硬件AXI Timer中断:)

XD
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-22 23:38 , Processed in 0.026808 second(s), 9 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表