ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:23.55KB ,
资源ID:10540778      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10540778.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C++常见程序计时方法.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

C++常见程序计时方法.docx

1、C+常见程序计时方法目录1.常规计时 11.1 time() 11.2 GetTickCount 32.使用CPU时间戳进行高精度计时 43.精确获取时间QueryPerformanceCounter 71.常规计时1.1 time()C语言中time()函数函数简介函数名: time头文件:time.h函数原型:time_t time(time_t * timer)功能: 获取当前的系统时间,返回的结果是一个time_t类型,其实就是一个大整数,其值表示从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到

2、当前时刻的秒数。然后调用localtime将time_t所表示的CUT时间转换为本地时间(我们是+8区,比CUT多8个小时)并转成struct tm类型,该类型的各数据成员分别表示年月日时分秒。补充说明:time函数的原型也可以理解为 long time(long *tloc),即返回一个long型整数。因为在time.h这个头文件中time_t实际上就是:#ifndef _TIME_T_DEFINEDtypedef long time_t; /* time value */#define _TIME_T_DEFINED /* avoid multiple defines of time_t

3、*/#endif即long。函数应用举例程序例1:time函数获得日历时间。日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。这个标准时间点对不同的编译器来说会有所不同,但对一个编译系统来说,这个标准时间点是不变的,该编译系统中的时间对应的日历时间都通过该标准时间点来衡量,所以可以说日历时间是“相对时间”,但是无论你在哪一个时区,在同一时刻对同一个标准时间点来说,日历时间都是一样的。#include #include #include int main(void)time_t t; t = time(NULL);printf(The number of seconds si

4、nce January 1, 1970 is %ld,t);return 0;程序例2:/time函数也常用于随机数的生成,用日历时间作为种子。#include #include #includeint main(void)int i;srand(unsigned) time(NULL);printf(ten random numbers from 0 to 99nn);for(i=0;i10;i+)printf(%dn,rand()%100);return 0;程序例3:用time()函数结合其他函数(如:localtime、gmtime、asctime、ctime)可以获得当前系统时间或是

5、标准时间。#include #include #include int main(void)time_t timer;/time_t就是long int 类型struct tm *tblock;timer = time(NULL);/这一句也可以改成time(&timer);tblock = localtime(&timer);printf(Local time is: %sn,asctime(tblock);return 0;1.2 GetTickCountGetTickCount函数函数功能:GetTickCount返回(retrieve)从操作系统启动到现在所经过(elapsed)的毫秒

6、数,它的返回值是DWORD。函数原型:DWORD GetTickCount(void);C+版CString s;DWORD k=:GetTickCount(); /获取毫秒级数目int se = k/1000; / se为秒coutseendl;库文件:kernl32.dllC/C+头文件:winbase.hwindows程序设计中可以使用头文件windows.h程序示例/代替time函数来初始化随机数生成器#include#includeint main()int i,k,r;for(i=0;i10;i+)srand(GetTickCount();printf(n);for(k=0;k5;

7、k+)r=rand();printf(%d ,r);return 0;注意事项GetTickcount函数:它返回从操作系统启动到当前所经过的毫秒数,常常用来判断某个方法执行的时间,其函数原型是DWORD GetTickCount(void),返回值以32位的双字类型DWORD存储,因此可以存储的最大值是2-1 ms约为49.71天,因此若系统运行时间超过49.71天时,这个数就会归0,MSDN中也明确的提到了:Retrieves the number of milliseconds that have elapsed since the system was started, up to 4

8、9.7 days.。因此,如果是编写服务器端程序,此处一定要万分注意,避免引起意外的状况。DWORD nowtime=0,lastime=0;nowtime=GetTickCount();1.3clock()clock()是C/C+中的计时函数,而与其相关的数据类型是clock_t。在MSDN中,查得对clock函数定义如下: clock_t clock(void) ; 这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock);若挂钟时间不可取,则返回-1。其中clock_t是用来

9、保存时间的数据类型,在time.h文件中,我们可以找到对它的定义: #ifndef _CLOCK_T_DEFINED typedef long clock_t; #define _CLOCK_T_DEFINED #endif 很明显,clock_t是一个长整形数。在time.h文件中,还定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,其定义如下: #define CLOCKS_PER_SEC (clock_t)1000) 可以看到每过千分之一秒(1毫秒),调用clock()函数返回的值就加1。下面举个例子,你可以使用公式clock()/CLOCKS_PER_

10、SEC来计算一个进程自身的运行时间: void elapsed_time() printf(Elapsed time:%u secs.n,clock()/CLOCKS_PER_SEC); 当然,你也可以用clock函数来计算你的机器运行一个循环或者处理其它事件到底花了多少时间: #include #include #include int main(void) long i = 10000000L; clock_t start, finish; double duration; /* 测量一个事件持续的时间*/ printf( Time to do %ld empty loops is , i

11、) ; start = clock(); while( i- ); finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; printf( %f secondsn, duration ); system(pause); 在笔者的机器上,运行结果如下: Time to do 10000000 empty loops is 0.03000 seconds 上面我们看到时钟计时单元的长度为1毫秒,那么计时的精度也为1毫秒,那么我们可不可以通过改变CLOCKS_PER_SEC的定义,通过把它定义的大一些,从而使计时

12、精度更高呢?通过尝试,你会发现这样是不行的。在标准C/C+中,最小的计时单位是一毫秒。2.使用CPU时间戳进行高精度计时对关注性能的程序开发人员而言,一个好的计时部件既是益友,也是良师。计时器既可以作为程序组件帮助程序员精确的控制程序进程,又是一件有力的调试武器,在有经验的程序员手里可以尽快的确定程序的性能瓶颈,或者对不同的算法作出有说服力的性能比较。在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对

13、于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount QueryPerformanceFrequency是一项基本功。本文要介绍的,是另一种直接利用PentiumCPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于Windows图形编程一书,第15页17页,有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。在IntelPentium以上级别的CPU中,有一个称为“时间戳(TimeStamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于

14、目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。在Pentium以上的CPU中,提供了一条机器指令RDTSC(ReadTimeStampCounter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C+语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:inlineunsigned_int64GetCycleCount()_asmRDTSC但是不行,因为RDTSC不被C+的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式

15、0X0F、0X31,如下:inlineunsigned_int64GetCycleCount()_asm_emit0x0F_asm_emit0x31以后在需要计数器的场合,可以像使用普通的Win32API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:unsignedlongt;t=(unsignedlong)GetCycleCount();/DoSomethingtime-intensive.t-=(unsignedlong)GetCycleCount();Windows图形编程第15页编写了一个类,把这个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了

16、更精确的定时,做了一点小小的改进,把执行RDTSC指令的时间,通过连续两次调用GetCycleCount函数计算出来并保存了起来,以后每次计时结束后,都从实际得到的计数中减掉这一小段时间,以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测,这条指令大概花掉了几十到100多个周期,在Celeron800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来说,这点时间完全可以忽略不计;而对那些确实要精确到纳秒数量级的应用来说,这个补偿也过于粗糙了。 这个方法的优点是: 高精度。可以直接达到纳秒级的计时精度(在1GHz的CPU上每个时钟周期就是一纳秒),这是其他计时方法

17、所难以企及的。 成本低。timeGetTime函数需要链接多媒体库winmm.lib,QueryPerformance*函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,可以参考图形程序开发人员指南,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而且函数调用的开销是最小的。 具有和CPU主频直接对应的速

18、率关系。一个计数相当于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,可以直接计算出时间。这和QueryPerformanceCount不同,后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。 这个方法的缺点是: 1.现有的C/C+编译器多数不直接支持使用RDTSC指令,需要用直接嵌入机器码的方式编程,比较麻烦。 2.数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。这是这种方

19、法高精度本身固有的矛盾。关于这个方法计时的最大长度,我们可以简单的用下列公式计算:自CPU上电以来的秒数=RDTSC读出的周期数/CPU主频速率(Hz)64位无符号整数所能表达的最大数字是1.81019,在我的Celeron800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。下面是几个小例子,简要比较了三种计时方法的用法与精度/Timer1.cpp使用了RDTSC指令的Timer类/KTimer类的定义可以参见Windows图形编程P15/编译行:CLTimer1.cpp/

20、linkUSER32.lib#include;#includeKTimer.hmain()unsignedt;KTimertimer;timer.Start();Sleep(1000);t=timer.Stop();printf(LastingTime:%dn,t);/Timer2.cpp使用了timeGetTime函数/需包含;,但由于Windows头文件错综复杂的关系/简单包含;比较偷懒:)/编译行:CLtimer2.cpp/linkwinmm.lib#include;#include;main()DWORDt1,t2;t1=timeGetTime();Sleep(1000);t2=tim

21、eGetTime();printf(BeginTime:%un,t1);printf(EndTime:%un,t2);printf(LastingTime:%un,(t2-t1);/Timer3.cpp使用了QueryPerformanceCounter函数/编译行:CLtimer3.cpp/linkKERNEl32.lib#include;#include;main()LARGE_INTEGERt1,t2,tc;QueryPerformanceFrequency(&tc);printf(Frequency:%un,tc.QuadPart);QueryPerformanceCounter(&t

22、1);Sleep(1000);QueryPerformanceCounter(&t2);printf(BeginTime:%un,t1.QuadPart);printf(EndTime:%un,t2.QuadPart);printf(LastingTime:%un,(t2.QuadPart-t1.QuadPart);/以上三个示例程序都是测试1秒钟休眠所耗费的时间file:/测试环境:Celeron800MHz/256MSDRAM/Windows2000ProfessionalSP2/MicrosoftVisualC+6.0SP5/以下是Timer1的运行结果,使用的是高精度的RDTSC指令L

23、astingTime:804586872以下是Timer2的运行结果,使用的是最粗糙的timeGetTimeAPIBeginTime:20254254EndTime:20255255LastingTime:1001以下是Timer3的运行结果,使用的是QueryPerformanceCountAPIFrequency:3579545BeginTime:3804729124EndTime:3808298836LastingTime:3569712古人说,触类旁通。从一本介绍图形编程的书上得到一个如此有用的实时处理知识,我感到非常高兴。有美不敢自专,希望大家和我一样喜欢这个轻便有效的计时器。参考资

24、料:YUAN2002FengYuan著,英宇工作室译,Windows图形编程,机械工业出版社,2002.4.,P15-173.精确获取时间QueryPerformanceCounterLARGE_INTEGER tima,timb; QueryPerformanceCounter(&tima); 在 Windows Server 2003 和 WindowsXP 中使用 QueryPerformanceCounter 函数的程序可能执行不当QueryPerformanceCounter 來精確計算執行時間QueryPerformanceCounter 來精確計算執行時間/ 這個程式展示了如何使

25、用QueryPerformanceCounter 來精確計算執行時間/代码1. LARGE_INTEGERm_liPerfFreq=0; 2. /获取每秒多少CPUPerformanceTick 3. QueryPerformanceFrequency(&m_liPerfFreq); 4. 5. LARGE_INTEGERm_liPerfStart=0; 6. QueryPerformanceCounter(&m_liPerfStart); 7. 8. for(inti=0;i100;i+) 9. coutiendl; 10. 11. LARGE_INTEGERliPerfNow=0; 12.

26、 /计算CPU运行到现在的时间 13. QueryPerformanceCounter(&liPerfNow); 14. 15. inttime=(liPerfNow.QuadPart-m_liPerfStart.QuadPart)*1000)/m_liPerfFreq.QuadPart); 16. 17. charbuffer100; 18. sprintf(buffer,執行時間%dmillisecond,time); 19. 20. coutbufferendl; QueryPerformanceCounter()这个函数返回高精确度性能计数器的值,它可以以微妙为单位计时.但是Query

27、PerformanceCounter()确切的精确计时的最小单位是与系统有关的,所以,必须要查询系统以得到QueryPerformanceCounter()返回的嘀哒声的频率.QueryPerformanceFrequency()提供了这个频率值,返回每秒嘀哒声的个数.计算确切的时间是从第一次调用QueryPerformanceCounter()开始的假设得到的LARGE_INTEGER为nStartCounter,过一段时间后再次调用该函数结束的,设得到nStopCounter.两者之差除以QueryPerformanceFrequency()的频率就是开始到结束之间的秒数.由于计时函数本身

28、要耗费很少的时间,要减去一个很少的时间开销.但一般都把这个开销忽略.公式如下:nStopCounter-nStartCounter ElapsedTime=- - overhead frequencydouble timei=(nStopCounter.QuadPart-nStartCounter.QuadPart)/frequency.QuadPart这两个函数是VC提供的仅供Windows 95及其后续版本使用的精确时间函数,并要求计算机从硬件上支持精确定时器。QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下: BOOL QueryPerformanceFrequency(LARGE_INTEGER lpFrequen

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1