記憶體階層與快取

三種未命中(three C's of misses)

若你的讀書一直卡住,因為對的書老是不在桌上,先診斷「為什麼」會有幫助。是你這輩子第一次需要這本書(你就是得抓一次)?還是你的桌子根本太小、裝不下你同時在處理的一切?又或者你的歸檔規則笨拙,使兩本書搶一個位置、即使桌上別處還有空間?三種未命中正是快取未命中的這種診斷,把每一次未命中歸入三個根因之一,好讓你知道哪種修法真正有用。

強制未命中(也叫冷啟動)是對某區塊的第一次參照:資料從未進過快取,所以第一次觸碰必然未命中,無論快取怎麼造。容量未命中發生在快取就是裝不下程式的工作集——有用資料被淘汰騰位、現在又被需要;即使是相同大小的全相聯快取,你也會看到這些。衝突未命中(也叫碰撞)是有限相聯度造成的額外未命中:映射到同一組的區塊不斷把彼此淘汰,即使整個快取並未塞滿——這些在全相聯快取裡會消失。強制+容量+衝突合起來,解釋了每一次未命中。

這套分類的價值在於,每個 C 指向不同的解藥,而它們彼此取捨。強制未命中靠更大的快取列(一次提取暖機更多資料)或預取(在第一次使用前先抓)來縮小。容量未命中靠更大的快取、或更便宜得多地、靠你程式碼更好的區域性讓工作集塞得下來縮小。衝突未命中靠更高的相聯度(或更聰明的索引映射)來縮小。誠實的陷阱是這些解藥會交互作用、甚至反噬:更大的列減少強制未命中、卻可能增加衝突未命中並浪費頻寬;更高的相聯度減少衝突未命中、卻可能抬高命中時間。三種未命中讓你能推理該轉哪個旋鈕,而非盲目地把快取放大。

把矩陣乘法分塊是在打擊容量未命中:藉由處理塞得進快取的小子塊,你在資料被淘汰前就重用它。從直接映射改成 4 路是在打擊衝突未命中。預取下一條列是在打擊強制未命中。不同的 C,不同的修法。

每次未命中不是強制、就是容量、就是衝突——而每個根因需要不同的解藥。

解藥彼此取捨,所以「把快取做大就好」並不總是對的:更大的列減少強制未命中、卻可能增加衝突未命中;更高的相聯度減少衝突未命中、卻可能抬高命中時間。這套分類在你轉旋鈕前,先告訴你哪個旋鈕才相關。

又称
3 Cscompulsory/capacity/conflict misses三C未命中