CSAPP lab8 Cache

考慮到能看到這篇文章的基本都是“同道中人”了,我就開門見山地寫東西不過多介紹了。。這次lab主要考察的是cache的內容,Part A要求用LRU規則模擬Cache,Part B則是將代碼優化成Cache-Friendly-Code。。體感難度是下下位吧,不耗時間但是略吃智力,P-B優化想不出來可能就沒戲了系列。。廢話不多說。上效果圖:


Part A

主要的坑是“禁止warning”,因爲編譯條件是-Werror,所以頻繁使用位運算(<<或者>>)可能會碰一些釘子。

LRU的實現有兩個思路:
1、採用全局時間參數,在全局弄個變量標記流程的進度(比如運行到第幾條指令了),然後賦給你自己設計的緩存,和tag綁定,這樣的話遇到緩存更新的時候就可以判斷剔除哪個元素了。
2、採用模擬隊列(我採用的方法),說是隊列其實就是個列表.jpg,每次miss的時候更新對應set中的tag list,全部後移一個單位,然後把新的放到[0]的位置,當然這個方法很容易忽略hit的時候,hit的時候同樣也需要更新這個list,把命中的tag丟到列表最前面

總之。。題目只有正確性要求,沒有效率要求,盡情遍歷列表吧.jpg

Part B

這個部分主要是讓學生優化一個矩陣轉置算法,讓它變得更加親民(親近緩存),具體講就是要減少Cache Miss的數量。

Cache的規格爲s=5(也就是32個set),每個set都是單行的,每行可以存8個元素(8 elements/line),題設的輸入規格是32*32,64*64,61*67三種

第一眼審題,61*67什麼玩意兒,太難了玩不了;做下去就會發現,64*64是最大的難點,61*67這種奇怪的規格給的容錯反而很大。

先做作爲鋪墊的32*32:
M=32,N=32
如果把矩陣和set的對應關係畫出來的話,策略是一目瞭然的(據說書上也有),如圖,每個格子代表8個int,對應數字表示對應的set

顯然的,我們使用矩陣分塊策略,以8*8爲單位,完成一個一個小矩陣的轉化,可以發現,基本上,原始的小矩陣和目標的小矩陣都完全在cache裏了,當然減少了很多的衝突。然而單單這樣並沒有達到滿分的要求(
還有一步重要的優化核心在對角線,因爲可以發現,對角線上的元素賦值時會造成緩存切換,這將會造成一部分的miss,不過我們可以用題中所說的“額外變量”來解決這個問題!(代碼最後一起附)

M=61,N=67

其實做完了上面那個,分塊的思想就已經浮出水面了,正激動,就出個質數相乘,導致分塊並沒有這麼滿足強迫症,不過由於題目給的Miss上限實在是過分高了,我試了一兩種分塊並調整了一下遍歷順序以後就莫名其妙滿分了。。所以我也不知道寫啥,略過了吧.jpg。

M=64,N=64

乍一看以爲是32的翻版,可以一以貫之,然而並不是這樣。。

很容易可以發現,新的8*8矩陣自己就已經產生了Cache Conflict,老辦法當然就行不通了,用4*4的話浪費了Cache Block的大小,顯然不是明智之舉。好在題目給的提示非常清晰,“你可以對目標矩陣做任何你想做的事情”,並且,題目僅僅統計Miss的數量,也就是說,多於的hit並不會影響你的分數,那麼!

首先先不考慮對角線的8*8們,考慮別的地方的轉置,轉置涉及到縱橫的變化,所以很容易會造成連續訪問不同的set,會造成極大的Miss數量,我介紹一下我的處理方法。

注意到因爲不在對角線上,所以原始和目標的8*8分別使用兩批set,互相不產生衝突,只需要考慮自身如何高效利用緩存即可

第一步:將原始矩陣的上半包含的兩個4*4方陣分別轉置放入目標矩陣

第二步:將原始8*8矩陣的緩存區挪到下面(不使用上面了),然後完成目標8*8的填值(一定要逐行,不然會造成大量Miss)

第三步:你發現對角線完蛋了,單靠上面的優化完不成滿分,不過,如果把對角線先做完,就會簡單很多很多,所以,
(劃去上面)第1.5步:處理對角線的8*8們

由於對角線上的8*8原始矩陣和目標矩陣都公用一套set,所以會很麻煩,但是,因爲我們先做對角線,所以所有其他的緩存,統統是可以使用的!

那,就直接去別的地方拆兩個4*8出來當臨時變量即可,相當於緩存的其他部分全部都是你可以用的臨時變量了!(這個方法同樣也可以用來優化上面的情況,不過因爲是後想到的所以就這樣子了,沒有實際測試)



void transpose_submit(int M, int N, int A[N][M], int B[M][N])
{
    int i,j,p,q;
    int t1,t2,t3,t4;//t5,t6,t7,t8;
    if (M==32){
        for (i=0;i<4;i++){
            for (j=0;j<4;j++){
                for (p=0;p<8;p++){
                    for (q=0;q<8;q++){
                        if (8*i+q==8*j+p){
                            t1 = A[8*i+q][8*j+p];//avoid same row conflict
                            t2 = 8*i+q;
                        }else{
                            B[8*i+q][8*j+p]=A[8*j+p][8*i+q];
                        }
                    }
                    if (i==j){
                        B[t2][t2] = t1;//set back        
                    }
                }
            }
        }
    }else if (M==61){
        for (j=0;j<5;j++){
            for (i=0;i<5;i++){
                for (p=0;p<16 && (16*i+p)<61;p++){
                    for (q=0;q<16 && (16*j+q)<67;q++){
                        if (16*i+p==16*j+q){
                            t1 = A[16*i+p][16*j+q];//avoid same row conflict
                            t2 = 16*i+p;
                        }else{
                            B[16*i+p][16*j+q]=A[16*j+q][16*i+p];
                        }
                    }
                    if (i==j){
                        B[t2][t2] = t1;//set back        
                    }
                }
            }
        }
    }else if (M==64){
        for (i=0;i<64;i+=8){
            // dui jiao xian
            for (p=0;p<4;p++){
                for (q=0;q<8;q++){
                    B[p][q+8] = A[i+p][i+q];
                }
                for (q=0;q<8;q++){
                    B[p][q+16] = A[i+p+4][i+q];
                }
            }
            for (p=0;p<4;p++){
                for (q=0;q<4;q++){
                    B[i+p][i+q] = B[q][p+8];
                    B[i+p][i+q+4] = B[q][p+16];
                }
                for (q=0;q<4;q++){
                    B[i+p+4][i+q] = B[q][p+12];
                    B[i+p+4][i+q+4] = B[q][p+20];
                }
            }
        }
        for (i=0;i<64;i+=8){
            for (j=0;j<64;j+=8){
                //[i][j] a 8*8 block
                if (i!=j){
                    //not special 8 blocks
                    for (q=i;q<i+4;q++){
                        for (p=j;p<j+4;p++){
                            B[p][q] = A[q][p];//convert 4*4
                            B[p][q+4] = A[q][p+4];//convert 4*4 in a temp place on right
                        }
                    }
                    for (p=j;p<j+4;p++){
                        t1 = B[p][i+4];
                        t2 = B[p][i+5];
                        t3 = B[p][i+6];
                        t4 = B[p][i+7];// save temp before cache tag change
                        B[p][i+4] = A[i+4][p];
                        B[p][i+5] = A[i+5][p];
                        B[p][i+6] = A[i+6][p];
                        B[p][i+7] = A[i+7][p];// correct the temp B line
                        B[p+4][i] = t1;
                        B[p+4][i+1] = t2;
                        B[p+4][i+2] = t3;
                        B[p+4][i+3] = t4;// replace temp line and change cache tag
                        for (q=i;q<i+4;q++){
                            B[p+4][q+4] = A[q+4][p+4];// normal convert
                        }
                    }
                }
            }
        }
    }
}




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