From a3d4aa5f1de2e5bdbe77a47d24f6edfb9fffc91b Mon Sep 17 00:00:00 2001 From: connormcmonigle Date: Sat, 6 Jan 2024 11:57:30 -0800 Subject: [PATCH] miscellaneous-cleanups (#186) Elo | -0.61 +- 1.91 (95%) SPRT | 8.0+0.08s Threads=1 Hash=32MB LLR | 0.43 (-2.94, 2.94) [-3.00, 0.00] Games | N: 62898 W: 15569 L: 15679 D: 31650 Penta | [317, 6521, 17876, 6425, 310] http://chess.grantnet.us/test/34956/ bench: 4473743 --- .clang-format | 1 + build/makefile | 3 +- include/chess/board.h | 2 +- include/chess/board_state.h | 1 - include/chess/castle_info.h | 2 +- include/chess/cuckoo_hash_table.h | 18 +++---- include/chess/move.h | 2 +- include/chess/move_list.h | 2 +- include/chess/pawn_info.h | 2 +- include/engine/bench.h | 2 +- include/engine/command_lexer.h | 2 +- include/engine/processor/condition_type.h | 2 +- include/engine/processor/consume_type.h | 2 +- include/engine/processor/emit_all_type.h | 2 +- include/engine/processor/emit_n_type.h | 2 +- include/engine/processor/emit_type.h | 2 +- include/engine/processor/invoke_type.h | 2 +- include/engine/processor/key_type.h | 2 +- include/engine/processor/null_type.h | 2 +- .../processor/parallel_combinator_type.h | 2 +- .../processor/receiver_combinator_type.h | 2 +- .../processor/sequential_combinator_type.h | 2 +- include/feature/util.h | 2 +- include/nnue/aligned_scratchpad.h | 2 +- include/nnue/aligned_slice.h | 3 +- include/nnue/aligned_vector.h | 2 +- include/nnue/dense_relu_affine_layer.h | 2 +- include/nnue/dot_type.h | 2 +- include/nnue/embedded_weights.h | 2 +- include/nnue/eval.h | 53 +++++++++++++++---- include/nnue/feature_transformer.h | 2 +- include/nnue/simd.h | 16 +++--- include/nnue/sparse_affine_layer.h | 7 ++- include/nnue/weights.h | 2 +- include/search/eval_cache.h | 13 ++--- include/search/eval_correction_history.h | 10 ++-- include/search/history_heuristic.h | 4 +- include/search/search_worker.h | 11 ++-- include/search/search_worker_external_state.h | 2 +- include/search/search_worker_orchestrator.h | 2 +- include/search/syzygy.h | 2 +- include/search/transposition_table.h | 6 ++- include/util/string.h | 2 +- include/util/swap.h | 2 +- include/util/tuple.h | 2 +- include/util/unreachable.h | 2 +- include/zobrist/zobrist_hasher.h | 2 +- src/chess/board.cc | 4 +- src/chess/move_list.cc | 2 +- src/engine/bench.cc | 2 +- src/engine/uci.cc | 7 ++- src/search/move_orderer.cc | 2 +- src/search/search_worker.cc | 40 ++++++++++---- src/search/search_worker_orchestrator.cc | 2 +- src/search/syzygy.cc | 2 +- src/search/transposition_table.cc | 2 +- 56 files changed, 166 insertions(+), 111 deletions(-) diff --git a/.clang-format b/.clang-format index afce7d3a..28c9ebc2 100644 --- a/.clang-format +++ b/.clang-format @@ -2,6 +2,7 @@ IndentWidth: 2 ColumnLimit: 150 AlignAfterOpenBracket: AlwaysBreak +AllowAllParametersOfDeclarationOnNextLine: 'false' AllowShortBlocksOnASingleLine: 'true' AllowShortCaseLabelsOnASingleLine: 'true' AllowShortFunctionsOnASingleLine: All diff --git a/build/makefile b/build/makefile index c8021e0d..c6b878c2 100644 --- a/build/makefile +++ b/build/makefile @@ -55,7 +55,8 @@ profileuse: CXXFLAGS += -fprofile-use profileuse: flto .PHONY: flto -flto: CXXFLAGS += -flto -fwhole-program +flto: CXXFLAGS += -flto -flto-partition=one -fwhole-program +flto: LDFLAGS += -flto=jobserver flto: binary .PHONY: plain diff --git a/include/chess/board.h b/include/chess/board.h index 931dff3e..12456c2f 100644 --- a/include/chess/board.h +++ b/include/chess/board.h @@ -320,4 +320,4 @@ struct board { [[maybe_unused]] std::ostream& operator<<(std::ostream& ostr, const board& bd) noexcept; -} // namespace chess \ No newline at end of file +} // namespace chess diff --git a/include/chess/board_state.h b/include/chess/board_state.h index d641978b..4139bda7 100644 --- a/include/chess/board_state.h +++ b/include/chess/board_state.h @@ -93,7 +93,6 @@ struct manifest { [[nodiscard]] constexpr const square_set& queen() const noexcept { return queen_; } [[nodiscard]] constexpr const square_set& king() const noexcept { return king_; } - template [[maybe_unused]] manifest& add_piece(const piece_type& pt, const S& at) noexcept; diff --git a/include/chess/castle_info.h b/include/chess/castle_info.h index fff6bcd1..bf5e7fca 100644 --- a/include/chess/castle_info.h +++ b/include/chess/castle_info.h @@ -128,4 +128,4 @@ struct castle_info_ { template inline constexpr castle_info_ castle_info = castle_info_{}; -} // namespace chess \ No newline at end of file +} // namespace chess diff --git a/include/chess/cuckoo_hash_table.h b/include/chess/cuckoo_hash_table.h index 20a3530a..35297d69 100644 --- a/include/chess/cuckoo_hash_table.h +++ b/include/chess/cuckoo_hash_table.h @@ -83,18 +83,18 @@ struct cuckoo_hash_table_impl { return std::nullopt; } - constexpr void insert(zobrist::hash_type hash, cuckoo_hash_table_entry entry) noexcept { + constexpr void insert(zobrist::hash_type hash, cuckoo_hash_table_entry entry) noexcept { std::size_t index = a_hash_function(hash); for (;;) { - util::copy_swap(entry, entries_[index]); - util::copy_swap(hash, hashes_[index]); - - if (hash == initial_hash) { break; } - - const std::size_t a_index = a_hash_function(hash); - const std::size_t b_index = b_hash_function(hash); - index = (index == a_index) ? b_index : a_index; + util::copy_swap(entry, entries_[index]); + util::copy_swap(hash, hashes_[index]); + + if (hash == initial_hash) { break; } + + const std::size_t a_index = a_hash_function(hash); + const std::size_t b_index = b_hash_function(hash); + index = (index == a_index) ? b_index : a_index; } } diff --git a/include/chess/move.h b/include/chess/move.h index 457aebb5..d3317544 100644 --- a/include/chess/move.h +++ b/include/chess/move.h @@ -142,4 +142,4 @@ struct move_hash { [[nodiscard]] std::size_t operator()(const move& mv) const noexcept { return std::hash{}(mv.data); } }; -} // namespace chess \ No newline at end of file +} // namespace chess diff --git a/include/chess/move_list.h b/include/chess/move_list.h index acabfb1f..13a800b2 100644 --- a/include/chess/move_list.h +++ b/include/chess/move_list.h @@ -81,4 +81,4 @@ struct move_list { std::ostream& operator<<(std::ostream& ostr, const move_list& mv_ls) noexcept; -} // namespace chess \ No newline at end of file +} // namespace chess diff --git a/include/chess/pawn_info.h b/include/chess/pawn_info.h index 280de9cb..78e931b4 100644 --- a/include/chess/pawn_info.h +++ b/include/chess/pawn_info.h @@ -51,4 +51,4 @@ struct pawn_info { static constexpr delta step = delta{0, -1}; }; -} // namespace chess \ No newline at end of file +} // namespace chess diff --git a/include/engine/bench.h b/include/engine/bench.h index 4ca8288a..b931dd64 100644 --- a/include/engine/bench.h +++ b/include/engine/bench.h @@ -105,4 +105,4 @@ struct bench_info { [[nodiscard]] std::size_t perft(const chess::board& bd, const search::depth_type& depth) noexcept; [[nodiscard]] bench_info get_perft_info(const chess::board& bd, const search::depth_type& depth) noexcept; -} // namespace engine \ No newline at end of file +} // namespace engine diff --git a/include/engine/command_lexer.h b/include/engine/command_lexer.h index 02463757..35146b7e 100644 --- a/include/engine/command_lexer.h +++ b/include/engine/command_lexer.h @@ -117,4 +117,4 @@ struct command_lexer { [[nodiscard]] lexed_command lex(const std::string& input) const noexcept { return lexed_command(input); } }; -} // namespace engine \ No newline at end of file +} // namespace engine diff --git a/include/engine/processor/condition_type.h b/include/engine/processor/condition_type.h index b1891fae..d11a7000 100644 --- a/include/engine/processor/condition_type.h +++ b/include/engine/processor/condition_type.h @@ -46,4 +46,4 @@ namespace def { } // namespace def -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/consume_type.h b/include/engine/processor/consume_type.h index bc37408a..0c60a599 100644 --- a/include/engine/processor/consume_type.h +++ b/include/engine/processor/consume_type.h @@ -42,4 +42,4 @@ namespace def { } // namespace def -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/emit_all_type.h b/include/engine/processor/emit_all_type.h index cce1f80d..1d316194 100644 --- a/include/engine/processor/emit_all_type.h +++ b/include/engine/processor/emit_all_type.h @@ -42,4 +42,4 @@ constexpr auto emit_all = emit_all_type{}; } -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/emit_n_type.h b/include/engine/processor/emit_n_type.h index 76795a2e..76901690 100644 --- a/include/engine/processor/emit_n_type.h +++ b/include/engine/processor/emit_n_type.h @@ -45,4 +45,4 @@ constexpr auto emit_n = emit_n_type{}; } -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/emit_type.h b/include/engine/processor/emit_type.h index 3a53a07f..b6f1a3f7 100644 --- a/include/engine/processor/emit_type.h +++ b/include/engine/processor/emit_type.h @@ -44,4 +44,4 @@ constexpr auto emit = emit_type{}; } -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/invoke_type.h b/include/engine/processor/invoke_type.h index 8650e6f9..4c408a86 100644 --- a/include/engine/processor/invoke_type.h +++ b/include/engine/processor/invoke_type.h @@ -49,4 +49,4 @@ template } // namespace def -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/key_type.h b/include/engine/processor/key_type.h index 83c71535..427ff314 100644 --- a/include/engine/processor/key_type.h +++ b/include/engine/processor/key_type.h @@ -50,4 +50,4 @@ template } // namespace def -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/null_type.h b/include/engine/processor/null_type.h index b3d01f58..1bd10b29 100644 --- a/include/engine/processor/null_type.h +++ b/include/engine/processor/null_type.h @@ -38,4 +38,4 @@ constexpr auto null = null_type{}; } -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/parallel_combinator_type.h b/include/engine/processor/parallel_combinator_type.h index 0a5dda8b..db583a44 100644 --- a/include/engine/processor/parallel_combinator_type.h +++ b/include/engine/processor/parallel_combinator_type.h @@ -47,4 +47,4 @@ template } // namespace def -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/receiver_combinator_type.h b/include/engine/processor/receiver_combinator_type.h index 5ae9928b..81e48a81 100644 --- a/include/engine/processor/receiver_combinator_type.h +++ b/include/engine/processor/receiver_combinator_type.h @@ -36,4 +36,4 @@ struct receiver_combinator_type { constexpr receiver_combinator_type(const A& processor, const B& receiver) noexcept : processor_{processor}, receiver_{receiver} {} }; -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/engine/processor/sequential_combinator_type.h b/include/engine/processor/sequential_combinator_type.h index d7d91af3..4f387a83 100644 --- a/include/engine/processor/sequential_combinator_type.h +++ b/include/engine/processor/sequential_combinator_type.h @@ -56,4 +56,4 @@ template } // namespace def -} // namespace engine::processor \ No newline at end of file +} // namespace engine::processor diff --git a/include/feature/util.h b/include/feature/util.h index 14287a25..59fac4f2 100644 --- a/include/feature/util.h +++ b/include/feature/util.h @@ -81,4 +81,4 @@ template return major * (ks.index() ^ mirror_constant)+offset(pt) + (sq.index() ^ mirror_constant); } -} // namespace feature::half_ka \ No newline at end of file +} // namespace feature::half_ka diff --git a/include/nnue/aligned_scratchpad.h b/include/nnue/aligned_scratchpad.h index cc474ac4..88d0ce7c 100644 --- a/include/nnue/aligned_scratchpad.h +++ b/include/nnue/aligned_scratchpad.h @@ -36,4 +36,4 @@ struct aligned_scratchpad { } }; -} // namespace nnue \ No newline at end of file +} // namespace nnue diff --git a/include/nnue/aligned_slice.h b/include/nnue/aligned_slice.h index d6a5156f..ccd61928 100644 --- a/include/nnue/aligned_slice.h +++ b/include/nnue/aligned_slice.h @@ -56,4 +56,5 @@ inline std::ostream& operator<<(std::ostream& ostr, const aligned_slice& ostr << vec.data[dim - 1] << "])"; return ostr; } -} // namespace nnue \ No newline at end of file + +} // namespace nnue diff --git a/include/nnue/aligned_vector.h b/include/nnue/aligned_vector.h index 8b17ee4e..859b69c4 100644 --- a/include/nnue/aligned_vector.h +++ b/include/nnue/aligned_vector.h @@ -135,4 +135,4 @@ inline std::ostream& operator<<(std::ostream& ostr, const aligned_vector return ostr; } -} // namespace nnue \ No newline at end of file +} // namespace nnue diff --git a/include/nnue/dense_relu_affine_layer.h b/include/nnue/dense_relu_affine_layer.h index c9a4f45d..a4da958d 100644 --- a/include/nnue/dense_relu_affine_layer.h +++ b/include/nnue/dense_relu_affine_layer.h @@ -83,4 +83,4 @@ struct dense_relu_affine_layer { } }; -} // namespace nnue \ No newline at end of file +} // namespace nnue diff --git a/include/nnue/dot_type.h b/include/nnue/dot_type.h index 1dd56593..4d45a6be 100644 --- a/include/nnue/dot_type.h +++ b/include/nnue/dot_type.h @@ -52,4 +52,4 @@ struct dot_type_impl { template using dot_type = typename dot_type_impl::type; -} \ No newline at end of file +} // namespace nnue diff --git a/include/nnue/embedded_weights.h b/include/nnue/embedded_weights.h index 39261d6a..9175286b 100644 --- a/include/nnue/embedded_weights.h +++ b/include/nnue/embedded_weights.h @@ -27,4 +27,4 @@ extern "C" { INCBIN(weights_file, EVALFILE); } -} // namespace nnue::embed \ No newline at end of file +} // namespace nnue::embed diff --git a/include/nnue/eval.h b/include/nnue/eval.h index 998e8061..e429c9eb 100644 --- a/include/nnue/eval.h +++ b/include/nnue/eval.h @@ -34,17 +34,47 @@ #include #include #include +#include #include namespace nnue { +struct void_encoding {}; + +struct void_final_output_encoder { + template + [[maybe_unused]] constexpr void_encoding operator()(Ts&&...) const noexcept { + return void_encoding{}; + } +}; + +template +struct propagate_data { + T final_output_encoding; + weights::parameter_type result; + + constexpr propagate_data(const T& final_output_encoding, const weights::parameter_type& result) noexcept + : final_output_encoding{final_output_encoding}, result{result} {} +}; + +template +struct evaluate_data { + T final_output_encoding; + search::score_type result; + + constexpr evaluate_data(const T& final_output_encoding, const search::score_type& result) noexcept + : final_output_encoding{final_output_encoding}, result{result} {} +}; + struct eval : public chess::sided> { static constexpr std::size_t base_dim = weights::base_dim; static constexpr std::size_t feature_transformer_dim = 2 * base_dim; static constexpr std::size_t scratchpad_depth = 256; + static constexpr std::size_t final_layer_dimension = 24; using parameter_type = weights::parameter_type; using quantized_parameter_type = weights::quantized_parameter_type; + using final_output_type = aligned_vector; using scratchpad_type = aligned_scratchpad; const quantized_weights* weights_; @@ -58,31 +88,29 @@ struct eval : public chess::sided white; feature_transformer black; - [[nodiscard]] inline std::pair propagate(const bool pov) const noexcept { + template + [[nodiscard]] inline propagate_data> propagate(const bool pov, F&& final_output_encoder) const noexcept { const auto x1 = (pov ? weights_->white_fc0 : weights_->black_fc0).forward(base_).dequantized(weights::dequantization_scale); const auto x2 = concat(x1, weights_->fc1.forward(x1)); const auto x3 = concat(x2, weights_->fc2.forward(x2)); - - constexpr std::size_t dimension = decltype(x3)::dimension; - const zobrist::quarter_hash_type quarter_hash = zobrist::zobrist_hasher.compute_hash( - [&x3](const std::size_t& i) { return x3.data[i] > parameter_type{}; }); - - return std::pair(quarter_hash, weights_->fc3.forward(x3).item()); + return propagate_data(final_output_encoder(x3), weights_->fc3.forward(x3).item()); } - [[nodiscard]] inline std::pair evaluate(const bool pov, const parameter_type& phase) const noexcept { + template + [[nodiscard]] inline evaluate_data> + evaluate(const bool pov, const parameter_type& phase, F&& final_output_encoder = void_final_output_encoder{}) const noexcept { constexpr auto one = static_cast(1.0); constexpr auto mg = static_cast(0.7); constexpr auto eg = static_cast(0.55); - const auto [hash, prediction] = propagate(pov); + const auto [final_output_encoding, prediction] = propagate(pov, std::forward(final_output_encoder)); const parameter_type eval = phase * mg * prediction + (one - phase) * eg * prediction; const parameter_type value = search::logit_scale * std::clamp(eval, search::min_logit, search::max_logit); const auto score = static_cast(value); - return std::pair(hash, score); + return evaluate_data(final_output_encoding, score); } [[nodiscard]] eval next_child() const noexcept { @@ -91,7 +119,10 @@ struct eval : public chess::sided>; - static inline void f( - const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { + static inline void + f(const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { for (std::size_t i(0); i < dim; i += num_units * per_unit) { { const __m512i a_0_0 = _mm512_load_si512((__m512i*)(a_0 + i + 0 * per_unit)); @@ -292,8 +292,8 @@ struct int16_add_add_sub_sub_x128 { }; template -inline void add_add_sub_sub( - const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { +inline void +add_add_sub_sub(const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { return overload_set>::f(a_0, a_1, s_0, s_1, out); } @@ -541,8 +541,8 @@ struct int16_add_add_sub_sub_x64 { static constexpr std::size_t num_units = 4; static constexpr bool available = divides>; - static inline void f( - const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { + static inline void + f(const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { for (std::size_t i(0); i < dim; i += num_units * per_unit) { { const __m256i a_0_0 = _mm256_load_si256((__m256i*)(a_0 + i + 0 * per_unit)); @@ -584,8 +584,8 @@ struct int16_add_add_sub_sub_x64 { }; template -inline void add_add_sub_sub( - const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { +inline void +add_add_sub_sub(const std::int16_t* a_0, const std::int16_t* a_1, const std::int16_t* s_0, const std::int16_t* s_1, std::int16_t* out) noexcept { return overload_set>::f(a_0, a_1, s_0, s_1, out); } diff --git a/include/nnue/sparse_affine_layer.h b/include/nnue/sparse_affine_layer.h index 96e55296..8d3336eb 100644 --- a/include/nnue/sparse_affine_layer.h +++ b/include/nnue/sparse_affine_layer.h @@ -45,7 +45,10 @@ struct sparse_affine_layer { } void insert_erase_idx( - const std::size_t insert_idx, const std::size_t erase_idx, const aligned_slice& src, aligned_slice dst) const { + const std::size_t insert_idx, + const std::size_t erase_idx, + const aligned_slice& src, + aligned_slice dst) const { const T* insert_mem_region = W + insert_idx * dim1; const T* erase_mem_region = W + erase_idx * dim1; simd::add_add_sub(src.data, insert_mem_region, erase_mem_region, dst.data); @@ -116,4 +119,4 @@ struct sparse_affine_layer { } }; -} // namespace nnue \ No newline at end of file +} // namespace nnue diff --git a/include/nnue/weights.h b/include/nnue/weights.h index 1897f20b..963e970f 100644 --- a/include/nnue/weights.h +++ b/include/nnue/weights.h @@ -158,4 +158,4 @@ struct quantized_weights { } }; -} // namespace nnue \ No newline at end of file +} // namespace nnue diff --git a/include/search/eval_cache.h b/include/search/eval_cache.h index e7cdb697..16504513 100644 --- a/include/search/eval_cache.h +++ b/include/search/eval_cache.h @@ -29,19 +29,20 @@ struct eval_cache_entry { using persisted_eval_type = std::int16_t; zobrist::half_hash_type hash_{}; - zobrist::quarter_hash_type feature_hash_{}; + zobrist::quarter_hash_type eval_feature_hash_{}; persisted_eval_type persisted_eval_{}; [[nodiscard]] constexpr const zobrist::half_hash_type& hash() const noexcept { return hash_; } - [[nodiscard]] constexpr const zobrist::quarter_hash_type& feature_hash() const noexcept { return feature_hash_; } + [[nodiscard]] constexpr const zobrist::quarter_hash_type& eval_feature_hash() const noexcept { return eval_feature_hash_; } + [[nodiscard]] constexpr score_type eval() const noexcept { return static_cast(persisted_eval_); } - [[nodiscard]] static constexpr eval_cache_entry make( - const zobrist::hash_type& hash, const zobrist::quarter_hash_type& feature_hash, const score_type& eval) noexcept { + [[nodiscard]] static constexpr eval_cache_entry + make(const zobrist::hash_type& hash, const zobrist::quarter_hash_type& eval_feature_hash, const score_type& eval) noexcept { const zobrist::half_hash_type hash_upper_half = zobrist::upper_half(hash); const persisted_eval_type persisted_eval = static_cast(eval); - return eval_cache_entry{hash_upper_half, feature_hash, persisted_eval}; + return eval_cache_entry{hash_upper_half, eval_feature_hash, persisted_eval}; } }; @@ -65,4 +66,4 @@ struct eval_cache { void clear() noexcept { return data.fill(eval_cache_entry{}); } }; -} // namespace search \ No newline at end of file +} // namespace search diff --git a/include/search/eval_correction_history.h b/include/search/eval_correction_history.h index a316ab44..54916643 100644 --- a/include/search/eval_correction_history.h +++ b/include/search/eval_correction_history.h @@ -40,16 +40,13 @@ struct eval_correction_history { return raw_correction / eval_correction_scale; } - constexpr void update(const zobrist::quarter_hash_type& feature_hash, const bound_type& bound, const score_type& error) noexcept { + constexpr void update(const zobrist::quarter_hash_type& feature_hash, const score_type& error) noexcept { constexpr score_type score_correction_limit = 65536; constexpr score_type filter_alpha = 1; constexpr score_type filter_c_alpha = 255; constexpr score_type filter_divisor = filter_alpha + filter_c_alpha; - if (bound == bound_type::upper && error >= 0) { return; } - if (bound == bound_type::lower && error <= 0) { return; } - auto& correction = data[hash_function(feature_hash)]; const score_type scaled_error = error * eval_correction_scale; @@ -88,9 +85,12 @@ struct composite_eval_correction_history { } constexpr void update(const composite_feature_hash& composite_hash, const bound_type& bound, const score_type& error) noexcept { + if (bound == bound_type::upper && error >= 0) { return; } + if (bound == bound_type::lower && error <= 0) { return; } + for (std::size_t i(0); i < N; ++i) { const zobrist::quarter_hash_type hash = composite_hash.hash(i); - histories_[i].update(hash, bound, error); + histories_[i].update(hash, error); } } diff --git a/include/search/history_heuristic.h b/include/search/history_heuristic.h index 4da138e3..7d569772 100644 --- a/include/search/history_heuristic.h +++ b/include/search/history_heuristic.h @@ -151,8 +151,8 @@ template struct combined { std::tuple...> tables_{}; - [[maybe_unused]] constexpr combined& update( - const context& ctxt, const chess::move& best_move, const chess::move_list& tried, const depth_type& depth) noexcept { + [[maybe_unused]] constexpr combined& + update(const context& ctxt, const chess::move& best_move, const chess::move_list& tried, const depth_type& depth) noexcept { constexpr value_type history_max = 400; auto single_update = [&, this](const auto& mv, const value_type& gain) { diff --git a/include/search/search_worker.h b/include/search/search_worker.h index 1b7dca49..6a09a0cd 100644 --- a/include/search/search_worker.h +++ b/include/search/search_worker.h @@ -47,7 +47,7 @@ struct pv_search_result { template using pv_search_result_t = typename pv_search_result::type; -struct evaluation_info { +struct evaluate_info { sided_eval_correction_history::hash_type hash; score_type static_value; score_type value; @@ -58,11 +58,8 @@ struct search_worker { search_worker_internal_state internal{}; template - [[nodiscard]] inline evaluation_info evaluate_( - const stack_view& ss, - nnue::eval_node& eval_node, - const chess::board& bd, - const std::optional& maybe) noexcept; + [[nodiscard]] inline evaluate_info + evaluate(const stack_view& ss, nnue::eval_node& eval_node, const chess::board& bd, const std::optional& maybe) noexcept; template [[nodiscard]] score_type q_search( @@ -120,4 +117,4 @@ struct search_worker { : external(weights, tt, constants, on_iter, on_update) {} }; -} // namespace search \ No newline at end of file +} // namespace search diff --git a/include/search/search_worker_external_state.h b/include/search/search_worker_external_state.h index fe4e5e90..41147747 100644 --- a/include/search/search_worker_external_state.h +++ b/include/search/search_worker_external_state.h @@ -43,4 +43,4 @@ struct search_worker_external_state { : weights{weights_}, tt{tt_}, constants{constants_}, on_iter{on_iter_}, on_update{on_update_} {} }; -} // namespace search \ No newline at end of file +} // namespace search diff --git a/include/search/search_worker_orchestrator.h b/include/search/search_worker_orchestrator.h index 8c9d7bad..44437a9a 100644 --- a/include/search/search_worker_orchestrator.h +++ b/include/search/search_worker_orchestrator.h @@ -61,4 +61,4 @@ struct worker_orchestrator { ~worker_orchestrator() noexcept; }; -} // namespace search \ No newline at end of file +} // namespace search diff --git a/include/search/syzygy.h b/include/search/syzygy.h index 2b26a4b7..779973c2 100644 --- a/include/search/syzygy.h +++ b/include/search/syzygy.h @@ -57,4 +57,4 @@ struct tb_dtz_result { void init(const std::string& path) noexcept; -} // namespace search \ No newline at end of file +} // namespace search::syzygy diff --git a/include/search/transposition_table.h b/include/search/transposition_table.h index 00e361e2..ea2489d7 100644 --- a/include/search/transposition_table.h +++ b/include/search/transposition_table.h @@ -113,7 +113,8 @@ struct alignas(cache_line_size) bucket { transposition_table_entry data[N]; [[nodiscard]] constexpr std::optional match( - const transposition_table_entry::gen_type& gen, const zobrist::hash_type& key) noexcept { + const transposition_table_entry::gen_type& gen, + const zobrist::hash_type& key) noexcept { for (auto& elem : data) { if (elem.key() == key) { return std::optional(elem.set_gen(gen)); } } @@ -122,7 +123,8 @@ struct alignas(cache_line_size) bucket { } [[nodiscard]] constexpr transposition_table_entry* to_replace( - const transposition_table_entry::gen_type& gen, const zobrist::hash_type& key) noexcept { + const transposition_table_entry::gen_type& gen, + const zobrist::hash_type& key) noexcept { auto worst = std::begin(data); for (auto iter = std::begin(data); iter != std::end(data); ++iter) { if (iter->key() == key) { return iter; } diff --git a/include/util/string.h b/include/util/string.h index db153b33..6548c7e2 100644 --- a/include/util/string.h +++ b/include/util/string.h @@ -33,4 +33,4 @@ template return result.str(); } -} // namespace util::string \ No newline at end of file +} // namespace util::string diff --git a/include/util/swap.h b/include/util/swap.h index d26bbcc7..7f82b56b 100644 --- a/include/util/swap.h +++ b/include/util/swap.h @@ -26,4 +26,4 @@ constexpr void copy_swap(T& a, T& b) { b = c; } -} +} // namespace util diff --git a/include/util/tuple.h b/include/util/tuple.h index a1ed1bc5..a92dc9e9 100644 --- a/include/util/tuple.h +++ b/include/util/tuple.h @@ -59,4 +59,4 @@ constexpr std::tuple append(const std::tuple& tuple, const return std::tuple_cat(tuple, std::tuple{args...}); } -} // namespace util::tuple \ No newline at end of file +} // namespace util::tuple diff --git a/include/util/unreachable.h b/include/util/unreachable.h index cbf5625a..cb999539 100644 --- a/include/util/unreachable.h +++ b/include/util/unreachable.h @@ -21,4 +21,4 @@ namespace util { inline void unreachable() { __builtin_unreachable(); } -} // namespace util \ No newline at end of file +} // namespace util diff --git a/include/zobrist/zobrist_hasher.h b/include/zobrist/zobrist_hasher.h index 087cc27b..3c5527cb 100644 --- a/include/zobrist/zobrist_hasher.h +++ b/include/zobrist/zobrist_hasher.h @@ -65,4 +65,4 @@ struct zobrist_hasher_impl { template inline constexpr zobrist_hasher_impl zobrist_hasher = zobrist_hasher_impl{}; -} // namespace zobrist \ No newline at end of file +} // namespace zobrist diff --git a/src/chess/board.cc b/src/chess/board.cc index f336f747..8b0f6082 100644 --- a/src/chess/board.cc +++ b/src/chess/board.cc @@ -598,12 +598,12 @@ template for (std::size_t reverse_idx = 3; reverse_idx <= limit; reverse_idx += 2) { const std::size_t idx = size - reverse_idx; const zobrist::hash_type delta = us_hash ^ history.at(idx).us(); - + if (delta == cuckoo_hash_table::value_type::initial_hash) { continue; } if (them_hash != history.at(idx).them()) { continue; } const std::optional entry = cuckoo_hash_table::instance.look_up(delta); - + if (entry.has_value()) { const square_set candidates = square_set::of(entry->one(), entry->two()); const square_set available = man_.us().get_plane(entry->piece()); diff --git a/src/chess/move_list.cc b/src/chess/move_list.cc index a8e83e7e..689aa676 100644 --- a/src/chess/move_list.cc +++ b/src/chess/move_list.cc @@ -24,4 +24,4 @@ std::ostream& operator<<(std::ostream& ostr, const move_list& mv_ls) noexcept { return ostr; } -} \ No newline at end of file +} // namespace chess \ No newline at end of file diff --git a/src/engine/bench.cc b/src/engine/bench.cc index 188ac668..3092ab2f 100644 --- a/src/engine/bench.cc +++ b/src/engine/bench.cc @@ -60,4 +60,4 @@ bench_info get_perft_info(const chess::board& bd, const search::depth_type& dept return bench_info{nodes, nodes_per_second}; } -} // namespace engine \ No newline at end of file +} // namespace engine diff --git a/src/engine/uci.cc b/src/engine/uci.cc index fb872e9b..5a564873 100644 --- a/src/engine/uci.cc +++ b/src/engine/uci.cc @@ -194,11 +194,10 @@ void uci::eval() noexcept { auto evaluator = nnue::eval(&weights_, scratchpad.get(), 0, 0); position.feature_full_reset(evaluator); - const auto [hash, score] = evaluator.evaluate(position.turn(), position.phase()); + const auto score = evaluator.evaluate(position.turn(), position.phase()); - os << "hash: " << hash << std::endl; os << "phase: " << position.phase() << std::endl; - os << "score(phase): " << score << std::endl; + os << "score(phase): " << score.result << std::endl; } void uci::probe() noexcept { @@ -309,4 +308,4 @@ uci::uci() noexcept orchestrator_.resize(default_thread_count); } -} // namespace engine \ No newline at end of file +} // namespace engine diff --git a/src/search/move_orderer.cc b/src/search/move_orderer.cc index a7df9d10..663e0ae1 100644 --- a/src/search/move_orderer.cc +++ b/src/search/move_orderer.cc @@ -72,4 +72,4 @@ move_orderer_iterator::move_orderer_iterator(const move_orderer_data& data } // namespace search template struct search::move_orderer_iterator; -template struct search::move_orderer_iterator; \ No newline at end of file +template struct search::move_orderer_iterator; diff --git a/src/search/search_worker.cc b/src/search/search_worker.cc index 6a73c212..e0466d54 100644 --- a/src/search/search_worker.cc +++ b/src/search/search_worker.cc @@ -22,8 +22,11 @@ namespace search { template -inline evaluation_info search_worker::evaluate_( - const stack_view& ss, nnue::eval_node& eval_node, const chess::board& bd, const std::optional& maybe) noexcept { +inline evaluate_info search_worker::evaluate( + const stack_view& ss, + nnue::eval_node& eval_node, + const chess::board& bd, + const std::optional& maybe) noexcept { const bool is_check = bd.is_check(); const eval_cache_entry entry = [&] { @@ -34,13 +37,20 @@ inline evaluation_info search_worker::evaluate_( const nnue::eval& evaluator = eval_node.evaluator(); const zobrist::hash_type hash = bd.hash(); - const auto [feature_hash, eval] = evaluator.evaluate(bd.turn(), bd.phase()); - return eval_cache_entry::make(hash, feature_hash, eval); + const auto [eval_feature_hash, eval] = evaluator.evaluate(bd.turn(), bd.phase(), [](const auto& final_output) { + constexpr std::size_t dimension = nnue::eval::final_output_type::dimension; + return zobrist::zobrist_hasher.compute_hash( + [&final_output](const std::size_t& i) { return final_output.data[i] > nnue::weights::parameter_type{}; }); + }); + + return eval_cache_entry::make(hash, eval_feature_hash, eval); }(); const auto pawn_feature_hash = zobrist::lower_quarter(bd.pawn_hash()); - const auto feature_hash = composite_feature_hash_of(pawn_feature_hash, entry.feature_hash()); + const auto eval_feature_hash = entry.eval_feature_hash(); + + const auto feature_hash = composite_feature_hash_of(pawn_feature_hash, eval_feature_hash); score_type static_value = entry.eval(); if (!is_check) { @@ -55,7 +65,7 @@ inline evaluation_info search_worker::evaluate_( if (maybe->bound() == bound_type::lower && static_value < maybe->score()) { value = maybe->score(); } } - return evaluation_info{feature_hash, static_value, value}; + return evaluate_info{feature_hash, static_value, value}; } template @@ -87,7 +97,7 @@ score_type search_worker::q_search( if (use_tt && is_cutoff) { return entry.score(); } } - const auto [feature_hash, static_value, value] = evaluate_(ss, eval_node, bd, maybe); + const auto [feature_hash, static_value, value] = evaluate(ss, eval_node, bd, maybe); if (!is_check && value >= beta) { return value; } if (ss.reached_max_height()) { return value; } @@ -215,7 +225,7 @@ pv_search_result_t search_worker::pv_search( if (should_iir) { --depth; } // step 4. compute static eval and adjust appropriately if there's a tt hit - const auto [feature_hash, static_value, value] = evaluate_(ss, eval_node, bd, maybe); + const auto [feature_hash, static_value, value] = evaluate(ss, eval_node, bd, maybe); // step 5. return static eval if max depth was reached if (ss.reached_max_height()) { return make_result(value, chess::move::null()); } @@ -527,7 +537,17 @@ void search_worker::iterative_deepening_loop() noexcept { } // namespace search template search::score_type search::search_worker::q_search( - const stack_view& ss, nnue::eval_node& eval_node, const chess::board& bd, score_type alpha, const score_type& beta, const depth_type& elevation); + const stack_view& ss, + nnue::eval_node& eval_node, + const chess::board& bd, + score_type alpha, + const score_type& beta, + const depth_type& elevation); template search::score_type search::search_worker::q_search( - const stack_view& ss, nnue::eval_node& eval_node, const chess::board& bd, score_type alpha, const score_type& beta, const depth_type& elevation); + const stack_view& ss, + nnue::eval_node& eval_node, + const chess::board& bd, + score_type alpha, + const score_type& beta, + const depth_type& elevation); diff --git a/src/search/search_worker_orchestrator.cc b/src/search/search_worker_orchestrator.cc index dccdbd6d..e5b5e1bf 100644 --- a/src/search/search_worker_orchestrator.cc +++ b/src/search/search_worker_orchestrator.cc @@ -95,4 +95,4 @@ worker_orchestrator::~worker_orchestrator() noexcept { std::for_each(threads_.begin(), threads_.end(), [](auto& thread) { thread.join(); }); } -} // namespace search \ No newline at end of file +} // namespace search diff --git a/src/search/syzygy.cc b/src/search/syzygy.cc index abfced73..90255d5d 100644 --- a/src/search/syzygy.cc +++ b/src/search/syzygy.cc @@ -85,4 +85,4 @@ tb_dtz_result probe_dtz(const chess::board& bd) noexcept { void init(const std::string& path) noexcept { tb_init(path.c_str()); } -} // namespace search \ No newline at end of file +} // namespace search::syzygy diff --git a/src/search/transposition_table.cc b/src/search/transposition_table.cc index 1615398a..fd69adaa 100644 --- a/src/search/transposition_table.cc +++ b/src/search/transposition_table.cc @@ -63,4 +63,4 @@ std::optional transposition_table::find(const zobrist // clang-format on -} // namespace search \ No newline at end of file +} // namespace search