zobrist哈希的增量更新

  随着对FoolGo优化的进行,每次落子时重复计算棋盘的zobrist哈希值成为眼见的性能热点之一,须要修改成增量计算。

   需要一个结构来表示落子前后,棋盘状态的变化:

class BrdChange
{
public:
    template <typename T>
    struct Change {
        T origin_, now_;
    };
    struct Pair {
        PointIndex indx_;
        Change<Point> pnt_;
        ...
    };
    ...
private:
    Change<PointIndex> ko_indx_;
    Change<PlayerColor> last_player_;
    std::vector<Pair> indxs_;
};

  则可为Zobhasher类增加接口:

HashKey GetHash(HashKey hash, const BrdChange &chng) const;

  计算每单位变化的哈希增量的函数:

template <typename T, typename GetHash>
inline static HashKey
HashChange(const BrdChange::Change<T> &chng, const GetHash &get)
{
    return get(chng.origin_) ^ get(chng.now_);
}

  则易实现新增的GetHash接口:

template <BoardLen BOARD_LEN>
HashKey
ZobHasher<BOARD_LEN>::GetHash(HashKey hash, const BrdChange &chng) const
{
    auto getko = [this](PointIndex ko_indx) {
        return (ko_indx == BoardInGm<BOARD_LEN>::NONE) ?
            noko_hash_ : ko_hash_[ko_indx];
    };
    auto getplayer = [this](PlayerColor color) {
        return player_hash_[color];
    };
    HashKey r = hash ^ HashChange(chng.KoChng(), getko) ^
                HashChange(chng.LastPlayerChng(), getplayer);

    for (auto pair : chng.PointsChng()) {
        PointIndex pair_indx = pair.indx_;
        auto getpnt = [this, pair_indx](Point pnt) {
            return board_hash_[pair_indx][pnt];
        };
        r ^= HashChange(pair.pnt_, getpnt);
    }

    return r;
}

  优化后的哈希计算开销小了很多:

  PS:依然在杭州找工作中……

posted @ 2012-12-23 15:50  chncwang  阅读(1976)  评论(0编辑  收藏  举报