如何计算C ++代码片段的执行时间

我必须在几秒钟内计算一个C ++代码片段的执行时间。 它必须在Windows或Unix机器上工作。

我使用下面的代码来做到这一点。 (之前导入)

clock_t startTime = clock(); // some code here // to compute its execution duration in runtime cout << double( clock() - startTime ) / (double)CLOCKS_PER_SEC<< " seconds." << endl; 

然而,对于小的input或简短的语句,如a = a + 1,我会得到“0秒”的结果。 我认为它一定是0.0000001秒或类似的东西。

我记得在这种情况下,Java中的System.nanoTime()工作得很好。 但是我不能从C ++的clock()函数中得到同样的function。

你有解决scheme吗?

你可以使用我写的这个函数。 您可以调用GetTimeMs64() ,它会返回自unix时期以来使用系统时钟所经过的毫秒数 – 就像time(NULL) ,除了以毫秒为单位。

它适用于Windows和Linux; 它是线程安全的。

请注意,窗口上的粒度为15毫秒; 在Linux上它是依赖于实现的,但通常也是15毫秒。

 #ifdef _WIN32 #include <Windows.h> #else #include <sys/time.h> #include <ctime> #endif /* Remove if already defined */ typedef long long int64; typedef unsigned long long uint64; /* Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both * windows and linux. */ uint64 GetTimeMs64() { #ifdef _WIN32 /* Windows */ FILETIME ft; LARGE_INTEGER li; /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it * to a LARGE_INTEGER structure. */ GetSystemTimeAsFileTime(&ft); li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; uint64 ret = li.QuadPart; ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */ ret /= 10000; /* From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals */ return ret; #else /* Linux */ struct timeval tv; gettimeofday(&tv, NULL); uint64 ret = tv.tv_usec; /* Convert from micro seconds (10^-6) to milliseconds (10^-3) */ ret /= 1000; /* Adds the seconds (10^0) after converting them to milliseconds (10^-3) */ ret += (tv.tv_sec * 1000); return ret; #endif } 

我有另一个使用微秒(UNIX,POSIX等)的工作示例。

  #include <sys/time.h> typedef unsigned long long timestamp_t; static timestamp_t get_timestamp () { struct timeval now; gettimeofday (&now, NULL); return now.tv_usec + (timestamp_t)now.tv_sec * 1000000; } ... timestamp_t t0 = get_timestamp(); // Process timestamp_t t1 = get_timestamp(); double secs = (t1 - t0) / 1000000.0L; 

这里是我们编码的文件:

https://github.com/arhuaco/junkcode/blob/master/emqbit-bench/bench.c

这是一个简单的解决scheme,在C + + 11中给你满意的决议。

 #include <iostream> #include <chrono> class Timer { public: Timer() : beg_(clock_::now()) {} void reset() { beg_ = clock_::now(); } double elapsed() const { return std::chrono::duration_cast<second_> (clock_::now() - beg_).count(); } private: typedef std::chrono::high_resolution_clock clock_; typedef std::chrono::duration<double, std::ratio<1> > second_; std::chrono::time_point<clock_> beg_; }; 

或者在* nix上,对于c ++ 03

 #include <iostream> #include <ctime> class Timer { public: Timer() { clock_gettime(CLOCK_REALTIME, &beg_); } double elapsed() { clock_gettime(CLOCK_REALTIME, &end_); return end_.tv_sec - beg_.tv_sec + (end_.tv_nsec - beg_.tv_nsec) / 1000000000.; } void reset() { clock_gettime(CLOCK_REALTIME, &beg_); } private: timespec beg_, end_; }; 

以下是示例用法:

 int main() { Timer tmr; double t = tmr.elapsed(); std::cout << t << std::endl; tmr.reset() double t = tmr.elapsed(); std::cout << t << std::endl; return 0; } 

https://gist.github.com/gongzhitaao/7062087

 #include <boost/progress.hpp> using namespace boost; int main (int argc, const char * argv[]) { progress_timer timer; // do stuff, preferably in a 100x loop to make it take longer. return 0; } 

progress_timer超出范围时,它将打印出自创build以来的时间。

更新 :我做了一个简单的独立replace(OSX / iOS,但易于端口): https : //github.com/catnapgames/TestTimerScoped

Windows提供了QueryPerformanceCounter()函数,Unix有gettimeofday()这两个函数都可以测量至less1微秒的差异。

我build议使用标准库函数从系统获取时间信息。

如果你想要更好的解决scheme,执行更多的执行迭代。 一次运行程序并获取样本,而不是运行1000次或更多。

性能计时只执行一次内循环,内循环的重复次数平均比运行整个事件(循环+性能计时)多次和平均更好。 这将减less性能计时代码相对于您的实际分析部分的开销。

包裹你的计时器调用适当的系统。 对于Windows,QueryPerformanceCounter是非常快速和“安全”的使用。

你也可以在任何现代的X86个人电脑上使用“rdtsc”,但在某些多核机器上可能会出现问题(核心跳变可能会改变计时器),或者你开启了某种速度步骤。

在我写的一些程序中,我使用了RDTS来达到这个目的。 RDTSC不是关于时间,而是关于处理器启动的周期数。 您必须在系统上对其进行校准以获得第二个结果,但是当您要评估性能时,它非常方便,甚至可以直接使用多个周期而不尝试将其更改回秒。

(上面的链接是一个法国维基百科页面,但它有C ++代码示例,英文版本在这里 )

如果你想得到好的确切结果,那么如上所述,你的执行时间取决于线程调度。 一个完全可靠的解决scheme,每次testing应该产生完全相同的时间,是编译你的程序独立于操作系统,启动你的计算机,以便在无OS的环境下运行程序。 但是,一个好的替代品就是将当前线程的关联性设置为1个核心,并将优先级设置为最高。 这样做的结果是非常一致的结果。 还有一件事是,你应该closures优化,g ++或gcc意味着在命令行中添加-O0,以防止被testing的代码被优化。 这里是我如何在Windows计算机上进行基准平方根function的一个例子。

 #include <iostream> #include <iomanip> #include <cstdio> #include <chrono> #include <cmath> #include <windows.h> #include <intrin.h> #pragma intrinsic(__rdtsc) class Timer { public: Timer() : beg_(clock_::now()) {} void reset() { beg_ = clock_::now(); } double elapsed() const { return std::chrono::duration_cast<second_> (clock_::now() - beg_).count(); } private: typedef std::chrono::high_resolution_clock clock_; typedef std::chrono::duration<double, std::ratio<1> > second_; std::chrono::time_point<clock_> beg_; }; unsigned int guess_sqrt32(register unsigned int n) { register unsigned int g = 0x8000; if(g*g > n) { g ^= 0x8000; } g |= 0x4000; if(g*g > n) { g ^= 0x4000; } g |= 0x2000; if(g*g > n) { g ^= 0x2000; } g |= 0x1000; if(g*g > n) { g ^= 0x1000; } g |= 0x0800; if(g*g > n) { g ^= 0x0800; } g |= 0x0400; if(g*g > n) { g ^= 0x0400; } g |= 0x0200; if(g*g > n) { g ^= 0x0200; } g |= 0x0100; if(g*g > n) { g ^= 0x0100; } g |= 0x0080; if(g*g > n) { g ^= 0x0080; } g |= 0x0040; if(g*g > n) { g ^= 0x0040; } g |= 0x0020; if(g*g > n) { g ^= 0x0020; } g |= 0x0010; if(g*g > n) { g ^= 0x0010; } g |= 0x0008; if(g*g > n) { g ^= 0x0008; } g |= 0x0004; if(g*g > n) { g ^= 0x0004; } g |= 0x0002; if(g*g > n) { g ^= 0x0002; } g |= 0x0001; if(g*g > n) { g ^= 0x0001; } return g; } unsigned int empty_function( unsigned int _input ) { return _input; } unsigned long long empty_ticks=0; double empty_seconds=0; Timer my_time; template<unsigned int benchmark_repetitions> void benchmark( char* function_name, auto (*function_to_do)( auto ) ) { register unsigned int i=benchmark_repetitions; register unsigned long long start=0; my_time.reset(); start=__rdtsc(); while ( i-- ) { (*function_to_do)( i << 7 ); } if ( function_name == nullptr ) { empty_ticks = (__rdtsc()-start); empty_seconds = my_time.elapsed(); std::cout<< "Empty:\n" << empty_ticks << " ticks\n" << benchmark_repetitions << " repetitions\n" << std::setprecision(15) << empty_seconds << " seconds\n\n"; } else { std::cout<< function_name<<":\n" << (__rdtsc()-start-empty_ticks) << " ticks\n" << benchmark_repetitions << " repetitions\n" << std::setprecision(15) << (my_time.elapsed()-empty_seconds) << " seconds\n\n"; } } int main( void ) { void* Cur_Thread= GetCurrentThread(); void* Cur_Process= GetCurrentProcess(); unsigned long long Current_Affinity; unsigned long long System_Affinity; unsigned long long furthest_affinity; unsigned long long nearest_affinity; if( ! SetThreadPriority(Cur_Thread,THREAD_PRIORITY_TIME_CRITICAL) ) { SetThreadPriority( Cur_Thread, THREAD_PRIORITY_HIGHEST ); } if( ! SetPriorityClass(Cur_Process,REALTIME_PRIORITY_CLASS) ) { SetPriorityClass( Cur_Process, HIGH_PRIORITY_CLASS ); } GetProcessAffinityMask( Cur_Process, &Current_Affinity, &System_Affinity ); furthest_affinity = 0x8000000000000000ULL>>__builtin_clzll(Current_Affinity); nearest_affinity = 0x0000000000000001ULL<<__builtin_ctzll(Current_Affinity); SetProcessAffinityMask( Cur_Process, furthest_affinity ); SetThreadAffinityMask( Cur_Thread, furthest_affinity ); const int repetitions=524288; benchmark<repetitions>( nullptr, empty_function ); benchmark<repetitions>( "Standard Square Root", standard_sqrt ); benchmark<repetitions>( "Original Guess Square Root", original_guess_sqrt32 ); benchmark<repetitions>( "New Guess Square Root", new_guess_sqrt32 ); SetThreadPriority( Cur_Thread, THREAD_PRIORITY_IDLE ); SetPriorityClass( Cur_Process, IDLE_PRIORITY_CLASS ); SetProcessAffinityMask( Cur_Process, nearest_affinity ); SetThreadAffinityMask( Cur_Thread, nearest_affinity ); for (;;) { getchar(); } return 0; } 

另外,还要把他的计时器归功于Mike Jarvis。

而且,请注意(这非常重要),如果你要运行更大的代码片段,那么你真的必须减less迭代次数,以防止计算机冻结。

boost :: timer可能会给你尽可能多的准确性,你会需要。 这远远不够准确,告诉你多久a = a+1; 将采取,但我有什么原因,你需要时间的东西,需要几个纳秒?

我创build了一个lambda函数调用N次,并返回平均值。

 double c = BENCHMARK_CNT(25, fillVectorDeque(variable)); 

你可以在这里findc ++ 11的头文件。

对于每次执行相同代码段的情况(例如对于认为可能是瓶颈的代码进行分析),下面是对Andreas Bonini函数的一个包装(稍作修改),我觉得它很有用:

 #ifdef _WIN32 #include <Windows.h> #else #include <sys/time.h> #endif /* * A simple timer class to see how long a piece of code takes. * Usage: * * { * static Timer timer("name"); * * ... * * timer.start() * [ The code you want timed ] * timer.stop() * * ... * } * * At the end of execution, you will get output: * * Time for name: XXX seconds */ class Timer { public: Timer(std::string name, bool start_running=false) : _name(name), _accum(0), _running(false) { if (start_running) start(); } ~Timer() { stop(); report(); } void start() { if (!_running) { _start_time = GetTimeMicroseconds(); _running = true; } } void stop() { if (_running) { unsigned long long stop_time = GetTimeMicroseconds(); _accum += stop_time - _start_time; _running = false; } } void report() { std::cout<<"Time for "<<_name<<": " << _accum / 1.e6 << " seconds\n"; } private: // cf. http://stackoverflow.com/questions/1861294/how-to-calculate-execution-time-of-a-code-snippet-in-c unsigned long long GetTimeMicroseconds() { #ifdef _WIN32 /* Windows */ FILETIME ft; LARGE_INTEGER li; /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it * * to a LARGE_INTEGER structure. */ GetSystemTimeAsFileTime(&ft); li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; unsigned long long ret = li.QuadPart; ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */ ret /= 10; /* From 100 nano seconds (10^-7) to 1 microsecond (10^-6) intervals */ #else /* Linux */ struct timeval tv; gettimeofday(&tv, NULL); unsigned long long ret = tv.tv_usec; /* Adds the seconds (10^0) after converting them to microseconds (10^-6) */ ret += (tv.tv_sec * 1000000); #endif return ret; } std::string _name; long long _accum; unsigned long long _start_time; bool _running; }; 

我使用chrono库的high_resolution_clock创build了一个用于测量代码块性能的简单实用程序: https : //github.com/nfergu/codetimer 。

时间可以logging在不同的键上,并且可以显示每个键的定时的汇总视图。

用法如下:

 #include <chrono> #include <iostream> #include "codetimer.h" int main () { auto start = std::chrono::high_resolution_clock::now(); // some code here CodeTimer::record("mykey", start); CodeTimer::printStats(); return 0; }