tianbing
    • 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 < [yc199911](https://github.com/yc199911) > ### Reviewed by `yenslife` - [ ] 共筆 除非要討論特定行數,否則程式碼區塊不該出現行號,將 \`\`\`c= 的 `=` 刪除即可。 :::info 已改進 ::: - [ ] git commit message 一個 commit 只能說明一個改動,在 commit [66da54e](https://github.com/yc199911/lab0-c/commit/66da54e282e0b595d9867d9e336af7617d12cf2b) 中,雖然 commit 標題為 "Fix q_delete_mid",實際上卻涉及了 `q_sort`, `MERGE_TWO_LISTS`,以及 Makefile 的修改。可以使用 `git rebase` 來修改 commit message。 :::info 謝謝提醒,等達到 95/100 後會先來將我的 commit message 符合老師所要求的規格。 ::: - [ ] Lima 因為我也是安裝 Lima,之前遇過無法讀寫的問題,如果你有遇到可以參考[在 Mac 上使用 lima 作為 Linux 環境](https://yenslife.top/2022/07/05/use-lima-on-mac-as-linux-environment/)。 :::info 謝謝,我會去使用。 ::: - [ ] 註解 使用英文來撰寫註解,讓全世界都看得懂台灣人寫的程式碼。 #### `q_remove_tail` / `q_remove_head` , `q_insert_head` / `q_insert_tail` 直接在 `q_remove_tail` 中呼叫 `q_remove_head` 即可,減少重複程式碼。注意 `list_first_entry` 會回傳 `head` 的下一個節點,所以要傳入 `head->prev->prev` 才是指向尾端節點。 ```graphviz digraph main { node[shape=plaintext] head [fontcolor="red"]; l [label="list_first_entry(head->prev->prev, ...)",fontcolor="blue"]; node[shape=box] s0 [label="1"]; s1 [label="2"]; s2 [label="3"]; s3 [label="4"]; s4 [label="5"]; s5 [label="6"]; { rank="same"; s0->s1 s1->s0 s1->s2 s2->s1 s2->s3 s3->s2 s3->s4 s4->s3 s4->s5 s5->s4 s5->s0 s0->s5 } head->s0 l->s5 } ``` `q_insert` 函式也是相同的道理。 #### `q_reverse` 利用 list API 來簡化 `q_reverse` 實作:其實可以用 `list_move` 直接將走訪到的節點移到開頭,減少程式碼數量。 ```diff struct list_head *node; struct list_head *safe; list_for_each_safe (node, safe, head) { + list_move(node, head); - node->next = node->prev; - node->prev = safe; } - node->next = node->prev; - node->prev = safe; return; ``` ### Reviewed by `yeh-sudo` #### Git commit messages Git commit message 的標題要用祈使句撰寫,另外,內文要清楚地描述什麼東西改變以及為什麼,以 commit [25ef64e](https://github.com/yc199911/lab0-c/commit/25ef64e2de46ffb9949db62a8730b8f7acdc5d0e) 為例,標題為 Q_delete_mid, q_delete_dup, q_swap, q_reverse ,並沒有以祈使句作為標題,也沒有內文,可以使用 `git rebase -i` 來作修改,撰寫 commit message 的部份可以參考〈[How to Write a Git Commit Message](https://cbea.ms/git-commit/)〉。 #### 註解 使用英文撰寫註解。 - [ ] `queue.c` ```c=47 INIT_LIST_HEAD(&new_node->list); // 分配足夠的記憶體來容納字串 s,包括結尾的空字符 '\0' char *new_char = malloc((strlen(s) + 1) * sizeof(char)); if (!new_char) { free(new_node); return false; } // 複製字串 s 的內容到新分配的記憶體中 strncpy(new_char, s, strlen(s)); new_char[strlen(s)] = '\0'; ``` #### `q_sort` `q_sort` 中有錯誤,沒辦法以降序的方式排列,每次排序的結果都是升序。 - [ ] 錯誤範例測試 ```shell cmd> option descend 1 cmd> new l = [] cmd> it RAND 1000 l = [hudumqb bdppnzl wymtypi sebldew azpxz pjhiq rcslvl zubsom yjqbkzisf dqewwj pivroo mewgkppc mtvkwln tpudayxj qmmcnqjvm qgglpj gcubqk qnkdrlyj jcfmfruo mmzzgionr dqojg ejpqojx dyonu cplkfmbny bkiwhjnc wkuzcm hdzho jqzuceg lpozuth avmhgnoao ... ] cmd> sort ERROR: Not sorted in descending order l = [abosmmy adsyvvzxx aftbathc ageuvu agijmnf agokvor agxldjnsd ahtwb aizpiwar ajnpj ajyxzlynx akantgjci aksymuk allhocnn alxmzytep amxunj anhekvive aomsd aoxgokvp arzfsu aseea asfxyx asurtc atjgaayyh atnetaig auomwt avmhgnoao axbsry axclmhhk axuabkixn ... ] cmd> free l = NULL cmd> quit Freeing queue ``` #### 共筆 時間複雜度或是數學式可以使用 Latex ,像是這樣 $O(n^2)$ ,會比較好看懂。 ### 系統安裝 一開始用實驗室電腦想要安裝 ubuntu 系統,但照著影片的方法都一直無法成功,後來看了許久才發現原來實驗室電腦老舊,沒有現在常用的 UEFI 讀取,而只有 legacy ,導致一開始一直誤以為是 usb 的 ubuntu 系統沒安裝好(這種狀況使用隨身碟開機會顯示"沒有讀取到東西,請按鍵繼續") 而我本身是 mac air m2 有找過網路好像也沒辦法使用雙系統,想問老師有其他方法嗎? (目前已有一台電腦能夠順利跑 ubuntu 系統) :::warning 請愛用 [lima](https://github.com/lima-vm/lima),作業說明已提過。 ::: ### 開發環境 $ gcc --version gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions.There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 48 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 16 On-line CPU(s) list: 0-15 Vendor ID: AuthenticAMD Model name: AMD Ryzen 7 7700X 8-Core Processor CPU family: 25 Model: 97 Thread(s) per core: 2 Core(s) per socket: 8 Socket(s): 1 Stepping: 2 CPU max MHz: 5573.0000 CPU min MHz: 400.0000 BogoMIPS: 8982.75 ### 閱讀文章吸取到的想法 原本看 list.h 後面所提及的程式都沒有太大的概念,再重看幾次[你所不知道的 C 語言: linked list 和非連續記憶體](/YA7RMqd6RE2UL8OmmjU9PQ) 這張圖讓我對於 list.h 裡的結構更加清楚,我們可以把 list_head 想成是將每個物件串連起來的鉤子, `list_head *node` 就是這個物件的<s>名子</s> ???,而像 int `value;char *s` 這種就像是物件裡面的內容,讓我對於 linked list 結構的閱讀更加迅速也<s>更有畫面</s> ![](https://hackmd.io/_uploads/ByHFSCRit.png) :::danger 改進你的漢語表達。 ::: ### 指定佇列操作 #### q_new 這是第一個開始寫的 function ,對於怎麼去使用 list.h 裡的函數很不熟悉,我處理的步驟是: 1. 看 queue.h 裡的介紹 2. 想好如何產生一個節點 3. 去 list.h 找所需使用到的函數 ```c= struct list_head *head = malloc(sizeof(struct list_head)); if (head == NULL) return NULL; INIT_LIST_HEAD(head); return head; ``` 雖然這個程式想法很單純,但對 linked list 不熟的時候還是需要花時間想 我覺得 [你所不知道的 C 語言: linked list 和非連續記憶體](/YA7RMqd6RE2UL8OmmjU9PQ) 的圖讓我對理解幫助很大 ```c= struct list_head { struct list_head *prev; struct list_head *next; }; ``` ```graphviz digraph list_head { rankdir=LR; node[shape=record, style=bold]; head [label="{<prev>prev|<next>next}"]; } ``` #### q_free 寫完 q_new 後對 list.h 比較了解後,q_free所花的時間就少很多 但目前僅僅是讓 ./qtest 執行上沒有出錯。 透過 ./qtest 後發現 ERROR: There is no queue, but 3 blocks are still allocated 發現我原本這樣寫只會 free element_t *entry 物件裡的指標,但因為 element_t 是一個包含 value 跟 list_head的結構,所以要使用 list.h 裡的 q_release_element 才能將 element_t 裡的結構移除,之後只剩下空的 list 在使用 free 將它移除 ```diff - list_del(&entry->list); - free(entry); + q_release_element(entry); + } + free(l); ``` #### q_insert_head ```c +++ TESTING trace trace-01-ops: # Test of insert_head and remove_head ERROR: Need to allocate and copy string for new queue element ERROR: Need to allocate and copy string for new queue element ERROR: Need to allocate and copy string for new queue element ERROR: Attempted to free unallocated block. Address = 0x561689a59a30 ERROR: Attempted to free unallocated or corrupted block. Address = 0x561689a59a30 ERROR: Corruption detected in block with address 0x561689a59a30 when attempting to free it Segmentation fault occurred. You dereferenced a NULL or invalid pointer--- trace-01-ops 0/5 ``` 在編譯完成後 做 make test 發現只有一題拿到分數 我從最上面開始檢查,看到我需要 "copy string for new queue element" 我去規格書上搜尋 copy copies copying 這些關鍵字接著在裡面發現 strcpy() , strncpy() 我就拿著這兩個關鍵字去規格書中搜尋, 因為 strcpy() 的資料型態沒有 size_t ,所以我選擇 strncpy() 接著重翻 [你所不知道的 C 語言:指標篇](/hqJBzualRcOrb2wMhheKCQ)發現其實下面的範例就有使用到 規格書裡 7.21.2.3 The strcpy function ```c char *strcpy(char * restrict s1,const char * restrict s2); ``` > strcpy() > The strcpy function copies the string pointed to by s2 (including the terminating null character) into the array pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined. 7.21.2.4 The strncpy function ```c char *strncpy(char * restrict s1,const char * restrict s2,size_t n); ``` > The strncpy function copies not more than n characters (characters that followanull character are not copied) from the array pointed to by s2 to the array pointed to by s1. > If copying takes place between objects that overlap, the behavior is undefined. 原本的 q_insert 雖然能夠成功編譯,但當我執行 ./qtest 時會得到 "l = [dolphinU���]" 參考過之前同學的文件後,有可能是記憶體問題,所以我將要以這個方向去檢查。 ```diff + new_char[strlen(s)] = '\0'; ``` <s> </s> :::danger 文字訊息避免用圖片來表示,否則不好搜尋和分類 ::: 因為原本 ih 一直會有亂碼,所以我打算用 `make SANITIZER=1` 去強化執行時期的記憶體檢測,接著照終端執行報錯進行更正,成功讓 ih dolphin 不再有亂碼。 覺得自己學到使用規格書的方法:在腦袋中思考步驟後將不知道如何實作的語法去搜尋再到規格書去確認正確性! #### q_remove_head #### q_swap 目前我自己的程式碼會導致 "ERROR: Time limit exceeded. Either you are in an infinite loop, or your code is too inefficient" ```diff - for (; curr && curr->next != head; curr = curr->next) - list_move(curr, curr->next); + list_for_each_safe (first, second, head){ + if (first == second) + break; + list_move(second, first); + head = first; + second = first->next; + } + } 改進後 commit 顯示這兩行沒有使用到 + head = first; + second = first->next; ``` :::danger 使用 `git diff` 或 `diff -u` 命令去產生程式碼之間的變異,不要憑感覺填入。 ::: 後來一直無法通過測試,我改使用更改每個結構的 `prev` 和 `next` 去達成 swap的效果。 一開始只想到兩個點將他們互換,而後來發現忽略了這兩個點的前後。 ```c second->prev = first->prev; first->next = second->next; first->prev = second; second->next = first; first = first->next; ``` 而當我補上要被交換的前後兩個點的 `prev` 和 `next` 後發現一樣無法通過測試,我丟到 chatgpt 上詢問有沒有語法或是哪裡錯誤時, Chatgpt 指出: ```c second->next->prev = first; ``` 應該在 `second` 和 `first` 節點交換位置之後,而不是之前。因為在交換位置之前,`second->next` 指向的節點可能已經被更改為 `first`,如果直接在這裡訪問 `second->next->prev`,可能會導致訪問到無效的內存,從而引發未定義的行為。 但後來我發現問題其實不是在那裡,是因為我初始化 `list_for_each_safe` 的條件用錯了,因為 `list_for_each_safe` 執行完一次本來就會將 `first = first->next` 而因為經過 swap 後 `first` 已經在 `second` 之後,所以只需要更新 `second` 的條件。 ```diff - first = first->next; + second = first->next; ``` #### q_del_mid 這題是看到 [分析「快慢指標」](/NDN4SlBNQvCVZZ1YgYBtHg) 裡學到使用一個fast指標再用一個 slow 指標 而再透過 for 迴圈後先執行的是 slow 指標,使 slow 指標會是 (floor(fast) / 2) + 1 這裡有發現 queue.h 裡面這兩句敘述有錯,但後來看到 leetcode 上面敘述 * ⌊n / 2⌋th node from the start using 0-based indexing. * If there're six elements, the third member should be returned. 如果有六個元素,應該是第四個要被輸出。 但現在的寫法會發生執行過久或無法跳出迴圈。 ```diff= -while (fast && fast->next) +while (fast->next != head && fast != head) ``` 中途有改一個判斷式結果只是因為條件很多所以自己在測試的時候會過,後來進行 make test 一直無法順利通過,我使用 valgrind 去看每個步驟,跑出segamentation fault 還有記憶體沒有釋放,一開始一直誤以為是有什麼地方忘記,但在重新看 q_release_element 發現他就已經有釋放記憶體,看了整整一個下午最後發現是 while 迴圈就已經出了問題。 Debug 時可以先檢查 while 或 for 迴圈裡面的條件再去逐一檢查其他的程式 #### `q_sort`, `q_merge` 一開始我使用最好想的方法: 1. 使用 list_for_each_safe 2. 將每個值去做 if else判斷 3. 再進行 merge 這樣就可以排序完成。 當初我有想到要用 merge sort ,但因為寫了很久,我參考 [chloe0919](https://hackmd.io/@Chloexyw/linux2024-homework1#%E9%96%8B%E7%99%BC%E7%92%B0%E5%A2%83),並將寫法學習起來。 [git commit](https://github.com/yc199911/lab0-c/commit/7ae3b7a3bb701e7fb2efa413a7274e739a3e6b03) ```diff - list_move(Rnode, Lnode->prev); + list_move(Rnode->prev, Lnode->prev); ``` 因為一開始一直沒注意到前一行 Rnode = Rnode->next 所以一直沒發現這裡寫錯 `list_move(Rnode, Lnode->prev)` 在這之中發現自己總是能想到程式大概怎麼樣能完成題目所需,但總是會東缺西漏,認知到自己基礎程式語言能力的不足。 目前已有去將 [C 語言入門](https://www.youtube.com/watch?v=yWPGumB64tM&list=PLY_qIufNHc293YnIjVeEwNDuqGo8y2Emx) 大部分內容看完。 #### q_descend ```c list_for_each_entry_safe (first, second, head, list) { if (second->value > first->value) list_del(&first->list); ``` 一開始誤以為這樣就能達成題目要求,後來發現如果題目為 [5, 1, 2, 4, 3 ] 那就不會是題目所要求的答案。 :::danger 改進你的漢語表達 ::: ```c max = list_entry(head->next, element_t, list); list_for_each_entry_safe(tmp, safe, head, list) { if (strcmp(max->value, tmp->value) < 0) { max = tmp; } } for (tmp = max; &tmp->list != head; tmp = safe) { safe = list_entry(tmp->list.next, element_t, list); if (strcmp(tmp->value, safe->value) < 0) { if (strcmp(max->value, safe->value) < 0) { list_del(&max->list); q_release_element(max); max = safe; } list_del(&tmp->list); q_release_element(tmp); } } return q_size(head); } ``` 後來我想先找到這個串列裡面的最大值 max ,接著將 max 之前的 element 都刪除,之後再從 max 之後的串列中進行比大小,但發現這樣會導致時間複雜度到 O(n^2) ,我參考 leetcode 的提示,發現如果一開始就將串列反轉,就可以省去很多不必要的重複比較,例如[5, 1, 3, 2, 4] 這個例子中,我就不需要再比較 3, 4 中哪一個比較大。 #### q_delete_dup 改進後,目前 TESTING trace trace-06-ops 出現以下問題,發現是 `q_delete_dup` 這個函式尚有問題。 Test of insert_head, insert_tail, delete duplicate, sort, descend and reverseK ERROR: Duplicate strings are in queue or distinct strings are not in queue ERROR: There is no queue, but 1 blocks are still allocated ERROR: There is no queue, but 1 blocks are still allocated ERROR: Freed queue, but 1 blocks are still allocated 原先 `temp` 指標誤配置了記憶體,導致 `There is no queue, but 1 blocks are still allocated`,修正完成後,這個 `error` 已經修正完畢,但還是有 `ERROR: Duplicate strings are in queue or distinct strings are not in queue` 這個問題,發現判斷式也出現了問題,我參考 [vax-r](https://hackmd.io/@vax-r/linux2024-homework1) 的作業進行調整。 調整後目前 qtest 分數為 95/100 ### 論文〈Dude, is my code constant time?〉 一開始看到[dudect.h](https://github.com/oreparaz/dudect/blob/master/src/dudect.h) 的程式碼想說能不能直接套用,但套用進去後執行會發現 ``` /usr/bin/ld: qtest.o: in function `queue_remove': /home/allen/linux2024/lab0-c/qtest.c:302: undefined reference to `is_remove_tail_const' /usr/bin/ld: /home/allen/linux2024/lab0-c/qtest.c:302: undefined reference to `is_remove_head_const' /usr/bin/ld: qtest.o: in function `queue_insert': /home/allen/linux2024/lab0-c/qtest.c:190: undefined reference to `is_insert_tail_const' /usr/bin/ld: /home/allen/linux2024/lab0-c/qtest.c:190: undefined reference to `is_insert_head_const' collect2: error: ld returned 1 exit status ``` 之後我參考 [vax-r](https://hackmd.io/@vax-r/linux2024-homework1) 同學的筆記,發現原來老師已經將這些用一個函式將這些 `simulation` 裡需要的函式精簡的寫在這個 marco。 ```c #define DUT_FUNC_IMPL(op) \ bool is_##op##_const(void) \ { \ return test_const(#op, DUT(op)); \ } #define _(x) DUT_FUNC_IMPL(x) DUT_FUNCS #undef _ ``` `DUT_FUNC_IMPL` 它接受一個參數 op,並將其用作函數名的一部分。這個定義了一個返回布爾值的函數,其名稱格式為 `is_op_const`,其中 `op` 是傳入的參數。 `#define _(x) DUT_FUNC_IMPL(x)`:定義將 _(x) 替換為 `DUT_FUNC_IMPL(x)`,這意味著當您使用 `_` 並提供一個參數時,它將展開為對應的 `DUT_FUNC_IMPL` 。 `DUT_FUNCS`:這個用來展開一系列 `_(x)` ,其中 x 是由 `DUT_FUNC_IMPL` 中的 `op` 參數提供的值。這將生成一系列函數的實作,其名稱格式為 `is_x_const`。 而這個 marco 的好處在於:可以自動生成一系列函數的實作,這些函數的名稱格式為 `is_x_const`,其中 x 是由 DUT_FUNCS 提供的一系列值。這樣可以節省大量的重複性工作,使代碼更加簡潔和易於維護。 :::danger 改進用語,macro 是「巨集」,implement 是「實作」 ::: :::info ok! ::: 在讀論文的 `Implementation` 的 `a. Pre-precessing` 寫著 ``` We pre-process measurements prior to statistical processing. We discard measurements that are larger than the p percentile, for various2 values of p. The rationale here is to test a restricted distribution range, especially the lower cycle count tail. The upper tail may be more influenced by data-independent noise. This (heuristic) process gives good empirical results (makes detection faster); nevertheless we also process measurements without pre-processing. ``` 而我在 [dudect.h](https://github.com/oreparaz/dudect/blob/master/src/dudect.h) 中發現有關 `percentile` 的程式碼理解並加入 lab0 裡面。 在這裡原始程式碼將迴圈從第十筆開始進行,我認為作者可能是為了跳過最初的幾個測量值,為了減輕實驗中可能存在的啟動效應或其他不穩定因素對結果的影響。 ```diff - for (size_t i = 0 /* discard the first few measurements */; i < (ctx->config->number_measurements-1); i++) { int64_t difference = ctx->exec_times[i]; + for (size_t i = 10 /* discard the first few measurements */; i < (ctx->config->number_measurements-1); i++) { int64_t difference = ctx->exec_times[i]; ``` ```c static int cmp(const int64_t *a, const int64_t *b) { if (*a == *b) return 0; return (*a > *b) ? 1 : -1; } static int64_t percentile(int64_t *a_sorted, double which, size_t size) { size_t array_position = (size_t)((double)size * (double)which); assert(array_position < size); return a_sorted[array_position]; } /* set different thresholds for cropping measurements. the exponential tendency is meant to approximately match the measurements distribution, but there's not more science than that. */ static void prepare_percentiles(dudect_ctx_t *ctx) { qsort(ctx->exec_times, ctx->config->number_measurements, sizeof(int64_t), (int (*)(const void *, const void *))cmp); for (size_t i = 0; i < DUDECT_NUMBER_PERCENTILES; i++) { ctx->percentiles[i] = percentile( ctx->exec_times, 1 - (pow(0.5, 10 * (double)(i + 1) / DUDECT_NUMBER_PERCENTILES)), ctx->config->number_measurements); } } ``` `cmp` 函數定義了一個比較函數,用於對整數陣列進行排序。該函數根據整數值的大小進行比較,如果第一個參數大於第二個參數,則返回 1;如果兩個參數相等,則返回 0;否則返回 -1。 `percentile` 函數計算了排序後整數陣列中特定百分位數的值。它接受三個參數:已經排序的整數陣列 a_sorted、要計算的百分位數 which、以及整數陣列的大小 size。該函數根據百分位數的大小將陣列位置計算為 `(size_t)((double)size * (double)which)`,並返回對應位置的值。 `prepare_percentiles` 函數根據給定的測量值陣列 `exec_times`,計算了一系列百分位數並存儲在 `percentiles` 陣列中。它首先將測量值陣列進行排序,然後使用 `percentile` 函數來計算一系列百分位數。該函數根據 `DUDECT_NUMBER_PERCENTILES` 定義的百分位數數量,計算不同百分位數的值。通過使用指數函數 `pow(0.5, 10 * (double)(i + 1) / DUDECT_NUMBER_PERCENTILES)`,可以在數學上更好地匹配測量值的分佈,但實際上並沒有更多的科學依據。 加入後成功使 make test 獲得 100/100 ### 研讀 Linux 核心原始程式碼的 lib/list_sort.c〉 #### 將 list_sort 加入lab0-c 參考 [wanghanchi](https://hackmd.io/@wanghanchi/linux2023-lab0#%E7%A0%94%E8%AE%80-Linux-%E6%A0%B8%E5%BF%83%E5%8E%9F%E5%A7%8B%E7%A8%8B%E5%BC%8F%E7%A2%BC%E7%9A%84-liblist_sortc) 學習他的做法順利將 list_sort 加入 lab0-c 其中不明白為什麼要將 Makefile 中 OBJS,新增一個 list_sort.o 經過<s>查詢</s> 後發現: :::danger 閱讀 GNU make 手冊,而非仰賴經由 Google 搜尋得來的隻字片語 ::: :::info 已有去查詢 GNU make 手冊,了解 OBJS 為一個變數,而將 list_sort.o 加入後在之後需要編譯時只需要加上 $ 即可不用重複輸入所要編譯的檔案。 ::: 在 Makefile 中添加 OBJS 列表的目的是為了告訴 make 工具程序編譯器需要編譯哪些檔案,並將它們編譯成最終的可執行文件。每個文件對應一個目標檔(object file),而 OBJS 列表就是這些目標檔的集合。 :::danger file 是「檔案」,而非「文件」(document)。 source file 是「原始程式碼」。 強調相互結合的意境時,譯作「連結」,例如「動態連結函式庫」(dynamic-link library),而強調資料因結合而呈現鏈狀樣貌,用「鏈結」,如鏈結串列 (linked list)。 project 是「專案」,而非「項目」(item) 參見[詞彙對照表](https://hackmd.io/@l10n-tw/glossaries) ::: :::info 了解! ::: 如果需要在 Makefile 中添加一個名為 list_sort.o 的目標檔,就是你的專案中引入了一個名為 list_sort.c 的檔案,並且需要將其編譯成一個目標檔。這通常發生在你的項目中使用了自行實作的排序演算法,並且需要將其編譯成一個獨立的目標檔,以便在連結時使用。

    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