// 協力詰め探索の反復深化のループ void id_loop(Position& pos, int thread_id, int thread_num) { pos.set_nodes_searched(0); auto start_time = now(); // 協力詰めの反復深化は2手ずつ深くして良い。 // lazy SMPっぽい並列化をする。 for (uint32_t depth = 1 + thread_id * 2; depth < MAX_PLY; depth += 2 * thread_num) { // 置換表のgenerationをインクリメントするのはmain threadだけ。 if (thread_id == 0) TT.new_search(); int no_mate_depth; id_depth_thread = depth; search(pos, depth, no_mate_depth); if (Signals.stop || mate_found) break; // 定期的にdepth、nodes、npsを出力する。 auto end_time = now(); auto node_searched = Threads.nodes_searched(); // 全スレッドでの探索合計 sync_cout << "info depth " << depth << " nodes " << node_searched << " nps " << (node_searched * 1000 / ((int64_t)(end_time - start_time + 1))) << " hashfull " << TT.hashfull() << sync_endl; // 最大探索深さに到達する前に王手が続かなくなっていたなら終了 if (no_mate_depth == MAX_PLY) { sync_cout << "checkmate nomate" << sync_endl; break; } // depth手では詰まないことが証明できたのでsearch_depthを書き換える。 // 他のスレッドが書き換える可能性もあるので値が大きいときのみ。 while (true) { auto sd = search_depth.load(); if (depth > sd) { if (search_depth.compare_exchange_weak(sd, depth)) break; } else break; // 下回っているので書き込む価値はない。 } } }