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

235

我想要找出在Linux上执行某个函数所需的时间。之后,我想进行速度比较。我看过几个计时函数,但最终选择了Boost库中的Chrono。

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

现在,我不确定如果我使用上面的函数,我是否只会得到CPU在该函数上花费的时间?

其次,我找不到使用上述功能的任何示例。有人可以帮忙告诉我如何使用上述函数吗?

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


2
对于Linux使用:clock_gettime。gcc定义其他时钟为:typedef system_clock steady_clock; typedef system_clock high_resolution_clock; 在Windows上,使用QueryPerformanceCounter - Brandon
这个问题不是重复的吗?与此问题相同,还是场景使解决方案不同? - northerner
我有两个函数实现,想要找出哪一个执行更好。 - northerner
2
非常重要:确保启用优化。未经优化的代码与正常优化的代码有不同的瓶颈,并且无法提供有意义的任何信息。C循环优化帮助(关闭编译器优化)。并且通常微基准测试有许多陷阱,特别是在CPU频率和页面故障方面首先未进行热身循环时可能会失败:性能评估的惯用方法?。还有此答案 - Peter Cordes
1
请参阅如何基准测试函数的性能?,了解Google Benchmark,它避免了自己编写微型基准测试时的许多陷阱。此外,还可以参考简单的for()循环基准测试对于任何循环绑定都需要相同的时间,以获取有关优化与基准测试循环交互以及如何处理它的更多信息。 - Peter Cordes
14个回答

1

由于提供的答案都不太准确,也无法给出可重复的结果,所以我决定添加一个链接到我的代码,该代码具有亚纳秒级精度和科学统计数据。

请注意,这仅适用于测量运行时间非常短(即几个时钟周期到几千个时钟周期)的代码:如果运行时间过长,可能会被某些中断打断,那么就不可能给出可重复和准确的结果;其后果是测量永远不会完成:换句话说,它会一直测量,直到在机器上发生其他进程运行时代码运行时间过长时,统计学上有99.9%的把握得到正确答案,但这种情况永远不会发生。

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


0
这是一个非常基础的计时器类,您可以根据自己的需求进行扩展。我想要一个简单明了的东西,可以在代码中干净地使用。您可以通过此链接在编码平台上进行测试:http://tpcg.io/nd47hFqr
class local_timer {
    private:
        std::chrono::_V2::system_clock::time_point start_time;
        std::chrono::_V2::system_clock::time_point stop_time;
        std::chrono::_V2::system_clock::time_point stop_time_temp;
        std::chrono::microseconds most_recent_duration_usec_chrono;
        double most_recent_duration_sec;
    public:

        local_timer() {

        };

        ~local_timer() {

        };

        void start() {
            this->start_time = std::chrono::high_resolution_clock::now();
        };

        void stop() {
            this->stop_time = std::chrono::high_resolution_clock::now();
        };

        double get_time_now() {
            this->stop_time_temp = std::chrono::high_resolution_clock::now();
            this->most_recent_duration_usec_chrono = std::chrono::duration_cast<std::chrono::microseconds>(stop_time_temp-start_time);
            this->most_recent_duration_sec = (long double)most_recent_duration_usec_chrono.count()/1000000;
            return this->most_recent_duration_sec;
        };

        double get_duration() {
            this->most_recent_duration_usec_chrono = std::chrono::duration_cast<std::chrono::microseconds>(stop_time-start_time);
            this->most_recent_duration_sec = (long double)most_recent_duration_usec_chrono.count()/1000000;
            return this->most_recent_duration_sec;
        };


};

这个的用途是

#include <iostream>
#include "timer.hpp" //if kept in an hpp file in the same folder, can also before your main function

int main() {
    //create two timers
    local_timer timer1 = local_timer();
    local_timer timer2 = local_timer();
    
    //set start time for timer1
    timer1.start();
    //wait 1 second
    while(timer1.get_time_now() < 1.0) {
    }
    //save time
    timer1.stop();
    //print time
    std::cout << timer1.get_duration() << " seconds, timer 1\n" << std::endl;

    timer2.start();
    for(long int i = 0; i < 100000000; i++) {
        //do something
        if(i%1000000 == 0) { 
            //return time since loop started
            std::cout << timer2.get_time_now() << " seconds, timer 2\n"<< std::endl;
        }
        
    }
    return 0;
}

0

C++11 清理过的 Jahid 回答的版本:

#include <chrono>
#include <thread>

void long_operation(int ms)
{
    /* Simulating a long, heavy operation. */
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

template<typename F, typename... Args>
double funcTime(F func, Args&&... args){
    std::chrono::high_resolution_clock::time_point t1 = 
        std::chrono::high_resolution_clock::now();
    func(std::forward<Args>(args)...);
    return std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::high_resolution_clock::now()-t1).count();
}

int main()
{
    std::cout<<"expect 150: "<<funcTime(long_operation,150)<<"\n";

    return 0;
}

0

你可以拥有一个简单的类,用于这种类型的测量。

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

唯一需要做的是在函数开头创建一个对象。
void veryLongExecutingFunction() {
    duration_calculator dc;
    for(int i = 0; i < 100000; ++i) std::cout << "Hello world" << std::endl;
}

int main() {
    veryLongExecutingFunction();
    return 0;
}

就是这样。该类可以根据您的要求进行修改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接