簡體   English   中英

我如何知道我的陣列存儲在哪個緩存級別?

[英]How do I know on which cache level my array is stored?

我知道,空間和時間的局部性對性能有巨大的影響。 我不明白我的數據結構是如何存儲在這些緩存中的? 為簡單起見,假設 L1 緩存有 8 個字節,L2 有 16 個字節,L3 有 32 個字節。 這是否意味着如果我們有:

std::array<double, 1> x = {1.}; 
std::array<double, 2> y = {1.,2.}; 
std::array<double, 4> z = {1.,2.,3.,4.};

還有一些 function 調用這些 arrays,x 會被加載到 L1 緩存中,y 在 L2 中,z 在 L3 中嗎? 或者將 y - 例如拆分為 L1 和 L2 緩存?

手動拆分這些 arrays 會在本地產生更好的緩存嗎? 例如,如果我這樣做:

std::array<std::array<double,2>,2> z;

當 function 調用它時,z 會在緩存級別上拆分嗎?

緩存線呢? 這些通常是 64 字節長 - 將我的 arrays 拆分為 64 字節的 arrays 的 arrays 會產生更好的訪問速度嗎?

std::array<std::array<double,8>,2> u;

我覺得這個主題很混亂,希望能提供任何幫助

您正在以錯誤的方式考慮緩存。

您只能使用特殊工具(想到英特爾調試器)查看哪些緩存具有它們,並且結果將特定於您的運行和架構。 更換處理器可以很容易地破壞您的設置。

也就是說,您可以嘗試使用緩存友好的解決方案。

緩存的工作方式是這樣的:假設您想讀取x[0] 您的程序將請求與其關聯的 memory 位置。 它將被L1攔截。 如果 L1 可以給你這個值(因為它已經在一個已經存儲的塊中)它會。 如果不是,請求將被 L2 攔截,依此類推。 如果沒有緩存級別具有該塊,它將從 RAM 請求。

現在,從 RAM 中僅讀取 4 個字節是低效的,因為存在開銷。 所以實際上你將從 ram 中讀取一個 L3 塊,其中包括你想要的字節。 您可能必須讀取 2 個塊,因為您的數據在它們之間被拆分(編譯器試圖避免這種情況)。 L2 塊大小的塊被發送到 L2 緩存進行存儲,L1 大小的塊被發送到 L1,所有這些都包括您想要的字節(字節可能在中間某處)。 對於下一個請求(比如'x[1]'),同樣的事情會發生。 如果下一次訪問接近上一次訪問,那么您可能會從 L1 獲得結果。 我說可能是因為您的程序可能已在具有不同 L1 的不同內核或處理器上暫停和恢復。

嘗試為特定設置進行設計通常是一個壞主意(除非您真的需要最后幾%的性能並且您已經嘗試過其他所有方法)。

經驗法則是繼續訪問彼此相鄰的 memory。 要避免的事情是訪問相距很遠的幾個字節。 遍歷數組非常快。 嘗試在同一個排序數組上實現線性搜索和二進制搜索,看看數組需要多長時間才能從二進制搜索中獲得顯着更好的性能(上次我去了大約 >100 個整數)。

在您的示例中,如果您首先訪問x的所有元素,然后轉到y等等,則設置很好。 相反,如果您訪問的是x[i], y[i], z[i]然后x[i+1], y[i+1], z[i+1]那么可能有一個結構體 {x,y ,z} 並將其放在數組中會更好(您需要進行基准測試才能確定)。

還有一些 function 調用這些 arrays,x 會被加載到 L1 緩存中,y 在 L2 中,z 在 L3 中嗎? 或者將 y - 例如拆分為 L1 和 L2 緩存?

它們都將在您訪問它們時加載的所有 L1、L2、L3 緩存中。 如果您經常訪問,您可以從較低級別的緩存中獲取它們。

手動拆分這些 arrays 會在本地產生更好的緩存嗎?

不會。處理器的 memory 管理處理拆分。 緩存位置取決於您訪問 memory 特定部分的頻率。 最好將所有訪問集中在一起,而不是隨着時間的推移分散開來。

緩存線呢? 這些通常是 64 字節長 - 將我的 arrays 拆分為 64 字節的 arrays 的 arrays 會產生更好的訪問速度嗎?

不,您可能看不到任何區別。 arrays 由處理器中的 memory 管理內容自動拆分。 再說一次,不要為你當前的處理器架構過度優化,你明天購買的 CPU 可能有兩倍長的開箱即用的緩存線。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM