• 沒有找到結果。

第四章 改良方法與步驟

4.5 Collision 避免

目前製作 Transposition Table 大多都會面臨 Collision 的問題,而現行的改善 低一倍的 Collision Rate。

而第二種方法,若增加資訊儲存量同樣也能夠確保 Collision Rate 的下降,但 同時儲存成本以及檢查成本則會大幅上升,這在要求搜尋速度的棋類遊戲搜尋顯 然是相當不適用。

雙層或多層的 Hash Table,若不增加儲存額外資訊的話,即使都有將值存入,

但發生 Collision 時,我們沒有辦法得知哪一筆資料才是正確的,所以仍需存入額 外資訊判別哪一個才是正確的資料,Hash Key 只是檢查的第一道關卡。

綜合目前許多程式的作法,普遍傾向於承擔 Collision 的風險,因為 Collision Rate 通常在數千到數萬分之一,看起來相當低,並且發生 Collision 的節點還有不 一定會出現在主要分支上,劇烈影響搜尋結果導致錯誤。

通過 Transposition Table,我們得以進行更深層的搜尋,但在同時由於搜尋節 點數量的急遽增加, Collision 所累積的風險會導致每次的搜尋都有更多的機會出 錯,而一盤棋只要出了數次錯誤通常就大勢已去,這是不允許的。

經過多方測試,我們發現一個方式可以有效的針對 Zobrist Hash 來做 Collision 的檢測,並且實作簡單效果好。其敘述如下。

這個方式的核心概念是針對所存的資料做二次檢查,但與前面所提方法不同 的是,我們所額外儲存的東西簡單而且可以有效降低 Collision Rate。

這個方式就是使用 64 Bits 的 Zobrist Key 來取代原本的 32 Bits,將 64 Bits 拆 為兩份 32 Bits,將其中一組作為檢測碼,另一組則為原本的 Zobrist Key,雖然會 占用較原本多一倍的空間,但可大幅降低 Collision Rate,較單純擴大一倍 Table 大小的效果好很多。

舉一個 64 Bits 的 Zobrist Key 的例子如下:

0x42f0aae1469c31d,其中 0x42f0aae 為 Key,0x1469c31d 為檢查碼。

本程式的實作上只使用 16 Bits 作為檢查碼,但這樣最佳情形下就可以將錯誤 率降至原本的 1/216,約為原本的六萬分之一。實驗證實這個改善方式非常有效,

降低後的 Collision Rate 在極端複雜盤面下仍不會超過三十萬分之一。

以下是使用一個複雜盤面搜尋 12 層的結果,其中除了 Alpha-Beta 外也加入 了其它必須的搜尋,Transposition Table 總大小為 4G bytes (不含監控結構),其盤 面與結果如下:

Transposition Table 使用

率 0.123865

第一層碰撞總次數 1193176

真實碰撞總次數 202

Hit Count 166958205 第一層碰撞率 0.003859902

Table Hit Rate 0.536227

真實碰撞率 0.0000007

改善率 5906.81

使用時間(秒) 76.7

圖 4.5.2 Collision Avoidance 實驗結果

圖 4.5.2 中,第一層碰撞代表初次檢查時通過但未經過二次檢測的存取行為,

圖 4.5.3 中可以很明顯看到,隨著 Table 空間使用率的上升,不但 Collision Rate Initialize 成本也相對沒那麼高,在許多實驗中我們也嘗試過使用更大的 Table,但 高昂的 Initialize 成本導致每一次開啟程式都需數秒來 Initial,而比賽中搜尋時間 是有限的,若每一手都會浪費數秒的話,累積的成本相當可觀。

相關文件