2010-05-12 73 views
0

編輯:編寫這篇長篇文章解釋每一個小細節後我才發現我的問題......如果有人能給我一個很好的答案,以及如何在幾秒鐘內獲得執行時間(使用帶有5位小數的浮點數),我會將其標記爲已接受。提示:問題在於我如何解釋clock_getttime()手冊頁。測量代碼塊執行時間N倍的問題

嗨,

比方說,我有一個名爲myOperation,我需要衡量的執行時間的功能。爲了衡量它,我使用了clock_gettime(),因爲在其中一條評論中推薦使用here

我的老師建議我們測量它N次所以我們可以得到最終報告的平均值,標準偏差和中位數。他還建議我們執行myOperationM次而不是一次。如果myOperation是一個非常快速的操作,那麼測量它可以讓我們瞭解所需的「實時」;導致正在使用的時鐘可能不具有測量此類操作所需的精度。所以,執行myOperation只有一次或M次真的取決於操作本身是否需要足夠長的時間來保證我們正在使用的時鐘精度。

我無法處理那個M次執行。增加M減少(很多)最終的平均值。這對我沒有意義。就像這樣,從A點到B點平均需要3到5秒鐘的時間。但是,你從A點到B點再返回到A點5次(這使它成爲10次,因此A到B和B一樣到A),然後你測量它。比你除以10,你得到的平均值應該是從A點到B點的平均值,這是3到5秒。

這是我想要我的代碼做的,但它不工作。如果我不斷增加從A到B和從A到A的次數,每次平均值會越來越低,這對我來說是沒有意義的。

理論已經足夠了,這裏是我的代碼:

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

#define MEASUREMENTS 1 
#define OPERATIONS 1 

typedef struct timespec TimeClock; 

TimeClock diffTimeClock(TimeClock start, TimeClock end) { 
    TimeClock aux; 

    if((end.tv_nsec - start.tv_nsec) < 0) { 
     aux.tv_sec = end.tv_sec - start.tv_sec - 1; 
     aux.tv_nsec = 1E9 + end.tv_nsec - start.tv_nsec; 
    } else { 
     aux.tv_sec = end.tv_sec - start.tv_sec; 
     aux.tv_nsec = end.tv_nsec - start.tv_nsec; 
    } 

    return aux; 
} 

int main(void) { 
    TimeClock sTime, eTime, dTime; 
    int i, j; 

    for(i = 0; i < MEASUREMENTS; i++) { 
     printf(" » MEASURE %02d\n", i+1); 

     clock_gettime(CLOCK_REALTIME, &sTime); 

     for(j = 0; j < OPERATIONS; j++) { 
      myOperation(); 
     } 

     clock_gettime(CLOCK_REALTIME, &eTime); 

     dTime = diffTimeClock(sTime, eTime); 

     printf(" - NSEC (TOTAL): %ld\n", dTime.tv_nsec); 
     printf(" - NSEC (OP): %ld\n\n", dTime.tv_nsec/OPERATIONS); 
    } 

    return 0; 
} 

注:以上diffTimeClock功能是從這個blog post。我用myOperation()取代了我的實際操作,因爲發佈我的真實功能沒有任何意義,因爲我必須發佈很長的代碼塊,如果您願意,可以使用任何喜歡的代碼輕鬆編碼myOperation()

正如你所看到的,OPERATIONS = 1和結果是:

» MEASURE 01 
    - NSEC (TOTAL): 27456580 
    - NSEC (OP): 27456580 

OPERATIONS = 100結果是:

» MEASURE 01 
    - NSEC (TOTAL): 218929736 
    - NSEC (OP): 2189297 

OPERATIONS = 1000結果是:

» MEASURE 01 
    - NSEC (TOTAL): 862834890 
    - NSEC (OP): 862834 

對於OPERATIONS = 10000結果是:

» MEASURE 01 
    - NSEC (TOTAL): 574133641 
    - NSEC (OP): 57413 

現在,我不是一個數學知識,實際上遠非如此,但這對我來說沒有任何意義。我已經和一個和我在一起的朋友談過這個問題,他也無法理解這些差異。我不明白爲什麼當我增加OPERATIONS時價值越來越低。無論執行多少次,操作本身應該是同一時間(平均而言,不是完全相同的時間)。

你能告訴我,實際上依賴於操作本身,正在讀取的數據和一些數據可能已經在緩存和喇嘛喇嘛,但我不認爲這是問題。在我的情況下,myOperation正在讀5000行文字從CSV文件,通過;分離值和插入這些值到數據結構中。對於每次迭代,我都銷燬數據結構並重新初始化它。

現在我想到了,我也認爲測量時間有一個問題,clock_gettime(),也許我沒有正確使用它。我的意思是,看最後一個例子,其中OPERATIONS = 10000。總共耗時574133641ns,大約爲0.5s;這是不可能的,花了幾分鐘,因爲我無法忍受看着屏幕等待,並去吃東西。

+0

由於您正在測量兩個事件之間的掛鐘時間,因此應該使用'CLOCK_MONOTONIC'而不是'CLOCK_REALTIME' - 如果系統時間更改,則前者不會受到影響,後者可以跳轉。 – caf 2010-05-12 22:37:42

+0

是的,但爲什麼系統時間會發生變化,而不需要我手動執行? – 2010-05-12 22:50:59

+0

因爲像'ntpd'這樣的系統守護進程改變了它? (或共享系統上的系統管理員?) – caf 2010-05-12 23:30:01

回答

1

你只需要改變你的diffTimeClock()函數返回秒差的數量,作爲double

double diffTimeClock(TimeClock start, TimeClock end) { 
    double diff; 

    diff = (end.tv_nsec - start.tv_nsec)/1E9; 
    diff += (end.tv_sec - start.tv_sec); 

    return diff; 
} 

,並在主程序變化dTimedouble,並用printfs適合:

printf(" - SEC (TOTAL): %f\n", dTime); 
printf(" - SEC (OP): %f\n\n", dTime/OPERATIONS); 
0

我通常使用的時間()函數這一點。它顯示了掛鐘的時間,但這真的是我最後關心的。性能測試

有一個問題是操作系統可以緩存文件系統相關的操作。所以第二次(及以後)的運行可能比第一次運行快得多。您通常需要測試可能的操作並對結果進行平均,以便對所做更改的結果有良好的感受。有這麼多的變量可以幫助你濾除噪音。

1

貌似時鐘進度類型有兩個字段,一個用於秒,一個用於納秒。將nanosec字段與操作次數分開是沒有意義的。你需要劃分總時間。

1

如果您使用的是POSIX系統中存在的gettimeofday()函數,你可以使用這樣的事情來獲得以微秒當前時間:

long long timeInMicroseconds(void) { 
    struct timeval tv; 

    gettimeofday(&tv,NULL); 
    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec; 
} 

之所以這樣,是非常方便的是,爲了計算你的函數多少了,你需要完成這一點:

long long start = timeInMicroseconds(); 
... do your task N times ... 
printf("Total microseconds: %lld", timeInMicroseconds()-start); 

所以你不必處理兩個整數,一個用秒和一個用微秒。增加和減少時間將以一種明顯的方式起作用。

+0

我不知道你是否意識到,但你只是做了你所說的我不必,「處理兩個整數」。看看return(((long long)tv.tv_sec)* 1000000)+ tv.tv_usec;'。我做了類似的事情來解決我原來的問題,我有納米精度,而不是微觀。 – 2010-05-12 22:15:31

+0

是的我的意思是,當你需要減去一次到另一個時間時,不要明確地處理兩個整數,否則很難檢查納秒的溢出(然後減去1秒並將1000000納秒添加到原始結果)。 取而代之的是,你以這樣的方式,並且我建議它,你只處理創建時間的函數中的兩個整數(以微秒爲單位)。所有其他的代碼將只使用簡單的單個數字。 – antirez 2010-05-13 09:12:32

+0

我已經在'diffTimeClock()'中已經這麼做了,所以我不太瞭解你的帖子... – 2010-05-13 11:09:45