我试图使用时间()来测量我的程序的各个点。

我不明白的是为什么前后的值是一样的?我知道这不是分析我的程序的最佳方式,我只是想看看需要多长时间。

printf("**MyProgram::before time= %ld\n", time(NULL));

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ld\n", time(NULL));

我试过:

struct timeval diff, startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

timersub(&endTV, &startTV, &diff);

printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);

我如何读取**时间花费= 0 26339的结果?这是否意味着26339纳秒= 26.3毫秒?

**时间= 4 45025,这是否意味着4秒25毫秒?


当前回答

#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;

void f1()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f2()
{
  timespec ts1,ts2;
  clock_gettime(CLOCK_REALTIME, &ts1);
  clock_gettime(CLOCK_REALTIME, &ts2);
  double dif = double( ts2.tv_nsec - ts1.tv_nsec );
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f3()
{
  struct timeval t1,t0;
  gettimeofday(&t0, 0);
  gettimeofday(&t1, 0);
  double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
  high_resolution_clock::time_point t1 , t2;
  double diff = 0;
  t1 = high_resolution_clock::now() ;
  for(int i = 1; i <= 10 ; i++)
  {
    t2 = high_resolution_clock::now() ;
    diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
    t1 = t2;
  }
  printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f5()
{
  timespec ts1,ts2;
  double diff = 0;
  clock_gettime(CLOCK_REALTIME, &ts1);
  for(int i = 1; i <= 10 ; i++)
  {
    clock_gettime(CLOCK_REALTIME, &ts2);
    diff+= double( ts2.tv_nsec - ts1.tv_nsec );
    ts1 = ts2;
  }
  printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f6()
{
  struct timeval t1,t2;
  double diff = 0;
  gettimeofday(&t1, 0);
  for(int i = 1; i <= 10 ; i++)
  {
    gettimeofday(&t2, 0);
    diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
    t1 = t2;
  }
  printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

int main()
{
  //  f1();
  //  f2();
  //  f3();
  f6();
  f4();
  f5();
  return 0;
}

其他回答

#include <ctime>

void f() {
  using namespace std;
  clock_t begin = clock();

  code_to_time();

  clock_t end = clock();
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

time()函数只精确到一秒内,但是一秒内有CLOCKS_PER_SEC“时钟”。这是一种简单、便携的测量方法,尽管它过于简化了。

我需要测量库中各个函数的执行时间。我不希望每个函数的每次调用都用一个时间度量函数来包装,因为这样做很难看,而且会加深调用堆栈。我也不想把定时器代码放在每个函数的顶部和底部,因为当函数可能提前退出或抛出异常时,这会造成混乱。所以我最终做了一个计时器,用它自己的生命周期来测量时间。

通过这种方式,我可以测量一个代码块的wallall时间,方法是在有问题的代码块(函数或任何作用域)的开头实例化这些对象之一,然后允许实例析构函数测量实例超出作用域时自构造以来所花费的时间。你可以在这里找到完整的例子,但结构体非常简单:

template <typename clock_t = std::chrono::steady_clock>
struct scoped_timer {
  using duration_t = typename clock_t::duration;
  const std::function<void(const duration_t&)> callback;
  const std::chrono::time_point<clock_t> start;

  scoped_timer(const std::function<void(const duration_t&)>& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  scoped_timer(std::function<void(const duration_t&)>&& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  ~scoped_timer() { callback(clock_t::now() - start); }
};

当函数超出作用域时,该结构体将回调所提供的函数,这样您就可以对计时信息做一些事情(打印它或存储它或其他什么)。如果你需要做一些更复杂的事情,你甚至可以使用std::bind和std::占位符来回调函数。

下面是一个快速使用它的例子:

void test(bool should_throw) {
  scoped_timer<> t([](const scoped_timer<>::duration_t& elapsed) {
    auto e = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(elapsed).count();
    std::cout << "took " << e << "ms" << std::endl;
  });

  std::this_thread::sleep_for(std::chrono::seconds(1));

  if (should_throw)
    throw nullptr;

  std::this_thread::sleep_for(std::chrono::seconds(1));
}

如果您希望更加谨慎,还可以使用new和delete显式地启动和停止计时器,而不依赖于作用域。

#include <ctime>
#include <functional>

using namespace std;

void f() {
  clock_t begin = clock();

  // ...code to measure time...

  clock_t end = clock();

  function<double(double, double)> convtime = [](clock_t begin, clock_t end)
  {
     return double(end - begin) / CLOCKS_PER_SEC;
  };

  printf("Elapsed time: %.2g sec\n", convtime(begin, end));

}

类似的例子,一个可用在这里,只有额外的转换功能+打印出来。

回答OP的三个具体问题。

“我不明白的是,为什么之前和之后的数值是一样的?”

第一个问题和示例代码显示time()的分辨率为1秒,因此答案必须是两个函数在1秒内执行。但如果两个计时器标记跨越了一秒的边界,它偶尔会(显然是不合逻辑的)通知1秒。

下一个示例使用gettimeofday()填充该结构体

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

第二个问题是:“我如何读取**时间= 0 26339的结果?这是否意味着26339纳秒= 26.3毫秒?”

我的第二个答案是所花费的时间是0秒和26339微秒,即0.026339秒,这证实了第一个示例在不到1秒的时间内执行。

第三个问题是:“**时间= 4 45025,这是否意味着4秒25毫秒?”

我的第三个答案是所用的时间是4秒和45025微秒,即4.045025秒,这表明OP改变了他之前计时的两个函数执行的任务。

0 -

使用delta函数计算时间差:

auto start = std::chrono::steady_clock::now();
std::cout << "Elapsed(ms)=" << since(start).count() << std::endl;

Since接受任何时间点并产生任何持续时间(毫秒为默认值)。它的定义为:

template <
    class result_t   = std::chrono::milliseconds,
    class clock_t    = std::chrono::steady_clock,
    class duration_t = std::chrono::milliseconds
>
auto since(std::chrono::time_point<clock_t, duration_t> const& start)
{
    return std::chrono::duration_cast<result_t>(clock_t::now() - start);
}

Demo

1 - 小时

使用基于std::chrono的计时器:

Timer clock; // Timer<milliseconds, steady_clock>

clock.tick();
/* code you want to measure */
clock.tock();

cout << "Run time = " << clock.duration().count() << " ms\n";

Demo

定时器定义为:

template <class DT = std::chrono::milliseconds,
          class ClockT = std::chrono::steady_clock>
class Timer
{
    using timep_t = typename ClockT::time_point;
    timep_t _start = ClockT::now(), _end = {};

public:
    void tick() { 
        _end = timep_t{}; 
        _start = ClockT::now(); 
    }
    
    void tock() { _end = ClockT::now(); }
    
    template <class T = DT> 
    auto duration() const { 
        gsl_Expects(_end != timep_t{} && "toc before reporting"); 
        return std::chrono::duration_cast<T>(_end - _start); 
    }
};

正如Howard Hinnant指出的那样,我们使用一个持续时间来保持在chrono类型系统中,并执行诸如平均或比较之类的操作(例如,这里这意味着使用std::chrono::milliseconds)。当我们只是执行IO时,我们使用持续时间的count()或tick(例如这里的毫秒数)。

2 -仪器仪表

任何可调用对象(函数、函数对象、lambda等)都可以用于基准测试。假设你有一个函数F调用参数arg1,arg2,这个技术会导致:

cout << "F runtime=" << measure<>::duration(F, arg1, arg2).count() << "ms";

Demo

度量定义为:

template <class TimeT  = std::chrono::milliseconds
          class ClockT = std::chrono::steady_clock>
struct measure
{
    template<class F, class ...Args>
    static auto duration(F&& func, Args&&... args)
    {
        auto start = ClockT::now();
        std::invoke(std::forward<F>(func), std::forward<Args>(args)...);
        return std::chrono::duration_cast<TimeT>(ClockT::now()-start);
    }
};

正如在(1)中提到的,使用持续时间w/o .count()对于那些希望在I/ o之前对一堆持续时间进行后处理的客户端是最有用的,例如average:

auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2;
std::cout << "Average run time " << avg.count() << " ms\n";

+这就是为什么被转发的函数调用。

完整的代码可以在这里找到

我试图建立一个基于chrono的基准测试框架的尝试记录在这里

+ Old演示