2012-06-30 79 views
6

我正在寫一個C程序,我需要刷新我的記憶。我想知道是否有任何UNIX系統命令刷新CPU緩存。如何從C程序中刷新Linux中的CPU緩存?

這是我的項目的一項要求,涉及計算我的邏輯所花費的時間。

我已閱讀關於cacheflush(char *s, int a, int b)函數,但我不確定它是否合適以及在參數中傳遞什麼。

+3

爲什麼你需要* *清空緩存? –

+0

這是我的項目需要計算我的邏輯花費的時間,因此我需要刷新緩存。 –

+0

http://stackoverflow.com/questions/1756825/cpu-cache-flush – Tudor

回答

6
  1. 我想你的意思是「CPU緩存」,而不是內存緩存

  2. 上面的鏈接是好的:建議「寫了很多通過CPU的數據」是 Windows特定

  3. 下面是關於同一主題的另一個變化:

  4. 下面是關於Linux和CPU緩存的文章:

注:

在這個(非常非常低)的水平, 「Linux的」 !=「Unix」

+0

感謝您的幫助。它真的是一個很好的社區,有幫助的人...你可以解釋我應該如何在我的C程序中使用'echo 3>/proc/sys/vm/drop_caches'和一個小例子代碼。 –

+0

* nix(Unix通常和Linux專用)的美麗部分之一是,你可以把「像文件一樣」。特別是:'fopen(「/ proc/sys/vm/drop_caches」,「w」); fprintf(fp,「3」); fclose(fp);'。 PS:如果這是*作業,請在您的問題中使用「作業」標籤。 – paulsm4

+0

我使用fopen(「proc/sys/vm.drop_caches」,「w」)....但我如何驗證我的緩存確實已被清除。 @ paulsm4感謝您早日的友善和幫助。希望你也能幫助這一次。 :) –

2

如果你正在編寫一個用戶模式(而不是內核模式)程序,並且如果它是單線程的,那麼真的沒有理由讓你首先忙於刷新緩存。您的用戶模式程序可能會忘記它甚至存在;它只是在那裏加快程序的執行速度,操作系統通過處理器的MMU管理它。

有,你可能真的想從您的用戶模式應用程序清空緩存只有幾個原因,我能想到的是:

  1. 您的應用程序的目的是對稱多處理器系統上運行,或有與外部硬件的數據交易)
  2. 您只需測試緩存以進行某種性能測試(在這種情況下,您應該真的應該編寫測試以在內核模式下運行,也許是作爲驅動程序)。

在任何情況下,假設你使用Linux ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

這裏假設你有你剛纔寫的內存塊,你想確保它衝出緩存回到主存。該塊開始於地址,這是爲nbytes長,它在兩個緩存中的一個(或兩者):

ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

通常情況下你只需要刷新將數據Cache,因爲當你將數據寫入到「內存「(即緩存),它通常是數據,而不是指令。如果你想刷新「所有的緩存」出於某種奇怪的測試原因,你可以malloc()一個大塊,你知道它比CPU的緩存大(拍攝,使它8倍!),寫入任何舊垃圾,並刷新整個塊。

參見:How to perform cache operations in C++?

+0

感謝您的幫助。我怎麼知道我的CPU緩存在ubuntu/unix/linux中的大小?我想衝出整個緩存 –

+0

請參閱http://superuser.com/questions/48505/how-to-find-virtual-memory -size-and-cache-size-of-linux-system另請參閱我的第二個答案,我認爲它可能更符合你在尋找的內容......我會說「更多你需要什麼「,除了我認爲你沖洗緩存進行性能測試的目標是錯誤的。我認爲性能測試更有意義的是測試代碼在加載到緩存後的性能,通過運行一次將其加載到緩存中,然後使用計時器測試它可能是10,000次,並將時間除以10,000。 – phonetagger

+0

'錯誤:asm/cachectl.h:沒有這樣的文件或目錄'linux上的gnu-gcc編譯器拋出這個錯誤。任何想法如何解決它...它接受cachectl.h作爲頭文件。 –

1

OK,我的第一個答案抱歉。我後來在你的問題的後面閱讀了你的後續評論,所以我現在意識到你想要刷新INSTRUCTION CACHE來將你的程序(或其中的一部分)從緩存中引導出來,這樣當你測試它的性能時,你還要測試其初始加載時間超出主存到指令緩存中。你是否還需要清空代碼將用於主內存的任何數據,以便數據和代碼都是全新的加載?

在此之前,我想提一下,主內存本身也是一種緩存形式,其中硬盤(磁盤上的程序或磁盤上的交換空間)是程序的最低,最慢的地方指示可能來自。也就是說,當你第一次運行一個例程時,如果它已經由於接近已經執行過的其他代碼而沒有從磁盤加載到主存儲器中,那麼它的CPU指令將首先被加載從磁盤。這比從主存儲器將其加載到緩存中的時間要長一個數量級或更多。然後,一旦將其加載到主內存中,就需要從主內存加載到緩存中的時間比從緩存加載到CPU的指令獲取器所需的時間長一些。所以,如果你想測試你的代碼的冷啓動性能,你必須決定什麼冷啓動手段......將其從磁盤中拔出,或將其從主內存中拔出。我不知道有什麼命令可以將指令/數據從主內存中「刷新」出來以便交換空間,所以將它衝出到主內存大約與你所能做的(我所知道的一樣),但請記住即使您執行刷新指令高速緩存的操作,您的測試結果仍可能與第一次運行(即將其從磁盤中拔出時)不同,以至於後續運行。

現在,我們將如何去刷新指令緩存以確保他們自己的代碼被刷新到主內存?

如果我需要做到這一點(我認爲很奇怪),我可能會先找到我的函數在內存中的大致位置。由於我使用的是Linux,因此我會發出命令「objdump -d {myprogram}> myprogram.dump.txt」,然後在編輯器中打開myprogram.dump.txt並搜索我想要刷新的函數通過使用十六進制計算器從他們的起始地址中減去它們的結束地址,計算出它們的持續時間。我會寫下每個的大小。稍後,我會在代碼中添加cacheflush()調用,並將其作爲'addr'刷新的每個函數的地址,以及我發現的'nbytes'和ICACHE的長度。只是爲了安全起見,我可能會添加約10%的大小,以防萬一我對代碼做了一些調整,並忘記調整nbytes。我會爲每個我想要刷新的函數調用cacheflush()。然後,如果我還需要清除數據,如果它使用全局/靜態數據,我也可以刷新這些數據(DCACHE),但是如果它是堆棧或堆數據,那麼我可以(或應該)執行刷新超出緩存。試圖這樣做將會是一種愚蠢的行爲,因爲它會創造一種在正常執行中永遠不會或很少存在的條件。 假設你正在使用Linux ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

...where cache is one of: 
    ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

順便說一句,這是家庭作業的一類?

+0

問:這隻適用於內核模式,對嗎? – paulsm4

+0

@ paulsm4 - Linux手冊頁並沒有提到任何有關這方面的信息。嗯。閱讀手冊頁...(我假設你使用的是Linux,對吧?如果是這樣,你是否嘗試過命令「man cacheflush」?)...在底部,我看到了兩個版本的引起關注的手冊頁....「BUGS - 當前的實現忽略了addr和nbytes參數,因此整個緩存總是被刷新。」再往下......「注 - 此係統調用僅適用於基於MIPS的系統,不應將其用於可移植的程序中。」 – phonetagger

+1

@ paulsm4錯誤:asm/cachectl.h:沒有這樣的文件或目錄linux上的gnu-gcc編譯器拋出這個錯誤。任何想法如何解決它...它接受cachectl.h作爲頭文件。 –

1

這是英特爾如何建議清空緩存:

mem_flush(const void *p, unsigned int allocation_size){ 
    const size_t cache_line = 64; 
    const char *cp = (const char *)p; 
    size_t i = 0; 

    if (p == NULL || allocation_size <= 0) 
      return; 

    for (i = 0; i < allocation_size; i += cache_line) { 
      asm volatile("clflush (%0)\n\t" 
         : 
         : "r"(&cp[i]) 
         : "memory"); 
    } 

    asm volatile("sfence\n\t" 
       : 
       : 
       : "memory"); 
} 
+0

你的來源是什麼? – horro

相關問題