---
# System prepended metadata

title: 2021q1 Homework3 (fibdrv)

---

# 2021q1 Homework3 (fibdrv)
contributed by < `idoleat` >

## 自我檢查清單

- [ ] 研讀 [Linux 效能分析的提示](https://hackmd.io/@sysprog/linux2021-fibdrv#-Linux-%E6%95%88%E8%83%BD%E5%88%86%E6%9E%90%E7%9A%84%E6%8F%90%E7%A4%BA) 描述，在自己的實體電腦運作 GNU/Linux，做好必要的設定和準備工作 $\to$ 從中也該理解為何不希望在虛擬機器中進行實驗;
- [ ] 研讀上述費氏數列相關材料 (包含論文)，摘錄關鍵手法，並思考 [clz / ctz](https://en.wikipedia.org/wiki/Find_first_set) 一類的指令對 Fibonacci 數運算的幫助。請列出關鍵程式碼並解說
- [ ] 複習 C 語言 [數值系統](https://hackmd.io/@sysprog/c-numerics) 和 [bitwise operation](https://hackmd.io/@sysprog/c-bitwise)，思考 Fibonacci 數快速計算演算法的實作中如何減少乘法運算的成本;
- [ ] 研讀 [KYG-yaya573142 的報告](https://hackmd.io/@KYWeng/rkGdultSU)，指出針對大數運算，有哪些加速運算和縮減記憶體操作成本的舉措？
- [ ] `lsmod` 的輸出結果有一欄名為 `Used by`，這是 "each module's use count and a list of referring modules"，但如何實作出來呢？模組間的相依性和實際使用次數 ([reference counting](https://en.wikipedia.org/wiki/Reference_counting)) 在 Linux 核心如何追蹤呢？
- [ ] 注意到 `fibdrv.c` 存在著 `DEFINE_MUTEX`, `mutex_trylock`, `mutex_init`, `mutex_unlock`, `mutex_destroy` 等字樣，什麼場景中會需要呢？撰寫多執行緒的 userspace 程式來測試，觀察 Linux 核心模組若沒用到 mutex，到底會發生什麼問題。嘗試撰寫使用 [POSIX Thread](https://en.wikipedia.org/wiki/POSIX_Threads) 的程式碼來確認。

## Linux 效能分析
為何不希望使用虛擬機
* 虛擬機無法對 CPU 進行最佳排程，虛擬機對原本的系統而言是一個 process，此 process 也需要被原系統排程，所以在虛擬機內的排程會被再次排程，變得不是當下排程演算法的最佳排程（:question:==那我就指定虛擬機完全霸佔某幾個 CPU 行不行？==）

:question:==為什麼 KVM 或 Docker 就可以？==
KVM 和 Docker 作業系統共用的部份是？

## clz / ctz 一類的指令對 Fibonacci 數運算的幫助
### 論文要點
* 計算模型：因為 oprand 變大，計算時間也會變久，所以用 uniform cost function 計算模型來測量時間不太對，這邊改用 bitwise model
* 計算方法一：repeated addition
* 計算方法二：遞迴
* 計算方法三

論文中的關鍵手法:
code explanation:

## 修正並改善 fibdrv
原先的程式碼存在以下問題
* 使用 long long 儲存數值，到 f(93) 的時候就會 overflow 了
* 在重新計算其他項次並沒有善用已計算過的項次，每次都是從第一項開始重算
* 使用的計算方法並非最快，有更好的算法

實做上還有幾個需要注意的點
* 使用浮點數會有誤差

```c
/* MAX_LENGTH is set to 92 because
 * ssize_t can't fit the number > 92
 */
#define MAX_LENGTH 92
```
why define MAX_LENGTH can effect the actual length of [ssize_t](https://man7.org/linux/man-pages/man7/system_data_types.7.html)? (No. It cannot.)
And why 92? 我用 sizeof 讀出來他的大小是 8


## 大數
原本想偷懶使用 `__int128_t` 快速修正 F(93) overflow 的問題，結果發現 [GCC 使用手冊](https://gcc.gnu.org/onlinedocs/gcc-10.3.0/gcc/_005f_005fint128.html) 說
> **6.8 128-bits integers**
>As an extension the integer scalar type `__int128` is supported for targets having an integer mode wide enough to hold 128-bit. Simply write `__int128` for a signed 128-bit integer, or unsigned `__int128` for an unsigned 128-bit integer. There is no support in GCC to express an integer constant of type `__int128` for targets having `long long` integer with less then 128 bit width. 

所以要把 `__int128_t` 的數字 print 出來，必須要分成兩個 `long long` 來 print，同樣的也查到別人[有一樣的疑惑](https://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc)。似乎直接使用 `__int128_t` 也沒有多偷懶，而且一樣有上限，那不如好好處理大數運算比較實際。
