緩存控制指令
在計算中,緩存控制指令是嵌入處理器指令流中的提示,旨在利用程序員或編譯器提供的關於內存訪問模式的信息來提高硬件緩存的性能。 [1]它們可以通過更好地控制工作集來減少快取污染、減少帶寬需求、繞過延遲。大多數緩存控制指令不會影響程序的語義,儘管有些可以。
例子
編輯此類指令受多個處理器指令集架構的支持,例如ARM、MIPS、PowerPC和x86。
預取
編輯也稱為數據緩存塊觸摸,其效果是請求加載與給定地址關聯的緩存行。這是由x86指令集中的PREFETCH
指令執行的。一些變體繞過更高級別的緩存層次結構,這在「流式」上下文中對於遍歷一次而不是保存在工作集中的數據很有用。預取應該發生得足夠早,以減輕內存訪問的延遲,例如在使用循環來線性遍歷內存時。 GCC內置函數__builtin_prefetch
可用於在編程語言C或C++中調用。
指令預取
編輯預取的一種變體,適用於指令緩存。
數據緩存塊分配零
編輯此提示用於在完全覆蓋內容之前準備緩存行。在這個例子中,CPU 不需要從主內存加載任何東西。語義效果等同於使用對齊的memset,將緩存行大小的塊設為零,但操作實際上是實現釋放。
數據緩存塊無效化
編輯此提示用於丟棄緩存行,而不將其內容提交到主內存。該指令可能會帶來不正確的運行結果,因此需要謹慎使用。與其他緩存提示不同,這條緩存提示會極大地改變程序語義。這與allocate zero
一起用於管理臨時數據。這節省了不需要的主內存帶寬,避免緩存污染。
數據緩存塊刷新
編輯此提示請求立即犧牲一個緩存行,為即將發生的分配讓路。當已知數據不再是工作集的一部分時使用它。
其他提示
編輯一些處理器支持加載-存儲指令的變體,這些指令也包含緩存提示。一個例子是PowerPC指令集中的load last
,這表明數據只會被使用一次,即相應緩存行可能會被送到等待犧牲的隊列的頭部。
替代方案
編輯自動預取
編輯最近,英特爾和ARM開發的越發先進的應用處理器將更多的晶體管用於加速用傳統語言編寫的代碼,例如執行自動預取、使用硬件來動態檢測線性訪問模式。因而緩存控制指令變得不那麼流行了。然而,這些技術可能對面向吞吐量的處理器仍然有效,它們具有不同的吞吐量-延遲的側重性,並且可能更傾向將更多區域用於執行單元。
暫存器內存
編輯一些處理器支持將臨時文件放入暫存器,並使用直接記憶體存取(DMA)在需要時將數據傳入傳出主內存。 Cell 處理器和一些嵌入式系統使用這種方法。這些允許更好地控制內存流量和位置(因為工作集由顯式傳輸管理),並消除了對多核機器中昂貴的快取一致性的需求。
缺點是它需要使用截然不同的編程技術。很難改寫用傳統語言(如 C 和 C++)編寫的程序,這些語言向程序員提供了一個大地址空間的統一視角(這是通過緩存模擬出來的錯覺)。傳統的微處理器可以更輕鬆地運行遺留代碼,然後可以通過緩存控制指令對其進行加速,而基於暫存器的機器則需要從頭開始進行專門編寫,直至能實現相同功能。緩存控制指令特定於某個緩存行大小,在實踐中,同一體系結構系列中的處理器各代之間可能不同。緩存還可以幫助從不可預測的訪問模式(例如,在材質貼圖的過程)中合併讀取和寫入,而暫存器 DMA 需要重新設計算法以實現更可預測的「線性」遍歷。
此類暫存器通常更難與傳統編程模型一起使用,不過對於資料流模型(例如TensorFlow)而言可能更合適。
向量讀取
編輯向量處理器(例如現代圖形處理單元(GPU) 和Xeon Phi)使用大規模並行計算來實現高吞吐量,同時解決內存延遲問題(減少預取的需要)。許多讀取操作是並行發出的,用於計算內核的後續調用;計算可能會暫停以等待後續的數據,而執行單元則盡力處理來自過去收到的請求的數據。對於程序員來說,這種模式更容易與適當的編程模型(內核函數)結合使用,但更難應用於通用編程。
缺點是臨時狀態的許多副本可能保存在處理元素的本地內存中,等待傳輸中的數據。
參考資料
編輯- ^ Power PC manual, see 1.10.3 Cache Control Instructions (PDF). [2022-12-19]. (原始內容 (PDF)存檔於2016-10-13).