2015-10-03 65 views
0

我試圖測量內存訪問所花費的時間,我們要從char數組中運行循環和訪問元素。這裏是我的代碼:在C中,數組'訪問'沒有存儲在實際從內存中讀取的變量中?

int i; 
clock_gettime(CLOCK_MONOTONIC, &start); 
for(i = 0; i < size; i+=stride) 
{ 
    array[i]; 
} 
clock_gettime(CLOCK_MONOTONIC, &stop); 

我的問題是:沒有將它的值存儲在變量中的語句'array [i]' char x = array [i],仍然讓數組訪問內存?

+5

取決於編譯器的實現。嘗試反編譯你的編譯器給你的結果。任何合理的優化編譯器都應該知道'array [i]'語句沒有副作用,因此可以安全地放棄。 – cyphar

回答

0

這取決於。

最可能的答案是否定的。編譯器應該消除這樣的代碼,因爲所有現代編譯器都執行優化。另外,即使在編譯器會將所有內容都保留原樣的情況下,處理器可能會緩存該數組,因此不會有真正的內存訪問(因此您將得到錯誤的計時)。

0

我試試你的代碼:

#include <time.h> 

struct timespec start, stop; 

void main() { 
    int i; 
    int size = 1000; 
    int stride = 1; 
    char array[size]; 

    clock_gettime(CLOCK_MONOTONIC, &start); 
    for(i = 0; i < size; i+=stride) { array[i]; } 
    clock_gettime(CLOCK_MONOTONIC, &stop); 
} 

然後編譯使用gcc和objdump的dissamble它:

... 
4005e1: eb 06     jmp 4005e9 <main+0x8c> 
4005e3: 8b 45 dc    mov -0x24(%rbp),%eax 
4005e6: 01 45 d4    add %eax,-0x2c(%rbp) 
4005e9: 8b 45 d4    mov -0x2c(%rbp),%eax 
4005ec: 3b 45 d8    cmp -0x28(%rbp),%eax 
4005ef: 7c f2     jl  4005e3 <main+0x86> 
... 

你可以看到,有沒有數組[1]。它只使用我,尺寸和步幅。

它沒有被接受。

就像在命令中任何體面的編譯器都會將其刪除。

1

這取決於你的意思是「內存訪問」。

語言規範沒有「內存訪問」的概念。它最接近的是左值轉換的概念,描述了C11的6.3.2.1。將左值轉換爲非左值的過程本質上是將數據從存儲器讀取到某個中間空靈「保存區域」進行進一步處理的語言級思想。語言規範說左值轉換總是被應用,「除非它是sizeof運算符的操作數,運算符的一元運算符,++運算符, - 運算符或左操作數或者賦值運算符「。這並不排除你的例子,這意味着將左值轉換應用於array[i]的結果,即純粹概念上從存儲器讀取數據。

當然,在現實生活中,沒有自尊心的編譯器會在評估array[i]的價值時僅僅爲了丟棄它而立即浪費精力。

0

正如其他人指出的 - 幾乎肯定不是。

但是,您可以強制編譯器通過使用volatile關鍵字來訪問內存。

uint8_t volatile dest; 
uint8_t volatile * p = malloc(size); 
int i; 
clock_gettime(CLOCK_MONOTONIC, &start); 
for(i = 0; i < size; i++) 
{ 
    dest = p[i]; 
} 
clock_gettime(CLOCK_MONOTONIC, &stop); 

(請注意,我還沒有運行該代碼,你需要調整的C類型相匹配,我刪除的跨距值)

,將讓你過去的編譯器(但無論如何,通過查看反彙編來驗證)。

正如馬克斯指出的那樣,此時,您的CPU的內存架構和內存管理器硬件配置將決定是否實際發生物理RAM的提取(以及按照什麼順序)。這裏的問題沒有足夠的信息來有效解決(雙關意圖,抱歉...)這個問題。

+1

在這一點上,目前還不清楚OP的計量時間與OP希望衡量的時間有多大關係。 –