如何在C++中获取代码执行时间?

3

我正在尝试对一段代码进行基准测试。这段代码是基于此代码编写的,其中有趣的部分基本上是这样的:

    auto t0 = std::chrono::high_resolution_clock::now();
    ...
    auto t1 = std::chrono::high_resolution_clock::now();
    std::cout << secs(t1-t0).count() << " s\n";

问题在于我使用的是共享机器,这导致我的结果不具有一致性。我真正需要的是一种秒表工具,它可以让我获得我的代码运行的时间,而不是墙上的时间。有哪些选项?如果涉及到系统特定调用,我使用的是Linux机器,但如果可能的话,我更愿意保持这段代码的可移植性。
我看过其他问题,例如这个这个,但它们似乎都提供墙上时间的解决方案。

3
你考虑过将代码隔离在 main 函数中,编译后通过 time 运行它吗?(不是衡量小段代码的最佳方法,但因为你使用秒,我认为这应该足够好了) - user123
我可以作为最后的手段这样做,但是我正在运行大量配置的大量测试,如果我不得不一直复制到主程序中,这个测试将需要更长时间,并且会变得更加繁琐。 - GBleaney
当你说“时间”时,你是指CPU时间吗?如果你要排除所有其他进程对CPU的使用,你是否希望时间包括I/O? - wallyk
在这种特定情况下,没有I/O时间。只是一些小的代码片段,用不同的算法和不同的输入测试无序映射的行为。 - GBleaney
我本来期望能看到一些关于gprof和gcc标志的提及,以使其正常工作。为什么不使用分析器来解决这个问题呢?可以参考类似于https://dev59.com/Unvaa4cB1Zd3GeqPATQw的问题。 - wojciii
4个回答

4

如果您的操作系统支持,您可以使用times API来获取类似于内置time命令的结果。

#include <sys/times.h>
...
struct tms  start, end;
times(&start);
//Do command
times(&end);
clock_t usr_time = end->tms_utime - start->tms_utime;
clock_t sys_time = end->tms_stime - start->tms_stime;

为了完整无误,您需要检查times的结果是否等于-1,并检查errno代码。

1
答案中有一个拼写错误。startend不是指针,所以计算应该是clock_t usr_time = end.tms_utime - start.tms_utime;clock_t sys_time = end.tms_stime - start.tms_stime; - joesdiner
另外,times() 返回的单位是根据 CLOCKS_PER_SEC 计算的经过的时钟周期数。因此,要获取经过的秒数,请执行 (double) usr_time / CLOCKS_PER_SEC(我想)。 - joesdiner
Kilian,请花点时间纠正上面的拼写错误。 - Alex M.M.

2

针对Linux系统

  #include <time.h>
  #include <stdio.h>

  double  theseSecs = 0.0;
  double  startSecs = 0.0;
  double  secs;
  double  CPUsecs = 0.0;
  double  CPUutilisation = 0.0;
  double  answer = 0;
  clock_t starts;

  void start_CPU_time()
  {      
      starts = clock();;
      return;
  }

  void end_CPU_time()
  {
      CPUsecs = (double)(clock() - starts)/(double)CLOCKS_PER_SEC;
      return;
  }    

  struct timespec tp1;
  void getSecs()
  {
     clock_gettime(CLOCK_REALTIME, &tp1);
     theseSecs =  tp1.tv_sec + tp1.tv_nsec / 1e9;           
     return;
  }

  void start_time()
  {
      getSecs();
      startSecs = theseSecs;
      return;
  }

  void end_time()
  {
      getSecs();
      secs    = theseSecs - startSecs;
      return;
  }    

  void calculate()
  {
      int i, j;
      for (i=1; i<100001; i++)
      {
          for (j=1; j<10001; j++)
          {
              answer = answer + (float)i / 100000000.0;
          }
      }
  }

 void main()
 {
     start_time();
     start_CPU_time();
     calculate();
     end_time();
     end_CPU_time();
     CPUutilisation = CPUsecs /  secs * 100.0;
     printf("\n Answer %10.1f, Elapsed Time %7.4f, CPU Time %7.4f, CPU Ut %3.0f%\n",
              answer, secs, CPUsecs, CPUutilisation);  
 }

1
我认为你需要使用 clock_gettime() 函数,同时使用以下时钟: CLOCK_PROCESS_CPUTIME_IDCLOCK_THREAD_CPUTIME_ID。它们可以显示进程/线程消耗的 CPU 时间。
CLOCK_PROCESS_CPUTIME_ID
  High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID
  Thread-specific CPU-time clock.

参考:

我认为merlin2011提供的建议在许多情况下是不可行的,因为隔离可能需要大量的工作,而添加两行带有clock_gettime()的代码则非常实用。 甚至可以将对clock_gettime()的调用封装在一个类中。


1
理想情况下,如您问题下的评论所提到的那样,您应该将要测量的代码片段隔离在main中,并只使用Unix命令行工具time,该工具报告usersystem时间。如果您无法这样做,请考虑查看time源代码,并可能使用相同的技术来对您的代码进行基准测试。

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