Cache Aliases 小註解

有一個有趣的問題: 假如 cache size 是 8KB, 而 virtual memory 的 page 是 4KB 會怎麼樣? 這個就是  cache alias的問題.

根據新版的 “See MIPS Run" 這本書的 10.3.4 Cache Aliases and Page Coloring, 名詞定義是這樣:

1. index range = the size of one “set" of cache. 舉例來說 4 KB 的 page 可以對應到 8KB 的 direct map, 或是 32KB 的 4-way set-associative cache.

2. page color = the value of those one or more virtual address bits that choose a page size chunk within the propriate page set.

3. cache aliases = two virtual pointers to the same physical data can produce an alias only if they have different page colors.

若是把 32KB 4-way associative cache memory 看作 4 塊 8KB 的 cache memory, 那麼每一塊都比 4KB page 大一倍, 一抓就有機會抓到和另外一個 way 重疊的內容. 

解法: 只要 virtual address 彼此距離夠遠, 比方說在 4KB page 下間隔 64KB, 那麼每個 page 的 color 都會一樣. 

另外有人說, 可以讓 virtual address 的 bit 12 (假設 page 是 4KB, 12 bis) 強制和 physical address 的 bit 12 一樣, 也就是說每 8KB 的第一個 4KB, 和第二個 4KB 在 physical address 上都沒有重疊. 由於每一個 way 不會抓到一樣的東西, 這就確保了兩個 way 之間的 cache 不會重複. 它聽起來等效於 page size 變成 8KB, 所以應該會沒問題.

先不管軟體實作上的困難, 這種 work around 的 hit rate 將會很低. 每次 hit 到奇數 page, 就要連前一個偶數 page 都抓進來. 那些資料通常已經是過去式了, 所以 cache 的效率應該挺差的.

 

——————————————————–

20090320 重新整理

cache alias 可能發生在 Linux user mode 之間, 也可能發生在 user mode kernel mode 之間.

單純在 user mode 的解法有很多種:

1.  只要 virtual address 彼此距離夠遠, 比方說在 4KB page 下間隔 64KB, 那麼每個 page color 都會一樣均勻, 如小魚的第一個回覆一樣

2.  根據小魚的說法: 奇數 8KB (i.e. 4(2n+1)KB) 和偶數 8KB (i.e. 4(2n)KB) physical address 都對應到不同組的 virtual address. memory cache 既然是根據 virtual address  所做的, 那麼就沒有機會 cache 到重複的  physical address.

有人說用這種說法: “可以讓 virtual address bit 12 (假設 page 4KB, 12 bis) 強制和 physical address bit 12 一樣, 也就是說每 8KB 的第一個 4KB, 和第二個 4KB physical address 上都沒有重疊. 由於每一個 way 不會抓到一樣的東西, 這就確保了兩個 way 之間的 cache 不會重複. 它聽起來等效於 page size 變成 8KB, 所以應該會沒問題.

為了 hit 8KB 裡的一個 Linux 4KB page, 現在必須抓 8 KB cache. 和原來的方式相比, 原來讀到 0x80001-000 的時候, 我們 cache 0x80001-000~0x80002-FFF, 是指望後面進到 cache 0x80002-000~0x80002-FFF 這個 page 等一下會用到. 根據新的方式, 就會變成 cache 0x80000-000~0x80001-FFF 8 KB. 所以還是會有一些差別, 如小魚第四篇回覆所說的: " 0×00410_000 0×00411_000 是無法同時對到 0×40400_000 “. 

本來我有個直覺, 覺得分了類之後, 對於大量連續資料, 又放在虛擬記憶體的連續位置時, 上面的做法可能會降低效率. 但想想也只是 cache 到不同 way cache memory 去了, 應該是還好.

[後記]

1. Kernel space user space 存取同一個 page 的話, 也會有 virtual alias 的問題.

2. 還是要感謝小魚啦!

    

Cache Aliases 小註解 有 “ 8 則迴響 ”

  1. 這個 page-coloring 應該有兩種用法
    針對不同的場合
    一是避免 cache conflict,假設我們有很大的 cache 比方說 64K direct map,
    採用 4K 當 page size,所以 cache 裡面可以塞 16 個 page。如此可以將所有的 memory 分成 16 種顏色,分別對應到 cache 不同的位置。如果說 OS 不好好分配 page 的位置的話,會使得 cache 使用率變差,有的地方很容易 cache miss,有的地方卻總是空的。所以比較好的做法是讓 OS 分配的顏色均勻一點。

    另一個就是避 virtual aliasing 了。
    以 8K-direct map 為例,4k 的 page 會造成 VIPT (virtual index, physical tag) 下產生 aliasing,不同的 VAddr 對到相同的 PAddr;在同時查找 cache 和 TLB 的情況下,簡單的硬體無法解掉這個問題。
    軟體上的解法一樣叫 page coloring,就是把所有的實體記憶體頁面以地址分成兩類,一類叫 4nKB,一類叫 (4n+1)KB;同樣的所有的虛擬記憶體頁面也是這樣。並規定虛實的對應 4n 那一類只能對到 4n 的頁面,(4n+1) 也是一樣。如此才能避掉 aliasing 的問題。

  2. 感謝 “小魚" 熱情回覆, 讓我獲益良多. 明天我可以去公司進一步的研究.

    最後一段, 並不是指 dual-mapped, 我的原意是說: 強制 virtual address 的 bit 12 等於 physical address 的 bit 12,這個 idea 是聽來的, 我想不通要如何做到? 並且對它的效果質疑. 文字我再想想怎麼修改好了.

    但它有沒有可能是 page coloring 解法的另一種說法呢? 現在有點昏了, 明天再推敲一下. 感謝!

  3. “但它有沒有可能是 page coloring 解法的另一種說法呢?"
    沒錯 就是這樣低
    比方說我們使用一虛擬地址 0x00400_000, TLB page size 是 4KB 的話,
    TLB 的轉譯就是把前面 20 bits 換成實體位置,
    0S 在資源許可的範圍內可以任意指定
    可以對應到 0x00000_xxx (最前面)
    也可以對到 0x00001_xxx (下面 4KB) [別的位置也可以]
    但是如果考慮解 cache aliasing 的問題
    就只能選 第一個 0x00000_xxx,或是 0x00002_xxx…
    不能挑 0x00001_xxx

  4. 繼續補充
    所以 “強制讓第 12 bit 相同" 就是這麼一回事
    之前也有寫錯的地方,正確的分類應該是 8nKB 和 (8n+4)KB
    附帶一提的是,
    這樣的解法在 memory share 時有時會有麻煩
    因為要顧及 cache aliasing
    所以不同的虛擬頁面對到同一個實體頁面時
    這些不同的頁面必須是同一個分類
    像是 0x00410_000 和 0x00411_000 是無法同時對到 0x40400_000 的
    本來 OS 不需要考慮這種 memory share 的問題的。

  5. 嗯…
    其實 cache aliasing 有時是沒問題的
    狀況發生的時候就會很大條
    沿用上面的例子
    假設我們的系統有 8KB 的 direct-map dcache,使用 4KB 的 page
    (幾個 way 沒有關係)
    當我們讓 0×00410_000 和 0×00411_000 同時對到 0×40400_000
    TLB 會把 0x00410 和 0x00411 都對應到 0x40400,這一直都不是問題
    問題是使用 virtual index 的 cache
    現在系統是 8KB (= 2^13)
    所以我們會拿 13 bit 出來找 cache 有沒有 hit
    所以有兩組 address: 0x0_000 和 0x1_000,
    (不同的地方在於先頭的 bit,沒經過 V to P 的轉換就拿來用了
    這也是 PIPT 決不會發生 aliasing 的原因)
    分別對應到 dcache 裡 0 和 4K 的位置

    如果我們兩邊都是 read only,那就沒問題
    (icache 很少聽過要解 aliasing 就是這樣)
    但如果有人想寫入,大條的情況就發生了:
    使用 0x00410_000 的人,改到的是 cache 0 位置的 data
    使用 0x00411_000 的人,改到的是 cache 4K 位置的 data
    這就造成了 data 不同步
    所以 8K-1way 的系統裡 任何一個實體的 address,
    cache 中都有兩個可能產生 aliasing 的位置

    如果我們有一個 16K 2way-associate 的系統,page 也是 4K 的話
    狀況跟上面其實一樣,有兩個產生 aliasing 的位置

    教科書上面的一個硬體解範例是
    只要發生 cache miss
    就 write-back-invalid 所有可能的 cacheline
    16K-2way 的話,可能的 cacheline 就是四條
    確保再次抓進來的 line 一定是被更新過的

回覆給小魚 取消回覆