测量计算时间

时间:2013-07-15 07:05:55

标签: c++ performance time chrono

如何正确测量计算时间?

变式1:

std::chrono::time_point<std::chrono::system_clock> start, end;  
    float elapsed = 0; 
    int N = 100;

    for(int i=0; i<N; ++i)
    {
        start = std::chrono::system_clock::now();
        func();//target function
        end = std::chrono::system_clock::now();
        elapsed += std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
    }

变式2:

start = std::chrono::system_clock::now();
for(int i=0; i<N; ++i)
    func();
end = std::chrono::system_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();

这些变体显示了截然不同的结果:我试图用std :: function替换虚函数:

struct Base
{
    virtual void f() = 0;
};

struct Der1 : public Base
{
    virtual void f() override 
    {
        int i=0; 
        for(int j=0; j<100; ++j)
            i += 2*j; 
    }
};

struct Der2 : public Base
{
    virtual void f() override 
    {
        int i=0; 
        for(int j=0; j<100; ++j)
            i += 3*j; 
    }
};

struct Base_
{
    Base_(std::function<void()> f_) : f(f_) {}
    std::function<void()> f;
};

struct Der1_ : public Base_
{
    Der1_() : Base_([]{
                       int i=0; 
                       for(int j=0; j<100; ++j)
                           i += 2*j;
                      }){}
};

struct Der2_ : public Base_
{
    Der2_() : Base_([]{
                       int i=0; 
                       for(int j=0; j<100; ++j)
                           i += 3*j;
                      }){}
};


void process1(std::vector<Base_*>& v)
{
    for(auto &elem : v)
        elem->f();
}

void process2(std::vector<Base*>& v)
{
    for(auto &elem : v)
        elem->f();
}

int main()
{

    std::vector<Base_*> vec1;
    vec1.push_back(new Der1_);
    vec1.push_back(new Der2_);
    vec1.push_back(new Der1_);
    vec1.push_back(new Der2_);

    std::vector<Base*> vec2;
    vec2.push_back(new Der1);
    vec2.push_back(new Der2);
    vec2.push_back(new Der1);
    vec2.push_back(new Der2);
    std::chrono::time_point<std::chrono::system_clock> start1, end1, start2, end2;   
    float elapsed1 = 0; 
    float elapsed2 = 0;

    int N = 6000;
    //Variant 2
    start1 = std::chrono::system_clock::now();
    for(int i=0; i<N; ++i)
        process1(vec1);
    end1 = std::chrono::system_clock::now();
    elapsed1 = std::chrono::duration_cast<std::chrono::microseconds>(end1-start1).count();

    start2 = std::chrono::system_clock::now();
    for(int i=0; i<N; ++i)
        process2(vec2);
    end2 = std::chrono::system_clock::now();
    elapsed2 = std::chrono::duration_cast<std::chrono::microseconds>(end2-start2).count();

    std::cout<<"virtual: "<<elapsed2<<"\npointer: "<<elapsed1;

    for(int i=0; i<vec1.size(); ++i)
        delete vec1[i];

    for(int i=0; i<vec2.size(); ++i)
        delete vec2[i];

    return 0;
}

我想了解std :: function上替换虚函数的性能是否有所提升。第二个变量表示2.5-3增益,而第一个变量表示性能下降。

4 个答案:

答案 0 :(得分:1)

您在时间上有所不同的最可能原因是分配到end所花费的时间,这将为您的计数器增加额外的时间。第二种方法是以计算循环中增加i所花费的时间为代价来避免这种情况,这可能会显着减少。

答案 1 :(得分:1)

在你测量的第一个:

N*(t_func+t_now)

在你测量的第二个:

N*t_func+t_now+t_loop_overhead

如果t_func很小并且t_now与那个相当......

阅读微观基准

答案 2 :(得分:0)

这真的取决于你测量的原因。第一种变体更好一点,只有100次迭代并不是那么多,当然这很大程度上取决于你的“功能”。但是不要以为每次调用都需要花费相同的时间,今天处理器,管道和其他组件都非常困难(而且很聪明)所以如果你需要真正准确的价值,最好找一些现有的测量测试框架,否则你需要自己处理缓存,预测等。

答案 3 :(得分:0)

我最近使用的代码std::sortqsort的时间安排(这里是std::sort的一个)

#include <algorithm>
#include <array>
#include <chrono>
#include <climits>
#include <iostream>
#include <random>

using std::chrono::duration_cast; 
using std::chrono::milliseconds; 
using std::chrono::high_resolution_clock;

std::default_random_engine generator; 
std::uniform_int_distribution<int> distribution{INT_MIN, INT_MAX};

constexpr auto size = 100000000; 
std::array<int, size> data;

int main() {
    auto start = high_resolution_clock::now();

    std::generate(std::begin(data), std::end(data), std::bind(distribution, generator));
    auto gen = high_resolution_clock::now();

    std::sort(std::begin(data), std::end(data));
    auto finish = high_resolution_clock::now();
    std::cout << 
        static_cast<double>(duration_cast<milliseconds>(finish - gen).count())/1000 <<
        "s for std::sort" << std::endl;
}

顺便说一句std:sort在我的电脑上快了近2倍。