Measuring execution time of a function in C++

后端 未结 11 685
小鲜肉
小鲜肉 2020-11-22 12:59

I want to find out how much time a certain function takes in my C++ program to execute on Linux. Afterwards, I want to make a speed comparison . I saw sever

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

    I recommend using steady_clock which is guarunteed to be monotonic, unlike high_resolution_clock.

    #include <iostream>
    #include <chrono>
    
    using namespace std;
    
    unsigned int stopwatch()
    {
        static auto start_time = chrono::steady_clock::now();
    
        auto end_time = chrono::steady_clock::now();
        auto delta    = chrono::duration_cast<chrono::microseconds>(end_time - start_time);
    
        start_time = end_time;
    
        return delta.count();
    }
    
    int main() {
      stopwatch(); //Start stopwatch
      std::cout << "Hello World!\n";
      cout << stopwatch() << endl; //Time to execute last line
      for (int i=0; i<1000000; i++)
          string s = "ASDFAD";
      cout << stopwatch() << endl; //Time to execute for loop
    }
    

    Output:

    Hello World!
    62
    163514
    
    0 讨论(0)
  • 2020-11-22 13:28

    You can have a simple class which can be used for this kind of measurements.

    class duration_printer {
    public:
        duration_printer() : __start(std::chrono::high_resolution_clock::now()) {}
        ~duration_printer() {
            using namespace std::chrono;
            high_resolution_clock::time_point end = high_resolution_clock::now();
            duration<double> dur = duration_cast<duration<double>>(end - __start);
            std::cout << dur.count() << " seconds" << std::endl;
        }
    private:
        std::chrono::high_resolution_clock::time_point __start;
    };
    

    The only thing is needed to do is to create an object in your function at the beginning of that function

    void veryLongExecutingFunction() {
        duration_calculator dc;
        for(int i = 0; i < 100000; ++i) std::cout << "Hello world" << std::endl;
    }
    
    int main() {
        veryLongExecutingFunction();
        return 0;
    }
    

    and that's it. The class can be modified to fit your requirements.

    0 讨论(0)
  • 2020-11-22 13:31

    In Scott Meyers book I found an example of universal generic lambda expression that can be used to measure function execution time. (C++14)

    auto timeFuncInvocation = 
        [](auto&& func, auto&&... params) {
            // get time before function invocation
            const auto& start = std::chrono::high_resolution_clock::now();
            // function invocation using perfect forwarding
            std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
            // get time after function invocation
            const auto& stop = std::chrono::high_resolution_clock::now();
            return stop - start;
         };
    

    The problem is that you are measure only one execution so the results can be very differ. To get a reliable result you should measure a large number of execution. According to Andrei Alexandrescu lecture at code::dive 2015 conference - Writing Fast Code I:

    Measured time: tm = t + tq + tn + to

    where:

    tm - measured (observed) time

    t - the actual time of interest

    tq - time added by quantization noise

    tn - time added by various sources of noise

    to - overhead time (measuring, looping, calling functions)

    According to what he said later in the lecture, you should take a minimum of this large number of execution as your result. I encourage you to look at the lecture in which he explains why.

    Also there is a very good library from google - https://github.com/google/benchmark. This library is very simple to use and powerful. You can checkout some lectures of Chandler Carruth on youtube where he is using this library in practice. For example CppCon 2017: Chandler Carruth “Going Nowhere Faster”;

    Example usage:

    #include <iostream>
    #include <chrono>
    #include <vector>
    auto timeFuncInvocation = 
        [](auto&& func, auto&&... params) {
            // get time before function invocation
            const auto& start = high_resolution_clock::now();
            // function invocation using perfect forwarding
            for(auto i = 0; i < 100000/*largeNumber*/; ++i) {
                std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
            }
            // get time after function invocation
            const auto& stop = high_resolution_clock::now();
            return (stop - start)/100000/*largeNumber*/;
         };
    
    void f(std::vector<int>& vec) {
        vec.push_back(1);
    }
    
    void f2(std::vector<int>& vec) {
        vec.emplace_back(1);
    }
    int main()
    {
        std::vector<int> vec;
        std::vector<int> vec2;
        std::cout << timeFuncInvocation(f, vec).count() << std::endl;
        std::cout << timeFuncInvocation(f2, vec2).count() << std::endl;
        std::vector<int> vec3;
        vec3.reserve(100000);
        std::vector<int> vec4;
        vec4.reserve(100000);
        std::cout << timeFuncInvocation(f, vec3).count() << std::endl;
        std::cout << timeFuncInvocation(f2, vec4).count() << std::endl;
        return 0;
    }
    

    EDIT: Ofcourse you always need to remember that your compiler can optimize something out or not. Tools like perf can be useful in such cases.

    0 讨论(0)
  • 2020-11-22 13:32

    It is a very easy-to-use method in C++11. You have to use std::chrono::high_resolution_clock from <chrono> header.

    Use it like so:

    #include <iostream>
    #include <chrono>
    
    void function()
    {
        long long number = 0;
    
        for( long long i = 0; i != 2000000; ++i )
        {
           number += 5;
        }
    }
    
    int main()
    {
        auto t1 = std::chrono::high_resolution_clock::now();
        function();
        auto t2 = std::chrono::high_resolution_clock::now();
    
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
    
        std::cout << duration;
        return 0;
    }
    

    This will measure the duration of the function.

    NOTE: You will not always get the same timing for a function. This is because the CPU of your machine can be less or more used by other processes running on your computer, just as your mind can be more or less concentrated when you solve a math exercise. In the human mind, we can remember the solution of a math problem, but for a computer the same process will always be something new; thus, as I said, you will not always get the same result!

    0 讨论(0)
  • 2020-11-22 13:36
    • It is a very easy to use method in C++11.
    • We can use std::chrono::high_resolution_clock from header
    • We can write a method to print the method execution time in a much readable form.

    For example, to find the all the prime numbers between 1 and 100 million, it takes approximately 1 minute and 40 seconds. So the execution time get printed as:

    Execution Time: 1 Minutes, 40 Seconds, 715 MicroSeconds, 715000 NanoSeconds
    

    The code is here:

    #include <iostream>
    #include <chrono>
    
    using namespace std;
    using namespace std::chrono;
    
    typedef high_resolution_clock Clock;
    typedef Clock::time_point ClockTime;
    
    void findPrime(long n, string file);
    void printExecutionTime(ClockTime start_time, ClockTime end_time);
    
    int main()
    {
        long n = long(1E+8);  // N = 100 million
    
        ClockTime start_time = Clock::now();
    
        // Write all the prime numbers from 1 to N to the file "prime.txt"
        findPrime(n, "C:\\prime.txt"); 
    
        ClockTime end_time = Clock::now();
    
        printExecutionTime(start_time, end_time);
    }
    
    void printExecutionTime(ClockTime start_time, ClockTime end_time)
    {
        auto execution_time_ns = duration_cast<nanoseconds>(end_time - start_time).count();
        auto execution_time_ms = duration_cast<microseconds>(end_time - start_time).count();
        auto execution_time_sec = duration_cast<seconds>(end_time - start_time).count();
        auto execution_time_min = duration_cast<minutes>(end_time - start_time).count();
        auto execution_time_hour = duration_cast<hours>(end_time - start_time).count();
    
        cout << "\nExecution Time: ";
        if(execution_time_hour > 0)
        cout << "" << execution_time_hour << " Hours, ";
        if(execution_time_min > 0)
        cout << "" << execution_time_min % 60 << " Minutes, ";
        if(execution_time_sec > 0)
        cout << "" << execution_time_sec % 60 << " Seconds, ";
        if(execution_time_ms > 0)
        cout << "" << execution_time_ms % long(1E+3) << " MicroSeconds, ";
        if(execution_time_ns > 0)
        cout << "" << execution_time_ns % long(1E+6) << " NanoSeconds, ";
    }
    
    0 讨论(0)
提交回复
热议问题