contributed by < Korin777
>
/etc/default/grub
中新增 isolcpus
參數
/boot/grub/grub.cfg
/proc/cmdline
裡是否有 isolcpu
參數
korin@korin-VivoBook-15-ASUS-Laptop-X542UF:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-5.13.0-30-generic root=UUID=0316da8c-1a94-4511-a7fc-a5133651768b ro quiet splash isolcpus=1 vt.handoff=7
taskset
查看 process 的 cpu affinity , 可以發現它已經不能在第一個 cpu 執行了
korin@korin-VivoBook-15-ASUS-Laptop-X542UF:~$ taskset -p 1
pid 1's current affinity mask: fd
cpufreq
是一個動態調整 cpu 頻率的模組,系統啟動時生成一個資料夾 /sys/devices/system/cpu/cpu0/cpufreq/
,裡面有幾個檔案,scalin_governor
代表 cpu 頻率調整模式,用它來控制 CPU 頻率 , 設為 performance
表示將 CPU 頻率固定工作在其支援的最高執行頻率上,而不動態調節
i | start | 4 | 3 | 2 | 1 | result |
---|---|---|---|---|---|---|
n | - | 1011 | 1011 | 1011 | 1011 | - |
F(n) | F(0) | F(0*2+1) | F(1*2) | F(2*2+1) | F(5*2+1) | F(11) |
F(n) = a | F(0)=0 | 1 | 1 | 5 | 89 | 89 |
F(n+1) = b | F(1)=1 | 1 | 2 | 8 | 144 | |
F(2n),F(2n+1) | - | 奇數(d,c+d) | 偶數(c,d) | 奇數(d,c+d) | 奇數(d,c+d) |
n
63 - __builtin_clzll(n)
來代替迴圈求出 n
要除以 2 多少次才等於 0c,d
需要大量的乘法運算fib
函式在計算 時 , 因為結果超過 64 位元所能表示的數 , 得定義新的資料結構來儲存 , 並改寫 fib_sequence
num
初始為 0 , 將大數從高位元到低位元 , 每次將 num
乘以 2 且若遇到 1 就將 num
加 1 , 最後即可將此數轉為 10 進位i | start = 6 | 5 | 4 | 3 | 2 | 1 | result |
---|---|---|---|---|---|---|---|
n(2進位) | 101000 | 101000 | 101000 | 101000 | 101000 | 101000 | - |
n(10進位) | 0 | 1 | 2 | 5 | 10 | 20 | 40 |
下一個數 | 0*2+1 | 1*2 | 2*2+1 | 5*2 | 10*2 | 20*2 | - |
kmalloc
定義於 linux/slab.h
, 用來配置核心的記憶體空間如果我們要用這個資料結構 , 運用 fast doubling 的手法計算費伯那西數 , 我們得另外實做用於此資列結構的 +
,-
,*
,<< 1
+
lower
相加 , 在將 higher
相加並加上 lower
的進位-
*
lower
轉型成 unsigned __int128
並相乘 , 避免 overflow , 結果的較低 64 位元即是新的 lower
, 較高 64 位元進位到 higher
higher
乘以另一數的 lower
並相加 , 在將上之前的進位 , 即為新的 higher
higher
乘以 higher
因無法儲存於此資料結構 , 暫時不處理<< 1
higher
左移並加上 lower
的最高位元 , 在將 lower
左移fib
為了計算出更大的費伯納西數 , 將 BigN
的 higher
及 lower
更改為 *digits
, 可以根據我們想儲存的數字大小 , 動態配置記憶體 , size
則用來表示數字真正用到的 記憶體大小(幾個 unsigned long long)
fib_sequence
f[k + 2]
改為 f1
,f2
及 tmp
, f1
,f2
用來保留前兩個費伯那西數 , tmp
則用來更換新的 f1
,f2
displayBigN
+
add
函式改寫 fib_sequence
-
*
<<1
fib
__builtin_clzll
傳 0 進去為 undefined behavior 所以得特別判斷 n
是否為 0透過這個改寫過的 BigN
, fib_sequence
及 fib
至少能正確計算到
bignum
的實做比我的實做還要快 3 ~ 4 倍在費伯那西數大於 ssize_t
的情況下 , 使用者就無法透過 read
的回傳值取得它 , 因此在進行大數運算時,我們得透過 copy_to_user
的方式 , 將大數傳給使用者
unsigned long copy_to_user(void *to, const void *from, unsigned long n)
to
:目標地址(使用者空間)from
:源地址(核心空間)n
:將要拷貝資料的位元組數透過 make check
我們能檢查我們所求的費氏數列是否正確 , 並將發生錯誤的地方給印出來
@diff -u out scripts/expected.txt && $(call pass)
註解 , expected.txt
裡的 ~ 是錯誤的並非我們想要的值fibdrc.c
的 MAX_LENG
、 client.c
的 offset
及 verify.py
的 range(2, 101)
CPU 優化建議使用 cpupower 設定 CPU Performance 模式
isolcpu參數 隔離cpu使其不被自動調度(linux 修改boot參數)