devarajabc
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 2024q1 Homework1 (lab0) contributed by < [devarajabc](https://github.com/devarajabc) > ## 開發環境 ```shell $ gcc --version gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 $ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 39 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 8 On-line CPU(s) list: 0-7 Vendor ID: GenuineIntel Model name: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz CPU family: 6 Model: 142 Thread(s) per core: 2 Core(s) per socket: 4 Socket(s): 1 Stepping: 11 CPU max MHz: 3900.0000 CPU min MHz: 400.0000 BogoMIPS: 3600.00 ``` ## 開發過程 :::danger 無論標題和內文中,中文和英文字元之間要有空白字元 (對排版和文字搜尋有利) ::: :::info 了解 ::: ### `q_new` :::danger 不懂就說不懂,不要不懂裝懂說「不太懂」。 改進你的漢語表達。 ::: :::info 1.了解 ::: 原本不懂要 new 的是哪個東西?是 queue_contex_t 還是element_t 或是單純的 list_head,直到翻閱 [qtest.c](https://github.com/devarajabc/lab0-c/blob/master/qtest.c#L143) 才知道 q_new 要新增的是佇列的 `head` (下圖藍色處) ```graphviz digraph ele_list { rankdir=LR node[shape=record] head [label="head|{<left>prev|<right>next}", style="bold" color = blue ] node4 [label="element_t|{<left>prev|<right>next}", style="bold"] node3 [label="etc.", style="bold"] node2 [label="element_t|{<left>prev|<right>next}", style="bold"] node1 [label="element_t|{<left>prev|<right>next}", style="bold"] list [label="qctx-&gt;q", style="normal", color="white"] head:right:e -> node4:w node4:left:w -> head:e node4:right:e -> node3:w node3:left:w -> node4:e node3:right:e -> node2:w node2:left:w -> node3:e node2:right:e -> node1:w node1:left:w -> node2:e head:left:e -> node1:w list -> head:n } ``` ```c queue_contex_t *qctx = malloc(sizeof(queue_contex_t)); list_add_tail(&qctx->chain, &chain.head); qctx->size = 0; qctx->q = q_new(); qctx->id = chain.size++; ``` 同時程式也說明了如何建立 `qctx` ,這對於思考如何進行 `q_merge` 很有幫助 :::danger 詳閱作業要求! ::: ### `q_free` 利用 `list_for_each_entry_safe`來走訪每一個節點,再利用 `q_release_element` 來釋放該節點( `element_t` )與節點內指向的字串(綠色部分),最後再釋放 head node (藍色部分) ```graphviz digraph list { rankdir=LR; node[shape=record, style=bold]; subgraph cluster_0 { style=invisible; value [label="{value}"]; head [label="{<prev>prev|<next>next}"]; style=bold; label=element_t } e1 [label="head node|{<left>prev|<right>next}", style="bold", color=blue]; e1 -> head :right:w [color=blue]; value->string string [color = green ] } ``` ### `q_insert_head`, `q_insert_tail` 原本是使用 `strncpy` 以及用 `strlen` 來判斷長度避免造成記憶體區段錯誤,後來發現函式 `strdup` 就可以達到所需的功能,而且記憶體配置失敗時會回傳 NULL ,非常方便 不過在 [stackoverflow](https://stackoverflow.com/questions/252782/strdup-what-does-it-do-in-c) 發現以下敘述 >Keeping in mind it's actually not part of the current (C17) ISO C standard itself(a) (it's a POSIX thing), it's effectively doing the same as the following code: 此外在 git commit 的時候一直收到 ``` queue.c:64:5: error: Memory leak: temp [memleak] return true; ^ queue.c:88:5: error: Memory leak: temp [memleak] return true; ^ Fail to pass static analysis. ``` 後來將 ```c INIT_LIST_HEAD(&(temp->list)); list_add_tail(&(temp->list), head)); ``` 改成 ```c INIT_LIST_HEAD(&temp->list); list_add_tail(&temp->list, head); ``` 就通過 static analysis 了,目前還不知道為什麼 :::warning 注意看 C 語言運算子的優先順序。 ::: ### `q_remove_head` / `q_remove_tail` 先利用 `list_first_entry` / `list_last_entry` 來取出欲移除的節點 `removed ` 接著使用 `list_del_init` 來將該節點移出佇列 並利用 `strncpy` 將 `removed->value` 拷貝到字串 `sp` 之中 最後要將字串 `sp` 的最後一元素 `sp[bufsize - 1]` 指派為 `'\0'` 。 :::danger 你該用 ChatGPT 改進你的漢語表達,並避免將自己的專業成長訴諸大語言模型。 > 我知道錯了 ::: ### `q_size` :::danger 避免贅字 ::: :::success 已刪除 ::: >參考[作業說明](https://hackmd.io/@sysprog/linux2024-lab0/%2F%40sysprog%2Flinux2024-lab0-a) 在範例的基礎上加入 `list_empty(head)` 來處理佇列為空的情況。 ### `q_delete_mid` 利用 `list_for_each_entry` 與一相反方向走訪的指標 `rev_node` 來尋找中間點,再利用`list_del_init`和 `q_release_element`來刪除節點,以下為部分程式碼: ```c if(node==rev_node||node->next==rev_node){ list_del_init(rev_node); q_release_element(list_entry(rev_node,element_t,list)); return true; } rev_node=rev_node->prev; ``` 選擇 `rev_node` 為要刪除的中間節點而非使用 `node` 是為了處理 node 數量為偶數的情況 ### `q_delete_dup` 程式的執行主要分成兩種情況: * 目前節點與下一個節點相同:利用 while loop 刪除相同的節點 * 目前節點與下一個節點相異:又可分成兩種可能: 1. 剛離開 while loop:刪除目前節點 2. 未曾進入 while loop:什麼都不必做 以下是細節說明: 利用 `list_for_each_entry_safe` 來走訪每節點,當發現下一個節點與目前節點相等時,就會利用 while loop 不斷走訪並刪除 「目前節點的下一個節點」直到出現相異的節點或是走訪到 head ,因此原先指向「目前節點的下一個節點」的指標 `safe` 會被改變。 此外在進入 while loop 之前會進行判斷,避免在 `entry->list.next` 為 `head` 的情況下使用 `list_entry` 而造成記憶體區段錯誤。 在第四行將指向「目前節點的下一個節點」的指標儲存在 `Next` 而非直接用 `list_entry` 的輸出節果來作為函式 `list_del` 與函式 `q_release_elemen` 的輸入,因為執行 `list_del` 之後的佇列會被改變,直接將 `list_entry` 的輸出作為 `q_release_element` 的輸入會破壞佇列的結構。 ```diff while (entry->list.next != head && !strcmp(entry->value, list_entry(entry->list.next, element_t, list)->value)) { + element_t *Next = list_entry(entry->list.next, element_t, list); - list_del(entry->list.next) + list_del(&Next->list); - q_release_element(list_entry(entry->list.next, element_t, list)); + q_release_element(Next); } ``` 接著要判斷 `safe` 是否被改變過,如果是 `safe` 依然是「目前節點的下一個節點」,代表該節點沒有進去過 while loop ,因此不需要刪除目前節點。 :::danger 改進你的漢語表達。 > <s>已對內容進行更改</s> > 還差得遠,要用清晰明確且流暢的漢語書寫,你該展現自己學了二十餘年漢語的能耐。 ::: 反之則要刪除該節點,並指派 `safe` 正確的值,以便 `list_for_each_entry_safe` 可以繼續運作。 ```diff +if (list_entry(entry->list.next, element_t, list) != safe) { -if (!safe){ safe = list_entry(entry->list.next, element_t, list); list_del_init(&entry->list); q_release_element(entry); } ``` `safe` 再其所指向的節點被刪除後,會指向一位置不明、不固定且無法 dereference 的地址而非 NULL,原因不明,甚妙。 所以若使用 `safe` 是否為 NULL 來判斷是否要刪除該節點,則會在後續的步驟造成記憶體區段錯誤,以下是 valgrind 的輸出結果: ```shell ==267663== Invalid read of size 8 ==267663== at 0x10FCB1: q_delete_dup (queue.c:168) ==267663== by 0x10C093: do_dedup (qtest.c:467) ==267663== by 0x10E0ED: interpret_cmda (console.c:181) ==267663== by 0x10E6A2: interpret_cmd (console.c:201) ==267663== by 0x10F30C: run_console (console.c:691) ==267663== by 0x10D4DF: main (qtest.c:1288) ``` ### `q_reverse`/`q_reverseK`/`q_swap` > 參考 [yanjiew](https://hackmd.io/@yanjiew/linux2023q1-lab0#q_delete_dup) 1. 利用 `list_for_each_safe` 走訪每一個節點並用 `list_move` 把目前節點移到 `head`,以達到翻轉順序的目的。 :::danger 避免非必要的項目縮排 (即 `* ` 和 `- `),以清晰、明確,且流暢的漢語書寫。 ::: 2. 在撰寫 `q_reverseK` 的時候一開始誤會題意,以為只要處理前 k 個,還好在 [HotMercury](https://hackmd.io/@NeedSleep/linux2024-homework1) 的提醒下才改正,實作如下: 利用 `list_for_each_safe` 走訪每個節點並利用 `list_move` 將其移至 `new_head` 。 每經歷 k 個 node 就會更新 `new_head` 的值,以達到題目的要求,當走訪的節點數量不足 k 時則不會改變 `new_head` 的值。 ```c list_for_each_safe (node, safe, head) { if (!i--) { new_head = node->prev; i = k - 1; } list_move(node, new_head); } ``` 3. `q_swap` 是 `q_reverseK` 的一個特例,用 K = 2 來實踐。 :::danger 1. 無論標題和內文中,中文和英文字元之間要有空白字元 (對排版和文字搜尋有利) 2. 改進漢語表達 ::: :::info 1.已改正 2. :notes: 沒做到的事,不要急著回應。斟酌字句值得佔用你的青春去淬鍊。 ::: ### `q_ascend`/`q_descend` :::danger 留意[資訊科技詞彙翻譯](https://hackmd.io/@sysprog/it-vocabulary) > 將「遍歷」全數更正為「走訪」、「當前」皆更新為「目前」 "queue" 更正為「佇列」、 "linked list" 更正為「鏈接串列」 > > 漢語詞彙不該直接對應到英語,仍該針對情境去調整。 :notes: jserv ::: 在走訪的過程中若目前節點大於 `min` 則會更新 `min` ,並將用於記錄 node 數量的變數 `i` 加一 ,反之則將其刪除,細節如下: ```c if (strcmp(entry->value, min->value) < 0) { list_del(&entry->list); q_release_element(entry); } else { min = entry; i++; } ``` 而 `q_descend` 則是把 `lish_for_each_safe` 改成往 prev 的方向走訪,其他部分則跟 `q_ascend` 一樣。 :::danger 這是環狀雙向鏈結串列,何來「右邊」?工程人員說話要精準。 ::: :::success 已更正 ::: ### ` q_sort`, `merge_two` >參考 [yanjiew](https://hackmd.io/@yanjiew/linux2023q1-lab0#q_delete_dup) 和[alanjian85](https://github.com/alanjian85/lab0-c) 的作法 `merge_two` 是額外寫的函式,是為了方便 `q_sort` 和 `q_merge` 使用而特別獨立出來。 參考 [(2023): 第 1 週作業檢討](https://youtu.be/pB0YOqkNk4Y?t=6588) 後決定在 void 前面標註 static . 使用 `list_first_entry` 來取出兩個佇列的第一個節點來進行比較,之後再依據 `descend` 的值來決定要插入較大或是較小的節點 。 ```c if ((descend && strcmp(l->value, r->value) > 0) || (!descend && strcmp(l->value, r->value) <= 0)) list_move_tail(&l->list, &temp); else list_move_tail(&r->list, &temp); ``` 在老師的提點之下才發現自己其實根本分不清出 Top-down 和 Bottom-Up 於是便去閱讀 [Linux 核心排序實作的演進](https://hackmd.io/@sysprog/linux2024-lab0/%2F%40sysprog%2Flinux2024-lab0-e) 使用 Top-down (recursive) merge sort 來實作 `q_sort ` 實作內容如下: 利用 `list_for_each_safe` 走訪每一個節點 * 若目前節點為佇列的**中間**節點: 1. 利用 `list_cut_position` 將佇列分成兩段並分別放入 `q_sort` 進行排序 2. 利用 `merge_two` 合併已排序好的佇列 3. 離開迴圈 * 反之則更新反向走訪的指標 `rev_node` 以利後續判斷是否走訪到中間節點 ```c LIST_HEAD(R); list_for_each_safe (node, safe, head) { if ((node == rev_node || node->next == rev_node) && rev_node != head) { list_cut_position(&R, node, head->prev); q_sort(&R, descend); q_sort(head, descend); merge_two(head, &R, descend); break; } rev_node = rev_node->prev; } ``` :::danger 你如何確認目前的測試已涵蓋排序演算法的最差狀況? ::: **確認目前的測試已涵蓋排序演算法的最差狀況** >參考 [排序測試和效能評估機制](https://hackmd.io/@sysprog/Hy5hmaKBh) 對於 Top-down (recursive) merge sort 而言,不管在最佳、平均、最差的情況下,時間複雜度皆為 $O(n\log{n})$ ,差別在於節點間比較的次數,假設有兩個子佇列 $Q_1, Q_2$ ,長度分別為 $n_1, n_2$ ,最差情況下的比較次數 $C_{n1,n2}$ 為 $n_1+n_2-1$ 次,即每一個節點皆被比較過。 $min(n_1,n_2)\leq C_{n1,n2} \leq n_1+n_2-1$ 1. 怎樣的測試資料是最差情況呢? > 參考 [When Will the Worst Case of Merge Sort Occur?](https://www.baeldung.com/cs/merge-sort-time-complexity) 、[2024-03-{19,21} 討論簡記](https://hackmd.io/3e8LI8_0SLOo_UTDAnPKYQ) 只要比較次數少於 $n_1+n_2-1$ 次,就不是最差的情況,例如在合併 $Q_1, Q_2$ 的過程中,其中一個子佇列提早被比較完,這樣比較次數就會少於 $n_1+n_2-1$ 次。 因此最差情況的測試資料要確保在每次合併的過程中都會比較到每一個節點。 2. 新增 `q_worst_case` > [commit 16f69b2](https://github.com/devarajabc/lab0-c/commit/16f69b2a5af1ab778850c6c37f5c3242fcb3e507) 先準備一個嚴格遞增的佇列,再使用遞迴的方式將佇列拆成奇數項、偶數項兩個子佇列,直至子佇列只剩一個節點,最後再將所有節點串連起來。 因為在合併兩個交錯排例的子佇列如 $[1,3,5,7], [2,4,6,8]$ 時就能避免其中一個子佇列提早被比較完的情況,然而為了確保每一次的合併都能達到最差的情況,所以要再將 $[1,3,5,7]$ 拆成 $[1,5], [3,7]$ 而 $[1,5]$ 又要再拆成 $[5], [1]$ $...........$ 流程如下: ```graphviz digraph list { l1 [shape=rect label="1,2,3,4,5,6,7,8"]; l21 [shape=rect label = "1,3,5,7" ]; l22 [shape=rect label = "2,4,6,8" ]; l31 [shape=rect label = "1,5" ]; l32 [shape=rect label = "3,7" ]; l33 [shape=rect label = "2,6" ]; l34 [shape=rect label = "4,8" ]; l41 [shape=rect label = "5" ]; l42 [shape=rect label = "1" ]; l43 [shape=rect label = "7" ]; l44 [shape=rect label = "3" ]; l45 [shape=rect label = "6" ]; l46 [shape=rect label = "2" ]; l47 [shape=rect label = "8" ]; l48 [shape=rect label = "4" ]; lf [shape=rect label="5,1,7,3,6,2,8,4"]; l1 -> { l21 l22 }; l21 -> { l31 l32 }; l22 -> { l33 l34 }; l31 -> { l41 l42 }; l32 -> { l43 l44 }; l33 -> { l45 l46 }; l34 -> { l47 l48 }; l41 -> lf; l42 -> lf; l43 -> lf; l44 -> lf; l45 -> lf; l46 -> lf; l47 -> lf; l48 -> lf; } ``` 我很好奇 $[5,1,7,3,6,2,8,4]$ 和 $[1,5,3,7,2,6,4,8]$ 會不會造成比較次數的不同 (在最差環境下的表現數據:比較次數、時間、cache miss ratio) (要確認是否符為合穩定排序,要有數學證明) (穩定排序的檢測?) ```shell Queue size = 8 l = [a b c d e f g i] cmd> worst_case l = [a e c g b f d i] cmd> list_sort Comparisons: 17 l = [a b c d e f g i] Freeing queue ``` **確認目前的排序是否為穩定排序** >參考 [yenslife](https://hackmd.io/@yenslife/linux2024-homework1#q_sort) 、[wiki](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability) 穩定排序的定義是:如果一個排序演算法是穩定的,當有兩個相等鍵值的紀錄 $R$ 和 $S$,且在原本的串列中 $R$ 出現在 $S$ 之前,在排序過的串列中 $R$ 也將會是在 $S$ 之前。 所以我使用常數列來判斷 `q_sort` 是否為穩定排序,若出現任何排列的動作則 `q_sort` 為不穩頂排序。 仔細檢查之後才發現原本的程式碼錯誤百出,至於為什麼能通過測資還待分析,以下是對程式碼做出的修改 ### `q_merge` :::danger 失敗的過程可能也值得反覆推敲。 ::: >參考[你所不知道的 C 語言: linked list 和非連續記憶體](https://hackmd.io/@sysprog/c-linked-list#%E6%A1%88%E4%BE%8B%E6%8E%A2%E8%A8%8E-LeetCode-86-Partition-List) : >naive 直觀地用第一條串列接上剩下的串列,這樣會導致 lists[0] 愈來愈長,立即會遇到的問題是:多數的情況下合併速度會愈來愈慢。 利用 list_first_entry 來找到第一個節點 (queue_context_t) 並用變數 `l` 來記錄其指標,而 `r` 則用來記錄「下一個」節點的指標。 在 while loop 中,利用 `merge_two` 將剩餘的節點都合併到 `l` 上,合併過後的節點會被移到尾端,若再次造訪則會跳出迴圈 ,這部分是參考自 [alanjian85](https://github.com/alanjian85/lab0-c) 的作法,但與 [alanjian85](https://github.com/alanjian85/lab0-c) 的做法不同之處在於是我利用 `list_empty(r->q)` 來判斷是否造訪過該節點。 :::danger 改進你的漢語表達。 ::: ```c while (!list_empty(r->q)) { merge_two(l->q, r->q, descend); list_move_tail(&r->chain, head); r = list_entry(l->chain.next, queue_contex_t, chain); } ``` >參考 [Queue-Mergesort](https://www.sciencedirect.com/science/article/abs/pii/002001909390088Q?via%3Dihub) >Queue-Mergesort --- ## 研讀論文 [〈Dude, is my code constant time?〉](https://eprint.iacr.org/2016/1123.pdf) > 參考 [jimmylu0303](https://hackmd.io/@jimmylu0303/linux2024-homework1#%E7%A0%94%E8%AE%80%E8%AB%96%E6%96%87-%E3%80%88Dude-is-my-code-constant-time%E3%80%89) 作者在 **Introduction** 中介紹了時間攻擊([Timing attack](https://en.wikipedia.org/wiki/Timing_attack))與其危害,在時間攻擊中,攻擊者會通過分析程式的執行時間差異來推斷出加密過程中使用的密鑰或者其他敏感資訊。 為了防範時間攻擊,工程師會設法讓特定程式的執行時間始終保持恆定 (Constant time),避免因輸入不同而造成執行時間差異,使攻擊者法從該程式的執行時間中獲得有用的資訊。 :::warning 指出之前手法的缺陷。 ::: 然而檢測特定程式是否能維持固定的執行時間絕非易事,作者指出了現行檢測方法的缺點並提出了一套新的測量工具 : > This manual approach can be very time consuming already for moderately sized code bases, and should be repeated for every exact combination of compiler flags being used. 有別於以往的測量方式,作者借用旁路攻擊([Side-channel attack](https://en.wikipedia.org/wiki/Side-channel_attack))的概念來測量程式的執行時間,並利用統計學方法對其進行分析,以便判斷該程式是否能在不同的輸入下依然保持恆定的執行時間。 接著作者在 **OUR APPROACH: TIMING LEAKAGE DETECTION** 中說明了**dudect** 運作的流程: 1. 測量程式在兩筆不同測試項目下的執行時間 2. 利用統計方法分析該程式是否有維持恆定的執行時間 :::warning 討論「恆定的執行時間」一詞是否精準。 ::: 以下是對流程的細節說明: ##### 1.測量執行時間(Repeatedly measure exeution time) * 使用兩筆不同類型(class)的測試資料,分別是固定值(fix)和隨機值(random),固定值為一常數,可以用來測試某些特殊臨界情況。 * 利用現代 CPU 提供的 cycle counters 來作為測量依據 * :::danger 不懂就說不懂,沒有「不太懂」這回事。 ::: 第三點<s>看不懂</s> 為何可以如此操作 >To minimize the effect of environmental changes in the results, each measurement corresponds to a randomly chosen class.1 The class assignment and input preparation tasks are performed prior to the measurement phase. ##### 2.資料預處理(Apply post-processing) * 為了避免程式執行的時候受到作業系統本身或其他外在因素干擾而造成測量錯誤,因此在開始統計前會去掉一些極端值 * High-order preprocessing (我不知道這是幹嘛的) ##### 3.進行統計分析(Apply statistical test) >參考 [2024-03-{19,21} 討論簡記 ](https://hackmd.io/3e8LI8_0SLOo_UTDAnPKYQ) ```graphviz digraph ele_list { //rankdir=LR node[shape=record] head [label="計算 test statistic ", style="bold"] node4 [label="決定自由度(degrees of freedom)", style="bold"] node3 [label="選擇顯著水準 (α)", style="bold"] node7 [label="決定是否拒絕虛無假說", style="bold"] head->node4 node4->node3 node3->node7 } ``` ## 改進 dudect 實作 >參考 [dudect.h](https://github.com/oreparaz/dudect/blob/master/src/dudect.h), [marvin0102](https://hackmd.io/@MpDQFnRmRl2viw8YhUt5Ww/r10UUW83p#percentile-implement), [cheezad](https://hackmd.io/@cheezad/linux2024-homework1#dudect-%E8%AB%96%E6%96%87%E8%88%87%E7%A8%8B%E5%BC%8F%E5%B8%B8%E6%95%B8%E6%99%82%E9%96%93%E7%9A%84%E9%81%94%E6%88%90), [HotMercury](https://github.com/HotMercury/lab0-c) 發現 lab0-c 中沒有做到 Apply post-processing ,因此在從 [dudect.h](https://github.com/oreparaz/dudect/blob/master/src/dudect.h) 中複製了三個函式到 fixture.c 裡面,分別是: * `compare_int64`: 比較兩個 64 位元整數的大小。它是給快速排序函式 (qsort) 使用的,以決定排序順序。 * `percentile`: 計算並返回一個已排序陣列中指定百分位數的值。例如,如果你想找到中位數(即 50% 百分位數),該函式可找到陣列中恰好位於中間位置的值。它首先計算出陣列中對應於所需百分位數的索引位置,然後返回該位置的值。 * `prepare_percentiles`: 對執行時間進行排序,然後計算一系列特定的百分位數。 使用 qsort 進行排序。 利用特殊的公式計算計算每一個元素的百分位數值 1 - (pow(0.5, 10 * (double) (i + 1) / (double) N_MEASURES)), N_MEASURES); :::danger 為何如此? ::: (我不知道) 接著將每個元素替換成對應的百分位數值。 最後記得要在 `fixture.c` 裡面的 `doit` 中加入 `prepare_percentiles(exec_times)` (為什麼?不知道) --- ## 亂數研究及 shuffle 實作 ### 亂數研究 >參考 [亂數](https://hackmd.io/@sysprog/linux2024-lab0/%2F%40sysprog%2Flinux2024-lab0-d) #### 如何確認亂數夠亂? ### q_shuffle >參考 [alanjian85](https://hackmd.io/@alanjian85/lab0-2023#%E5%AF%A6%E4%BD%9C-shuffle-%E5%91%BD%E4%BB%A4) 如何在 qtest 中新增 shuffle 實作、 參考 [HotMercury](https://github.com/HotMercury/lab0-c) 如何使用 extern 、[2024-03-19 討論簡記](https://hackmd.io/3e8LI8_0SLOo_UTDAnPKYQ?both)、[Pearson's chi-squared test ](https://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test) 在 queue.c 中新增 `q_shuffle`: >[commit1030b5](https://github.com/devarajabc/lab0-c/commit/1030b5d4f20d6dce5d6692a51837121a668a6d02) 利用 [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm)演算法來實作洗牌(shuffle) 為什麼要用 [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm) ? :::danger 注意空白字元。 ::: ### 實測與成果 使用 [Pearson's chi-squared test](https://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test) 來驗證 `q_shuffle` (為何不使用 [t-test](https://en.wikipedia.org/wiki/Student%27s_t-test) )? + $H_0$(虛無假說): shuffle 的結果發生的機率相同,遵守 Uniform distribution + $H_1$(對立假說): shuffle 的結果發生的機率至少有一個不同 :::danger 列出 `diff -u` 的結果,不用張貼完整程式碼。 ::: ## 比較亂數產生器 >觀察亂數字串的分布,並運用「資訊與熵互補,資訊就是負熵」的觀念,設計一組新的命令或選項,得以在 qtest 切換不同的 PRNG 的實作 參考 [由大數法則理解訊息熵的數學意義](https://hackmd.io/@8dSak6oVTweMeAe9fXWCPA/ryoegPgw_) 、[yanjiew1](https://hackmd.io/@yanjiew/linux2023q1-lab0#Linux-%E6%A0%B8%E5%BF%83-Linked-List-%E6%8E%92%E5%BA%8F%E7%A0%94%E7%A9%B6) ## 解釋 select 系統呼叫在本程式的使用方式 --- ## 針對 Linux 核心風格的鏈結串列開發 Timsort 排序程式 > 參考 [Timsort 研究與對 Linux 核心貢獻嘗試](https://hackmd.io/@yanjiew/linux2023q1-timsort#Timsort-%E5%B0%8D-Mergesort-%E7%9A%84%E6%94%B9%E5%96%84)、[Wikipedia: Timsort](https://en.wikipedia.org/wiki/Timsort) :::danger 使用明確清晰且流暢的漢語表達。 ::: 以下是我實作的幾個版本: 1. `Timsort_naive` [commit 103640d](https://github.com/devarajabc/lab0-c/commit/103640de08779abba3021449f98ccf5e88c9b83d) > 參考 [第一週測驗](https://hackmd.io/@sysprog/linux2024-quiz1#%E6%B8%AC%E9%A9%97-2) 中使用的版本 、 [yanjiew1](https://github.com/yanjiew1/lab0-c/blob/master/ksort.c) 、[HotMercury](https://hackmd.io/@NeedSleep/linux2024-homework1#%E6%95%B4%E5%90%88-timsort-mergesort-libsort)、[jimmylu890303](https://github.com/jimmylu890303/lab0-c/commit/45a04b7b43f3c6b6e06a17970a55b7ad4b49f201) 此版本使用逐對合併(one-pair-at-a-time) 而非 [Galloping mode](https://en.wikipedia.org/wiki/Timsort#Galloping_mode_during_merge) 且缺乏計算 minrun (最小運行長度)的機制。 此外我看不懂函式指標 `list_cmp_func_t cmp` 的用法,在 閱讀 [Function pointer](https://en.wikipedia.org/wiki/Function_pointer) 後才知道其正確的用法。 :::warning 參照 C 語言規格書。 ::: 參考 [jimmylu890303](https://github.com/jimmylu890303/lab0-c/commit/45a04b7b43f3c6b6e06a17970a55b7ad4b49f201) 將 `q_tim_sort` 加入 `qtest` ,並使用 [jimmylu890303](https://github.com/jimmylu890303/lab0-c/commit/5412ca760c9828229ba56d007d2a073966d336a3) 的測資來測試 `q_tim_sort` ```shell $ ./qtest < traces/trace-test_tim_sort.cmd l = [] l = [jlojw ibobf wojsmiifc bqxdfxw tcqgbze ncfuuzqy ijvzbmtpk ddmwn ggkhinkmv lvvakzhbm zazpevqtq jnxhg vxclmor oaetwm jhrglvn qessrobxy ffdletlf oxzmevgpx yrlejf mxxuxk ftqpbyyxo lsstizr btxxe yfvjr nljrxoag aupsot rmgvx jxrwpyg mzubdze hoypriitx ... ] l = [aaaatuqw aaabcbj aaabxaxkk aaabzdv aaadre aaadt aaadxb aaaed aaafbdz aaafen aaafofg aaafxxnff aaagdmf aaagfy aaagtibpi aaaguse aaahqwm aaahxzvmi aaaioytq aaaiuyo aaaiw aaaiwpc aaajpqey aaajscy aaakjhvx aaakuqts aaamjce aaanasm aaantzl aaanx ... ] Delta time = 1.315 Freeing queue ``` 不過在使用 valgrind cachegrind 分析 cache miss ratio 的時候會遇到錯誤,原因未知 ```shell valgrind --tool=cachegrind ./qtest -f traces/trace-test_tim_sort.cmd --293068-- warning: L3 cache found, using its data for the LL simulation. l = [] ERROR: Time limit exceeded. Either you are in an infinite loop, or your code is too inefficient ERROR: Insertion of uzwwcvas failed (1 failures total) l = [rdsrgsl ... ] l = [aaaaob aaacxjy aaafv aaaigh aaammvz aaamwqgk aaaxieid aabbitjf aabbzzkd aabie aabjj aaboposi aabtcqhd aabxf aabxw aacajv aaccaz aacpcfed aacpgxxo aacpwe aacqnk aacqt aacvstpm aaczayj aaddhmo aadji aadqu aadshzupc aaduij aaduzhn ... ] Freeing queue ERROR: Freed queue, but 1 blocks are still allocated ``` :::danger 幻滅是成長的開始 ::: :::danger 使用明確清晰且流暢的漢語表達。 ::: ## 分析 [lib/list_sort.c](https://github.com/torvalds/linux/commit/b5c56e0cdd62979dd538e5363b06be5bdf735a09) > 參考 [Linux 核心專題: 改進 lib/list_sort.c](https://hackmd.io/@sysprog/Hy5hmaKBh) 、 [csotaku0926](https://hackmd.io/@csotaku0926/linux2024-homework1#%E6%8E%A2%E8%A8%8E-liblib_sortc) 、[kdnvt](https://hackmd.io/byNYeoGvQv-a9TNDc2CKFQ?view#comparison-%E6%AC%A1%E6%95%B8) 、 [ blueskyson](https://hackmd.io/0oQNR91SSRKprDpLbObf6w?view#%E6%AF%94%E8%BC%83%E8%87%AA%E5%B7%B1%E7%9A%84-sort-%E8%88%87-list_sort-%E6%95%88%E8%83%BD%E8%90%BD%E5%B7%AE) 、 [yanjiew1 ](https://hackmd.io/@yanjiew/linux2023q1-lab0#Linux-%E6%A0%B8%E5%BF%83-Linked-List-%E6%8E%92%E5%BA%8F%E7%A0%94%E7%A9%B6) 、[bakudr18](https://hackmd.io/@bakudr18/BkvLMLkeq#Linux-Kernel-list_sort-%E5%AF%A6%E4%BD%9C) (原本的版本有什麼問題?為何需要修改?怎麼修改?) (merge sort vs. quicksort locality) 原先的版本已經用 DFS 來讓比較次數 $n*log_2(n) - K*n + O(1)$ 的領導係數降到理論的極限值(理由做法待補),因此作者著重在一次項的改進。 作者確保兩個子佇列在最糟情況下合併時的長度比為 $2:1$ ,因為當合併兩個**大小差異非常大**的子佇列的時候比較次數會大大上升(理由、數據待補充) 改進後的效果相當顯著: >This achieves the same average K=1.207 as queue-mergesort, which is 0.2*n better then bottom-up, and only 0.04*n behind top-down mergesort. ### 引入至 lab0-c >[commit 83a8434](https://github.com/devarajabc/lab0-c/commit/83a84347c7de996a5c445791bf4fa4b32fc79ad8) u8 是啥? unlikely 是啥 ? ```shell struct list_head *head, **tail = &head; ^ Fail to pass static analysis. ``` ### 該設計對應的排序測試實驗方案 > 參考 [用效能分析工具比較 list_sort.c 及自己實作的排序](https://hackmd.io/byNYeoGvQv-a9TNDc2CKFQ?view#comparison-%E6%AC%A1%E6%95%B8)、[排序測試和效能評估機制](https://hackmd.io/@sysprog/Hy5hmaKBh)、[listsort 的說明文件](https://github.com/python/cpython/blob/main/Objects/listsort.txt) 參考 [fennecJ](https://hackmd.io/@fennecJ/linux2024-q1q2#%E5%8F%83%E8%80%83-cpython-%E6%BA%96%E5%82%99%E8%B3%87%E6%96%99%E9%9B%86%E9%80%B2%E8%A1%8C%E5%AF%A6%E9%A9%97) 所使用的方法: 在 `q_test` 中新增 `test_config` 來將創造測資 將測試以下幾種情況: 1. random data 1. descending data 1. ascending data 1. ascending, then 3 random exchanges 1. ascending, then 10 random at the end 1. ascending, then randomly replace 1% of elements with random values 1. many duplicates 1. all equal 1. worst case scenario --- ## 整合 ttt ### 研讀Linux 核心的浮點數運算 ### 研讀(MCTS) 演算法 ### 針對 ttt 命令的「電腦 vs. 電腦」的對弈模式,引入若干 coroutine ### 嘗試引入其他快速的 PRNG 實作並比較 MCTS 實作獲得的效益 ### 運用定點數來統計不同 AI 實作機制對系統負載的使用率 ### 改寫既有的 `shannon_entropy.c` 和 `log2_lshift16.h`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully