Skip to content

Commit

Permalink
- search()のUSE_LAZY_EVALUATEでttHitかつPvNodeのときにevaluate()呼び出すのやめる。
Browse files Browse the repository at this point in the history
- USE_DIFF_EVAL導入。MATERIAL評価関数では、次nodeに行く場合も、evaluate()呼び出しを強制しないようにする。
  • Loading branch information
yaneurao committed Nov 28, 2024
1 parent 9fe01d6 commit 0056b40
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 49 deletions.
8 changes: 8 additions & 0 deletions source/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@
// 検討目的なら、これをオンにするのは好ましくない。)
// #define ENABLE_QUICK_DRAW

// 差分計算型評価関数であるか?(次のnodeに行く前に必ずevaluate()が必要である場合にdefineする)
// #define USE_DIFF_EVAL

// ===============================================================
// ここ以降では、↑↑↑で設定した内容に基づき必要なdefineを行う。
// ===============================================================
Expand Down Expand Up @@ -437,6 +440,11 @@ constexpr int MAX_PLY_NUM = 246;
#define USE_SHARED_MEMORY_IN_EVAL
#endif

#if defined(YANEURAOU_ENGINE_KPPT) || defined(YANEURAOU_ENGINE_KPP_KKPT) || defined(YANEURAOU_ENGINE_NNUE)
// 差分計算型評価関数である場合、次のnodeに行く前に必ずevaluate()が必要である。
#define USE_DIFF_EVAL
#endif

// 学習機能を有効にするオプション。
// 教師局面の生成、定跡コマンド(makebook thinkなど)を用いる時には、これを
// 有効化してコンパイルしなければならない。
Expand Down
101 changes: 56 additions & 45 deletions source/engine/yaneuraou-engine/yaneuraou-search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,28 +203,6 @@ Value futility_margin(Depth d, bool noTtCutNode, bool improving, bool oppWorseni
return futilityMult * d - improvingDeduction - worseningDeduction;
}

// 【計測資料 30.】 Reductionのコード、Stockfish 9と10での比較

// Reductions lookup table initialized at startup
// 探索深さを減らすためのReductionテーブル。起動時に初期化する。
std::array<int,MAX_MOVES> reductions; // [depth or moveNumber]

// 残り探索深さをこの深さだけ減らす。
// 注意 : Stockfish 17(2024.11)で、1024倍して返すことになった。
//
// 引数の意味
// d : depth
// mn : move_count
// i : improving , 評価値が2手前から上がっているかのフラグ。
// 上がっていないなら悪化していく局面なので深く読んでも仕方ないからreduction量を心もち増やす。
// delta, rootDelta : staticEvalとchildのeval(value)の差が一貫して低い時にreduction量を増やしたいので、
// そのためのフラグ。(これがtrueだとreduction量が1増える)
Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
int reductionScale = reductions[d] * reductions[mn];
return (reductionScale + PARAM_REDUCTION_ALPHA - delta * PARAM_REDUCTION_GAMMA / rootDelta)
+ (!i && reductionScale > PARAM_REDUCTION_BETA) * 1135;
// PARAM_REDUCTION_BETAの値、将棋ではもう少し小さくして、reductionの適用範囲を広げた方がいいかも?
}

// 【計測資料 29.】 Move CountベースのFutiliy Pruning、Stockfish 9と10での比較

Expand Down Expand Up @@ -287,6 +265,28 @@ int stat_bonus(Depth d) { return std::min(168 * d - 100, 1718); }
// TODO : あとで
int stat_malus(Depth d) { return std::min(768 * d - 257, 2351); }

// 【計測資料 30.】 Reductionのコード、Stockfish 9と10での比較

// Reductions lookup table initialized at startup
// 探索深さを減らすためのReductionテーブル。起動時に初期化する。
std::array<int, MAX_MOVES> reductions; // [depth or moveNumber]

// 残り探索深さをこの深さだけ減らす。
// 注意 : Stockfish 17(2024.11)で、1024倍して返すことになった。
//
// 引数の意味
// d : depth
// mn : move_count
// i : improving , 評価値が2手前から上がっているかのフラグ。
// 上がっていないなら悪化していく局面なので深く読んでも仕方ないからreduction量を心もち増やす。
// delta, rootDelta : staticEvalとchildのeval(value)の差が一貫して低い時にreduction量を増やしたいので、
// そのためのフラグ。(これがtrueだとreduction量が1増える)
Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
int reductionScale = reductions[d] * reductions[mn];
return (reductionScale + PARAM_REDUCTION_ALPHA - delta * PARAM_REDUCTION_GAMMA / rootDelta)
+ (!i && reductionScale > PARAM_REDUCTION_BETA) * 1135;
// PARAM_REDUCTION_BETAの値、将棋ではもう少し小さくして、reductionの適用範囲を広げた方がいいかも?
}

#if 0
// チェスでは、引き分けが0.5勝扱いなので引き分け回避のための工夫がしてあって、
Expand Down Expand Up @@ -902,9 +902,9 @@ void search_thread_init(Thread* th, Stack* ss , Move pv[])
// counterMovesをnullptrに初期化するのではなくNO_PIECEのときの値を番兵として用いる。
for (int i = 7; i > 0; --i)
{
(ss - i)->continuationHistory = &th->continuationHistory[0][0](NO_PIECE, SQ_ZERO); // Use as a sentinel
(ss - i)->continuationHistory = &th->continuationHistory[0][0](NO_PIECE, SQ_ZERO); // Use as a sentinel
// (ss - i)->continuationCorrectionHistory = &this->continuationCorrectionHistory[NO_PIECE][0];
(ss - i)->staticEval = VALUE_NONE;
(ss - i)->staticEval = VALUE_NONE;
}

// Stack(探索用の構造体)上のply(手数)は事前に初期化しておけば探索時に代入する必要がない。
Expand Down Expand Up @@ -2023,25 +2023,30 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
}

// -----------------------
// Step 6. Static evaluation of the position
// Step 6. 局面の静的な評価
// Lazy Evaluator
// 評価関数の遅延評価子(やねうら王独自拡張)
// -----------------------

Value unadjustedStaticEval = VALUE_NONE;

// この局面で評価関数を呼び出したのか。(do_move()までには呼ばないと駄目)
// ※ やねうら王開発版にて独自追加
bool evaluated = false;
auto evaluate = [&](Position& pos) { evaluated = true; return ::evaluate(pos); };
auto lazy_evaluate = [&](Position& pos) {
#if defined(USE_LAZY_EVALUATE)
#if defined(USE_LAZY_EVALUATE) && defined(USE_DIFF_EVAL)
// まだこのnodeでevaluate()が呼び出されていなかったのであれば呼び出す。
if (!evaluated)
{
evaluated = true;
evaluate_with_no_return(pos);
}
#endif
};
};

// -----------------------
// Step 6. Static evaluation of the position
// Step 6. 局面の静的な評価
// -----------------------

Value unadjustedStaticEval = VALUE_NONE;

if (ss->inCheck)
{
Expand Down Expand Up @@ -2107,19 +2112,17 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
// Stockfish 17のコード
if (unadjustedStaticEval == VALUE_NONE)
// TT raceで破壊されてるっぽい?
unadjustedStaticEval =
// evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]);
evaluate(pos);

// unadjustedStaticEval = evaluate(networks[numaAccessToken], pos, refreshTable, thisThread->optimism[us]);
unadjustedStaticEval = evaluate(pos);

// 置換表にhitしたなら、評価値が記録されているはずだから、それを取り出しておく。
// あとで置換表に書き込むときにこの値を使えるし、各種枝刈りはこの評価値をベースに行なうから。

else if (PvNode)
else if (PvNode) {
// Eval::NNUE::hint_common_parent_position(pos, networks[numaAccessToken], refreshTable);
// → TODO : hint_common_parent_position()実装するか検討する。
unadjustedStaticEval = evaluate(pos);
// ないほうがいいか? ⇨ V836dev_oとV836dev_pの比較
// ⇨ スレッド数が多くてTT raceが起きやすいと違うかもな…。
}
#else
unadjustedStaticEval = evaluate(pos);
#endif
Expand Down Expand Up @@ -2293,7 +2296,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
// ⇨ evalがbetaを超えているので1手パスしてもbetaは超えそう。だからnull moveを試す
&& ss->staticEval >= beta - PARAM_NULL_MOVE_MARGIN1 * depth + PARAM_NULL_MOVE_MARGIN2
&& !excludedMove
// && pos.non_pawn_material(us) // これ終盤かどうかを意味する。将棋でもこれに相当する条件が必要かも。
// && pos.non_pawn_material(us) // 盤上にpawn以外の駒がある ≒ pawnだけの終盤ではない。将棋でもこれに相当する条件が必要かも。
&& ss->ply >= thisThread->nmpMinPly
&& beta > VALUE_TB_LOSS_IN_MAX_PLY
// 同じ手番側に連続してnull moveを適用しない
Expand Down Expand Up @@ -2713,7 +2716,7 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo
ss->staticEval + (bestValue < ss->staticEval - 45 ? 140 : 43) + 141 * lmrDepth;

// Futility pruning: parent node (~13 Elo)
if (!ss->inCheck && lmrDepth < PARAM_FUTILITY_AT_PARENT_NODE_DEPTH/*12*/ && futilityValue <= alpha)
if (!ss->inCheck && lmrDepth < PARAM_FUTILITY_AT_PARENT_NODE_DEPTH && futilityValue <= alpha)
{
if (bestValue <= futilityValue
&& std::abs(bestValue) < VALUE_TB_WIN_IN_MAX_PLY
Expand Down Expand Up @@ -3730,16 +3733,16 @@ Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth)
return ttData.value;

// -----------------------
// Step 4. Static evaluation of the position
// Step 4. この局面の静止評価
// Lazy Evaluator
// 評価関数の遅延評価子(やねうら王独自拡張)
// -----------------------

// 置換表に書いてあったevalの値をなるべく壊さずに保存するための変数
Value unadjustedStaticEval = VALUE_NONE;
// この局面で評価関数を呼び出したのか。(do_move()までには呼ばないと駄目)
bool evaluated = false;
auto evaluate = [&](Position& pos) { evaluated = true; return ::evaluate(pos); };
auto lazy_evaluate = [&](Position& pos) {
#if defined(USE_LAZY_EVALUATE)
#if defined(USE_LAZY_EVALUATE) && defined(USE_DIFF_EVAL)
// まだこのnodeでevaluate()が呼び出されていなかったのであれば呼び出す。
if (!evaluated)
{
evaluated = true;
Expand All @@ -3748,6 +3751,14 @@ Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth)
#endif
};

// -----------------------
// Step 4. Static evaluation of the position
// Step 4. この局面の静止評価
// -----------------------

// 置換表に書いてあったevalの値をなるべく壊さずに保存するための変数
Value unadjustedStaticEval = VALUE_NONE;

if (ss->inCheck)
{

Expand Down
8 changes: 4 additions & 4 deletions source/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ void Thread::clear()
{
#if defined(USE_MOVE_PICKER)
mainHistory.fill(0);
captureHistory.fill(0);
captureHistory.fill(-758);
#if defined(ENABLE_PAWN_HISTORY)
pawnHistory.fill(0);
pawnHistory.fill(-1158);
pawnCorrectionHistory.fill(0);
materialCorrectionHistory.fill(0);
majorPieceCorrectionHistory.fill(0);
Expand All @@ -73,11 +73,11 @@ void Thread::clear()
for (StatsType c : { NoCaptures, Captures })
//for (auto& to : continuationHistory[inCheck][c])
// for (auto& h : to)
// h->fill(-678);
// h->fill(-675);

// ↑この初期化コードは、ContinuationHistory::fill()に移動させた。

continuationHistory[inCheck][c].fill(-678);
continuationHistory[inCheck][c].fill(-645);

#endif
}
Expand Down

0 comments on commit 0056b40

Please sign in to comment.