clock()介绍

11 篇文章 0 订阅


1.先代码:

20 int main() {
 21     clock_t t1 = clock();
 22     struct timeval start;
 23     struct timeval end;
 24     gettimeofday(&start, NULL);
 25     for (int i = 0 ; i < 5000000; ++i) {
 26     }
 27     sleep(2);
 28     gettimeofday(&end, NULL);
 29     time_t u = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec;
 30     clock_t t2 = clock();
 31     double v = (t2 - t1)*1.0/CLOCKS_PER_SEC*1000000;
 32     cout << u << " " << v << endl;
 33     
 34     return 0;
 35 }   



在Linux下编译运行,
2010550 10000


clock returns the processor time used by program since the beginning of the execution, or -1 if unavailable. 

这里提到clock()函数返回的是程序运行过程中耗掉得process time,也就是CPU time;

注意:在不同平台下的返回值不同,使用时,需要clock() / CLOCKS_PER_SEC is a time in seconds,CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,也就是硬件滴答数。
先不管什么叫硬件滴答数,你需要知道clock()是基于时钟计时单元(clock tick)的这个东西来计数的。一个clock tick不是CPU的一个时钟周期,而是C/C++的一个基本计时单位,因此只与编译器有关。在TC2.0中硬件每18.2个滴答是一秒,在VC中硬件每1000个滴答是一秒,在标准POSIX中定义为1000000个滴答为一秒。

注意:精度问题,经搜索发现,标准POSIX平台的clock()只能精确到10ms,至于为什么我目前还不得而知。

2. 关于系统计时误差

     精确测量某一个程序运行的确切时间是几乎时不可能的,至少现在是这样。想精确获取程序运行时间并不是那么容易的。也许你会想,程序不就是一条条指令么,每一条指令序列都有固定执行时间,为什么不好算?真实情况下,我们的计算机并不是只运行一个程序的,进程的切换,各种中断,共享的多用户,网络流量,高速缓存的访问,转移预测等,都会对计时产生影响。
    对于进程调度来讲,花费的时间分为两部分,第一是计时器中断处理的时间,也就是当且仅当这个时间间隔的时候,操作系统会选择,是继续当前进程的执行还是切换到另外一个进程中去。第二是进程切换时间,当系统要从进程A切换到进程B时,它必须先进入内核模式将进程A的状态保存,然后恢复进程B的状态。因此,这个切换过程是有内核活动来消耗时间的。具体到进程的执行时间,这个时间也包括内核模式和用户模式两部分,模式之间的切换也是需要消耗时间,不过都算在进程执行时间中了”。

        读完上面这段话,你应该很清楚的知道一个程序即使每次执行相同的命令,所花费的时间也不一定相同,因为其花费的时间与系统运行相关。原因就在于无论是windows还是linux,都是多任务操作系统。为了让你更明白,现在从另一个角度对执行一个程序所消耗的时间进行分类,如下:

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

(2) 用户CPU时间(user CPU time):命令在用户态中执行时间的总和;

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

       现在有没有这样的疑问,实际运行时间(1)是不是等于(2)+(3)?对于一个进程而言,除了用户和系统之外难道还有别人么?

答案是肯定的。抬头看看上面提到的进程调度,回头想想你大二学的操作系统课程里的时间片轮转,进程五状态,明白了吧,此时的程序表面在给你执行代码,CPU早跑别人家去了。

3.clock()算出的时间究竟属于上面的哪一个呢?
sleep函数会使程序暂时挂起,也就是阻塞状态,CPU并不在该进程上花费时间。

clock的定义里明确之处计算的是processor time,不就是CPU时间啊,好吧,我就算设计一个实验证实了这个说法没错,但究竟clock函数计算的是哪个CPU时间,暂时是无能为力证明了。

偏执狂你的开始不满意了,究竟有没有办法分别统计一个程序的这三样时间呢?答案是有的。

Linux下有一个很简单很好用的命令就可以来统计程序运行的这三种时间——time命令。此命令的用途在于测量特定指令执行

时所需消耗的时间及系统资源等资讯。如果你只是在优化一小段精简的代码,这对你来说是个好消息。

下面用time命令运行上面的那段测试代码:

运行shell命令

time ./test

显示结果

real 0m2.012s
user 0m0.011s
sys 0m0.001s

    现在简单分析结果,终于真相大白了。上面程序中使用clock()函数计算出来的时间就为总的CPU时间。也就是说,clock函数不能区分用户空间和内核空间。
    上面介绍的time命令能测量特定进程执行时所消耗的时间,它是怎么做到的呢?方法叫做间隔计数。如果你对他感兴趣的话,

可以继续读读下面的介绍,你会发现原理其实很简单。

操作系统用计时器来记录每个进程使用的累计时间,计时器中断发生时,操作系统会在当前进程列表中寻找哪个进程是活动的,一

旦发现进程A正在运行立马就给进程A的计数值增加计时器的时间间隔(这也是引起较大误差的原因)。当然不是统一增加的,还要确定这个进程是在用户空间活动还是在内核空间活动,如果是用户模式,就增加用户时间,如果是内核模式,就增加系统时间。这种方法的原理虽然简单但不精确。如果一个进程的运行时间很短,短到和系统的计时器间隔一个数量级,用这种方法测出来的结果必然是不够精确的,头尾都有误差。不过,如果程序的时间足够长,这种误差有时能够相互弥补,一些被高估一些被低估,平均下来刚好。从理论上很难分析这个误差的值,所以一般只有程序达到秒的数量级时用这种方法测试程序时间才有意义。这种方法最大的优点是它的准确性不是非常依赖于系统负载。

 4. 事实果真如此么?关于”三多“话题

多核多进程多线程技术的发展使得运算效率不断提高的同时,也给码农们带来新的烦恼。

4.1 多核计算
上面已经知道了clock函数的实现是基于时钟计时单元的。问题就出在了cpu的时钟计时单元上。当采用多核cpu时,进程或线程调

用clock,记录了当前核时钟。但在下次调用clock之前很可能发生cpu调度,进程或线程被调度到其他cpu上运行。这导致两次取得

计时单元并不是同一个cpu的,产生计时错误。但究竟这个误差有多大,有待实验论证。

4.2 多进程计算

上面通过time函数进行了验证,clock函数计算的时间貌似是等于用户CPU时间+系统CPU时间。果真如此么?我们再次对测试代码

进行修改,将循环次数减少至一千次,并在空循环里加一句

system("cd");

这一句用于模拟子进程的运行,这里图方便选择系统进程作为子进程。

运行shell命令

time ./test

显示结果

Time to do 1000 empty loops is 0.010000 seconds

real 0m3.492s
user 0m0.512s
sys 0m2.972s

这个实验说明了,clock函数并没有考虑CPU被子进程消耗的时间。

4.3 多线程计算

上面提到了三个时间Real time, User time和Sys time。real time > user time + sys time 这种关系始终成立么?

答案是否定的。原因就在于并行计算。现在再次回忆一下这三种时间的概念:

Real指的是实际经过的时间,User和Sys指的是该进程使用的CPU时间。
1. Real也就是进程从开始到结束所用的实际时间。这个时间包括其他进程使用的时间片和进程阻塞的时间(比如等待I/O完成)。
2. User指进程执行用户态代码(核心之外)所使用的时间。这是执行此进程所消耗的实际CPU时间,其他进程和此进程阻塞的时间并不包括在内。
3. Sys指进程在内核态消耗的CPU时间,即在内核执行系统调用所使用的CPU时间。
那么,什么情况下进程开始到结束所经过的时间会比进程所消耗的用户时间和系统时间(user time + sys time)小呢?
User+Sys为进程所使用的实际CPU时间。在多处理器的系统上,一个进程如果有多个线程或者有多个子进程并行执行,就可能导致Real time比CPU time(User + Sys time)要小,这是很容易理解的。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Shadowplay Clock是一款名为Shadowplay的计时器应用。它是专门为需要计时的人群设计的,无论是用于计时各种活动、比赛、工作任务还是学习等,Shadowplay Clock都能提供简洁实用的计时功能。 首先,Shadowplay Clock具有简洁直观的界面设计,用户可以轻松进行计时设置。它提供了多种计时模式,例如倒计时、正计时和间隔计时。用户可以根据自己的需求选择适合的计时模式,并设置计时时长。此外,Shadowplay Clock还支持多重计时,用户可以同时设置多个计时器,满足不同任务的计时需求,提高工作效率。 其次,Shadowplay Clock具有友好的提醒功能。当计时器结束时,Shadowplay Clock会通过咔咔声或震动提醒用户。这样,即使在忙碌的工作环境中,用户也能确保不会错过任何时间节点。同时,Shadowplay Clock还提供了可自定义的提醒音效功能,用户可以根据自己的喜好选择提醒音乐,更好地与计时器互动。 最后,Shadowplay Clock具有实用的统计功能。它可以记录每次计时的起始时间和结束时间,以及计时的总时长。这为用户提供了方便的任务记录和时间管理。用户可以通过Shadowplay Clock的统计数据,更好地追踪自己的时间分配情况,合理规划工作和生活。 总结来说,Shadowplay Clock是一款功能强大、操作简单的计时器应用。无论是需要计时的各种场景,Shadowplay Clock都能满足用户的需求。无论是专业人士、学生还是日常生活中需要计时的人群,都可以依靠Shadowplay Clock来提高工作、学习和生活的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MyObject-C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值