執行人: Daniel-0224
期末專題錄影
chloe0919
能否增加圖表顯示 Fixed point Square root 的實作和浮點數 sqrt 之間的誤差
fennecJ
圖片存取權限未正確設定
問題一
針對 Fixed point Square root 的實做方法,除了第三周測驗一的方法外,也可使用牛頓法進行,可否針對兩者實做方法進行比較,針對 ttt 的應用場景探討兩個作法的優劣
問題二
專題中的定點數採用 Q23.8 的二補數型態,然而本次實做中 mcts 使用到定點數運算的場合應不涉及負數, log 以及開根號也不能針對負數進行運算。是否有機會善用因不會遇到負數而多出來的 1 bit 增加運算精度?
討論一
我嘗試執行了同學提供於 github 上的 專案 ,commit = e4fceab27 ,卻發生 Segmentation fault 。這邊提供發生 Segmentation fault 時我輸入的命令以便同學重現:
之後便發生 Segmentation fault ,請找出導致 Segmentation fault 的原因並改善。
yu-hsiennn
圖片存取權限失敗,以及使用 lab0 規範的程式碼書寫風格,務必用 clang-format 確認一致。
dockyu
如果想以 Linux Kernel 的標準來撰寫程式,要遵循以下的規範,使用 \** *\
The opening comment mark /** is used for kernel-doc comments. The kernel-doc tool will extract comments marked this way. The rest of the comment is formatted like a normal multi-line comment with a column of asterisks on the left side, closing with */ on a line by itself.
ChenFuhuangKye
如何證明歐拉方法的結果幾乎和浮點數 log 相等。
eleanorLYJ
逼近求近似 裡的公式推導 少一個 ")"
randyuncle
能否精簡的呈現您的程式碼,而非直接張貼所有的程式?並對呈現出來的程式碼做說明?
jujuegg
請問你在電腦 vs 電腦的對弈中會有每次測試的棋譜都一樣的問題嗎,只要第一步下的是一樣的位置,接著後面所有的步驟都會完全相同。
重做第三次作業,並彙整其他學員的成果。
MCTS(Monte Carlo Tree Search)
是一種搜尋樹的算法。它通常應用於決策問題的求解,特別是在棋類等遊戲中。MCST
通過隨機模擬和搜尋樹的擴展來評估每個可能的決策,以找到最佳的行動策略。
MCTS
在每一次的疊代一共會有 4
步,分別為:
Selection :
在搜尋樹中從根節點開始,根據某種策略選擇下一步要擴展的節點,以找到潛在最佳的行動。
Expansion :
對於選擇的節點,擴展子節點,即生成可能的下一步行動或狀態。這些子節點尚未被完全探索,需要進一步評估其價值。
Simulation :
對每個擴展的子節點進行模擬或評估。通常使用蒙特卡羅模擬來模擬隨機的遊戲或決策過程,以估計每個子節點的潛在價值或勝率。
Backpropagation :
將模擬結果向上反向傳播到搜尋樹的根節點,更新每個節點的統計信息,如訪問次數和累計獎勵。這有助於調整每個節點的價值估計,以改進未來的選擇策略。
透過不斷迭代的選擇、擴展、模擬和反向傳播,MCTS
能夠在復雜的決策問題中尋找到較佳的解決方案。
定點數運算中, Q notation 是一種指定二進制定點數參數的方法。
假設我們將 fraction bit 設為 ,則一定點數 的實際值為 因此當我們在做定點數的加減時可以直接相加。
但是如果對於定點數的乘除不多加處理的話,結果會變為:
顯然與預期的結果不同,因此在計算完定點樹的乘除之,需要額外對積數與商數右移或左移 位
了解定點數,將 MCTS
當中浮點數運算進行以下更動。
首先在 console.h
定義 SCALING_BITS
。
calculate_win_value
,將 1.0, 0.0, 0.5
全部更換成自定義定點數的形式。
另外一處重點變更在於 uct_score
的計算函式。
公式如下
因為在 EXPLORATION_FACTOR * sqrt(log(n_total) / n_visits)
這一項, sqrt()
, log()
本身就使用浮點數運算,因此我們要設計對應的定點數運算來取代這兩個函式。
此處,利用 第三周測驗一 的方法實作,並且轉為定點數。
嘗試使用泰勒展開實作自然對數的計算,公式如下:
以下是我的實作:
但自己實作時遇到了一些問題,目前還沒解決。
因此參考了
marvin0102
同學的實作
上圖是我利用同學的方法與浮點數 log 比較,可以從實驗結果發現使用泰勒展開,當數字越大時,誤差越大,且需要越多的項次才能做精準的估算。
為了改善泰勒展開數字越大時誤差越大的問題,嘗試利用逼近法求 log 的近似值,假設 ,求其近似值,方法如下:
,因為 ,因此我們可以得到 為 、 的平均。
接著比較 與 ,如果 及得到我們所求,如果 ,我們則將 替換成 ,如果 ,我們則將 替換成 ,繼續下一輪的求近似。
因為求近似值時,須先知道 、 的實際值,因此實作時,將以 做計算,且 分別為 及 ,其中 。
實作如下:
歐拉方法的結果幾乎和浮點數 log 相等。
linux/list.h
和 jserv/ttt
首先將 Linux
核心的 linux/list.h
標頭檔與 hlist
相關的程式碼抽出,成為 hlist.h
整合進 lab-0
,再將 jserv/ttt
專案的程式碼部分整合進 lab0-c
。其中包含 console
,game
, mt19937
, mcts
, negamex
等檔案。
ttt
命令將 jserv/ttt
的 main
檔案修改整合入 console.c
,新增ADD_COMMMAND
,修改 Makefile
讓程式能夠執行。
commit 95a09bc
做完上述方法就能執行 qtest
再使用 do_ttt
開始玩 Tic-Tac-Toe
。
增加 option
指令 AI_vs_AI
,讓 AI
和 AI
對弈,使用的演算法是 negamax
。
預設值為 0
,欲更改時需要設定 AI_vs_AI
的參數。在 qtest
要下的命令是:option AI_vs_AI 1
螢幕顯示當下的時間 (含秒數):
部份結果:
使用 coroutine 的方式實作「電腦 vs 電腦」的對弈模式,其中電腦 A 是使用 negamax 演算法,而電腦 B 是使用 MCTS 演算法。而電腦 A、B 分別對應到 task0 及 task1。至於任務之間的切換,是採用 setjmp
+ longjmp
的方法。
首先可以看到 struct task
有 2 個成員,分別為用於 setjmp()
的 jmp_buf
env
以及用於排程的 list
。第一個成員變數 env
即是用來儲存這次進入任務前的程式執行狀態。
這兩個函式可以轉換程式執行的順序,其中 setjmp
可以利用 jum_buf
儲存目前程式的狀態,並且在遇到 longjmp(jum_buf)
後跳回 setjmp
並恢復程式的儲存狀態,這樣的函式設計可以方便程式執行時在不同任務間轉換。
這是主要切換任務的函式,我們用 list_head
構成的循環雙向鏈結串列存放即將執行的任務,也就是存放 jmp_buf
。其中 task_add
可以將任務加到串列當中, task_switch
可以切換到我們紀錄的下一個任務執行。
流程設計參照下方程式碼, schedule
函式會將兩個任務放到佇列中,而任務執行完的當下會再將這個任務加到佇列當中,若此對局勝負揭曉則不會再將加到佇列當中,佇列為空也就代表並行程式結束執行。
而 task0
和 task1
的結構一樣,有三大部份,第一部份根據 schedule()
設定的參數決定迴圈次數,將 task 加入排程後呼叫 longjmp(sched, 1)
,讓 schedule()
可繼續將新任務加進排程。當所有任務被加入排程後,schedule()
會呼叫 task_join(&tasklist)
,其中,會根據 list 的 first entry longjmp
回該 task 的 setjmp
位置:
第二部份是兩個 task 交互排程,每次執行一個 loop 後,呼叫 task_add()
重新將 task 加入 list 的尾端,並呼叫 task_switch
指定 list 的 first task 執行:
第三部份完成該 task,會呼叫 longjmp(sched, 1)
跳到 schedule()
,接著會執行 task_join(&tasklist)
執行尚未執行完的 task:
在 MCTS
中,利用 PRNG
來產生亂數,以隨機挑選每次模擬中下一步的位置。原本的實作使用 glibc
的 rand()
函式來產生亂數。以 4x4
的棋盤為例,每次最多可能有 15
種不同的選項,我用 0
到 14
來代表這些選項,並使用 rand()
進行了一億次的抽樣,接著利用 perf stat
執行五次 ttt
來測量程式的效能表現,分佈結果如下。
結論:
亂數分佈除了 mt19937_rand()
相對平均一些,其他分佈都有較明顯的差異。
雖然每個方法都大約差了0.05 至 0.2秒,和差幾億個 cycle,但是沒有像 vax-r
同學的實驗結果差異那麽明顯,目前不確定是否是實驗方法有細節的不同。
改寫 lab0-c 既有的 shannon_entropy.c 和 log2_lshift16.h,採用更有效、準確度 (accuracy) 更高的定點數運算實作,需要有對應的數學統計分析和實際執行的討論。