Easily measure elapsed time

前端 未结 26 2183
栀梦
栀梦 2020-11-22 04:13

I am trying to use time() to measure various points of my program.

What I don\'t understand is why the values in the before and after are the same? I understand thi

相关标签:
26条回答
  • 2020-11-22 04:58

    I have created a class to automatically measure elapsed time, Please check the code (c++11) in this link: https://github.com/sonnt174/Common/blob/master/time_measure.h

    Example of how to use class TimeMeasure:

    void test_time_measure(std::vector<int> arr) {
      TimeMeasure<chrono::microseconds> time_mea;  // create time measure obj
      std::sort(begin(arr), end(arr));
    }
    
    0 讨论(0)
  • 2020-11-22 05:03

    C++ std::chrono has a clear benefit of being cross-platform. However, it also introduces a significant overhead compared to POSIX clock_gettime(). On my Linux box all std::chrono::xxx_clock::now() flavors perform roughly the same:

    std::chrono::system_clock::now()
    std::chrono::steady_clock::now()
    std::chrono::high_resolution_clock::now()
    

    Though POSIX clock_gettime(CLOCK_MONOTONIC, &time) should be same as steady_clock::now() but it is more than x3 times faster!

    Here is my test, for completeness.

    #include <stdio.h>
    #include <chrono>
    #include <ctime>
    
    void print_timediff(const char* prefix, const struct timespec& start, const 
    struct timespec& end)
    {
        double milliseconds = end.tv_nsec >= start.tv_nsec
                            ? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
                            : (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
        printf("%s: %lf milliseconds\n", prefix, milliseconds);
    }
    
    int main()
    {
        int i, n = 1000000;
        struct timespec start, end;
    
        // Test stopwatch
        clock_gettime(CLOCK_MONOTONIC, &start);
        for (i = 0; i < n; ++i) {
            struct timespec dummy;
            clock_gettime(CLOCK_MONOTONIC, &dummy);
        }
        clock_gettime(CLOCK_MONOTONIC, &end);
        print_timediff("clock_gettime", start, end);
    
        // Test chrono system_clock
        clock_gettime(CLOCK_MONOTONIC, &start);
        for (i = 0; i < n; ++i)
            auto dummy = std::chrono::system_clock::now();
        clock_gettime(CLOCK_MONOTONIC, &end);
        print_timediff("chrono::system_clock::now", start, end);
    
        // Test chrono steady_clock
        clock_gettime(CLOCK_MONOTONIC, &start);
        for (i = 0; i < n; ++i)
            auto dummy = std::chrono::steady_clock::now();
        clock_gettime(CLOCK_MONOTONIC, &end);
        print_timediff("chrono::steady_clock::now", start, end);
    
        // Test chrono high_resolution_clock
        clock_gettime(CLOCK_MONOTONIC, &start);
        for (i = 0; i < n; ++i)
            auto dummy = std::chrono::high_resolution_clock::now();
        clock_gettime(CLOCK_MONOTONIC, &end);
        print_timediff("chrono::high_resolution_clock::now", start, end);
    
        return 0;
    }
    

    And this is the output I get when compiled with gcc7.2 -O3:

    clock_gettime: 24.484926 milliseconds
    chrono::system_clock::now: 85.142108 milliseconds
    chrono::steady_clock::now: 87.295347 milliseconds
    chrono::high_resolution_clock::now: 84.437838 milliseconds
    
    0 讨论(0)
  • 2020-11-22 05:03

    From what is see, tv_sec stores the seconds elapsed while tv_usec stored the microseconds elapsed separately. And they aren't the conversions of each other. Hence, they must be changed to proper unit and added to get the total time elapsed.

    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))
        );
    
    0 讨论(0)
  • 2020-11-22 05:04

    the time(NULL) function will return the number of seconds elapsed since 01/01/1970 at 00:00. And because, that function is called at different time in your program, it will always be different Time in C++

    0 讨论(0)
  • 2020-11-22 05:04
    #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;
    }
    
    0 讨论(0)
  • 2020-11-22 05:04

    As others have already noted, the time() function in the C standard library does not have a resolution better than one second. The only fully portable C function that may provide better resolution appears to be clock(), but that measures processor time rather than wallclock time. If one is content to limit oneself to POSIX platforms (e.g. Linux), then the clock_gettime() function is a good choice.

    Since C++11, there are much better timing facilities available that offer better resolution in a form that should be very portable across different compilers and operating systems. Similarly, the boost::datetime library provides good high-resolution timing classes that should be highly portable.

    One challenge in using any of these facilities is the time-delay introduced by querying the system clock. From experimenting with clock_gettime(), boost::datetime and std::chrono, this delay can easily be a matter of microseconds. So, when measuring the duration of any part of your code, you need to allow for there being a measurement error of around this size, or try to correct for that zero-error in some way. Ideally, you may well want to gather multiple measurements of the time taken by your function, and compute the average, or maximum/minimum time taken across many runs.

    To help with all these portability and statistics-gathering issues, I've been developing the cxx-rtimers library available on Github which tries to provide a simple API for timing blocks of C++ code, computing zero errors, and reporting stats from multiple timers embedded in your code. If you have a C++11 compiler, you simply #include <rtimers/cxx11.hpp>, and use something like:

    void expensiveFunction() {
        static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
        auto scopedStartStop = timer.scopedStart();
        // Do something costly...
    }
    

    On program exit, you'll get a summary of timing stats written to std::cerr such as:

    Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)
    

    which shows the mean time, its standard-deviation, the upper and lower limits, and the number of times this function was called.

    If you want to use Linux-specific timing functions, you can #include <rtimers/posix.hpp>, or if you have the Boost libraries but an older C++ compiler, you can #include <rtimers/boost.hpp>. There are also versions of these timer classes that can gather statistical timing information from across multiple threads. There are also methods that allow you to estimate the zero-error associated with two immediately consecutive queries of the system clock.

    0 讨论(0)
提交回复
热议问题