C/C++ 测量程序效率

Posted

技术标签:

【中文标题】C/C++ 测量程序效率【英文标题】:C/C++ Measuring Program Efficiency 【发布时间】:2016-03-08 02:14:33 【问题描述】:

我认为衡量我的程序效率的最佳方法是检查它运行所花费的时间,但是当我这样做时,我总是得到随机时间。

我正在使用 Roger Pate 在this 这个线程中显示的以下代码:

#include <ctime>

void func()

    using namespace std;
    clock_t begin = clock();

    //Function to measure here

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

我认为这是因为我有一些程序在后台运行。

我不想每次想重新检查我的功能的时间时都重新启动计算机,所以我的问题是:有没有更好的方法来衡量程序的效率?

IDE 是 Codeblocks,OS 是 Win7 64bit。

【问题讨论】:

这些可能是:1. 优化相关(可能您测量的代码已被优化掉......在这种情况下结果无效),2. 堆栈内存覆盖(您的结果无效) , 3. 上下文切换 / IO 相关问题(这些是原子操作,锁争用可能会极大地改变性能,因此结果是有效的,但会有所不同)等等...... 请发布一个实际显示的示例代码问题 您看到的典型时间是什么时候? @CaptainGiraffe 很确定它是CLOCKS_PER_SEC @Qix 哎呀。也不能编辑。 不要为此使用clock()。并记住正确拼写您的定义。后果可能是可怕的 使用clock_gettime()CLOCK_PROCESS_CPUTIME_ID 作为第一个参数。这仅返回在当前进程中花费的时间。开始时间调用一次,结束时间再调用一次。阅读手册页了解详细信息 【参考方案1】:

使用现代的数千兆赫兹 CPU 和高速 RAM I/O,除非您的代码运行时间超过几分钟左右,否则测量其执行时间不太可能产生任何有意义的结果。信噪比太高了。 I/O 中断和自然的抢先式多任务处理会产生过多的噪音,并淹没任何有意义的运行时指标。

尤其是在您的情况下,在 MS Windows 上,它不断启动各种后台 O/S 进程。重新启动计算机只会让事情变得更糟。 Windows O/S 通常会在重启后在接下来的几分钟内启动大量后台进程,这些进程会做一件事或另一件事。通常您需要等待 10-15 分钟,自然背景活动才会平静下来。

【讨论】:

【参考方案2】:

您需要测量用户时间。您可以在基于 UNIX 的系统 (https://en.wikipedia.org/wiki/Time_(Unix)) 中使用 time 命令完成此操作。我不确定微软是否有类似的东西。

用户时间是操作系统为您的进程测量的时间,因此它更准确地描述了您的程序运行了多长时间。它之所以能够做到这一点,是因为它是实体调度任务。

【讨论】:

【参考方案3】:

如果您担心 I/O 中断或抢占式多任务的噪音,请使用 GetThreadTimes 函数。

不过,我更关心clock() 函数的分辨率。在 Windows 上,我会使用 QueryPerformanceCounter 函数。

【讨论】:

【参考方案4】:

正如其他人已经指出的那样,使用 clock() 是一种不精确的时间测量方式,更好的方法是直接查询 TSC 计数器。 TSC 计数器非常准确,查询速度很快,并且能够测量单个指令的执行速度(受一些限制,如下所示)。

作为查询TSC的例子,见下面的代码;

#ifdef WIN32
#define uint64_t unsigned __int64
#endif 

static inline uint64_t rdtsc (void) 
  static struct 
    union 
      struct  uint32_t hi; uint32_t lo; ;
      uint64_t ret;
    ;
   tsc;
  asm volatile (
    "RDTSCP\n\t"
    "mov %%edx, %0\n\t"
    "mov %%eax, %1\n\t"
    : "=r" (tsc.lo), "=r" (tsc.hi)
    :: "%rax", "%rbx", "%rcx", "%rdx"
  );
  return tsc.ret;


// example: uint64_t start = rdtsc();
//          // Code goes here 
//          uint64_t end   = rdtsc();
//  printf("Code executed in %zd cycles\n", end-start);

使用 TSC 计数器的唯一警告是,TSC 仅在您正在使用的内核上准确,因此对于中断驱动的工作负载或长时间运行的进程,您最好查询系统时间计数器。很久以前,TSC 计数器也受处理器运行频率的影响。

TLDR;使用 TSC 测量短 sn-ps 代码的运行时间。

【讨论】:

【参考方案5】:

这是我在这里的第一次行动,所以请善待。

1) 如前所述,对于计时器的“较低”精度(在我们周围),QueryPerformanceCounter() 函数可以正常工作。此外,您应该询问此计时器使用 QueryPerformanceFrequency() 步进的频率。然后您可以确定从开始到结束的滴答声的差异并将其除以频率。

2)更高的分辨率(也提到)是直接读取您机器的TSC(TimeStampCounter)寄存器。命令 _rdtscp() 是在 windows (afaik) 下执行此操作的最佳方法。这里的困难是确定您的机器当前运行的频率。一种方法是测量用于 sleep(1000) 的滴答声,然后通过简单地将滴答声差作为以赫兹为单位的频率来确定频率。

1) 的示例代码

#include "Windows.h"

_LARGE_INTEGER Start,Stop,Frequency;

DWORD64 Time_taken;

int YourFunction ()

 Start = QueryPerformanceCounter();

 // Run Code to measure here

 Stop = QueryPerformanceCounter();

 Frequency = QueryPerformanceFrequency();

 Time_taken = (Stop.QuadPart-Start.QuadPart)/Frequency.QuadPart;
 

对于 2)

 #include <intrin.h> 
 #include <stdio.h>

 unsigned __int64 Start,Stop,Frequency,Time_taken;   // Variables for measurement
 unsigned int test;    // Pointer-buffer for Machine AUX register (non-relevant)

 int YourFunction(void) 
 
  // Measure current frequency
 Start = __rdtscp(&test);

 Sleep(1000);

 Stop = __rdtscp(&test);

 Frequency = Stop-Start;

 // Measure your function
 Start = __rdtscp(&test);

 // Code to measure

 Stop = __rdtscp(&test);

 Time_taken = (Stop-Start)/Frequency;
 

参考见 1) https://msdn.microsoft.com/de-de/library/windows/desktop/ms644904%28v=vs.85%29.aspx

和 2) https://msdn.microsoft.com/de-de/library/bb385235.aspx

我希望这能回答你的问题。

你好,萨沙

【讨论】:

【参考方案6】:

在分析器下运行您的代码,代码可以优化但带有调试信息。

对 VerySleepy 有很好的体验:http://www.codersnotes.com/sleepy/

【讨论】:

以上是关于C/C++ 测量程序效率的主要内容,如果未能解决你的问题,请参考以下文章

测量搜索次数

神级程序员教你如何在C语言中巧用正则表达式,简化处理,提高效率

保姆级C语言版高斯坐标正算反算倾情奉献!

保姆级C语言版高斯坐标正算反算倾情奉献!

C/C++:freecplus框架介绍

C/C++ Native 包大小测量