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++ 测量程序效率的主要内容,如果未能解决你的问题,请参考以下文章