2013-11-27 66 views
0

我在編寫代碼來測量內核中代碼序列的時間消耗,方法是將代碼作爲模塊加載到內核中。我使用普通的rdtsc例程來計算時間。有趣的是,在用戶模式下運行的類似例程的結果爲正常值,而在內核模式下運行時結果始終爲0,無論我在time_count函數中添加了多少行代碼。我在這裏使用的計算是一個共同的矩陣乘積函數,並且通過增加矩陣維數,運行週期應該迅速增加。任何人都可以指出我的代碼中的錯誤,爲什麼我無法測量內核中的循環數?在內核中使用rdtsc測量執行時間

#include <linux/init.h> 
#include <linux/module.h> 

int matrix_product(){ 
    int array1[500][500], array2[500][500], array3[500][500]; 
    int i, j, k, sum; 

    for(i = 0; i < 50000; i++){ 
    for(j = 0; j < 50000; j++){ 
     array1[i][j] = 5*i + j; 
     array2[i][j] = 5*i + j; 
    } 
    } 

    for(i = 0; i < 50000; i++){ 
    for(j = 0; j < 50000; j++){ 
     for(k = 0; k < 50000; k++) 
    sum += array1[i][k]*array2[k][j]; 
     array3[i][j] = sum; 
     sum = 0; 
    } 
    } 
    return 0; 
} 

static __inline__ unsigned long long rdtsc(void) 
{ 
unsigned long hi, lo; 
__asm__ __volatile__ ("xorl %%eax,%%eax\ncpuid" ::: "%rax", "%rbx", "%rcx", "%rdx"); 
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 
return ((unsigned long long)lo) | (((unsigned long long)hi)<<32) ; 
} 

static int my_init(void) 
{ 
    unsigned long str, end, curr, best, tsc, best_curr; 
    long i, t; 

#define time_count(codes) for(i=0; i<120000; i++){str=rdtsc(); codes; end=rdtsc(); curr=end-str; if(curr<best)best=curr;} 

best = ~0; 
time_count(); 
tsc = best; 

best = ~0; 
time_count(matrix_product()); 
best_curr = best; 
printk("<0>matrix product: %lu ticks\n", best_curr-tsc); 

return 0; 
} 

static void my_exit(void){ 
    return; 
} 

module_init(my_init); 
module_exit(my_exit);` 

任何幫助表示讚賞!謝謝。

+1

問題是什麼? – wildplasser

+0

我想知道如何更改此代碼,以便正確測量內核中的執行週期數。 – lordofire

+0

我明白了。 BTW:rdtsc是一個_terrible_指令:它需要消耗指令流水線(IIRC你也需要獲取CPUID,以獲得可靠的結果),甚至可能是TLB,有時甚至會迫使內核重新同步它們的時鐘。很可能是內核以某種方式禁用了這條指令,我不知道如何,但是對於用戶空間的執行,指令可以以某種方式被禁用,也許對於ring-0也是如此。 – wildplasser

回答

1

rdtsc不保證在每個CPU上可用,或以恆定速率運行,或在不同核心之間保持一致。

除非您對時間戳有特殊要求,否則您應該使用可靠和便攜的功能,如getrawmonotonic

如果你真的想直接使用週期,內核已經爲此定義了get_cyclescpuid函數。

+0

謝謝,我相信rdtsc已經過優化,並且在我的測試中不能在內核中工作。 – lordofire