Skip to content

Commit

Permalink
- movepicker.cppのStagesの定数でアンダースコアが入っていたもの、アンダースコア削除。
Browse files Browse the repository at this point in the history
  - movepicker.cppに状態遷移図追加。
  • Loading branch information
yaneurao committed Nov 27, 2023
1 parent bfb658a commit b58a4fe
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 58 deletions.
106 changes: 53 additions & 53 deletions source/engine/yaneuraou-engine/yaneuraou-search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4114,72 +4114,72 @@ Move Skill::pick_best(size_t multiPV) {
// main threadからしか呼び出されないのでロジックがシンプルになっている。
void MainThread::check_time()
{
// When using nodes, ensure checking rate is not lower than 0.1% of nodes
// 4096回に1回ぐらいのチェックで良い。
if (--callsCnt > 0)
return;
// When using nodes, ensure checking rate is not lower than 0.1% of nodes
// 4096回に1回ぐらいのチェックで良い。
if (--callsCnt > 0)
return;

// "stop"待ちなので以降の判定不要。
if (Threads.main()->time_to_return_bestmove)
return ;
// "stop"待ちなので以降の判定不要。
if (Threads.main()->time_to_return_bestmove)
return ;

// Limits.nodesが指定されているときは、そのnodesの0.1%程度になるごとにチェック。
// さもなくばデフォルトの値を使う。
// このデフォルト値、ある程度小さくしておかないと、通信遅延分のマージンを削ったときに
// ちょうど1秒を超えて計測2秒になり、損をしうるという議論があるようだ。
// cf. Check the clock every 1024 nodes : https://github.com/official-stockfish/Stockfish/commit/8db75dd9ec05410136898aa2f8c6dc720b755eb8
// main threadでしか判定しないからチェックに要するコストは微小だと思われる。
// Limits.nodesが指定されているときは、そのnodesの0.1%程度になるごとにチェック。
// さもなくばデフォルトの値を使う。
// このデフォルト値、ある程度小さくしておかないと、通信遅延分のマージンを削ったときに
// ちょうど1秒を超えて計測2秒になり、損をしうるという議論があるようだ。
// cf. Check the clock every 1024 nodes : https://github.com/official-stockfish/Stockfish/commit/8db75dd9ec05410136898aa2f8c6dc720b755eb8
// main threadでしか判定しないからチェックに要するコストは微小だと思われる。

// When using nodes, ensure checking rate is not lower than 0.1% of nodes
// → NodesLimitを有効にした時、その指定されたノード数の0.1%程度の誤差であって欲しいのでそれくらいの頻度でチェックする。
// When using nodes, ensure checking rate is not lower than 0.1% of nodes
// → NodesLimitを有効にした時、その指定されたノード数の0.1%程度の誤差であって欲しいのでそれくらいの頻度でチェックする。

callsCnt = Limits.nodes ? std::min(512, int(Limits.nodes / 1024)) : 512;
callsCnt = Limits.nodes ? std::min(512, int(Limits.nodes / 1024)) : 512;

// 1秒ごとにdbg_print()を呼び出す処理。
// dbg_print()は、dbg_hit_on()呼び出しによる統計情報を表示する。
// 1秒ごとにdbg_print()を呼び出す処理。
// dbg_print()は、dbg_hit_on()呼び出しによる統計情報を表示する。

static TimePoint lastInfoTime = now();
TimePoint tick = now();
static TimePoint lastInfoTime = now();
TimePoint tick = now();

// 1秒ごとに
if (tick - lastInfoTime >= 1000)
{
lastInfoTime = tick;
dbg_print();
}
// 1秒ごとに
if (tick - lastInfoTime >= 1000)
{
lastInfoTime = tick;
dbg_print();
}

// We should not stop pondering until told so by the GUI
// ponder中においては、GUIがstopとかponderhitとか言ってくるまでは止まるべきではない。
if (ponder)
return;

// "ponderhit"時は、そこからの経過時間で考えないと、elapsed > Time.maximum()になってしまう。
// elapsed_from_ponderhit()は、"ponderhit"していないときは"go"コマンドからの経過時間を返すのでちょうど良い。
TimePoint elapsed = Time.elapsed_from_ponderhit();

// 今回のための思考時間を完璧超えているかの判定。

// 反復深化のループ内でそろそろ終了して良い頃合いになると、Time.search_endに停止させて欲しい時間が代入される。
// (それまではTime.search_endはゼロであり、これは終了予定時刻が未確定であることを示している。)
// ※ 前半部分、やねうら王、独自実装。
if ((Limits.use_time_management() &&
(elapsed > Time.maximum() || (Time.search_end > 0 && elapsed > Time.search_end)))
|| (Limits.movetime && elapsed >= Limits.movetime)
|| (Limits.nodes && Threads.nodes_searched() >= uint64_t(Limits.nodes))
)
{
if (Limits.wait_stop)
// We should not stop pondering until told so by the GUI
// ponder中においては、GUIがstopとかponderhitとか言ってくるまでは止まるべきではない。
if (ponder)
return;

// "ponderhit"時は、そこからの経過時間で考えないと、elapsed > Time.maximum()になってしまう。
// elapsed_from_ponderhit()は、"ponderhit"していないときは"go"コマンドからの経過時間を返すのでちょうど良い。
TimePoint elapsed = Time.elapsed_from_ponderhit();

// 今回のための思考時間を完璧超えているかの判定。

// 反復深化のループ内でそろそろ終了して良い頃合いになると、Time.search_endに停止させて欲しい時間が代入される。
// (それまではTime.search_endはゼロであり、これは終了予定時刻が未確定であることを示している。)
// ※ 前半部分、やねうら王、独自実装。
if ((Limits.use_time_management() &&
(elapsed > Time.maximum() || (Time.search_end > 0 && elapsed > Time.search_end)))
|| (Limits.movetime && elapsed >= Limits.movetime)
|| (Limits.nodes && Threads.nodes_searched() >= uint64_t(Limits.nodes))
)
{
// stopが来るまで待つので、Threads.stopは変化させない。
// 代わりに"info string time to return bestmove."と出力する。
output_time_to_return_bestmove();
if (Limits.wait_stop)
{
// stopが来るまで待つので、Threads.stopは変化させない。
// 代わりに"info string time to return bestmove."と出力する。
output_time_to_return_bestmove();

} else {
} else {

Threads.stop = true;
Threads.stop = true;
}
}
}
}

// --- Stockfishの探索のコード、ここまで。

Expand Down
26 changes: 21 additions & 5 deletions source/movepick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ enum Stages: int {
GOOD_CAPTURE, // 捕獲する指し手(CAPTURES_PRO_PLUS)を生成して指し手を一つずつ返す
REFUTATION, // killer move,counter move
QUIET_INIT, // (QUIETの指し手生成)
QUIET_, // CAPTURES_PRO_PLUSで生成しなかった指し手を生成して、一つずつ返す。SEE値の悪い手は後回し。
QUIET, // CAPTURES_PRO_PLUSで生成しなかった指し手を生成して、一つずつ返す。SEE値の悪い手は後回し。
BAD_CAPTURE, // 捕獲する悪い指し手(SEE < 0 の指し手だが、将棋においてそこまで悪い手とは限らないが…)

// 将棋ではBAD_CAPTUREをQUIET_の前にやったほうが良いという従来説は以下の実験データにより覆った。
Expand Down Expand Up @@ -75,11 +75,27 @@ enum Stages: int {

QSEARCH_TT, // 置換表の指し手を返すフェーズ
QCAPTURE_INIT, // (QCAPTUREの指し手生成)
QCAPTURE_, // 捕獲する指し手 + 歩を成る指し手を一手ずつ返す
QCAPTURE, // 捕獲する指し手 + 歩を成る指し手を一手ずつ返す
QCHECK_INIT, // 王手となる指し手を生成
QCHECK // 王手となる指し手(- 歩を成る指し手)を返すフェーズ
};

/*
状態遷移の順番は、
王手がかかっていない時。
通常探索時 : MAIN_TT → CAPTURE_INIT → GOOD_CAPTURE → REFUTATION → QUIET_INIT → QUIET → BAD_CAPTURE
ProbCut時 : PROBCUT_TT → PROBCUT_INIT → PROBCUT
静止探索時 : QSEARCH_TT → QCAPTURE_INIT → QCAPTURE → (王手を生成するなら) QCHECK_INIT → QCHECK
※ 通常探索時にしか、REFUTATIONを呼び出していないので、すなわちProbCut時と静止探索時には
killerとかcountermoveの生成はしない。
※ 通常探索時に GOOD_CAPTUREとBAD_CAPTUREがあるのは、前者でスコアが悪かった指し手をBAD_CAPTUREに回すためである。
王手がかかっている時。
通常探索、静止探索共通 : EVASION_TT → EVASION_INIT → EVASION
*/

// -----------------------
// partial insertion sort
// -----------------------
Expand Down Expand Up @@ -554,7 +570,7 @@ Move MovePicker::next_move(bool skipQuiets) {
// 駒を捕獲しない指し手を返す。
// (置換表の指し手とkillerの指し手は返したあとなのでこれらの指し手は除外する必要がある)
// ※ これ、指し手の数が多い場合、AVXを使って一気に削除しておいたほうが良いのでは..
case QUIET_:
case QUIET:
if ( !skipQuiets
&& select<Next>([&]() { return *cur != refutations[0].move
&& *cur != refutations[1].move
Expand Down Expand Up @@ -594,10 +610,10 @@ Move MovePicker::next_move(bool skipQuiets) {
// PROBCUTの指し手を返す
case PROBCUT:
return select<Next>([&]() { return pos.see_ge(*cur, threshold); });
// threadshold以上のSEE値で、ベストのものを一つ
// threadshold以上のSEE値で、ベストのものを一つずつ返す

// 静止探索用の指し手を返す処理
case QCAPTURE_:
case QCAPTURE:
// depthがDEPTH_QS_RECAPTURES(-5)以下(深い)なら、recaptureの升に移動する指し手(直前で取られた駒を取り返す指し手)のみを生成。
if (select<Next>([&]() { return depth > DEPTH_QS_RECAPTURES
|| to_sq(*cur) == recaptureSquare; }))
Expand Down

0 comments on commit b58a4fe

Please sign in to comment.