Cache Thrashing

考慮如下代碼,三個大向量結合到第四個向量。

parameter max = 1024 * 1024
dimension a(max), b(max), c(max), d(max).
do i = 1, max
  a(i) = b(i) + c(i)d(i)
enddo

這四個向量逐個聲明,因此他們在內存連續分配。每個向量都是 4MB 大小,102410244 bytes。因此這四個元素地址的低22位是相同的。向量映射到關聯緩存的相同的位置。

爲了執行某次計算,a(i), b(i), c(i), and d(i) 必須駐留在主存中,首先對 c(i), and d(i) 執行乘法。他們映射到緩存的相同位置,單兩者可以同時駐留,因爲緩存是2路組相聯。在相同的地址位它可以容下2個cache line。爲了執行加法,b(i) 需要在緩存中。它映射到緩存的相同位置,因此含c(i) 的cache line 挪出位置用於存放b(i),這裏假設最近訪問的是c(i)。爲了存儲結果到a(i),含d(i) 的 cache line 必須被替換。

現在,循環處理到了i+1迭代,含 c(i+1) 的cache line 必須重新載入cache,與因爲有兩個事實:

  1. c(i+1) 是一個不同於c(i) 的cache line,因此第一次它的 line 必須被載入
  2. c(i+1) 是一個相同於c(i)的cache line,但是已經被替換了在先前的迭代中,

相似的,cache line 含d(i+1) 的也同樣需要被重新載入。事實上,每一個對一個向量元素的引用會導致一個cache miss,因爲4箇中只有兩個需要的值可以同時駐留在cache中。儘管訪問是一次一步的,沒有cache line reuse。

這些行爲稱爲 cache trashing,並且它導致非常差的性能。本質上減少了程序無緩存地使用內存。trashing 的原因是因爲不合理的向量對準(vector alignment)。他們所有映射到相同的cache 位置。上面程序的對照是特別壞的因爲 max 是非常大的會引起 trashing 在主存喻二級緩存。

使用 array padding 防止 trashing

兩種方法防止 cache trashing

  1. 改變向量維度,使得其不再是 2 的平方。一個新的size將溢出內存,因此a(1),b(1),c(1),d(1) 將所有映射到不同的位置是理想的,比如 max = 1024*1024+32 將偏置每一個向量32個元素,或128bytes。這是一個 二級cache line 的大小。因此每個向量開始於一個不同的cache 地址。所有4個值可能同時駐留在cache,因此可能實現 cache line reuse。
  2. 對於2維向量。將主維改成奇數是有效的,如
dimension a(1024+1, 1024)

對於多維數組,改變兩個甚至更多的維數:

dimension a(64+1, 64=1, 64)

消除cache trashing 使得循環加速至少100倍。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章