使用C ++ 14 Lambda测量任意函数的执行时间 [英] Measure execution time of arbitrary functions with C++14 lambda

查看:81
本文介绍了使用C ++ 14 Lambda测量任意函数的执行时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

斯科特·迈耶(Scott Meyer)的书有效的现代C ++的第24条让我很兴奋。他提到可以编写C ++ 14 lambda来记录任意函数调用所花费的时间。

I have been excited by item 24 of Scott Meyer's book "Effective Modern C++". He mentions the possibility to write a C++14 lambda to record the time taken in an arbitrary function invocation.

我还处于学习C ++ 14的初期。特征。我的尝试(Main.cpp)看起来像这样,用于测量成员函数调用的时间:

I am still in an early of learning C++14 features. My attempt (Main.cpp) looks like this for measuring the time of a member function call:

#include <chrono>
#include <iostream>

auto measure = [](auto&& function, auto&&... parameters) -> decltype(function)
{
    const std::chrono::steady_clock::time_point startTimePoint =
    std::chrono::steady_clock::now();

    const auto returnValue = std::forward<decltype(function)>(function)(
            std::forward<decltype(parameters)>(parameters)...);

    const std::chrono::steady_clock::time_point stopTimePoint =
    std::chrono::steady_clock::now();

    const std::chrono::duration<double> timeSpan = std::chrono::duration_cast<
    std::chrono::duration<double>>(stopTimePoint - startTimePoint);

    std::cout << "Computation took " << timeSpan.count()
    << " seconds." << std::endl;

    return returnValue;
};

class Test
{
public:

    int computation(double dummy)
    {
        std::cout << "Received " << dummy << ". Computing..." << std::endl;

        return 123;
    }
};

int main(int, char**)
{
    Test instance;

    using Function = int (Test::*)(double);
    Function function = instance.computation;

    int result = measure(function, 1.0);

    std::cout << "Result: " << result << std::endl;

    return 0;
}

我收到以下编译错误:

..\src\Main.cpp: In function 'int main(int, char**)':
..\src\Main.cpp:43:36: error: cannot convert 'int (Test::*)(double)' to 'int' in initialization
    int result = measure(function, 1.0);
                                                                        ^
..\src\Main.cpp: In instantiation of '<lambda(auto:1&&, auto:2&& ...)> [with auto:1 = int (Test::*&)(double); auto:2 = {double}; decltype (function) = int (Test::*&)(double)]':
..\src\Main.cpp:43:36:   required from here
..\src\Main.cpp:9:69: error: must use '.*' or '->*' to call pointer-to-member function in 'std::forward<int (Test::*&)(double)>((* & function)) (...)', e.g. '(... ->* std::forward<int (Test::*&)(double)>((* & function))) (...)'
    const auto returnValue = std::forward<decltype(function)>(function)(
                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        std::forward<decltype(parameters)>(parameters)...);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                

显然我做错了,但我不知道该怎么做对。有谁能够帮助我?非常感谢!

Obviously I am doing it wrong, but I could not figure out how to do it right. Can anybody help me? Thank you very much!

推荐答案

有两种方法可以完成此任务。

There are two ways to approach this task.


  1. 接受一个函数(或一个函数对象),返回一个修改后的函数,该函数执行的功能与原始函数相同,并计算时间。返回的对象类型不能与接受的参数类型相同。它必须是lambda(或自定义类类型,但lambda更简单)。当调用 returned 对象时,将执行实际测量。用法示例示例:

  1. Accept a function (or a function object), return a modified function that does the same thing the original function does, plus measures the time. The returned object type cannot be the same as the accepted parameter type. It must be a lambda (or a custom class type, but the lambda is simpler). The actual measurement is performed when the returned object is invoked. Example usage syntax:

result = measure(foo)(param1, param2);  // variant 1
auto measured_foo = measure(foo);
result = measured_foo(param1, param2);  // variant 2


  • 接受一个函数(或一个函数对象) and 它的参数,调用它并执行测量。返回类型是原始函数的类型。使用语法示例:

  • Accept a function (or a function object) and its parameters, call it and perform the measurement. The return type is that of the original function. Example usage syntax:

    result = measure(foo, param1, param2);
    


  • 您的措施最接近第二个变体,唯一错误的地方是声明。这是正确的:

    Your measure is closest to the second variant, the only thing that is wrong with it is the declaration. This is the correct one:

    auto measure = [](auto&& function, auto&&... parameters) -> decltype(auto)
    

    确切地说,这不是唯一的错误。如果被测函数返回参考,则返回类型将是错误的。要解决此问题,请替换

    To be precise, this is not the only wrong thing. If the measured function returns a reference, the return type will be wrong. To fix this, replace

    const auto returnValue = ...
    

    with

    decltype(auto) returnValue = ...
    

    在lambda体内

    程序有其他问题(但不是 measure 本身),是您尝试使用成员函数的方式。

    The other thing that is wrong with your program (but not the measure itself) is the way you are trying to use a member function.

    Function function = instance.computation;
    

    这是行不通的。使用lambda或 std :: bind 创建绑定的成员函数。关于在stackoverflow上执行此操作的正确方法的疑问不计其数。

    This just doesn't work. Use a lambda or std::bind to create a bound member function. There's about a zillion questions (and great answers) about the correct way to do it on stackoverflow.

    实时演示(可通过引用返回)。

    Live demo (with return by reference working).

    如果您想要第一种创建测量函数的方法,请按以下步骤操作:

    If you want the first way of creating a measured function, here's how:

    auto measure = [](auto&& function) -> decltype(auto)
    {
        return [=](auto&&... parameters) mutable -> decltype(auto) {
    
            const std::chrono::steady_clock::time_point startTimePoint = 
                std::chrono::steady_clock::now();
    
            decltype(auto) result = function(std::forward<decltype(parameters)>(parameters)...);
    
            const std::chrono::steady_clock::time_point stopTimePoint =
                std::chrono::steady_clock::now();
    
            const std::chrono::duration<double> timeSpan = std::chrono::duration_cast<
            std::chrono::duration<double>>(stopTimePoint - startTimePoint);
    
            std::cout << "Computation took " << timeSpan.count()
                    << " seconds." << std::endl;
    
            return result;
        };
    };
    

    现场演示(参考返回)。

    请特别注意 decltype(auto)。在第二个版本中也是可变

    Pay special attention to religious use of decltype(auto). Also mutable in the second version.

    这篇关于使用C ++ 14 Lambda测量任意函数的执行时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆