2016-03-08 50 views
0

我認爲測量程序效率的最好方法是通過檢查它運行的時間,但是當我這樣做的時候,我總是得到隨機時間。C/C++測量程序效率

我用下面的代碼爲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

這些可能是:1,優化相關的(也許你測量代碼得到優化掉......在這種情況下,結果是無效的),2組內存覆蓋(您的結果無效),3.上下文切換/ IO相關問題(這些是原子操作和鎖爭用可能會轉移性能相當多,所以結果是有效的,但各不相同)以及更多... **請發佈一個示例代碼,實際顯示問題**。 – Myst

+0

你看到什麼是典型的時間? – user3386109

+0

@CaptainGiraffe很確定它是'CLOCKS_PER_SEC'。 – Qix

回答

3

隨着現代,多千兆赫的CPU和高速RAM I/O,除非你的代碼的時間超過幾分鐘,左右,運行,測量其執行時間不太可能產生任何有意義的結果。信噪比太高。 I/O中斷,自然搶先式多任務會產生太多噪音,並淹沒任何有意義的運行時指標。

尤其是,在你的情況下,在MS Windows上,它不斷啓動各種後臺操作系統進程。重新啓動電腦只會讓事情變得更糟。 Windows O/S在重啓之後通常會在接下來的幾分鐘內啓動一個巨大的後臺進程,這些進程會做某件事或另一件事。通常,在自然背景活動平靜之前,您需要等待10-15分鐘。

1

您需要測量用戶時間。您可以在基於UNIX的系統(https://en.wikipedia.org/wiki/Time_(Unix))中使用time命令完成此操作。我不確定微軟是否有類似的東西。

用戶時間是OS爲您的過程測量的時間,因此它更準確地描述了程序運行的時間。它能夠做到這一點,因爲它是實體調度任務。

0

如果您擔心I/O中斷或搶先式多任務的噪音,請使用GetThreadTimes函數。

但是,我會更關心clock()函數的分辨率。在Windows上,我會使用QueryPerformanceCounter函數。

0

正如其他人已經指出的,使用clock()是一種不精確的測量時間的方法,更好的方法是直接查詢TSC計數器。查詢計數器的一種方法是使用如下所示的函數;

在大多數情況下(即您的代碼沒有等待I/O,並且大部分駐留在內存中),即使負載較重的系統也應該有非常一致的結果。注: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(); 
0

這是我第一次在這裏行動,所以請親切。

1)如前所述,對於定時器(我們周圍)的「較低」精度,函數QueryPerformanceCounter()可以正常工作。此外,您應該詢問此計時器使用QueryPerformanceFrequency()步進的頻率。然後,您可以確定從開始到結束的滴答差異,並將其除以頻率。

2)較高的分辨率(也提到)是直接讀取機器的TSC(TimeStampCounter)寄存器。命令_rdtscp()是在Windows(afaik)下執行此操作的最佳方式。難點在於確定您的機器當前運行的頻率。一種方法是測量用於睡眠的刻度(1000),然後通過簡單地將刻度差作爲以Hz爲單位的頻率來確定頻率。

示例代碼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

我希望這回答了你的問題。

問候薩沙