将 value/depth 分别改为16位和8位以减少内存占用

内存占用由778MB下降到552MB;
自对弈时长也从128s减少到113s,提速12%。
This commit is contained in:
CalciteM Team 2019-08-04 23:04:09 +08:00
parent 48d2f1d1d1
commit 2365d711b2
3 changed files with 55 additions and 48 deletions

View File

@ -72,8 +72,9 @@ public:
// 预定义的规则数目 // 预定义的规则数目
static const int N_RULES = 4; static const int N_RULES = 4;
// 定义 move // 定义类型
typedef int move_t; typedef int32_t move_t;
// 位置迭代器 // 位置迭代器
// typedef typename std::vector<move_t>::iterator posIterator; // typedef typename std::vector<move_t>::iterator posIterator;

View File

@ -78,9 +78,9 @@ void NineChessAi_ab::buildRoot()
struct NineChessAi_ab::Node *NineChessAi_ab::addNode( struct NineChessAi_ab::Node *NineChessAi_ab::addNode(
Node *parent, Node *parent,
int value, value_t value,
int move, move_t move,
int bestMove, move_t bestMove,
enum NineChess::Player player enum NineChess::Player player
) )
{ {
@ -213,7 +213,7 @@ void NineChessAi_ab::shuffleMovePriorityTable()
#endif // #ifdef RANDOM_MOVE #endif // #ifdef RANDOM_MOVE
#endif // MOVE_PRIORITY_TABLE_SUPPORT #endif // MOVE_PRIORITY_TABLE_SUPPORT
void NineChessAi_ab::generateLegalMoves(Node *node, int bestMove) void NineChessAi_ab::generateLegalMoves(Node *node, move_t bestMove)
{ {
const int MOVE_PRIORITY_TABLE_SIZE = NineChess::N_RINGS * NineChess::N_SEATS; const int MOVE_PRIORITY_TABLE_SIZE = NineChess::N_RINGS * NineChess::N_SEATS;
int pos = 0; int pos = 0;
@ -493,7 +493,7 @@ int NineChessAi_ab::evaluateMotif(Node *node)
int NineChessAi_ab::evaluate(Node *node) int NineChessAi_ab::evaluate(Node *node)
{ {
// 初始评估值为0对先手有利则增大对后手有利则减小 // 初始评估值为0对先手有利则增大对后手有利则减小
int value = 0; value_t value = 0;
int nPiecesInHandDiff = INT_MAX; int nPiecesInHandDiff = INT_MAX;
int nPiecesOnBoardDiff = INT_MAX; int nPiecesOnBoardDiff = INT_MAX;
@ -629,31 +629,31 @@ int NineChessAi_ab::evaluate(Node *node)
} }
// 赋值返回 // 赋值返回
node->value = (int16_t)value; node->value = value;
return value; return value;
} }
int NineChessAi_ab::changeDepth(int originalDepth) NineChessAi_ab::depth_t NineChessAi_ab::changeDepth(depth_t originalDepth)
{ {
int newDepth = originalDepth; depth_t newDepth = originalDepth;
if ((chessTemp.context.stage) & (NineChess::GAME_PLACING)) { if ((chessTemp.context.stage) & (NineChess::GAME_PLACING)) {
#ifdef GAME_PLACING_DYNAMIC_DEPTH #ifdef GAME_PLACING_DYNAMIC_DEPTH
#ifdef DEAL_WITH_HORIZON_EFFECT #ifdef DEAL_WITH_HORIZON_EFFECT
#ifdef HASH_MAP_ENABLE #ifdef HASH_MAP_ENABLE
int depthTable[] = { 4, 11, 12, 13, 14, 14, 14, 12, 11, 10, 6, 6, 1 }; depth_t depthTable[] = { 4, 11, 12, 13, 14, 14, 14, 12, 11, 10, 6, 6, 1 };
#else // HASH_MAP_ENABLE #else // HASH_MAP_ENABLE
int depthTable[] = { 2, 11, 11, 11, 11, 10, 9, 8, 8, 8, 7, 7, 1 }; depth_t depthTable[] = { 2, 11, 11, 11, 11, 10, 9, 8, 8, 8, 7, 7, 1 };
#endif // HASH_MAP_ENABLE #endif // HASH_MAP_ENABLE
#else // DEAL_WITH_HORIZON_EFFECT #else // DEAL_WITH_HORIZON_EFFECT
#ifdef HASH_MAP_ENABLE #ifdef HASH_MAP_ENABLE
#ifdef RAPID_CHESS #ifdef RAPID_CHESS
int depthTable[] = { 6, 14, 15, 16, 15, 15, 15, 13, 10, 9, 8, 7, 1 }; depth_t depthTable[] = { 6, 14, 15, 16, 15, 15, 15, 13, 10, 9, 8, 7, 1 };
#else #else
int depthTable[] = { 6, 15, 16, 17, 16, 16, 16, 15, 12, 10, 9, 7, 1 }; depth_t depthTable[] = { 6, 15, 16, 17, 16, 16, 16, 15, 12, 10, 9, 7, 1 };
#endif // RAPID_CHESS #endif // RAPID_CHESS
#else // HASH_MAP_ENABLE #else // HASH_MAP_ENABLE
int depthTable[] = { 2, 13, 13, 13, 12, 11, 10, 9, 9, 8, 8, 7, 1 }; depth_t depthTable[] = { 2, 13, 13, 13, 12, 11, 10, 9, 9, 8, 8, 7, 1 };
#endif #endif
#endif // DEAL_WITH_HORIZON_EFFECT #endif // DEAL_WITH_HORIZON_EFFECT
newDepth = depthTable[chessTemp.getPiecesInHandCount_1()]; newDepth = depthTable[chessTemp.getPiecesInHandCount_1()];
@ -674,12 +674,12 @@ int NineChessAi_ab::changeDepth(int originalDepth)
return newDepth; return newDepth;
} }
int NineChessAi_ab::alphaBetaPruning(int depth) int NineChessAi_ab::alphaBetaPruning(depth_t depth)
{ {
QTime time1; QTime time1;
int value = 0; value_t value = 0;
int d = changeDepth(depth); depth_t d = changeDepth(depth);
unsigned int time0 = (unsigned)time(nullptr); unsigned int time0 = (unsigned)time(nullptr);
srand(time0); srand(time0);
@ -729,7 +729,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth)
#ifdef IDS_SUPPORT #ifdef IDS_SUPPORT
// 深化迭代 // 深化迭代
for (int i = 2; i < d; i += 2) { for (depth_t i = 2; i < d; i += 2) {
#ifdef HASH_MAP_ENABLE #ifdef HASH_MAP_ENABLE
#ifdef CLEAR_HASH_MAP #ifdef CLEAR_HASH_MAP
clearHashMap(); // 每次走子前清空哈希表 clearHashMap(); // 每次走子前清空哈希表
@ -756,19 +756,19 @@ int NineChessAi_ab::alphaBetaPruning(int depth)
return 0; return 0;
} }
int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) int NineChessAi_ab::alphaBetaPruning(depth_t depth, value_t alpha, value_t beta, Node *node)
{ {
// 评价值 // 评价值
int value; value_t value;
// 当前节点的 MinMax 值,最终赋值给节点 value与 alpha 和 Beta 不同 // 当前节点的 MinMax 值,最终赋值给节点 value与 alpha 和 Beta 不同
int minMax; value_t minMax;
// 临时增加的深度,克服水平线效应用 // 临时增加的深度,克服水平线效应用
int epsilon = 0; int epsilon = 0;
// 子节点的最优着法 // 子节点的最优着法
int bestMove = 0; move_t bestMove = 0;
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING)) #if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
// 哈希值 // 哈希值
@ -791,9 +791,9 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
HashType type = hashfEMPTY; HashType type = hashfEMPTY;
int probeVal = probeHash(hash, depth, alpha, beta, bestMove, type); value_t probeVal = probeHash(hash, depth, alpha, beta, bestMove, type);
if (probeVal != INT32_MIN && node != rootNode) { if (probeVal != INT16_MIN /* TODO: valUNKOWN */ && node != rootNode) {
hashHitCount++; hashHitCount++;
#ifdef DEBUG_AB_TREE #ifdef DEBUG_AB_TREE
node->isHash = true; node->isHash = true;
@ -1076,7 +1076,7 @@ const char* NineChessAi_ab::bestMove()
return move2string(bestMoves[0]->move); return move2string(bestMoves[0]->move);
} }
const char *NineChessAi_ab::move2string(int move) const char *NineChessAi_ab::move2string(move_t move)
{ {
int c, p; int c, p;
@ -1097,9 +1097,11 @@ const char *NineChessAi_ab::move2string(int move)
} }
#ifdef HASH_MAP_ENABLE #ifdef HASH_MAP_ENABLE
int NineChessAi_ab::probeHash(uint64_t hash, int depth, int alpha, int beta, int &bestMove, HashType &type) NineChessAi_ab::value_t NineChessAi_ab::probeHash(uint64_t hash,
depth_t depth, value_t alpha, value_t beta,
move_t &bestMove, HashType &type)
{ {
const int valUNKNOWN = INT32_MIN; const value_t valUNKNOWN = INT16_MIN;
HashValue hashValue; HashValue hashValue;
if (hashmap.find(hash, hashValue) == false) { if (hashmap.find(hash, hashValue) == false) {
@ -1158,7 +1160,7 @@ bool NineChessAi_ab::findHash(uint64_t hash, HashValue &hashValue)
#endif #endif
} }
int NineChessAi_ab::recordHash(int value, int depth, HashType type, uint64_t hash, int bestMove) int NineChessAi_ab::recordHash(value_t value, depth_t depth, HashType type, uint64_t hash, move_t bestMove)
{ {
// 同样深度或更深时替换 // 同样深度或更深时替换
// 注意: 每走一步以前都必须把散列表中所有的标志项置为 hashfEMPTY // 注意: 每走一步以前都必须把散列表中所有的标志项置为 hashfEMPTY

View File

@ -53,12 +53,17 @@ using namespace CTSL;
class NineChessAi_ab class NineChessAi_ab
{ {
public: public:
// 定义类型
typedef uint8_t depth_t;
typedef int16_t value_t;
typedef NineChess::move_t move_t;
// 定义一个节点结构体 // 定义一个节点结构体
struct Node struct Node
{ {
public: public:
int move; // 着法的命令行指令,图上标示为节点前的连线 move_t move; // 着法的命令行指令,图上标示为节点前的连线
int value; // 节点的值 value_t value; // 节点的值
vector<struct Node*> children; // 子节点列表 vector<struct Node*> children; // 子节点列表
struct Node* parent; // 父节点 struct Node* parent; // 父节点
#ifdef SORT_CONSIDER_PRUNED #ifdef SORT_CONSIDER_PRUNED
@ -93,7 +98,7 @@ public:
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING)) #if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
// 定义哈希值的类型 // 定义哈希值的类型
enum HashType enum HashType : uint8_t
{ {
hashfEMPTY = 0, hashfEMPTY = 0,
hashfALPHA = 1, // 结点的值最多是 value hashfALPHA = 1, // 结点的值最多是 value
@ -104,10 +109,10 @@ public:
// 定义哈希表的值 // 定义哈希表的值
struct HashValue struct HashValue
{ {
int value; value_t value;
int depth; depth_t depth;
enum HashType type; enum HashType type;
int bestMove; move_t bestMove;
}; };
#endif #endif
@ -128,7 +133,7 @@ public:
} }
// Alpha-Beta剪枝算法 // Alpha-Beta剪枝算法
int alphaBetaPruning(int depth); int alphaBetaPruning(depth_t depth);
// 返回最佳走法的命令行 // 返回最佳走法的命令行
const char *bestMove(); const char *bestMove();
@ -153,7 +158,7 @@ public:
protected: protected:
// 生成所有合法的着法并建立子节点 // 生成所有合法的着法并建立子节点
void generateLegalMoves(Node *node, int bestMove); void generateLegalMoves(Node *node, move_t bestMove);
// 对合法的着法降序排序 // 对合法的着法降序排序
void sortLegalMoves(Node *node); void sortLegalMoves(Node *node);
@ -165,7 +170,9 @@ protected:
void buildRoot(); void buildRoot();
// 增加新节点 // 增加新节点
struct Node *addNode(Node *parent, int value, NineChess::move_t move, int bestMove, enum NineChess::Player player); struct Node *addNode(Node *parent, value_t value,
move_t move, move_t bestMove,
enum NineChess::Player player);
// 评价函数 // 评价函数
int evaluate(Node *node); int evaluate(Node *node);
@ -194,13 +201,13 @@ protected:
#endif /* EVALUATE_ENABLE */ #endif /* EVALUATE_ENABLE */
// Alpha-Beta剪枝算法 // Alpha-Beta剪枝算法
int alphaBetaPruning(int depth, int alpha, int beta, Node *node); int alphaBetaPruning(depth_t depth, value_t alpha, value_t beta, Node *node);
// 返回着法的命令行 // 返回着法的命令行
const char *move2string(int move); const char *move2string(move_t move);
// 篡改深度 // 篡改深度
int changeDepth(int originalDepth); depth_t changeDepth(depth_t originalDepth);
// 随机打乱着法搜索顺序 // 随机打乱着法搜索顺序
#ifdef MOVE_PRIORITY_TABLE_SUPPORT #ifdef MOVE_PRIORITY_TABLE_SUPPORT
@ -212,10 +219,10 @@ protected:
#ifdef HASH_MAP_ENABLE #ifdef HASH_MAP_ENABLE
// 查找哈希表 // 查找哈希表
bool findHash(uint64_t hash, HashValue &hashValue); bool findHash(uint64_t hash, HashValue &hashValue);
int probeHash(uint64_t hash, int depth, int alpha, int beta, int &bestMove, HashType &type); value_t probeHash(uint64_t hash, depth_t depth, value_t alpha, value_t beta, move_t &bestMove, HashType &type);
// 插入哈希表 // 插入哈希表
int recordHash(int value, int depth, HashType type, uint64_t hash, int bestMove); int recordHash(value_t value, depth_t depth, HashType type, uint64_t hash, move_t bestMove);
#endif // HASH_MAP_ENABLE #endif // HASH_MAP_ENABLE
private: private:
@ -264,10 +271,7 @@ private:
#endif // MOVE_PRIORITY_TABLE_SUPPORT #endif // MOVE_PRIORITY_TABLE_SUPPORT
// 定义极大值 // 定义极大值
static const int INF_VALUE = 0x1 << 30; static const value_t INF_VALUE = 0x1 << 14;
// 定义未知值
static const int UNKNOWN_VALUE = INT32_MAX;
private: private:
// 命令行 // 命令行