主講人: jserv / 課程討論區: 2023 年系統軟體課程
返回「Linux 核心設計/實作」課程進度表Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
sysprog21/bignum 在 API 的設計想法,區分
bn
APIapm
APIapm
表示 Arbitrary-Precision arithmetic (高精度運算),利用數字陣列來進行大數運算,uint8_t
的最大值是 255,該如何表示 300 呢?
uint8_t *digit
的數字陣列來儲存(同時也可以指定此陣列的 size,本例中假設 size = 3)視覺化表示就是
最後要輸出要經過格式轉換,才能成為十進位,可見 format.c。
由於除以 2 可以看作是進行 binary code
右移,結合 clz / ctz
的指令搭配 fastdoubling
(先去除以數字 MSB 起算的開頭 0 位元,因為真正的數字不包含 leading 0s),最後呈現出 sysprog21/bignum 計算費氏數列的實作
Karatsuba 的概念是將 、 以第 位數為界,拆成兩半 、、、,把這他們視為較小的數相乘,然後再透過左移補回 、 損失的位數,以十進位為例:
則 可以化為:
上述算法計算 、、 需要四次乘法,我們還可以透過以下技巧優化成三次乘法:
觀察 展開的結果
移項之後,我們就能利用 、、 來計算
最後計算 便能得到 相乘的結果。
接著以 2 個 8 位元數值相乘變成 16 bit 為例,解說 Karatsuba 演算法(假設所採用的處理器只支援 8 位元乘法):
令
其中 可以用左移運算代替。
接續上一個例子,當 、 超過 8 bit 時,可以透過分治法實作 Karatsuba。、、、 的位元數超出處理器的乘法的位數時,就把他們再切為 、、、、…,再使用 Karatsuba 計算。以下以兩個 16 bit 數值相乘變成 32 bit 來演示(假設所採用的處理器只支援 8 位元乘法):
由上圖可以看出計算 、、 時,透過分治法將 、、、 切成更小的數字執行乘法運算。最後再用左移與加法計算 即可求得結果。
至此可透過分治法,運用 Karatsuba 演算法計算任意位數的大數。
使用 Karatsuba algorithm
來加速乘法與平方運算,乘法與平方由於運算較複雜,占用程式執行時間的比例也最高,因此sysprog21/bignum
使用 Karatsuba algorithm
來加速乘法與平方運算。對 sysprog21/bignum
使用 perf
進行分析如下 (只擷取部分)
可見使用 Karatsuba algorithm 的 sysprog21/bignum,其乘法與平方是程式執行時間佔比最高的運算,分別為 19.35% 與 26.61%,合計近 46% 的時間占比。
Schönhage–Strassen 的概念是將 、 以 個位數為單位,將大數拆成若干個較小的數 、…、、、…,對 和 線性摺積,執行完線性摺積後將所有元素依據自己的位數左移並相加就可以完成乘法運算。舉例:
令
將 、 以 2 個位數為界分割會得到以下兩個數列:
對數列線性摺積:
為 與 的線性摺積,接下來透過左移和加法將線性摺積的結果相加即可完成大數乘法: