轻松测量经过的时间

我正在尝试使用time()来测量我的程序的各个点。

我不明白的是为什么前后的值是一样的? 我知道这不是描述我的程序的最好方法,我只想看看有什么东西需要。

printf("**MyProgram::before time= %ld\n", time(NULL)); doSomthing(); doSomthingLong(); printf("**MyProgram::after time= %ld\n", time(NULL)); 

我努力了:

 struct timeval diff, startTV, endTV; gettimeofday(&startTV, NULL); doSomething(); doSomethingLong(); gettimeofday(&endTV, NULL); timersub(&endTV, &startTV, &diff); printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec); 

如何读取**time taken = 0 26339 ? 这是否意味着26339纳秒= 26.3毫秒?

**time taken = 4 45025 ,这是否意味着4秒和25毫秒?

 #include <ctime> void f() { using namespace std; clock_t begin = clock(); code_to_time(); clock_t end = clock(); double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; } 

time()函数只能精确到一秒之内,但是CLOCKS_PER_SEC “时钟”在一秒之内。 这是一个简单的便携式测量,尽管它过于简单。

您可以抽象时间测量机制,并通过一个计时器结构来调用每个可调用的运行时间,并以最少的额外代码进行度量。 另外,在编译时,您可以参数化时序类型 (毫秒,纳秒等)。

感谢Loki Astari的评论以及使用可变模板的建议。 这就是为什么转发的函数调用。

 #include <iostream> #include <chrono> template<typename TimeT = std::chrono::milliseconds> struct measure { template<typename F, typename ...Args> static typename TimeT::rep execution(F&& func, Args&&... args) { auto start = std::chrono::steady_clock::now(); std::forward<decltype(func)>(func)(std::forward<Args>(args)...); auto duration = std::chrono::duration_cast< TimeT> (std::chrono::steady_clock::now() - start); return duration.count(); } }; int main() { std::cout << measure<>::execution(functor(dummy)) << std::endl; } 

演示

根据霍华德·欣南特Howard Hinnant)的评论,最好不要逃离计时系统,直到我们不得不这样做。 所以上面的类可以让用户选择通过提供一个额外的静态方法手动调用count (以C ++ 14显示)

 template<typename F, typename ...Args> static auto duration(F&& func, Args&&... args) { auto start = std::chrono::steady_clock::now(); std::forward<decltype(func)>(func)(std::forward<Args>(args)...); return std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now()-start); } // call .count() manually later when needed (eg IO) auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0; 

对客户来说是最有用的

“想在I / O之前(例如平均)后处理一堆持续时间”


完整的代码可以在这里找到 。 我在这里记录基于chrono构建基准测试工具的尝试。


如果C ++ 17的std::invoke可用,那么在execution可调用的调用可以这样完成:

 invoke(forward<decltype(func)>(func), forward<Args>(args)...); 

提供指向成员函数的可调用函数。

 //***C++11 Style:*** std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now(); std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() <<std::endl; std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() <<std::endl; 

正如我从你的问题中可以看到的,看起来你想知道执行某段代码之后所经过的时间。 我想你会很舒服,看第二(s)的结果。 如果是这样,请尝试使用difftime()函数,如下所示。 希望这可以解决你的问题。

 #include <time.h> #include <stdio.h> time_t start,end; time (&start); . . . <your code> . . . time (&end); double dif = difftime (end,start); printf ("Elasped time is %.2lf seconds.", dif ); 

仅Windows:(我发布这个答案后添加了Linux标签)

您可以使用GetTickCount()来获取自系统启动以来经过的毫秒数。

 long int before = GetTickCount(); // Perform time-consuming operation long int after = GetTickCount(); 

时间(NULL)函数将返回自01/01/1970在00:00以来经过的秒数。 而且,因为该函数在程序中的不同时间被调用,所以它在C ++中始终是不同的时间

time(NULL)返回自01/01/1970在00:00( Epoch )以来经过的秒数。 所以两个值之间的差异是你处理的秒数。

 int t0 = time(NULL); doSomthing(); doSomthingLong(); int t1 = time(NULL); printf ("time = %d secs\n", t1 - t0); 

getttimeofday()可以得到更精细的结果,它返回当前时间(以秒为单位),如time() ,也以微秒为单位。

 #include<time.h> // for clock #include<math.h> // for fmod #include<cstdlib> //for system #include <stdio.h> //for delay using namespace std; int main() { clock_t t1,t2; t1=clock(); // first time capture // Now your time spanning loop or code goes here // i am first trying to display time elapsed every time loop runs int ddays=0; // d prefix is just to say that this variable will be used for display int dhh=0; int dmm=0; int dss=0; int loopcount = 1000 ; // just for demo your loop will be different of course for(float count=1;count<loopcount;count++) { t2=clock(); // we get the time now float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds // now get the time elapsed in seconds float seconds = difference/1000; // float value of seconds if (seconds<(60*60*24)) // a day is not over { dss = fmod(seconds,60); // the remainder is seconds to be displayed float minutes= seconds/60; // the total minutes in float dmm= fmod(minutes,60); // the remainder are minutes to be displayed float hours= minutes/60; // the total hours in float dhh= hours; // the hours to be displayed ddays=0; } else // we have reached the counting of days { float days = seconds/(24*60*60); ddays = (int)(days); float minutes= seconds/60; // the total minutes in float dmm= fmod(minutes,60); // the rmainder are minutes to be displayed float hours= minutes/60; // the total hours in float dhh= fmod (hours,24); // the hours to be displayed } cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs"; // the actual working code here,I have just put a delay function delay(1000); system("cls"); } // end for loop }// end of main 

第二个程序打印的值是秒和微秒。

 0 26339 = 0.026'339 s = 26339 µs 4 45025 = 4.045'025 s = 4045025 µs 
 struct profiler { std::string name; std::chrono::high_resolution_clock::time_point p; profiler(std::string const &n) : name(n), p(std::chrono::high_resolution_clock::now()) { } ~profiler() { using dura = std::chrono::duration<double>; auto d = std::chrono::high_resolution_clock::now() - p; std::cout << name << ": " << std::chrono::duration_cast<dura>(d).count() << std::endl; } }; #define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn) 

用法如下

 { PROFILE_BLOCK("Some time"); // your code or function } 

这与范围上的RAII相似

注意这不是我的,但我认为这是相关的

 #include <ctime> #include <cstdio> #include <iostream> #include <chrono> #include <sys/time.h> using namespace std; using namespace std::chrono; void f1() { high_resolution_clock::time_point t1 = high_resolution_clock::now(); high_resolution_clock::time_point t2 = high_resolution_clock::now(); double dif = duration_cast<nanoseconds>( t2 - t1 ).count(); printf ("Elasped time is %lf nanoseconds.\n", dif ); } void f2() { timespec ts1,ts2; clock_gettime(CLOCK_REALTIME, &ts1); clock_gettime(CLOCK_REALTIME, &ts2); double dif = double( ts2.tv_nsec - ts1.tv_nsec ); printf ("Elasped time is %lf nanoseconds.\n", dif ); } void f3() { struct timeval t1,t0; gettimeofday(&t0, 0); gettimeofday(&t1, 0); double dif = double( (t1.tv_usec-t0.tv_usec)*1000); printf ("Elasped time is %lf nanoseconds.\n", dif ); } void f4() { high_resolution_clock::time_point t1 , t2; double diff = 0; t1 = high_resolution_clock::now() ; for(int i = 1; i <= 10 ; i++) { t2 = high_resolution_clock::now() ; diff+= duration_cast<nanoseconds>( t2 - t1 ).count(); t1 = t2; } printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 ); } void f5() { timespec ts1,ts2; double diff = 0; clock_gettime(CLOCK_REALTIME, &ts1); for(int i = 1; i <= 10 ; i++) { clock_gettime(CLOCK_REALTIME, &ts2); diff+= double( ts2.tv_nsec - ts1.tv_nsec ); ts1 = ts2; } printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 ); } void f6() { struct timeval t1,t2; double diff = 0; gettimeofday(&t1, 0); for(int i = 1; i <= 10 ; i++) { gettimeofday(&t2, 0); diff+= double( (t2.tv_usec-t1.tv_usec)*1000); t1 = t2; } printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 ); } int main() { // f1(); // f2(); // f3(); f6(); f4(); f5(); return 0; } 

内部函数将访问系统的时钟,这就是为什么每次调用它时都会返回不同的值。 一般来说,对于非函数式语言来说,函数中可能会有很多副作用和隐藏状态,只是通过查看函数的名称和参数才能看到。

time(NULL)函数调用将返回从epoc:1970年1月1日起经过的秒数。也许你要做的是取两个时间戳之差:

 size_t start = time(NULL); doSomthing(); doSomthingLong(); printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start); 

从所看到的,tv_sec存储tv_usec单独存储微秒后经过的秒数。 他们不是彼此的转换。 因此,他们必须改变到适当的单位,并添加到总时间已过。

 struct timeval startTV, endTV; gettimeofday(&startTV, NULL); doSomething(); doSomethingLong(); gettimeofday(&endTV, NULL); printf("**time taken in microseconds = %ld\n", (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec)) ); 

在linux上,clock_gettime()是很好的选择之一。 您必须链接实时库(-lrt)。

 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #define BILLION 1000000000L; int main( int argc, char **argv ) { struct timespec start, stop; double accum; if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) { perror( "clock gettime" ); exit( EXIT_FAILURE ); } system( argv[1] ); if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) { perror( "clock gettime" ); exit( EXIT_FAILURE ); } accum = ( stop.tv_sec - start.tv_sec ) + ( stop.tv_nsec - start.tv_nsec ) / BILLION; printf( "%lf\n", accum ); return( EXIT_SUCCESS ); } 

它们是相同的,因为doSomething函数的发生速度比定时器的粒度要快。 尝试:

 printf ("**MyProgram::before time= %ld\n", time(NULL)); for(i = 0; i < 1000; ++i) { doSomthing(); doSomthingLong(); } printf ("**MyProgram::after time= %ld\n", time(NULL)); 

两个值相同的原因是因为你的漫长过程不需要那么长 – 不到一秒钟。 你可以尝试在函数的末尾添加一个长循环(for(int i = 0; i <100000000; i ++);)以确保这是问题,那么我们可以从那里…

如果上述结果是真实的,你将需要找到一个不同的系统功能(我知道你在Linux上工作,所以我不能帮你的功能名称)更准确地测量时间。 我相信在Linux中有一个类似于GetTickCount()的函数,你只需要找到它。

我通常使用以下内容:

 #include <chrono> #include <type_traits> using perf_clock = std::conditional< std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock, std::chrono::steady_clock >::type; using floating_seconds = std::chrono::duration<double>; template<class F, class... Args> floating_seconds run_test(Func&& func, Args&&... args) { const auto t0 = perf_clock::now(); std::forward<Func>(func)(std::forward<Args>(args)...); return floating_seconds(perf_clock::now() - t0); } 

这与@ nikos-athanasiou提出的一样,只是我避免使用非稳定时钟,并使用浮点数作为持续时间。

回答OP的三个具体问题。

“我不明白为什么前后的价值观是一样的?

一个问题和示例代码显示time()的分辨率为1秒,所以答案必须是两个函数在1秒内执行。 偶尔它会(显然不合逻辑)通知1秒,如果两个计时器标记跨越一秒的边界。

下一个例子使用gettimeofday()来填充这个结构体

 struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; 

第二个问题是“我如何读取**time taken = 0 26339的结果**time taken = 0 26339 ?这意味着26,339纳秒= 26.3毫秒?

我的第二个答案是所需要的时间是0秒和26339微秒,即0.026339秒,这就是第一个例子在不到1秒内执行的结果。

第三个问题是**time taken = 4 45025 ,这是否意味着4秒25毫秒?

我的第三个答案是所需要的时间是4秒45025微秒,即4.045025秒,这表明OP已经改变了他先前计时的两个功能所执行的任务。

您可以使用SFML库 ,这是简单和快速的多媒体库。 它包括许多有用的定义良好的类,如时钟,套接字,声音,图形等。它非常容易使用和强烈推荐。

这是这个问题的一个例子。

 sf::Clock clock; ... Time time1 = clock.getElapsedTime(); ... Time time2 = clock.restart();