用C++测量函数的执行时间

Xar*_*ara 110 c++ optimization profiling

我想知道某个函数在我的C++程序中执行多长时间才能在Linux上执行.之后,我想进行速度比较.我看到了几个时间功能,但结果来自于boost.计时:

process_user_cpu_clock, captures user-CPU time spent by the current process
Run Code Online (Sandbox Code Playgroud)

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

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

PS:现在,我std::chrono::system_clock::now()用来在几秒钟内获得时间,但由于每次CPU负载不同,这给了我不同的结果.

Vic*_*tor 219

这是一个非常容易使用的C++ 11方法.您必须使用std::chrono::high_resolution_clock<chrono>头.

像这样使用它:

#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;
}
Run Code Online (Sandbox Code Playgroud)

这将测量功能的持续时间.

注意:并不要求始终获得相同的输出,因为计算机上运行的其他进程可能会减少或更多地使用计算机的CPU.正如您将要解决数学练习一样,您的思维可能会或多或少地集中在一起,因此您将在不同的时间解决这个问题.在人类的头脑中,我们可以记住数学问题的解决方案,但对于计算机来说,同样的过程总是会有新的东西,所以,正如我所说的,不需要总是得到相同的结果!

  • 这不应该是一个“steady_clock”吗?难道“high_resolution_clock”可能是一个非单调时钟吗? (5认同)
  • 不可以。您计算机的处理器可以少用或多用。`high_resolution_clock` 将为您提供函数运行所需的物理和实时时间。因此,在您的第一次运行中,您的 CPU 使用率低于下一次运行。“使用”是指其他应用程序工作使用 CPU。 (3认同)
  • 您能否在不使用“使用命名空间”的情况下发布代码。它使查看来自何处的内容变得更加容易。 (3认同)
  • 是的,如果您需要平均时间,这是获得它的好方法。运行三遍,并计算平均值。 (2认同)
  • 顺便说一句:我建议将“长长数字”更改为“易失性长长数字”。否则,优化器可能会优化掉该循环,并且您的运行时间将为零。 (2认同)

Jah*_*hid 13

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

#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);
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

norm: 15555
algo: 2976
Run Code Online (Sandbox Code Playgroud)

  • @MikeMB :好点,将其设为标题绝对是个坏主意。不过,最后,这只是一个示例,如果您有复杂的需求,则必须考虑标准实践并相应地调整代码。例如,在编写代码时,当它位于我现在正在工作的 cpp 文件中时,我会很方便,但是当需要将它移到其他地方时,我会采取一切必要步骤使其健壮,这样我就不必再看一遍。而且我认为,每个不是完全菜鸟的程序员都会在时间到期时进行广泛的思考。希望,我澄清了我的观点:D。 (3认同)
  • @ RestlessC0bra:它是实现定义的,`high_resolution_clock`可能是`system_clock`(挂钟),`steady_clock`或第三个独立时钟的别名.[详见此处](http://en.cppreference.com/w/cpp/chrono/high_resolution_clock).对于cpu时钟,可以使用`std :: clock` (2认同)
  • 两个宏和一个全局 typedef - 没有一个是安全的一个单一的击键 - 当然不是我称之为优雅的东西。另外传递一个函数对象并单独完美地转发参数有点矫枉过正(并且在重载函数的情况下甚至不方便),当您可以只要求将定时代码放入 lambda 时。但是,只要传递参数是可选的。 (2认同)
  • 这是违反有关宏命名的每条准则的理由吗?你不给它们加前缀,不使用大写字母,你选择一个很常见的名字,它很可能与一些本地符号发生冲突,最重要的是:你为什么要使用宏(而不是函数) )?当我们在做的时候:为什么你首先将持续时间返回为代表纳秒的双精度值?我们可能应该同意我们不同意。我最初的观点是:“这不是我所说的优雅代码”。 (2认同)
  • @Jahid:谢谢.在这种情况下,请考虑我的注释void和null. (2认同)

小智 9

找到函数执行时间的简单程序.

#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;
}
Run Code Online (Sandbox Code Playgroud)

  • 它非常不准确,只显示秒,但没有毫秒 (5认同)

v.c*_*lin 6

较旧的 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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这不是便携式的。它在 Linux 上测量处理器时间,在 Windows 上测量时钟时间。 (2认同)

Ran*_*til 6

#include <iostream>
#include <chrono>

void function()
{
    // code here;
}

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<<"/n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这对我有用。


笔记:

在不同的标准库实现中,它的high_resolution_clock实现并不一致,应该避免使用它。std::chrono::steady_clock它通常只是或的别名std::chrono::system_clock,但具体是哪一个取决于库或配置。当它是 a 时system_clock,它不是单调的(例如,时间可以倒退)。

例如,对于 gcc 来说,libstdc++它是system_clock,对于 MSVC 来说,它是steady_clock,而对于 clang 来说libc++,它取决于配置。

一般来说,应该只使用std::chrono::steady_clockorstd::chrono::system_clock直接代替std::chrono::high_resolution_clock: 用于steady_clock持续时间测量和system_clock挂钟时间。


Krz*_*eld 5

在Scott Meyers的书中,我找到了一个通用通用lambda表达式的示例,该示例可用于度量函数执行时间。(C ++ 14)

auto timeFuncInvocation = 
    [](auto&& func, auto&&... params) {
        // get time before function invocation
        const auto& start = 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 = high_resolution_clock::now();
        return stop - start;
     };
Run Code Online (Sandbox Code Playgroud)

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

实测时间:tm = t + tq + tn +至

哪里:

tm-测量(观察)的时间

t-实际的关注时间

tq-量化噪声相加的时间

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

至-开销时间(测量,循环,调用函数)

根据他在演讲的稍后部分所说的,您应该从大量执行中获取最少的结果。我鼓励您看一下他解释其原因的演讲。

谷歌还有一个很好的库-https: //github.com/google/benchmark。该库非常易于使用且功能强大。您可以在YouTube上查看钱德勒·卡鲁斯(Chandler Carruth)在实践中使用此库的一些讲座。例如CppCon 2017:钱德勒·卡鲁斯(Chandler Carruth)“走得更快”。

用法示例:

#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;
}
Run Code Online (Sandbox Code Playgroud)

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


归档时间:

查看次数:

148684 次

最近记录:

6 年,2 月 前