關於CSAPP 6.18的習題分析
下面的站點能找到我搜集的所有和CSAPP有關的學習資料.
https://github.com/jasonleaster/CSAPP
問題背景:
強調一下,問題的針對性很強.在這個題目裏面,cache究竟遵循什麼策略就是這個題目定的.
其他的策略如果題目沒說明,不考慮!題目旨在很簡明而要的告訴讀者替換策略的一種實現而已.
說明了int 的大小是4 byte.這裏假設了src 從地址0開始儲存, src和dst大小都是是16 bytes,那麼 dst的起始地址就是 0x10. 這裏只有一級緩存, CPU下面就是一層cache,再往下就是 main memory了.
There is a single L1 data cache that is direct-mapped, write-through, and write-allocate, with a block size of 8 bytes.
題目假設規定了,cache的每個操作都是以 8 byte進行了.
一開始的時候, cache裏面啥也沒有.每當我們試圖去訪問某個變量的時候,我們會先訪問cache,看看裏面有沒有個備份,因爲訪問cache的速度和訪問內存的速度兩種不是一個數量級的.
法則:
如果cache裏面有,那麼hit.我們就可以直接讀取使用這個數據在cache裏面的備份.
如果cache裏面沒有,從main memory去讀取數據,寫入到cache中.再從cache中立馬讀取這個數據.
對於A問:
這裏重要的就是自己要畫個圖出來方便理解.答案裏面有了.
對應的你能看到src從0x00開始,dst從0x10開始.
src的前8byte數據和 dst前8 byte數據都會落在 line 0中.
src的後8byte和dst的後八個字節會落在 line 1中.
dst[ j ][ i ] = src[ i ] [ j ].
運行程序前假設cache裏什麼都沒有空數據
cache裏面 line 0 裝的是 NULL NULL
line 1 裝的是 NULL NULL
i = 0; j = 0;
讀取 src[0][0], 第一次訪問cache空的 src[0][0] miss.把 src[0][0] src[0][1]都拷貝到cache裏去
cache裏面 line 0 裝的是 src[0][0] src[0][1]
line 1 裝的是 NULL NULL
賦值操作要求寫入到dst[0][0] ,訪問cache,此時cache裏面有dst嘛?沒有.line 0 裝的 src,line 1空着.
dst的前8 bytes和 src的前 8 bytes衝突,於是這個時候,把在cache裏面的src[0][0] src[0][1]寫回內存.
然後再把dst拷貝到cache line 0.
cache裏面 line 0 裝的是 dst[0][0] dst[0][1]
line 1 裝的是 NULL NULL
結論: src[0][0] miss dst[0][0] miss
如果以上沒看懂就反覆看,因爲上面看不懂下面絕壁白搭...
i = 0; j = 1;
讀取src[0][1], .和之前第一次賦值操作結束後的cache一樣.
由於這時候cache裏面的情況是 line 0 裝的dst前8 bytes line 1 空着.
讀取src[0][1]又和cache裏現有數據dst衝突,於是又把dst寫回到內存,把內存裏賣弄的src[0][0] src[0][1]讀取到cache line 0. src[0][1] miss
cache裏面 line 0 裝的是 src[0][0] src[0][1]
line 1 裝的是 NULL NULL
開始賦值操作.需要寫入的是 dst[1] [0] , 這裏需要訪問 line 1,line 1此時是空的.於是 dst[1][0] miss.把dst後8 bytes讀取到cache的 line 1
結論: src[0][1] miss dst[1][0]
賦值操作完成後
此時 cache裏面 line 0 裝的是 src[0][0] src[0][1]
line 1 裝的是 dst[1][0] dst[1][1]
i = 1; j = 0;
讀取src[1][0], miss 而且和line 1的dst衝突,需要把dst寫回到內存.然後讀取src[1][0] src[1][1]到cache
此時 cache裏面 line 0 裝的是 src[0][0] src[0][1]
line 1 裝的是 src[1][0] src[1][1]
開始賦值操作.需要寫入的是 dst[ 0 ] [ 1 ] , 這裏需要訪問 line 0,line 0此時是非空的.衝突,裏面裝着src. 於是把line 0的數據寫回內存.把dst[0][0] dst[0][1]讀取到cache.
此時 cache裏面 line 0 裝的是 dst[0][0] dst[0][1]
line 1 裝的是 src[1][0] src[1][1]
賦值操作.結論: src[0][1] miss dst[1][0] miss
i = 1; j = 1;
讀取src[1][1], hit cache裏面有上次賦值操作後被緩存的src[1][1],
此時 cache裏面 line 0 裝的是 src[0][0] src[0][1]
line 1 裝的是 src[1][0] src[1][1]
開始賦值操作.需要寫入的是 dst[ 1 ] [ 1 ] , 這裏需要訪問 line 1,line 1此時是非空的.衝突 miss,裏面裝着src. 於是把line 1的數據寫回內存.把dst[1][0] dst[1][1]讀取到cache.
此時 cache裏面 line 0 裝的是 src[0][0] src[0][1]
line 1 裝的是 dst[1][0] dst[1][1]
賦值操作.
結論 結論: src[1][1] hit dst[1][1] miss
對於B嘛:
注意 , 這裏只改變了cache的大小,cache每次讀取寫入的數據大小還是沒變.8 byte
@LeDy 看下面這個圖,分析方法還是和前面一樣,掌握方法,就能自己分析了.