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 一定是被更新過的

發表留言