2016-11-02 65 views
1

所以我正在嘗試實現一個黑白棋遊戲的蒙特卡洛搜索樹。我有一個根節點和子節點,如果您可以在一次合法移動中從「y」移動到「x」,那麼'x'是'y'的子節點。由於製作新對象而在C++中耗盡內存

在每個節點上,我存儲一個包含所有棋盤信息的「棋盤」對象,例如每塊棋子的值。我遇到的第一個問題是,如果我更改了子節點的板對象,它也更改了父節點的值。我通過爲每個子節點創建一個'NEW'Board對象來解決這個問題,但是當我運行模擬數千次時,導致內存過多,直到內存耗盡。

我只是徘徊,如果有一種方法來改變孩子節點中的電路板信息,而不改變父母的電路板信息,或者如果有更好的方式來存儲電路板信息在每個節點而不是爲每個節點創建一個新的Board對象。

如果有什麼需要澄清下面的評論,謝謝閱讀!

編輯:

 for (int x = 0; x < numberOfChildren; x += 1) { 

     // Resets *currentBoard to the same state as the node being expanded 
     Board *currentBoard = nodeToExpand->getCurrentBoard(); 

     // Retrives the board value information 
     int** temporaryBoardValues = currentBoard->getBoardValues(); 

     // Makes a new board object with the previous parameters 
     Board *temporaryBoard = new Board(blockSize, boardSize, offset); 

     // Sets the new board values to the same as the old ones 
     temporaryBoard->setBoardValues(temporaryBoardValues); 

     // Creates a clone of that board state 
     // Board *temporaryBoard = cloneBoard(*currentBoard); 

     // Creates a node with the cloned board state, setting the parent to be the node being expanded. 
     // Assigns it one of the available moves 
     // Produces the array of child nodes 
     myChildren[x] = new Node(nodeToExpand, temporaryBoard, availableMoves[x], currentPlayer); 

     //delete temporaryBoard; 
    } 

一小段代碼。它是我創建一個耗盡所有內存的新Board對象的部分。

+5

你可以發佈一個小代碼示例? –

+0

您是否存儲這些信息以進行某種撤消操作? – NathanOliver

+3

對於深度爲n的分支樹搜索:您只需要在內存中保留當前最佳移動節點和n節點。你不需要保持整個樹只有當前的搜索/評估沿着一個分支深入'n',這可以很容易地保存在堆棧中 - 如果你在堆上掛着許多板,那麼你可能做錯了。 (也參見alpha-beta算法)。 –

回答

0

蒙特卡洛樹搜索(MCTS)的典型實現不使用任何技巧來明確地避免內存不足。理論上,如果你繼續模擬,你確實會耗盡內存,但是這通常需要的遠遠超過OP中提到的幾千個模擬。

現在,大多數MCTS的實現僅將每個模擬的樹擴展一個節點。您發佈的代碼看起來像是在每個模擬中將b節點添加到樹中,其中b是分支因子(兒童人數)。所以這是你可以考慮改變的東西。

此外,你可以看看你在Board類中存儲了什麼,並確保你真的只有這些東西,而沒有其他東西。只是遊戲狀態的數據,僅此而已。例如,確保你沒有任何數據,這只是GUI所必需的(這是我多年前犯的一個錯誤)。

如果在研究這兩點後仍然有內存問題,可以考慮jaggedSpire評論的建議。您可以存儲移動而不是板狀態,並在仿真中通過節點運行時重新構建板狀態。這將顯着減少您的內存消耗,但也會增加每次模擬的處理時間。如果你每回合只有有限的思考時間,這可能會導致弱者。

最後,考慮到您正在使用我在您發佈的代碼中看到的new操作執行手動內存管理,您總是有可能忘記了某個地方匹配delete並且存在內存泄漏。如果在查看以上幾點後,只有幾千次模擬仍然存在內存問題,這可能是最可能的原因,因爲MCTS確實不應該遇到內存問題,除非您的仿真計數超過幾千。

+0

我已經設法修復了創建多個板子對象的內存泄漏問題,正如你現在提到的那樣,做了什麼jaggedSpire提到關於存儲操作。我對MCTS的一般方法是從根開始,如果已經擴展,則根據它的Upper Confidence Bound選擇正確的孩子。如果它沒有被展開,那麼展開它並隨機模擬直到遊戲結束。 –

+0

但是我確實有一個問題,即在每次從計算機移動過程中都會產生大量的* NEW *節點,但是這些節點在每次移動後會保存在內存中,因此隨着遊戲的進行,內存被舊的節點信息堵塞,只是我不確定如何釋放內存 –

+0

@MatthewFennell您的意思是內存使用量增加了,因爲您在真正的遊戲中進行實際移動後沒有清理搜索樹?如果是這樣,是的,你需要確保在實際遊戲中進行實際移動後刪除整個搜索樹。或者,您可以將深度爲2的節點設置爲與您做出的一次移動相對應的移動,再加上一次移動對手,作爲新的根節點。然後,您仍然需要確保刪除該新根之上的節點以及該節點下方的那些節點 –