将 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;
// 定义 move
typedef int move_t;
// 定义类型
typedef int32_t move_t;
// 位置迭代器
// 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(
Node *parent,
int value,
int move,
int bestMove,
value_t value,
move_t move,
move_t bestMove,
enum NineChess::Player player
)
{
@ -213,7 +213,7 @@ void NineChessAi_ab::shuffleMovePriorityTable()
#endif // #ifdef RANDOM_MOVE
#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;
int pos = 0;
@ -493,7 +493,7 @@ int NineChessAi_ab::evaluateMotif(Node *node)
int NineChessAi_ab::evaluate(Node *node)
{
// 初始评估值为0对先手有利则增大对后手有利则减小
int value = 0;
value_t value = 0;
int nPiecesInHandDiff = 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;
}
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)) {
#ifdef GAME_PLACING_DYNAMIC_DEPTH
#ifdef DEAL_WITH_HORIZON_EFFECT
#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
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
#else // DEAL_WITH_HORIZON_EFFECT
#ifdef HASH_MAP_ENABLE
#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
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
#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 // DEAL_WITH_HORIZON_EFFECT
newDepth = depthTable[chessTemp.getPiecesInHandCount_1()];
@ -674,12 +674,12 @@ int NineChessAi_ab::changeDepth(int originalDepth)
return newDepth;
}
int NineChessAi_ab::alphaBetaPruning(int depth)
int NineChessAi_ab::alphaBetaPruning(depth_t depth)
{
QTime time1;
int value = 0;
value_t value = 0;
int d = changeDepth(depth);
depth_t d = changeDepth(depth);
unsigned int time0 = (unsigned)time(nullptr);
srand(time0);
@ -729,7 +729,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth)
#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 CLEAR_HASH_MAP
clearHashMap(); // 每次走子前清空哈希表
@ -756,19 +756,19 @@ int NineChessAi_ab::alphaBetaPruning(int depth)
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 不同
int minMax;
value_t minMax;
// 临时增加的深度,克服水平线效应用
int epsilon = 0;
// 子节点的最优着法
int bestMove = 0;
move_t bestMove = 0;
#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;
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++;
#ifdef DEBUG_AB_TREE
node->isHash = true;
@ -1076,7 +1076,7 @@ const char* NineChessAi_ab::bestMove()
return move2string(bestMoves[0]->move);
}
const char *NineChessAi_ab::move2string(int move)
const char *NineChessAi_ab::move2string(move_t move)
{
int c, p;
@ -1097,9 +1097,11 @@ const char *NineChessAi_ab::move2string(int move)
}
#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;
if (hashmap.find(hash, hashValue) == false) {
@ -1158,7 +1160,7 @@ bool NineChessAi_ab::findHash(uint64_t hash, HashValue &hashValue)
#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

View File

@ -53,12 +53,17 @@ using namespace CTSL;
class NineChessAi_ab
{
public:
// 定义类型
typedef uint8_t depth_t;
typedef int16_t value_t;
typedef NineChess::move_t move_t;
// 定义一个节点结构体
struct Node
{
public:
int move; // 着法的命令行指令,图上标示为节点前的连线
int value; // 节点的值
move_t move; // 着法的命令行指令,图上标示为节点前的连线
value_t value; // 节点的值
vector<struct Node*> children; // 子节点列表
struct Node* parent; // 父节点
#ifdef SORT_CONSIDER_PRUNED
@ -93,7 +98,7 @@ public:
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
// 定义哈希值的类型
enum HashType
enum HashType : uint8_t
{
hashfEMPTY = 0,
hashfALPHA = 1, // 结点的值最多是 value
@ -104,10 +109,10 @@ public:
// 定义哈希表的值
struct HashValue
{
int value;
int depth;
value_t value;
depth_t depth;
enum HashType type;
int bestMove;
move_t bestMove;
};
#endif
@ -128,7 +133,7 @@ public:
}
// Alpha-Beta剪枝算法
int alphaBetaPruning(int depth);
int alphaBetaPruning(depth_t depth);
// 返回最佳走法的命令行
const char *bestMove();
@ -153,7 +158,7 @@ public:
protected:
// 生成所有合法的着法并建立子节点
void generateLegalMoves(Node *node, int bestMove);
void generateLegalMoves(Node *node, move_t bestMove);
// 对合法的着法降序排序
void sortLegalMoves(Node *node);
@ -165,7 +170,9 @@ protected:
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);
@ -194,13 +201,13 @@ protected:
#endif /* EVALUATE_ENABLE */
// 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
@ -212,10 +219,10 @@ protected:
#ifdef HASH_MAP_ENABLE
// 查找哈希表
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
private:
@ -264,10 +271,7 @@ private:
#endif // MOVE_PRIORITY_TABLE_SUPPORT
// 定义极大值
static const int INF_VALUE = 0x1 << 30;
// 定义未知值
static const int UNKNOWN_VALUE = INT32_MAX;
static const value_t INF_VALUE = 0x1 << 14;
private:
// 命令行