# 2024q1 Homework1 (lab0)
contributed by < `tseng0201` >
# 開發環境
```shell
$ gcc -v
gcc version 12.3.0 (Ubuntu 12.3.0-1ubuntu1~23.04)
$ 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): 16
On-line CPU(s) list: 0-15
Vendor ID: GenuineIntel
Model name: 12th Gen Intel(R) Core(TM) i7-12650H
CPU family: 6
Model: 154
Thread(s) per core: 2
Core(s) per socket: 10
Socket(s): 1
Stepping: 3
CPU(s) scaling MHz: 39%
CPU max MHz: 4700.0000
CPU min MHz: 400.0000
BogoMIPS: 5376.00
```
## 指定的佇列操作
> 延伸 [2023q1 Homework1 (lab0)](https://hackmd.io/6-xzV21LTWGz9I2uOnYSdg?view),本頁面紀錄今年度的更改。
### `q_ascend`
:::danger
對照 Dictionary.com 對 [implement](https://www.dictionary.com/browse/implement) 一詞的解釋:
* to fulfill; perform; carry out:
* to put into effect according to or by means of a definite plan or procedure.
* Computers. to realize or instantiate (an element in a program), often under certain conditions as specified by the software involved.
* to fill out or supplement
「實作」會是符合上述 "implement" 語意的譯詞,取「起」以「創作」的意思,而「製造」本質上是固定輸入並通常產生固定輸出的行為。
$\to$ [資訊科技詞彙翻譯](https://hackmd.io/@sysprog/it-vocabulary)
:::
<s>實現</s> 與 q_descend 大致相同,只是將 if 判斷式由 (cmp >= 0) 改為 (cmp <= 0)
```c
int q_ascend(struct list_head *head)
{
// https://leetcode.com/problems/remove-nodes-from-linked-list/
if (!head || list_empty(head))
return 0;
struct list_head *ptr = head->prev;
while (ptr != head && ptr->prev != head) {
int cmp = strcmp(list_entry(ptr, element_t, list)->value,
list_entry(ptr->prev, element_t, list)->value);
if (cmp <= 0)
q_delete_element(ptr->prev);
else
ptr = ptr->prev;
}
return q_size(head);
}
```
### `merge_two_sorted_list`
:::danger
在中文敘述中,使用全形標點符號,例如該用「,」,而非 ","
:::
加入 bool descend 參數,決定排序的方式是升序還是降序<s>, </s> 透過對 strcmp 的回傳值與 descend 進行 XOR 運算改變比較的結果。
```diff
- struct list_head *merge_two_sorted_list(struct list_head *q_1, struct list_head *q_2)
+ struct list_head *merge_two_sorted_list(struct list_head *q_1, struct list_head *q_2, bool descend)
{
if (!q_1 || !q_2)
return (struct list_head *) ((__UINTPTR_TYPE__) q_1 |
(__UINTPTR_TYPE__) q_2);
struct list_head *head = NULL, **ptr = &head, **node;
for (node = NULL; (__UINTPTR_TYPE__) q_1 & (__UINTPTR_TYPE__) q_2;
*node = (*node)->next) {
node = ((strcmp(list_entry(q_1, element_t, list)->value,
- list_entry(q_2, element_t, list)->value) <= 0))
+ list_entry(q_2, element_t, list)->value) <= 0) ^ descend)
? &q_1
: &q_2;
*ptr = *node;
ptr = &(*ptr)->next;
}
*ptr =
(struct list_head *) ((__UINTPTR_TYPE__) q_1 | (__UINTPTR_TYPE__) q_2);
return head;
}
```
---
## 改進 dudect
### 引入 [oreparaz/dudect](https://github.com/oreparaz/dudect) 中 percentile 處理
### 修正排序後數據不匹配的問題
在原始論文中,prepare_percentiles 函數僅對 ctx->exec_times 進行排序,卻未對其相應的 ctx->classes 進行同步排序,這造成了排序後的時間和類別之間失去了一致對應關係。以下由 ChatGPT 提供的程式碼示例引入了一個新的結構體,用於在排序過程中保留 exec_times 與 classes 之間的關聯性。
:::danger
程式碼註解一律使用美式英語書寫。
:::
```diff
+// 定義一個結構體來存儲每次測量的時間和類別
+typedef struct {
+ uint64_t time; // 假設時間使用 uint64_t 類型
+ int class; // 對應的類別
+} measurement_t;
+// 比較函數,用於根據時間排序
+int compare_measurements(const void *a, const void *b) {
+ const measurement_t *ma = (const measurement_t *)a;
+ const measurement_t *mb = (const measurement_t *)b;
+ return ma->time - mb->time;
+}
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);
+ measurement_t *measurements = malloc(ctx->config->number_measurements * sizeof(measurement_t));
+ // 填充結構體數據
+ for (size_t i = 0; i < ctx->config->number_measurements; i++) {
+ measurements[i].time = ctx->exec_times[i];
+ measurements[i].class = ctx->classes[i];
+ }
+ // 對結構體數組進行排序
+ qsort(measurements, ctx->config->number_measurements, sizeof(measurement_t), compare_measurements);
+ // 將排序後的數據寫回 ctx 結構
+ for (size_t i = 0; i < ctx->config->number_measurements; i++) {
+ ctx->exec_times[i] = measurements[i].time;
+ ctx->classes[i] = measurements[i].class;
+ }
+ free(measurements); // 釋放臨時數組
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);
}
}
```
:::warning
改進此部分程式後,以數學分析確認其效益。
:::