程序计时

来源:互联网 发布:ubuntu安装deb软件命令 编辑:程序博客网 时间:2024/05/19 16:22
程序计时
一、基本概念
1、时间表示
Coordinated Universal Time(UTC):世界协调时间
Calendar Time:日历时间,即从一个标准时间点到此时的时间所经过的秒数。该标准时间点因编译器而异,但对编译系统而言标准时间点不变。该编译系统中的时间对应的日历时间都通过该标准时间点衡量,故日历时间是“相对时间”。一般,标准时间点指定为1970年1月1日0时0分0秒。日历时间与时区无关。
Epoch:时间点。时间点在标准C/C++中是一个整数(time_t),它用此刻的时间和标准时间点相差的秒数(即日历时间)来表示。目前大部分UNIX系统采用32位记录时间,正值表示为1970年以后,负值则表示1970年以前。可简单地估算出所能表达的时间范围:1970±((231-1)/3600/24/365)≈[1901,2038]年。为表示更久远的时间,某些编译器厂商引入64位甚至更长的整型数来保存日历时间。


2、进程时间
CPU时间,用以度量进程使用的中央处理器资源。进程时间以时钟滴嗒计算,通常使用三个进程时间值:实际时间(Real)、用户时间(User)和系统时间(Sys)。
实际时间:进程开始执行到完成所经历的挂钟时间,包括其他进程使用的时间片和本进程耗费在阻塞(如等待I/O操作完成)上的时间。该时间对应秒表(stopwatch)直接测量。
用户时间:进程执行用户态代码(内核外)耗费的CPU时间,仅统计该进程执行时实际使用的CPU时间,而不计入其他进程使用的时间片和本进程阻塞的时间。

系统时间:进程在内核态运行所耗费的CPU时间。


二、计时方式
1、通用的C/C++
(1) time_t time(time_t *timer)
以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数
eg:

#include <iostream>#include <stdio.h>#include <time.h>using std::cout;using std::endl;void fun();int main(int argc, char* argv[]){time_t timeBegin, timeEnd;timeBegin = time(NULL);fun();timeEnd = time(NULL);printf("%I64ds\n", (timeBegin - timeEnd));return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}
其运行结果:
0s


(2) clock_t clock(void)
进程启动到调用函数时所经过的CPU时钟计时单元(clock tick)数

eg:

#include <iostream>#include <stdio.h>#include <time.h>using std::cout;using std::endl;void fun();int main(int argc, char* argv[]){clock_t clockBegin, clockEnd;clockBegin = clock();fun();clockEnd = clock();printf("%dms\n", clockEnd - clockBegin);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}
其运行结果:
211ms


2、Windows平台特有函数
(1) DWORD timeGetTime(void)
系统时间,以毫秒为单位。其取值范围为0~2^32,约为49.71天。

eg:

#include <iostream>#include <stdio.h>#include <time.h>#include <Windows.h>#pragma   comment(lib, "winmm.lib ")using std::cout;using std::endl;void fun();int main(int argc, char* argv[]){DWORD t1, t2;t1 = timeGetTime();fun();t2 = timeGetTime();printf("%dms\n", t2 - t1);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}

其运行结果:

214ms


(2) DWORD WINAPI GetTickCount(void)
系统时间,以毫秒为单位。
eg:

#include <iostream>#include <Windows.h>using std::cout;using std::endl;void fun();int main(int argc, char* argv[]){DWORD  dwGTCBegin, dwGTCEnd;dwGTCBegin = GetTickCount();fun();dwGTCEnd = GetTickCount();printf("%dms\n", dwGTCEnd - dwGTCBegin);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}

其运行结果:

218ms


(3) 高精度计时

BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount):
高精度计时器的值.
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency):
返回硬件支持的高精度计数器的频率(次每秒),返回0表示失败。

eg:

#include <iostream>#include <stdio.h>#include <Windows.h>using std::cout;using std::endl;void fun();int main(int argc, char* argv[]){LARGE_INTEGER t1, t2, tc;QueryPerformanceFrequency(&tc);QueryPerformanceCounter(&t1);fun();QueryPerformanceCounter(&t2);printf("计时器差:%I64d\n", t2.QuadPart - t1.QuadPart);printf("%fms\n", (t2.QuadPart - t1.QuadPart)*1.0 / tc.QuadPart * 1000);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}

其运行结果:

计时器差:536520

211.792682ms


(4) RDTSC指令

eg:

#include <iostream>#include <stdio.h>#include <time.h>#include <Windows.h>//FREQUENCY指CPU的频率#define  FREQUENCY 2600000000using std::cout;using std::endl;void fun();inline unsigned __int64 GetCycleCount(){__asm{_emit 0x0F;_emit 0x31;}}int main(int argc, char* argv[]){unsigned long t1, t2;t1 = (unsigned long)GetCycleCount();fun();t2 = (unsigned long)GetCycleCount();printf("%fms\n", (t2 - t1)*1.0 / FREQUENCY * 1000);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}

其运行结果:

217.940375ms


3、Linux平台特有函数

(1) int gettimeofday(struct timeval *tv,struct timezone *tz)
获得当前精确时间(1970年1月1日到现在的时间),精度为微秒。
保存时间的结构体
strut timeval {
long tv_sec; //秒数
long tv_usec; //微秒数
};
eg:

#include <iostream>#include <sys/time.h>#include <stdio.h>using std::cout;using std::endl;void fun();int main(int argc, char* argv[]){struct timeval t1, t2;double timeuse;gettimeofday(&t1, NULL);fun();gettimeofday(&t2, NULL);timeuse = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) / 1000000.0;printf("%fms\n", timeuse * 1000);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}

其运行结果:

222.673000ms


(2) RDTSC指令

eg:

#include <iostream>#include <sys/time.h>#include <stdio.h>using std::cout;using std::endl;//FREQUENCY  CPU的频率#define  FREQUENCY 2600000000void fun();#if defined (__i386__)static __inline__ unsigned long long GetCycleCount(void){unsigned long long int x;__asm__ volatile("rdtsc":"=A"(x));return x;}#elif defined (__x86_64__)static __inline__ unsigned long long GetCycleCount(void){unsigned hi, lo;__asm__ volatile("rdtsc":"=a"(lo), "=d"(hi));return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);}#endifint main(int argc, char* argv[]){unsigned long t1, t2;t1 = (unsigned long)GetCycleCount();fun();t2 = (unsigned long)GetCycleCount();printf("%fms\n", (t2 - t1)*1.0 / FREQUENCY * 1000);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}

其运行结果:

221.486439ms


(3)Shell内置time

eg:

#include <iostream>#include <sys/time.h>#include <stdio.h>using std::cout;using std::endl;//FREQUENCY  CPU的频率#define  FREQUENCY 2600000000void fun();#if defined (__i386__)static __inline__ unsigned long long GetCycleCount(void){unsigned long long int x;__asm__ volatile("rdtsc":"=A"(x));return x;}#elif defined (__x86_64__)static __inline__ unsigned long long GetCycleCount(void){unsigned hi, lo;__asm__ volatile("rdtsc":"=a"(lo), "=d"(hi));return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);}#endifint main(int argc, char* argv[]){unsigned long t1, t2;t1 = (unsigned long)GetCycleCount();fun();t2 = (unsigned long)GetCycleCount();printf("%fms\n", (t2 - t1)*1.0 / FREQUENCY * 1000);return 0;}void fun(){long i = 0;for (; i < 100000000; i++){}}

austin@austin:~/Workspace$time ./test_time.exe

219.347928ms

 

real   0m0.222s

user   0m0.216s

sys 0m0.002s


三、精度等级比较


参考文献
[1] 计时函数比较. http://www.cnblogs.com/dwdxdy/p/3214905.html. 
[2] Windows 各种计时函数总结. http://blog.csdn.net/morewindows/article/details/6854764. 
[3] linux计时函数的使用. http://blog.chinaunix.net/uid-22237530-id-1781810.html.
[4] linux下c++的计时函数. http://blog.csdn.net/luyafei_89430/article/details/11016321. 
[5]Windows及Linux平台下的计时函数总结. http://www.cnblogs.com/lizhenghn/p/3587799.html. 
[6] Linux用户态程序计时方式详解. http://www.cnblogs.com/clover-toeic/p/3845210.html. 



注:为了便于自己学习,无心侵权,尽可能将所引用的文章列举出来;有些文章的内容可能会与原作重复度较高,还请谅解。如作者举报,愿意删除此文。

0 0
原创粉丝点击