2012-11-20 44 views
3

我在開發板上使用Zynq芯片(ZC702), ,它具有667MHz的雙cortex-A9 MPCore並帶有一個Linux內核3.3 我想比較執行時間一個程序首先使用了clock_gettime,然後使用了ARM的協處理器 提供的計數器。計數器每增加一個處理器週期。 (在此基礎上question of stackoverflowthisARM性能計數器vs linux clock_gettime

我編譯程序用-O0標誌(因爲我不想做任何重新排序或優化)

我與性能計數器測量的時間是 583833498(週期)/ 666.666687兆赫= 875750.221(微秒)

在使用clock_gettime()(或者實時或單調或MONOTONIC_RAW) 測量的時間是: 731627.126(微秒) 這是微秒少..

任何人能解釋我爲什麼會這樣? 爲什麼會有差異?處理器不會進行時鐘縮放,如何通過clock_gettime獲得更少的執行時間?我在下面的示例代碼:


#define RUNS 50000000 
#define BENCHMARK(val) \ 
__asm__ __volatile__("mov r4, %1\n\t" \ 
       "mov r5, #0\n\t" \ 
       "1:\n\t"\ 
       "add r5,r5,r4\n\t"\ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "mov r4 ,r4 \n\t" \ 
       "sub r4,r4,#1\n\t" \ 
       "cmp r4, #0\n\t" \ 
       "bne 1b\n\t" \ 
       "mov %0 ,r5 \n\t" \ 
       :"=r" (val) \ 
       : "r" (RUNS) \ 
       : "r4","r5" \ 
     ); 
clock_gettime(CLOCK_MONOTONIC_RAW,&start); 
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(start_cycles)); 
for(index=0;index<5;index++) 
{ 
    BENCHMARK(i); 
} 
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(end_cycles)); 
clock_gettime(CLOCK_MONOTONIC_RAW,&stop); 

回答

3

我找到了解決方案。我將該平臺從3.3.0版本的Linux內核升級到3.5版本,其值與性能計數器的值相似。顯然3.3.0中的時鐘計數器的頻率假設高於(約400MHz),而不是CPU頻率的一半。可能是舊版本的移植錯誤。

+0

@auselen這不是我的錯,因爲時鐘問題,我只是使用板附帶的BSP。我認爲它會工作。 – akarapatis

0

POSIX的時鐘一定的精度,您可以與clock_getres得到內運行。檢查150,000us的差異是否在誤差範圍之內或之外。

在任何情況下,應該沒有關係,你應該多次重複你的基準,而不是5,但1000或更多。然後,您可以得到一個單一的基準測試中的時序像

((end + e1) - (start + e0))/1000,或

(end - start)/1000 + (e1 - e0)/1000

如果e1e0是誤差項,它們被一個很小的常數限制,那麼最大測量誤差將是abs (e1 - e0)/1000,隨着迴路數量的增加,這個誤差可以忽略不計。

+0

由於基準測試已經是一個循環,我不需要再運行該程序多次。我更新了上面粘貼的代碼。 正如@auselen提到的getres是1nsec – akarapatis