在 C++ 中测量函数的执行时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22387586/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:03:41  来源:igfitidea点击:

Measuring execution time of a function in C++

c++optimizationprofiling

提问by Xara

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 several time function but ended up with this from boost. Chrono:

我想知道在我的 C++ 程序中某个函数在Linux上执行需要多少时间。之后,我想做一个速度比较。我看到了几个时间函数,但最终从 boost 得到了这个。计时:

process_user_cpu_clock, captures user-CPU time spent by the current process

Now, I am not clear if I use the above function, will I get the only time which CPU spent on that function?

现在,我不清楚是否使用上述功能,我是否会获得 CPU 在该功能上花费的唯一时间?

Secondly, I could not find any example of using the above function. Can any one please help me how to use the above function?

其次,我找不到任何使用上述功能的例子。任何人都可以帮助我如何使用上述功能吗?

P.S: Right now , I am using std::chrono::system_clock::now()to get time in seconds but this gives me different results due to different CPU load every time.

PS:现在,我使用std::chrono::system_clock::now()以秒为单位获取时间,但是由于每次 CPU 负载不同,这会给我不同的结果。

回答by Victor

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

它是 C++11 中非常易于使用的方法。您必须使用std::chrono::high_resolution_clockfrom<chrono>标头。

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!

注意:您不会总是获得相同的功能计时。这是因为计算机上运行的其他进程可能会更少或更多地使用机器的 CPU,就像您在解决数学练习时或多或少地集中注意力一样。在人类的头脑中,我们可以记住数学问题的解决方案,但对于计算机来说,同样的过程将永远是新的;因此,正如我所说,您不会总是得到相同的结果!

回答by Jahid

Here's a function that will measure the execution time of any function passed as argument:

这是一个函数,它将测量作为参数传递的任何函数的执行时间:

#include <chrono>
#include <utility>

typedef std::chrono::high_resolution_clock::time_point TimeVar;

#define duration(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()

template<typename F, typename... Args>
double funcTime(F func, Args&&... args){
    TimeVar t1=timeNow();
    func(std::forward<Args>(args)...);
    return duration(timeNow()-t1);
}

Example usage:

用法示例:

#include <iostream>
#include <algorithm>

typedef std::string String;

//first test function doing something
int countCharInString(String s, char delim){
    int count=0;
    String::size_type pos = s.find_first_of(delim);
    while ((pos = s.find_first_of(delim, pos)) != String::npos){
        count++;pos++;
    }
    return count;
}

//second test function doing the same thing in different way
int countWithAlgorithm(String s, char delim){
    return std::count(s.begin(),s.end(),delim);
}


int main(){
    std::cout<<"norm: "<<funcTime(countCharInString,"precision=10",'=')<<"\n";
    std::cout<<"algo: "<<funcTime(countWithAlgorithm,"precision=10",'=');
    return 0;
}

Output:

输出:

norm: 15555
algo: 2976

回答by Abdullah Farweez

simple program to find a function execution time taken.

查找一个函数执行时间所花费的简单程序。

#include <iostream>
#include <ctime> // time_t
#include <cstdio>

void function()
{
     for(long int i=0;i<1000000000;i++)
     {
        // do nothing
     }
}

int main()
{

time_t begin,end; // time_t is a datatype to store time values.

time (&begin); // note time before execution
function();
time (&end); // note time after execution

double difference = difftime (end,begin);
printf ("time taken for function() %.2lf seconds.\n", difference );

return 0;
}

回答by Krzysztof Sommerfeld

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

在 Scott Meyers 的书中,我找到了一个通用通用 lambda 表达式的例子,它可以用来测量函数执行时间。(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:

问题是您只测量一次执行,因此结果可能非常不同。为了获得可靠的结果,您应该测量大量的执行。根据 Andrei Alexandrescu 在 code::dive 2015 会议上的演讲 - 编写快速代码 I:

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

测量时间:tm = t + tq + tn + to

where:

在哪里:

tm - measured (observed) time

tm - 测量(观察)时间

t - the actual time of interest

t - 实际感兴趣的时间

tq - time added by quantization noise

tq - 量化噪声添加的时间

tn - time added by various sources of noise

tn - 各种噪声源添加的时间

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

to - 开销时间(测量、循环、调用函数)

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”;

还有一个来自 google 的非常好的库 - https://github.com/google/benchmark。这个库使用起来非常简单且功能强大。你可以在 youtube 上查看 Chandler Carruth 的一些讲座,他正在实践中使用这个库。例如 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.

编辑:当然,您始终需要记住您的编译器可以优化或不优化某些内容。在这种情况下,像 perf 这样的工具会很有用。

回答by v.chaplin

Easy way for older C++, or C:

较旧的 C++ 或 C 的简单方法:

#include <time.h> // includes clock_t and CLOCKS_PER_SEC

int main() {

    clock_t start, end;

    start = clock();
    // ...code to measure...
    end = clock();

    double duration_sec = double(end-start)/CLOCKS_PER_SEC;
    return 0;
}

Timing precision in seconds is 1.0/CLOCKS_PER_SEC

以秒为单位的计时精度为 1.0/CLOCKS_PER_SEC

回答by Pratik Patil

  • 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.
  • 这是 C++11 中非常易于使用的方法。
  • 我们可以使用标头中的 std::chrono::high_resolution_clock
  • 我们可以编写一个方法来以一种更易读的形式打印方法执行时间。

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:

例如,要找出 1 到 1 亿之间的所有质数,大约需要 1 分 40 秒。所以执行时间打印为:

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, ";
}

回答by Gillespie

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

我建议使用steady_clockwhich 保证是单调的,不像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

回答by arsdever

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.

就是这样。可以修改该类以满足您的要求。

回答by Carlo Wood

Since none of the provided answers are very accurate or give reproducable results I decided to add a link to my code that has sub-nanosecond precision and scientific statistics.

由于提供的答案都不是非常准确或可重现的结果,我决定添加一个链接到我的代码,该链接具有亚纳秒精度和科学统计数据。

Note that this will only work to measure code that takes a (very) short time to run (aka, a few clock cycles to a few thousand): if they run so long that they are likely to be interrupted by some -heh- interrupt, then it is clearly not possible to give a reproducable and accurate result; the consequence of which is that the measurement never finishes: namely, it continues to measure until it is statistically 99.9% sure it has the right answer which never happens on a machine that has other processes running when the code takes too long.

请注意,这仅适用于测量运行时间(非常)短(也就是几个时钟周期到几千个)的代码:如果它们运行时间太长以至于它们很可能被某些 -heh- 中断,那么显然不可能给出可重复且准确的结果;其结果是测量永远不会结束:也就是说,它会继续测量,直到在统计上 99.9% 确定它有正确的答案,当代码花费太长时间时,这永远不会发生在运行其他进程的机器上。

https://github.com/CarloWood/cwds/blob/master/benchmark.h#L40

https://github.com/CarloWood/cwds/blob/master/benchmark.h#L40

回答by Constantin Geier

If you want to safe time and lines of code you can make measuring the function execution time a one line macro:

如果您想要安全的时间和代码行,您可以将测量函数执行时间设为一行宏:

a)Implement a time measuring class as already suggested above ( here is my implementation for android):

a)实现上面已经建议的时间测量类(这是我的 android 实现):

class MeasureExecutionTime{
private:
    const std::chrono::steady_clock::time_point begin;
    const std::string caller;
public:
    MeasureExecutionTime(const std::string& caller):caller(caller),begin(std::chrono::steady_clock::now()){}
    ~MeasureExecutionTime(){
        const auto duration=std::chrono::steady_clock::now()-begin;
        LOGD("ExecutionTime")<<"For "<<caller<<" is "<<std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()<<"ms";
    }
};

b)Add a convenient macro that uses the current function name as TAG (using a macro here is important, else __FUNCTION__will evaluate to MeasureExecutionTimeinstead of the function you wanto to measure

b)添加一个使用当前函数名作为 TAG 的方便的宏(这里使用宏很重要,否则__FUNCTION__将评估为MeasureExecutionTime而不是您想要测量的函数

#ifndef MEASURE_FUNCTION_EXECUTION_TIME
#define MEASURE_FUNCTION_EXECUTION_TIME const MeasureExecutionTime measureExecutionTime(__FUNCTION__);
#endif

c)Write your macro at the begin of the function you want to measure. Example:

c)在要测量的函数的开头编写宏。例子:

 void DecodeMJPEGtoANativeWindowBuffer(uvc_frame_t* frame_mjpeg,const ANativeWindow_Buffer& nativeWindowBuffer){
        MEASURE_FUNCTION_EXECUTION_TIME
        // Do some time-critical stuff 
}

Which will result int the following output:

这将导致以下输出:

ExecutionTime: For DecodeMJPEGtoANativeWindowBuffer is 54ms

Note that this (as all other suggested solutions) will measure the time between when your function was called and when it returned, not neccesarily the time your CPU was executing the function. However, if you don't give the scheduler any change to suspend your running code by calling sleep() or similar there is no difference between.

请注意,这(与所有其他建议的解决方案一样)将测量调用函数和返回函数之间的时间,而不一定是 CPU 执行函数的时间。但是,如果您没有通过调用 sleep() 或类似方法对调度程序进行任何更改以暂停正在运行的代码,则两者之间没有区别。