优化C ++树生成

时间:2010-05-03 11:35:40

标签: c++ optimization

我正在生成一个Tic-Tac-Toe游戏树(第一次移动后9秒),我被告知它应该只需要几毫秒。所以我正在尝试优化它,我通过CodeAnalyst运行它,这些是前5个调用(我使用bitsets代表Tic-Tac-Toe板):

std::_Iterator_base::_Orphan_me

std::bitset<9>::test

std::_Iterator_base::_Adopt

std::bitset<9>::reference::operator bool

std::_Iterator_base::~_Iterator_base

void BuildTreeToDepth(Node &nNode, const int& nextPlayer, int depth)
{
   if (depth > 0)
   {
      //Calculate gameboard states
      int evalBoard = nNode.m_board.CalculateBoardState();
      bool isFinished = nNode.m_board.isFinished();
      if (isFinished || (nNode.m_board.isWinner() > 0))
      {
         nNode.m_winCount = evalBoard;
      }
      else
      {
         Ticboard tBoard = nNode.m_board;
         do
         {
            int validMove = tBoard.FirstValidMove();
            if (validMove != -1)
            {
               Node f;
               Ticboard tempBoard = nNode.m_board;
               tempBoard.Move(validMove, nextPlayer);
               tBoard.Move(validMove, nextPlayer);
               f.m_board = tempBoard;
               f.m_winCount = 0;
               f.m_Move = validMove;
               int currPlay = (nextPlayer == 1 ? 2 : 1);
               BuildTreeToDepth(f,currPlay, depth - 1);
               nNode.m_winCount += f.m_board.CalculateBoardState();
               nNode.m_branches.push_back(f);
            }
            else
            {
               break;
            }
         }while(true);
      }
   }
}

我应该在哪里优化它?我应该如何优化这5个电话(我不认识他们=。

7 个答案:

答案 0 :(得分:3)

tic-tac-toe游戏树非常多余。消除旋转和镜像板将使游戏树的最终层减少3或4个数量级。没有多少优化会使bubblesort像introsort一样快。

struct Game_board;

struct Node
{
   Game_board game_board;
   Node* parent;
   std::vector<Node*> children;
   enum { X_Win, Y_Win, Draw, Playing } outcome;
};

// returns the same hash value for all "identical" boards.
// ie boards that can be rotated or mirrored to look the
// same will have the same hash value
int hash( const Game_board& game_board );

// uses hash() function to generate hashes from Node*
struct Hash_functor;

// nodes yet to be explored.
std::hash_set<Node*,Hash_functor> open;

//nodes already explored.
std::hash_set<Node*,Hash_functor> closed;

while( ! open.empty() )
{
   Node* node_to_expore = get_a_node( open );
   assert( node_to_expore not in close or open sets )
   if( node_to_expore is win lose or draw )
   {
      Mark node as win lose or draw
      add node to closed set
   }
   loop through all children of node_to_expore
   {
      if( child in close )
      {
         add node from closed set to children list of node_to_expore
      }
      else if( child in open )
      {
         add node from open set to children list of node_to_explore
      }
      else
      {
         add child to open set
         add child to children list of node_to_expore
      }
   }
}

答案 1 :(得分:2)

这些功能通常是微不足道的。这意味着优化(“发布”)构建通常会将它们内联。但是,在调试版本中,它们不是。结果是调试版本较慢,但允许您在这些函数上设置断点。因此,“毫秒评论”应该应用于发布版本,你甚至不再拥有这些函数。

答案 2 :(得分:1)

您将全部包含在数据结构中。 不要建造树,只是走它。只有一份董事会副本。在搜索树中的每个节点上,只需修改电路板,在退回的路上,取消修改它。

如果您想知道它在做什么,只需随机点击暂停按钮即可。它将告诉你为什么它在那些你不认识的例程中会花费所有时间。

答案 3 :(得分:0)

老实说,我并不是说这是对你的抨击,你要求我们检查一段记录不完整的代码,这对于更大的代码库来说是一个较小的部分。我们没有提供大量信息的上下文。我个人也因为检查他人的代码而被关闭,因为他们似乎并没有做他们自己可以做的所有事情(我并不是说我对你或任何事情感到恼火,只是我的眼睛盯着看你的代码。)

我建议您通过分析器运行代码,并确定究竟花了多少时间。像调试那样对待这个分析。当你发现一个模块需要很长时间时,请在一小部分中检查该模块(就好像你正在寻找一个bug)来了解原因。

如果您仍需要提问,可以提出更为明智的问题。

答案 4 :(得分:0)

让我补充一点,如果你的系统需要9秒才能完成它的工作,这意味着某些东西被称为数十亿甚至数十亿倍。如果您没有发布级别性能分析功能,请在代码中放置一些全局计数器,并在每次调用它们所在的代码时递增它们。这将为您提供一个可用于发布版本的穷人配置文件。如果你看到一个你想不到的数十亿电话,你现在可以近距离接触。

实际上,如果你需要速度,Tic-Tac-Toe的整个移动树应该是很容易存储的哈希。 9!移动只是不是一个领域(不再)。 362k的移动不应该打破银行,这是一个暴力分析。当您考虑所有各种数据的相关性时,该域可以缩减。

呸,如果我编码它,我会怎么做,因为人们已经锁定了我的信封背面数据:

我甚至不会走树路,只是做一些规则而且要做 转1.进入中心。
转2.如果中心空置,去那里,否则进入角落
转3.如果对手填满角落,进入对角,否则进入角落 - 你赢了。
如果需要,转4.阻止。如果Xs占据相反的角落,则填充边缘。如果Xs占据中心和对角,请填充角落。如果Xs占据相反的边缘,填补角落并获胜。如果Xs填充相邻边缘,则填充角落在它们之间 如果可能的话,转5赢。如果需要阻止。否则进入相邻边缘移动的角落并获胜。
如果可能,转6-9赢。如果需要阻止。否则,随意选择绘图。

答案 5 :(得分:0)

你发布的代码太少了。

答案 6 :(得分:0)

您正在询问如何优化代码,但您也应该询问如何优化算法。

我立即看到了两件事。

  1. 正如“迈克尔·多根”所说,生成一次移动树。

  2. 你在树上生成了多少广泛的? 362880?您的代码似乎正在生成冗余条目。例如,对于空板,实际上有三个移动而不是九个移动。所有其他组合都是旋转的板(相同)。您可以减少需要生成的板数,并加快树的生成。

  3. 以下是三个第一步(旋转最后两块板以生成其他板)

     | |
     |X|
     | |
    
     |X|
     | |
     | |
    
    X| |
     | |
     | |
    
相关问题