記憶體階層與快取

快取列/快取塊(cache line)

當你從遠處的書架取一本書,為了一頁就跑完整趟路很浪費。你會把整本書帶回來——往往還順手帶幾本鄰居——因為昂貴的是那趟路,不是搬運本身。快取列就是電腦版的「別為一個位元組跑一趟遠路」:它是快取以單一單位搬移與儲存的固定大小記憶體區塊,通常 32、64 或 128 位元組。

記憶體在概念上被切成等大、對齊的區塊。以 64 位元組的快取列為例,它涵蓋一段 64 位元組對齊的範圍,像位址 0..63,然後 64..127,依此類推。當某區塊內任何位元組被需要而不在快取,快取就一次抓回整個區塊,並連同一個標籤一起存放,記錄它裝的是哪一段記憶體。這正是快取兌現空間區域性的方式:把你所要位元組的鄰居一起帶進來,意味著接下來幾次(區域性說很可能就在附近的)存取,免費變成命中。位址的低位位元(位移)只是用來挑你要快取列中的哪一個位元組。

快取列大小是真正的取捨。較大的列更善用空間區域性(一次未命中帶進更多有用鄰居),並把一趟記憶體之旅的固定成本攤到更多位元組上,但在區域性差時會浪費頻寬與快取空間(你拖進了從不使用的鄰居),也可能增加衝突未命中。一個微妙而重要的後果出現在多核心:因為共享以快取列為粒度,兩顆核心更新剛好共用一條列的不同變數時,會把整條列在彼此間來回拋接——這個效能陷阱叫偽共享(屬一致性層次的議題,此處點出只為讓你知道共享的單位是列、不是位元組)。

在 64 位元組的快取列上,一個 32 位元位址把低 6 位當作位移(2^6 = 64 個列內位元組位置)。觸碰位元組 0x1004 會帶進涵蓋 0x1000..0x103F 的列;之後存取 0x1008 或 0x1020 便都命中。

快取以整塊搬移的固定大小單位;一併取回鄰居正是它存入空間區域性的方式。

快取從不孤立地存單一位元組——它總是存整條列。這就是為什麼一次零散存取會拉進 63 個你沒要的位元組,也是為什麼把相關資料散到許多列上、即使總資料量很小也會毀掉效能。

又称
cache blockblockline快取塊