is_little_endian
,在 Little endian 機器上返回 1
,反之返回 0
,應能再任意機器上,無論幾位元的架構都適用 (Page 88)已知一台 little endian 的機器,byte order如下
且對於所有位元來說 unsigned char 的大小較 int 為小,因此當將 int 強制轉為 unsigned char 時會使得最高位為 1 因此我們可以藉由排列順序特性來判斷電腦是 little endian 還是 big endian。
leftmost_one
,產生得以找出數值 x 最高位 1
的位元遮罩 (Page 90)首先該程式碼只能夠在 32 bit 電腦上執行,若要在 64 bit 電腦上執行則需要對應的修改,如:
舉個例子來說,10 進位 65280
轉為 2 進位為 1111 1111 0000 0000
,因此遮罩就是二進位 1000 0000 0000 0000
的 32768
,這題有點類似先前的 clz,我們先來回顧計算 clz 的方法
是以每次 shift 2 的次方位來計算最大的1
所在的位置,但不同的地方在於 clz 要算的是位數,而本題想要得到的答案為最大1
和後面無數0
的數值,因此我們可以透過轉換 1111 1111 0000 0000
成 1111 1111 1111 1111
的方式再藉由與向右 shift 1 位的111 1111 1111 1111
做 xor 得到1000 0000 0000 0000
,因此透過每次向右 shift 2 次方位取 or 的方式轉換結果,code 如上所示。
float_negate
,給定浮點數 f
,回傳 -f
,倘若 f
是 ,直接回傳 f
。輸入數值範圍為有效的 232 個數值 (Page 96)本題需要複習 IEEE754 的浮點數表示法,在 IEEE 的標準中,32bit 的浮點數可以表示為 1 bit 的 sign,8 bit 的 exponent 以及 23 bit 的 significand,而完整的浮點數可以由 表示,而另外有幾種特別的表示法:
有了上述觀念之後,本題的解題方向就很清楚了,題目要求判斷 ,因此不能夠簡單的把 sign 取 not,而需要判斷 exponent 是否全為 1 即 0xFF 且 significand 是否為 0,這時候就需要將浮點數完全拆開來,最後將浮點數的 3 個部分合在一起輸出即可。
由於需要使用指標來當索引,因此最顯著的差別就是一開始 last = data + count - 1 直接將 last 指向該序列的最後一欄,原本的 last > 0 改寫為 last > data,只要指標位置在 data 後則迴圈繼續執行,而其他部分則與原本的類似,只差在使用了 *i 去指向原先的 data 欄位。
N=64
和 N=60
的 cache miss rate (Page 455)首先看 A 的部分,sumA 會先讀取整列,而讀取的單位為 16 byte 即 4 個 int,因此由於 N=64 與 60 都是 4 的倍數,所以每 4 個 int 組為 miss hit hit hit
所以 sumA 都是 25%。
再來是 sumB,由程式碼中可以看出 A 與 B 差在讀取的順序差異,A 先讀列,B則先讀直行,已知 direct map 的 cache 大小為 4K,因此可以塞得下 4096 個整數,所以以 N=64 來說前 64 次讀取都會是 miss,再來連 3 次 64 直行讀取都會全中,同樣的 N=60 也是 4 的倍數因此也會有相同的過程,故 cache miss 一樣是 25%。
比較麻煩的是 sumC,同時讀取一整塊 2×2 ( a[i][j], a[i+1][j], a[i][j+1], a[i+1][j+1])的整數,因為一次讀 2×2 個,因此 miss rate 為 50%,分別為 miss miss hit hit
但因為該迴圈有兩層,故第一層讀完之後,外面那層會全命中,故最終答案為 25%,N=60 時亦同。
該題答案皆為 25%。
首先使用原先提供的函式,以 perf 執行 100 次得到結果如下 ( dim = 1024 )
perf 執行 100 次得到的結果如下
第一個加速版本只將行列 i, j 進行調換,使得讀取資料彼此接近,locality 發揮作用,大量減少 cache-miss,以 dim = 1024 為例,執行時間由 0.012327468 秒提升為 0.003801669 秒。
第二個加速版本透過上題的 sumC 啟發,一次處理一整塊 2×2,以下為改寫後的 code
以 perf 執行 100 次的結果如下,可看出效果比一個一個來還要好,時間提升了 0.007078113 秒
如果將第一個與第二個合在一起實作,可以比單使用第一個加速方法還要好上一點點,cache-miss 甚至少了 26.4%
那有沒有可能 4×4 一組會更提升效能呢?以下做了實驗,code 修改如下
perf 結果如下,發現並沒有提升很多,cache-miss 甚至不減反增,可得一次處理 2×2 是比較好的執行結果
若我們使用了上題一次處理 2×2 的解法,code 修改如下
可得執行結果如下,得到較好的執行時間