计算函数在C ++中使用多长时间的最佳方法是什么?

时间:2010-02-19 16:24:11

标签: c++ timing

在C#中,我会启动秒表类,以便对某些方法需要多长时间做一些快速和肮脏的时间。

C ++中的等价物是什么?是否内置了高精度计时器?

9 个答案:

答案 0 :(得分:4)

我之前已经为这种情况实现了一个计时器:我实际上最终得到了一个具有两种不同实现的类,一个用于Windows,另一个用于POSIX。

原因是Windows具有QueryPerformanceCounter()功能,可让您访问非常精确的时钟,这对于此类时序非常理想。

在POSIX上然而这不可用所以我只使用boost.datetime的类来存储开始和结束时间,然后从那些计算持续时间。它提供了一个“高分辨率”计时器,但分辨率未定义,因平台而异。

答案 1 :(得分:3)

我使用自己的Python time_it函数版本。该功能的优点在于它可以根据需要重复计算多次以获得有意义的结果。如果计算速度非常快,则会重复多次。最后,您将获得所有重复的平均时间。它不使用任何非标准功能:

#include <ctime>

double clock_diff_to_sec(long clock_diff)
{
    return double(clock_diff) / CLOCKS_PER_SEC;
}

template<class Proc>
double time_it(Proc proc, int N=1) // returns time in microseconds
{   
    std::clock_t const start = std::clock();
    for(int i = 0; i < N; ++i)
        proc();
    std::clock_t const end = std::clock(); 
    if(clock_diff_to_sec(end - start) < .2) 
        return time_it(proc, N * 5); 
    return clock_diff_to_sec(end - start) * (1e6 / N);
}

以下示例使用time_it函数来衡量不同STL容器的性能:

void dummy_op(int i)
{
    if(i == -1)
        std::cout << i << "\n";
}

template<class Container>
void test(Container const & c)
{
    std::for_each(c.begin(), c.end(), &dummy_op);
}

template<class OutIt>
void init(OutIt it)
{
    for(int i = 0; i < 1000; ++i)
        *it = i;
}

int main( int argc, char ** argv )
{
    {
        std::vector<int> c;
        init(std::back_inserter(c));
        std::cout << "vector: " 
                  << time_it(boost::bind(&test<std::vector<int> >, c)) << "\n";
    }      
    {
        std::list<int> c;
        init(std::back_inserter(c));
        std::cout << "list: "
                  << time_it(boost::bind(&test<std::list<int> >, c)) << "\n";
    }
    {
        std::deque<int> c;
        init(std::back_inserter(c));
        std::cout << "deque: " 
                  << time_it(boost::bind(&test<std::deque<int> >, c)) << "\n";
    }
    {
        std::set<int> c;
        init(std::inserter(c, c.begin()));
        std::cout << "set: " 
                  << time_it(boost::bind(&test<std::set<int> >, c)) << "\n";
    }
    {
        std::tr1::unordered_set<int> c;
        init(std::inserter(c, c.begin()));
        std::cout << "unordered_set: " 
           << time_it(boost::bind(&test<std::tr1::unordered_set<int> >, c)) << "\n";
    }    
}

如果有人好奇,这是我得到的输出(在发布模式下用VS2008编译):

  

vector:8.7168

     

列表:27.776

     

deque:91.52

     

设置:103.04

     

unordered_set:29.76

答案 2 :(得分:3)

我使用boost::timer来测量操作的持续时间。它提供了一种非常简单的方法来进行测量,同时与平台无关。这是一个例子:

boost::timer myTimer;
doOperation();
std::cout << myTimer.elapsed();

P.S。为了克服精度误差,测量几秒钟的操作会很棒。特别是当您尝试比较几种替代方案时。如果你想测量一些花费很少时间的东西,试试把它放到一个循环中。例如,运行操作1000次,然后将总时间除以1000。

答案 3 :(得分:2)

您可以使用ctime library以秒为单位获取时间。以毫秒为单位获取时间是特定于实现的。 Here is a discussion探索了一些方法。

另请参阅:How to measure time in milliseconds using ANSI C?

答案 4 :(得分:1)

高精度计时器是特定于平台的,因此未由C ++标准指定,但有可用的库。有关讨论,请参阅this question

答案 5 :(得分:1)

我谦卑地提交我自己的micro-benchmarking mini-library (on Github)。它非常简单 - 它拥有的唯一优势就是它已经拥有为Windows和Linux实现的高性能定时器代码,并抽象出令人烦恼的样板。

只需传入一个函数(或lambda),每次测试运行应调用的次数(默认值:1),以及测试运行次数(默认值:100)。返回最快的测试运行(以小数毫秒为单位):

// Example that times the compare-and-swap atomic operation from C++11
// Sample GCC command: g++ -std=c++11 -DNDEBUG -O3 -lrt main.cpp microbench/systemtime.cpp -o bench
#include "microbench/microbench.h"

#include <cstdio>
#include <atomic>

int main()
{
    std::atomic<int> x(0);
    int y = 0;

    printf("CAS takes %.4fms to execute 100000 iterations\n",
        moodycamel::microbench(
            [&]() { x.compare_exchange_strong(y, 0); },  /* function to benchmark */
            100000, /* iterations per test run */
            100 /* test runs */
        )
    );

    // Result: Clocks in at 1.2ms (12ns per CAS operation) in my environment

    return 0;
}

答案 6 :(得分:0)

这可能是依赖于操作系统的问题,而不是语言问题。

如果你在Windows上,那么你可以通过GetTickCount()或GetTickCount64()访问毫秒 10到16毫秒的计时器。只需在开始时调用一次,在结束时调用一次,然后减去。

如果我没记错的话,这就是我之前使用过的。链接页面还有其他选项。

答案 7 :(得分:0)

#include <time.h>

clock_t start, end;
start = clock();
//Do stuff
end = clock();

printf("Took: %f\n", (float)((end - start) / (float)CLOCKS_PER_SEC));

答案 8 :(得分:0)

您可以找到有用的this课程。

使用RAII习语,它会在调用析构函数时打印构造中给出的文本,用正确的值填充已用时间占位符。

使用示例:

int main()
{
   trace_elapsed_time t("Elapsed time: %ts.\n");
   usleep(1.005 * 1e6);
} 

输出:

Elapsed time: 1.00509s.