主講人: 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 計算費氏數列的實作
bn *a1 = fib; /* Use output param fib as a1 */
bn_t a0, tmp, a;
bn_init_u32(a0, 0); /* a0 = 0 */
bn_set_u32(a1, 1); /* a1 = 1 */
bn_init(tmp); /* tmp = 0 */
bn_init(a);
/* Start at second-highest bit set. */
for (uint64_t k = ((uint64_t) 1) << (62 - __builtin_clzll(n)); k; k >>= 1) {
/* Both ways use two squares, two adds, one multipy and one shift. */
bn_lshift(a0, 1, a); /* a03 = a0 * 2 */
bn_add(a, a1, a); /* ... + a1 */
bn_sqr(a1, tmp); /* tmp = a1^2 */
bn_sqr(a0, a0); /* a0 = a0 * a0 */
bn_add(a0, tmp, a0); /* ... + a1 * a1 */
bn_mul(a1, a, a1); /* a1 = a1 * a */
if (k & n) {
bn_swap(a1, a0); /* a1 <-> a0 */
bn_add(a0, a1, a1); /* a1 += a0 */
}
}
/* Now a1 (alias of output parameter fib) = F[n] */
Karatsuba 的概念是將
則
上述算法計算
觀察
移項之後,我們就能利用
最後計算
接著以 2 個 8 位元數值相乘變成 16 bit 為例,解說 Karatsuba 演算法(假設所採用的處理器只支援 8 位元乘法):
令
其中
接續上一個例子,當
由上圖可以看出計算
至此可透過分治法,運用 Karatsuba 演算法計算任意位數的大數。
使用 Karatsuba algorithm
來加速乘法與平方運算,乘法與平方由於運算較複雜,占用程式執行時間的比例也最高,因此sysprog21/bignum
使用 Karatsuba algorithm
來加速乘法與平方運算。對 sysprog21/bignum
使用 perf
進行分析如下 (只擷取部分)
$ sudo perf report --stdio -g graph,0.5,caller
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 5K of event 'cycles'
# Event count (approx.): 7673070456
#
# Children Self Command Shared Object Symbol >
# ........ ........ ......... ................. ..............................>
#
75.85% 2.07% fibonacci fibonacci [.] main
|
|--73.78%--main
| |
| |--26.61%--bn_sqr
| | |
| | |--9.77%--_apm_mul_base
| | | |
| | | |--2.89%--apm_dmul
| | | |
| | | --2.13%--apm_dmul_add
| | |
| | |--3.40%--__GI___libc_realloc (inlined)
| | | |
| | | --2.85%--_int_realloc
| | | |
| | | |--0.93%--_int_free
| | | |
| | | --0.85%--_int_malloc
| | |
| | |--2.27%--__GI___libc_malloc (inlined)
| | | |
| | | --0.52%--tcache_get (inlined)
| | |
| | |--2.04%--apm_sqr
| | |
| | |--1.97%--_int_free
| | |
| | |--1.37%--__memmove_avx_unaligned_erms
| | |
| | --0.52%--__GI___libc_free (inlined)
| |
| |--19.35%--bn_mul
| | |
| | |--4.56%--_apm_mul_base
| | | |
| | | |--1.31%--apm_dmul
| | | |
| | | --0.97%--apm_dmul_add
| | |
| | |--3.90%--__GI___libc_malloc (inlined)
| | | |
| | | |--1.20%--tcache_get (inlined)
| | | |
| | | --0.56%--checked_request2size (inlin>
| | |
| | |--2.56%--_int_free
| | |
| | |--1.80%--apm_mul
| | |
| | |--1.25%--__GI___libc_realloc (inlined)
| | | |
| | | --0.96%--_int_realloc
| | |
| | |--1.12%--__memmove_avx_unaligned_erms
| | |
| | --0.68%--__GI___libc_free (inlined)
| |
| |--16.17%--bn_add
| | |
| | |--3.82%--apm_add_n
| | |
| | |--3.45%--__GI___libc_realloc (inlined)
| | | |
| | | --2.77%--_int_realloc
| | | |
| | | |--0.90%--_int_malloc
| | | |
| | | --0.60%--_int_free
| | |
| | --3.08%--apm_add
| |
| |--3.87%--bn_lshift
| | |
| | |--1.31%--apm_lshift
| | |
| | --0.77%--__memset_avx2_unaligned_erms
| |
| |--1.99%--bn_init
| | |
| | --1.54%--__libc_calloc
| | |
| | --0.71%--_int_malloc
| |
| |--1.83%--_int_free
| |
| |--1.62%--bn_swap
| |
| --1.21%--bn_init_u32
| |
| --1.08%--bn_init
| |
| --0.91%--__libc_calloc
|
|--1.30%--_start
| __libc_start_main
| main
|
--0.77%--0xffffffffffffffff
main
可見使用 Karatsuba algorithm 的 sysprog21/bignum,其乘法與平方是程式執行時間佔比最高的運算,分別為 19.35% 與 26.61%,合計近 46% 的時間占比。
Schönhage–Strassen 的概念是將
令
將
對數列線性摺積:
2 66 99
x 1 88
-----------------------
176 5808 8712
2 66 99
-----------------------
2 242 5907 8712
8712
5907
242
+ 2
--------------
5019412