contributed by <HotMercury>
在執行第一版 i_sqrt
時嘗試使用 gcc
編譯,有以下錯誤,但如果把 n 變成常數,就可以正常執行,error In using math function in gcc? 可以知道如果使用的是 const 編譯器會最佳化成對應的值,如果要正確執行要加上 -lm
link math library.
第一版的方式 可以得知 與 間的大小不會影響答案。
這裡做更正我原本以為的作法是找到最靠近且略小於 的方式再繼續找,但現在發現是找到 N 向上取 這樣可以確保最高位,之後再以 2 的冪逼近。
接下來思考如何不透過 log
也可以保有原有的精度,isqrt2 就是透過 shift 方式判斷 MSB 在第幾位。
上述 isqrt1 和 isqrt2 都是逐位元搜尋,且乘法成本太高,接下來可以使用 Digit-by-digit calculation 直式開方的方法。
跟著公式實際推演
及為我們想要求的平方根,所以我們從最高位慢慢遞減 。
但不想要透過成本過高的乘法,因此使用上一輪差值 減去() :
又由以下組成
程式邏輯
先透過 __builtin_clz
找到 msb, 在依據上述數學式完成,以下為對應代號程式碼
直接透過 C library 的方式呼叫 ffs
commit 575c64b
使用第二周測驗用到的 __ffs
函式可以應用在 32 位元的參數
這裡先只用 32 位元,因此先不啟用 #define BITS_PER_LONG 64,這裡用的方式是 binary search 的變形,透過 bitwise 的操作可以減少次數,以 i_sqrt1
為例子,需要一個一個右移,而 binary 只需要以 2 的冪來尋找。
commit 2fffd11
不使用到 branch,使用 bitwise 的方式
a. 先將第一個為 1 的位置以後都設成 1
b. 透過 bitwise 算出總共有多少個 1 bit
c. total bit - 算出的 bit 數
我在 block/blk-wbt.c
中找到 rwb_arm_timer
會使用到 int_sqrt
,接下來要嘗試理解這個 function 在做什麼。為了測試我能不能有觀察 linux kernel 的 sense,我先單純看 function 來猜測,以 block 底下來說 rwb 可能就是 request write back,接下來 arm 跟 timer 就是 arm 架構下 write back 的時間,以上猜測時間結束。
trace code
第一步嘗試去找誰呼叫了這個 function,wb_timer_fn
and wbt_wait
但可惜的是資料結構太多且不熟悉用途,所以從 rwb_arm_timer
程式碼下手,先拿到 struct rq_depth
可以從裡面得知會有兩種情況來調整 window size(這裡還不知道是什麼,目前猜是時間)
在計算新的 window size 裡註解有提到 We should speed this up
所以目前是認為這個是特定方式的運算,之後提到 fast integer inverse square 是一個計算 的方法,
看到一個很有趣的 patch blk-wbt: fix a divide-by-zero error in rwb_arm_timer() 之後嘗試理解
針對字串加法,暴力法可以通過 carry bit 的方式往前累進,所以一次運算會用到一次除法(for carry) 與 mod 運算,接下來參考《Hacker's Delight》我們想用 bitwise 的方式取代 divide and mod operation。
想要透過 bitwise 計算的方式一定是 (因為分母要用 shift 的方式),計算出符合 目前 a : 13, : 18,只要在範圍內就可以,( 這裡教材寫只要判定最大的不會超過就好,這個還需要理解 )。
再來我們的目標就是要乘 13 除 128,這裡我一開始想到的是直接使用乘法,但這裡將 13 拆分為 2 進位的方式,以此達到乘 13 的效果,底下為
而以下說明一個問題,即右移後,會有部分位元被捨棄,因此要另行處理。並不是很清楚為什麼是拿 q 來右移且要加三個,所以我嘗試用定點數的方式來計算。
如何解出以下的 code
其他的還沒想出來
udpate
不要太頻繁