From 2084d94266f76f1ab5631f32708916a4d5cca246 Mon Sep 17 00:00:00 2001 From: Carlos Esparza Date: Thu, 13 Nov 2025 11:45:45 -0800 Subject: [PATCH] inline make_index() and avoid templating perspective combination of two patches. pass perspective as argument passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 52832 W: 13725 L: 13528 D: 25579 Ptnml(0-2): 154, 5756, 14412, 5927, 167 https://tests.stockfishchess.org/tests/view/69162e307ca8781852331c6a inline make_index passed STC: LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 68768 W: 17786 L: 17607 D: 33375 Ptnml(0-2): 187, 7591, 18694, 7680, 232 https://tests.stockfishchess.org/tests/view/6916859e7ca8781852331d36 closes https://github.com/official-stockfish/Stockfish/pull/6429 No functional change --- src/misc.h | 9 + src/nnue/features/full_threats.cpp | 113 +++++-------- src/nnue/features/full_threats.h | 15 +- src/nnue/features/half_ka_v2_hm.cpp | 47 ++--- src/nnue/features/half_ka_v2_hm.h | 18 +- src/nnue/nnue_accumulator.cpp | 254 +++++++++++++++------------- src/nnue/nnue_accumulator.h | 19 ++- 7 files changed, 231 insertions(+), 244 deletions(-) diff --git a/src/misc.h b/src/misc.h index fce6f17df..66c03b806 100644 --- a/src/misc.h +++ b/src/misc.h @@ -412,6 +412,15 @@ void move_to_front(std::vector& vec, Predicate pred) { } } +#if defined(__GNUC__) + #define sf_always_inline __attribute__((always_inline)) +#elif defined(__MSVC) + #define sf_always_inline __forceinline +#else + // do nothign for other compilers + #define sf_always_inline +#endif + #if defined(__GNUC__) && !defined(__clang__) #if __GNUC__ >= 13 #define sf_assume(cond) __attribute__((assume(cond))) diff --git a/src/nnue/features/full_threats.cpp b/src/nnue/features/full_threats.cpp index 994d2160c..122478dc6 100644 --- a/src/nnue/features/full_threats.cpp +++ b/src/nnue/features/full_threats.cpp @@ -58,35 +58,6 @@ constexpr std::array AllPieces = { PiecePairData index_lut1[PIECE_NB][PIECE_NB]; // [attacker][attacked] uint8_t index_lut2[PIECE_NB][SQUARE_NB][SQUARE_NB]; // [attacker][from][to] -namespace { - -template -IndexType make_index_with_orientation( - Piece attacker, Square from, Square to, Piece attacked, int orientation) { - from = Square(int(from) ^ orientation); - to = Square(int(to) ^ orientation); - - if constexpr (Perspective == BLACK) - { - attacker = ~attacker; - attacked = ~attacked; - } - - const auto piecePairData = index_lut1[attacker][attacked]; - - const bool less_than = static_cast(from) < static_cast(to); - if ((piecePairData.excluded_pair_info() + less_than) & 2) - return FullThreats::Dimensions; - - const IndexType index = - piecePairData.feature_index_base() + offsets[attacker][from] + index_lut2[attacker][from][to]; - - sf_assume(index != FullThreats::Dimensions); - return index; -} - -} // namespace - static void init_index_luts() { for (Piece attacker : AllPieces) { @@ -155,27 +126,49 @@ void init_threat_offsets() { } // Index of a feature for a given king position and another piece on some square -template -IndexType -FullThreats::make_index(Piece attacker, Square from, Square to, Piece attacked, Square ksq) { - return make_index_with_orientation(attacker, from, to, attacked, - OrientTBL[Perspective][ksq]); +inline sf_always_inline +IndexType FullThreats::make_index(Color perspective, + Piece attacker, + Square from, + Square to, + Piece attacked, + Square ksq) { + const int orientation = OrientTBL[perspective][ksq]; + from = Square(int(from) ^ orientation); + to = Square(int(to) ^ orientation); + + std::int8_t swap = 8 * perspective; + attacker = Piece(attacker ^ swap); + attacked = Piece(attacked ^ swap); + + const auto piecePairData = index_lut1[attacker][attacked]; + + const bool less_than = static_cast(from) < static_cast(to); + if ((piecePairData.excluded_pair_info() + less_than) & 2) + return FullThreats::Dimensions; + + const IndexType index = piecePairData.feature_index_base() + offsets[attacker][from] + + index_lut2[attacker][from][to]; + + sf_assume(index != FullThreats::Dimensions); + return index; } // Get a list of indices for active features in ascending order -template -void FullThreats::append_active_indices(const Position& pos, IndexList& active) { + +void FullThreats::append_active_indices(Color perspective, + const Position& pos, + IndexList& active) { static constexpr Color order[2][2] = {{WHITE, BLACK}, {BLACK, WHITE}}; - Square ksq = pos.square(Perspective); - const int orientation = OrientTBL[Perspective][ksq]; + Square ksq = pos.square(perspective); Bitboard occupied = pos.pieces(); for (Color color : {WHITE, BLACK}) { for (PieceType pt = PAWN; pt <= KING; ++pt) { - Color c = order[Perspective][color]; + Color c = order[perspective][color]; Piece attacker = make_piece(c, pt); Bitboard bb = pos.pieces(c, pt); @@ -193,8 +186,7 @@ void FullThreats::append_active_indices(const Position& pos, IndexList& active) Square to = pop_lsb(attacks_left); Square from = to - right; Piece attacked = pos.piece_on(to); - IndexType index = make_index_with_orientation( - attacker, from, to, attacked, orientation); + IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); if (index < Dimensions) active.push_back(index); @@ -205,8 +197,7 @@ void FullThreats::append_active_indices(const Position& pos, IndexList& active) Square to = pop_lsb(attacks_right); Square from = to - left; Piece attacked = pos.piece_on(to); - IndexType index = make_index_with_orientation( - attacker, from, to, attacked, orientation); + IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); if (index < Dimensions) active.push_back(index); @@ -223,8 +214,8 @@ void FullThreats::append_active_indices(const Position& pos, IndexList& active) { Square to = pop_lsb(attacks); Piece attacked = pos.piece_on(to); - IndexType index = make_index_with_orientation( - attacker, from, to, attacked, orientation); + IndexType index = make_index( + perspective, attacker, from, to, attacked, ksq); if (index < Dimensions) active.push_back(index); @@ -235,23 +226,15 @@ void FullThreats::append_active_indices(const Position& pos, IndexList& active) } } -// Explicit template instantiations -template void FullThreats::append_active_indices(const Position& pos, IndexList& active); -template void FullThreats::append_active_indices(const Position& pos, IndexList& active); -template IndexType -FullThreats::make_index(Piece attkr, Square from, Square to, Piece attkd, Square ksq); -template IndexType -FullThreats::make_index(Piece attkr, Square from, Square to, Piece attkd, Square ksq); - // Get a list of indices for recently changed features -template -void FullThreats::append_changed_indices(Square ksq, + +void FullThreats::append_changed_indices(Color perspective, + Square ksq, const DiffType& diff, IndexList& removed, IndexList& added, FusedUpdateData* fusedData, bool first) { - const int orientation = OrientTBL[Perspective][ksq]; for (const auto& dirty : diff.list) { @@ -292,28 +275,14 @@ void FullThreats::append_changed_indices(Square ksq, } } - const IndexType index = - make_index_with_orientation(attacker, from, to, attacked, orientation); + const IndexType index = make_index(perspective, + attacker, from, to, attacked, ksq); if (index < Dimensions) (add ? added : removed).push_back(index); } } -// Explicit template instantiations -template void FullThreats::append_changed_indices(Square ksq, - const DiffType& diff, - IndexList& removed, - IndexList& added, - FusedUpdateData* fd, - bool first); -template void FullThreats::append_changed_indices(Square ksq, - const DiffType& diff, - IndexList& removed, - IndexList& added, - FusedUpdateData* fd, - bool first); - bool FullThreats::requires_refresh(const DiffType& diff, Color perspective) { return perspective == diff.us && OrientTBL[diff.us][diff.ksq] != OrientTBL[diff.us][diff.prevKsq]; diff --git a/src/nnue/features/full_threats.h b/src/nnue/features/full_threats.h index 458b04dd1..d5c91d8c2 100644 --- a/src/nnue/features/full_threats.h +++ b/src/nnue/features/full_threats.h @@ -89,16 +89,19 @@ class FullThreats { using IndexList = ValueList; using DiffType = DirtyThreats; - template - static IndexType make_index(Piece attkr, Square from, Square to, Piece attkd, Square ksq); + static IndexType make_index(Color perspective, + Piece attkr, + Square from, + Square to, + Piece attkd, + Square ksq); // Get a list of indices for active features - template - static void append_active_indices(const Position& pos, IndexList& active); + static void append_active_indices(Color perspective, const Position& pos, IndexList& active); // Get a list of indices for recently changed features - template - static void append_changed_indices(Square ksq, + static void append_changed_indices(Color perspective, + Square ksq, const DiffType& diff, IndexList& removed, IndexList& added, diff --git a/src/nnue/features/half_ka_v2_hm.cpp b/src/nnue/features/half_ka_v2_hm.cpp index f652ba0b8..5a6f610cf 100644 --- a/src/nnue/features/half_ka_v2_hm.cpp +++ b/src/nnue/features/half_ka_v2_hm.cpp @@ -28,58 +28,45 @@ namespace Stockfish::Eval::NNUE::Features { // Index of a feature for a given king position and another piece on some square -template -IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq) { - const IndexType flip = 56 * Perspective; - return (IndexType(s) ^ OrientTBL[ksq] ^ flip) + PieceSquareIndex[Perspective][pc] + +IndexType HalfKAv2_hm::make_index(Color perspective, Square s, Piece pc, Square ksq) { + const IndexType flip = 56 * perspective; + return (IndexType(s) ^ OrientTBL[ksq] ^ flip) + PieceSquareIndex[perspective][pc] + KingBuckets[int(ksq) ^ flip]; } // Get a list of indices for active features -template -void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active) { - Square ksq = pos.square(Perspective); + +void HalfKAv2_hm::append_active_indices(Color perspective, + const Position& pos, + IndexList& active) { + Square ksq = pos.square(perspective); Bitboard bb = pos.pieces(); while (bb) { Square s = pop_lsb(bb); - active.push_back(make_index(s, pos.piece_on(s), ksq)); + active.push_back(make_index(perspective, s, pos.piece_on(s), ksq)); } } -// Explicit template instantiations -template void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active); -template void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active); -template IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq); -template IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq); - // Get a list of indices for recently changed features -template -void HalfKAv2_hm::append_changed_indices(Square ksq, + +void HalfKAv2_hm::append_changed_indices(Color perspective, + Square ksq, const DiffType& diff, IndexList& removed, IndexList& added) { - removed.push_back(make_index(diff.from, diff.pc, ksq)); + removed.push_back(make_index(perspective, diff.from, diff.pc, ksq)); if (diff.to != SQ_NONE) - added.push_back(make_index(diff.to, diff.pc, ksq)); + added.push_back(make_index(perspective, diff.to, diff.pc, ksq)); if (diff.remove_sq != SQ_NONE) - removed.push_back(make_index(diff.remove_sq, diff.remove_pc, ksq)); + removed.push_back(make_index(perspective, diff.remove_sq, diff.remove_pc, ksq)); if (diff.add_sq != SQ_NONE) - added.push_back(make_index(diff.add_sq, diff.add_pc, ksq)); + added.push_back(make_index(perspective, diff.add_sq, diff.add_pc, ksq)); } -// Explicit template instantiations -template void HalfKAv2_hm::append_changed_indices(Square ksq, - const DiffType& dp, - IndexList& removed, - IndexList& added); -template void HalfKAv2_hm::append_changed_indices(Square ksq, - const DiffType& dp, - IndexList& removed, - IndexList& added); - bool HalfKAv2_hm::requires_refresh(const DiffType& diff, Color perspective) { return diff.pc == make_piece(perspective, KING); } diff --git a/src/nnue/features/half_ka_v2_hm.h b/src/nnue/features/half_ka_v2_hm.h index e695b273a..e9448f838 100644 --- a/src/nnue/features/half_ka_v2_hm.h +++ b/src/nnue/features/half_ka_v2_hm.h @@ -107,17 +107,21 @@ class HalfKAv2_hm { using DiffType = DirtyPiece; // Index of a feature for a given king position and another piece on some square - template - static IndexType make_index(Square s, Piece pc, Square ksq); + + static IndexType make_index(Color perspective, Square s, Piece pc, Square ksq); // Get a list of indices for active features - template - static void append_active_indices(const Position& pos, IndexList& active); + + static void append_active_indices(Color perspective, + const Position& pos, + IndexList& active); // Get a list of indices for recently changed features - template - static void - append_changed_indices(Square ksq, const DiffType& diff, IndexList& removed, IndexList& added); + static void append_changed_indices(Color perspective, + Square ksq, + const DiffType& diff, + IndexList& removed, + IndexList& added); // Returns whether the change stored in this DirtyPiece means // that a full accumulator refresh is required. diff --git a/src/nnue/nnue_accumulator.cpp b/src/nnue/nnue_accumulator.cpp index fa059463e..3d99b8063 100644 --- a/src/nnue/nnue_accumulator.cpp +++ b/src/nnue/nnue_accumulator.cpp @@ -40,39 +40,43 @@ using namespace SIMD; namespace { -template -void double_inc_update(const FeatureTransformer& featureTransformer, +template +void double_inc_update(Color perspective, + const FeatureTransformer& featureTransformer, const Square ksq, AccumulatorState& middle_state, AccumulatorState& target_state, const AccumulatorState& computed); -template -void double_inc_update(const FeatureTransformer& featureTransformer, +template +void double_inc_update(Color perspective, + const FeatureTransformer& featureTransformer, const Square ksq, AccumulatorState& middle_state, AccumulatorState& target_state, const AccumulatorState& computed, const DirtyPiece& dp2); -template void update_accumulator_incremental( + Color perspective, const FeatureTransformer& featureTransformer, const Square ksq, AccumulatorState& target_state, const AccumulatorState& computed); -template -void update_accumulator_refresh_cache(const FeatureTransformer& featureTransformer, +template +void update_accumulator_refresh_cache(Color perspective, + const FeatureTransformer& featureTransformer, const Position& pos, AccumulatorState& accumulatorState, AccumulatorCaches::Cache& cache); -template -void update_threats_accumulator_full(const FeatureTransformer& featureTransformer, +template +void update_threats_accumulator_full(Color perspective, + const FeatureTransformer& featureTransformer, const Position& pos, AccumulatorState& accumulatorState); } @@ -143,71 +147,73 @@ void AccumulatorStack::evaluate(const Position& pos, AccumulatorCaches::Cache& cache) noexcept { constexpr bool UseThreats = (Dimensions == TransformedFeatureDimensionsBig); - evaluate_side(pos, featureTransformer, cache); + evaluate_side(WHITE, pos, featureTransformer, cache); if (UseThreats) - evaluate_side(pos, featureTransformer, cache); + evaluate_side(WHITE, pos, featureTransformer, cache); - evaluate_side(pos, featureTransformer, cache); + evaluate_side(BLACK, pos, featureTransformer, cache); if (UseThreats) - evaluate_side(pos, featureTransformer, cache); + evaluate_side(BLACK, pos, featureTransformer, cache); } -template -void AccumulatorStack::evaluate_side(const Position& pos, +template +void AccumulatorStack::evaluate_side(Color perspective, + const Position& pos, const FeatureTransformer& featureTransformer, AccumulatorCaches::Cache& cache) noexcept { const auto last_usable_accum = - find_last_usable_accumulator(); + find_last_usable_accumulator(perspective); if ((accumulators()[last_usable_accum].template acc()) - .computed[Perspective]) - forward_update_incremental(pos, featureTransformer, - last_usable_accum); + .computed[perspective]) + forward_update_incremental(perspective, pos, featureTransformer, + last_usable_accum); else { if constexpr (std::is_same_v) - update_accumulator_refresh_cache(featureTransformer, pos, - mut_latest(), cache); + update_accumulator_refresh_cache(perspective, featureTransformer, pos, + mut_latest(), cache); else - update_threats_accumulator_full(featureTransformer, pos, - mut_latest()); + update_threats_accumulator_full(perspective, featureTransformer, pos, + mut_latest()); - backward_update_incremental(pos, featureTransformer, - last_usable_accum); + backward_update_incremental(perspective, pos, featureTransformer, + last_usable_accum); } } // Find the earliest usable accumulator, this can either be a computed accumulator or the accumulator // state just before a change that requires full refresh. -template -std::size_t AccumulatorStack::find_last_usable_accumulator() const noexcept { +template +std::size_t AccumulatorStack::find_last_usable_accumulator(Color perspective) const noexcept { for (std::size_t curr_idx = size - 1; curr_idx > 0; curr_idx--) { - if ((accumulators()[curr_idx].template acc()).computed[Perspective]) + if ((accumulators()[curr_idx].template acc()).computed[perspective]) return curr_idx; - if (FeatureSet::requires_refresh(accumulators()[curr_idx].diff, Perspective)) + if (FeatureSet::requires_refresh(accumulators()[curr_idx].diff, perspective)) return curr_idx; } return 0; } -template +template void AccumulatorStack::forward_update_incremental( + Color perspective, const Position& pos, const FeatureTransformer& featureTransformer, const std::size_t begin) noexcept { assert(begin < accumulators().size()); - assert((accumulators()[begin].template acc()).computed[Perspective]); + assert((accumulators()[begin].template acc()).computed[perspective]); - const Square ksq = pos.square(Perspective); + const Square ksq = pos.square(perspective); for (std::size_t next = begin + 1; next < size; next++) { @@ -223,9 +229,8 @@ void AccumulatorStack::forward_update_incremental( if (dp2.remove_sq != SQ_NONE && (accumulators[next].diff.threateningSqs & square_bb(dp2.remove_sq))) { - double_inc_update(featureTransformer, ksq, accumulators[next], - accumulators[next + 1], accumulators[next - 1], - dp2); + double_inc_update(perspective, featureTransformer, ksq, accumulators[next], + accumulators[next + 1], accumulators[next - 1], dp2); next++; continue; } @@ -237,8 +242,8 @@ void AccumulatorStack::forward_update_incremental( { const Square captureSq = dp1.to; dp1.to = dp2.remove_sq = SQ_NONE; - double_inc_update(featureTransformer, ksq, accumulators[next], - accumulators[next + 1], accumulators[next - 1]); + double_inc_update(perspective, featureTransformer, ksq, accumulators[next], + accumulators[next + 1], accumulators[next - 1]); dp1.to = dp2.remove_sq = captureSq; next++; continue; @@ -246,32 +251,33 @@ void AccumulatorStack::forward_update_incremental( } } - update_accumulator_incremental(featureTransformer, ksq, - mut_accumulators()[next], - accumulators()[next - 1]); + update_accumulator_incremental(perspective, featureTransformer, ksq, + mut_accumulators()[next], + accumulators()[next - 1]); } - assert((latest().acc()).computed[Perspective]); + assert((latest().acc()).computed[perspective]); } -template -void AccumulatorStack::backward_update_incremental( +template +void AccumulatorStack::backward_update_incremental(Color perspective, + const Position& pos, const FeatureTransformer& featureTransformer, const std::size_t end) noexcept { assert(end < accumulators().size()); assert(end < size); - assert((latest().template acc()).computed[Perspective]); + assert((latest().template acc()).computed[perspective]); - const Square ksq = pos.square(Perspective); + const Square ksq = pos.square(perspective); for (std::int64_t next = std::int64_t(size) - 2; next >= std::int64_t(end); next--) - update_accumulator_incremental(featureTransformer, ksq, - mut_accumulators()[next], - accumulators()[next + 1]); + update_accumulator_incremental(perspective, featureTransformer, ksq, + mut_accumulators()[next], + accumulators()[next + 1]); - assert((accumulators()[end].template acc()).computed[Perspective]); + assert((accumulators()[end].template acc()).computed[perspective]); } // Explicit template instantiations @@ -304,15 +310,18 @@ void fused_row_reduce(const ElementType* in, ElementType* out, const Ts* const.. vecIn[i], reinterpret_cast(rows)[i]...); } -template +template struct AccumulatorUpdateContext { + Color perspective; const FeatureTransformer& featureTransformer; const AccumulatorState& from; AccumulatorState& to; - AccumulatorUpdateContext(const FeatureTransformer& ft, + AccumulatorUpdateContext(Color persp, + const FeatureTransformer& ft, const AccumulatorState& accF, AccumulatorState& accT) noexcept : + perspective{persp}, featureTransformer{ft}, from{accF}, to{accT} {} @@ -330,22 +339,22 @@ struct AccumulatorUpdateContext { }; fused_row_reduce( - (from.template acc()).accumulation[Perspective], - (to.template acc()).accumulation[Perspective], to_weight_vector(indices)...); + (from.template acc()).accumulation[perspective], + (to.template acc()).accumulation[perspective], to_weight_vector(indices)...); fused_row_reduce( - (from.template acc()).psqtAccumulation[Perspective], - (to.template acc()).psqtAccumulation[Perspective], + (from.template acc()).psqtAccumulation[perspective], + (to.template acc()).psqtAccumulation[perspective], to_psqt_weight_vector(indices)...); } void apply(const typename FeatureSet::IndexList& added, const typename FeatureSet::IndexList& removed) { - const auto fromAcc = from.template acc().accumulation[Perspective]; - const auto toAcc = to.template acc().accumulation[Perspective]; + const auto fromAcc = from.template acc().accumulation[perspective]; + const auto toAcc = to.template acc().accumulation[perspective]; - const auto fromPsqtAcc = from.template acc().psqtAccumulation[Perspective]; - const auto toPsqtAcc = to.template acc().psqtAccumulation[Perspective]; + const auto fromPsqtAcc = from.template acc().psqtAccumulation[perspective]; + const auto toPsqtAcc = to.template acc().psqtAccumulation[perspective]; #ifdef VECTOR using Tiling = SIMDTiling; @@ -469,31 +478,33 @@ struct AccumulatorUpdateContext { } }; -template -auto make_accumulator_update_context(const FeatureTransformer& featureTransformer, +template +auto make_accumulator_update_context(Color perspective, + const FeatureTransformer& featureTransformer, const AccumulatorState& accumulatorFrom, AccumulatorState& accumulatorTo) noexcept { - return AccumulatorUpdateContext{ - featureTransformer, accumulatorFrom, accumulatorTo}; + return AccumulatorUpdateContext{ + perspective, featureTransformer, accumulatorFrom, accumulatorTo}; } -template -void double_inc_update(const FeatureTransformer& featureTransformer, +template +void double_inc_update(Color perspective, + const FeatureTransformer& featureTransformer, const Square ksq, AccumulatorState& middle_state, AccumulatorState& target_state, const AccumulatorState& computed) { - assert(computed.acc().computed[Perspective]); - assert(!middle_state.acc().computed[Perspective]); - assert(!target_state.acc().computed[Perspective]); + assert(computed.acc().computed[perspective]); + assert(!middle_state.acc().computed[perspective]); + assert(!target_state.acc().computed[perspective]); PSQFeatureSet::IndexList removed, added; - PSQFeatureSet::append_changed_indices(ksq, middle_state.diff, removed, added); + PSQFeatureSet::append_changed_indices(perspective, ksq, middle_state.diff, removed, added); // you can't capture a piece that was just involved in castling since the rook ends up // in a square that the king passed assert(added.size() < 2); - PSQFeatureSet::append_changed_indices(ksq, target_state.diff, removed, added); + PSQFeatureSet::append_changed_indices(perspective, ksq, target_state.diff, removed, added); assert(added.size() == 1); assert(removed.size() == 2 || removed.size() == 3); @@ -505,7 +516,7 @@ void double_inc_update(const FeatureTransformer& f sf_assume(removed.size() == 2 || removed.size() == 3); auto updateContext = - make_accumulator_update_context(featureTransformer, computed, target_state); + make_accumulator_update_context(perspective, featureTransformer, computed, target_state); if (removed.size() == 2) { @@ -517,51 +528,52 @@ void double_inc_update(const FeatureTransformer& f removed[2]); } - target_state.acc().computed[Perspective] = true; + target_state.acc().computed[perspective] = true; } -template -void double_inc_update(const FeatureTransformer& featureTransformer, +template +void double_inc_update(Color perspective, +const FeatureTransformer& featureTransformer, const Square ksq, AccumulatorState& middle_state, AccumulatorState& target_state, const AccumulatorState& computed, const DirtyPiece& dp2) { - assert(computed.acc().computed[Perspective]); - assert(!middle_state.acc().computed[Perspective]); - assert(!target_state.acc().computed[Perspective]); + assert(computed.acc().computed[perspective]); + assert(!middle_state.acc().computed[perspective]); + assert(!target_state.acc().computed[perspective]); ThreatFeatureSet::FusedUpdateData fusedData; fusedData.dp2removed = dp2.remove_sq; ThreatFeatureSet::IndexList removed, added; - ThreatFeatureSet::append_changed_indices(ksq, middle_state.diff, removed, added, - &fusedData, true); - ThreatFeatureSet::append_changed_indices(ksq, target_state.diff, removed, added, - &fusedData, false); + ThreatFeatureSet::append_changed_indices(perspective, ksq, middle_state.diff, removed, added, + &fusedData, true); + ThreatFeatureSet::append_changed_indices(perspective, ksq, target_state.diff, removed, added, + &fusedData, false); auto updateContext = - make_accumulator_update_context(featureTransformer, computed, target_state); + make_accumulator_update_context(perspective, featureTransformer, computed, target_state); updateContext.apply(added, removed); - target_state.acc().computed[Perspective] = true; + target_state.acc().computed[perspective] = true; } -template void update_accumulator_incremental( + Color perspective, const FeatureTransformer& featureTransformer, const Square ksq, AccumulatorState& target_state, const AccumulatorState& computed) { - assert((computed.template acc()).computed[Perspective]); - assert(!(target_state.template acc()).computed[Perspective]); + assert((computed.template acc()).computed[perspective]); + assert(!(target_state.template acc()).computed[perspective]); // The size must be enough to contain the largest possible update. // That might depend on the feature set and generally relies on the @@ -571,29 +583,27 @@ void update_accumulator_incremental( // is 2, since we are incrementally updating one move at a time. typename FeatureSet::IndexList removed, added; if constexpr (Forward) - FeatureSet::template append_changed_indices(ksq, target_state.diff, removed, - added); + FeatureSet::append_changed_indices(perspective, ksq, target_state.diff, removed, added); else - FeatureSet::template append_changed_indices(ksq, computed.diff, added, - removed); + FeatureSet::append_changed_indices(perspective, ksq, computed.diff, added, removed); if (!added.size() && !removed.size()) { auto& targetAcc = target_state.template acc(); const auto& sourceAcc = computed.template acc(); - std::memcpy(targetAcc.accumulation[Perspective], sourceAcc.accumulation[Perspective], - sizeof(targetAcc.accumulation[Perspective])); - std::memcpy(targetAcc.psqtAccumulation[Perspective], - sourceAcc.psqtAccumulation[Perspective], - sizeof(targetAcc.psqtAccumulation[Perspective])); + std::memcpy(targetAcc.accumulation[perspective], sourceAcc.accumulation[perspective], + sizeof(targetAcc.accumulation[perspective])); + std::memcpy(targetAcc.psqtAccumulation[perspective], + sourceAcc.psqtAccumulation[perspective], + sizeof(targetAcc.psqtAccumulation[perspective])); - targetAcc.computed[Perspective] = true; + targetAcc.computed[perspective] = true; return; } auto updateContext = - make_accumulator_update_context(featureTransformer, computed, target_state); + make_accumulator_update_context(perspective, featureTransformer, computed, target_state); if constexpr (std::is_same_v) updateContext.apply(added, removed); @@ -633,7 +643,7 @@ void update_accumulator_incremental( } } - (target_state.template acc()).computed[Perspective] = true; + (target_state.template acc()).computed[perspective] = true; } Bitboard get_changed_pieces(const Piece oldPieces[SQUARE_NB], const Piece newPieces[SQUARE_NB]) { @@ -660,16 +670,17 @@ Bitboard get_changed_pieces(const Piece oldPieces[SQUARE_NB], const Piece newPie #endif } -template -void update_accumulator_refresh_cache(const FeatureTransformer& featureTransformer, +template +void update_accumulator_refresh_cache(Color perspective, + const FeatureTransformer& featureTransformer, const Position& pos, AccumulatorState& accumulatorState, AccumulatorCaches::Cache& cache) { using Tiling [[maybe_unused]] = SIMDTiling; - const Square ksq = pos.square(Perspective); - auto& entry = cache[ksq][Perspective]; + const Square ksq = pos.square(perspective); + auto& entry = cache[ksq][perspective]; PSQFeatureSet::IndexList removed, added; const Bitboard changedBB = get_changed_pieces(entry.pieces, pos.piece_array().data()); @@ -679,19 +690,19 @@ void update_accumulator_refresh_cache(const FeatureTransformer& feat while (removedBB) { Square sq = pop_lsb(removedBB); - removed.push_back(PSQFeatureSet::make_index(sq, entry.pieces[sq], ksq)); + removed.push_back(PSQFeatureSet::make_index(perspective, sq, entry.pieces[sq], ksq)); } while (addedBB) { Square sq = pop_lsb(addedBB); - added.push_back(PSQFeatureSet::make_index(sq, pos.piece_on(sq), ksq)); + added.push_back(PSQFeatureSet::make_index(perspective, sq, pos.piece_on(sq), ksq)); } entry.pieceBB = pos.pieces(); std::copy_n(pos.piece_array().begin(), SQUARE_NB, entry.pieces); auto& accumulator = accumulatorState.acc(); - accumulator.computed[Perspective] = true; + accumulator.computed[perspective] = true; #ifdef VECTOR vec_t acc[Tiling::NumRegs]; @@ -700,7 +711,7 @@ void update_accumulator_refresh_cache(const FeatureTransformer& feat for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) { auto* accTile = - reinterpret_cast(&accumulator.accumulation[Perspective][j * Tiling::TileHeight]); + reinterpret_cast(&accumulator.accumulation[perspective][j * Tiling::TileHeight]); auto* entryTile = reinterpret_cast(&entry.accumulation[j * Tiling::TileHeight]); for (IndexType k = 0; k < Tiling::NumRegs; ++k) @@ -747,7 +758,7 @@ void update_accumulator_refresh_cache(const FeatureTransformer& feat for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) { auto* accTilePsqt = reinterpret_cast( - &accumulator.psqtAccumulation[Perspective][j * Tiling::PsqtTileHeight]); + &accumulator.psqtAccumulation[perspective][j * Tiling::PsqtTileHeight]); auto* entryTilePsqt = reinterpret_cast(&entry.psqtAccumulation[j * Tiling::PsqtTileHeight]); @@ -805,25 +816,26 @@ void update_accumulator_refresh_cache(const FeatureTransformer& feat // The accumulator of the refresh entry has been updated. // Now copy its content to the actual accumulator we were refreshing. - std::memcpy(accumulator.accumulation[Perspective], entry.accumulation.data(), + std::memcpy(accumulator.accumulation[perspective], entry.accumulation.data(), sizeof(BiasType) * Dimensions); - std::memcpy(accumulator.psqtAccumulation[Perspective], entry.psqtAccumulation.data(), + std::memcpy(accumulator.psqtAccumulation[perspective], entry.psqtAccumulation.data(), sizeof(int32_t) * PSQTBuckets); #endif } -template -void update_threats_accumulator_full(const FeatureTransformer& featureTransformer, +template +void update_threats_accumulator_full(Color perspective, + const FeatureTransformer& featureTransformer, const Position& pos, AccumulatorState& accumulatorState) { using Tiling [[maybe_unused]] = SIMDTiling; ThreatFeatureSet::IndexList active; - ThreatFeatureSet::append_active_indices(pos, active); + ThreatFeatureSet::append_active_indices(perspective, pos, active); auto& accumulator = accumulatorState.acc(); - accumulator.computed[Perspective] = true; + accumulator.computed[perspective] = true; #ifdef VECTOR vec_t acc[Tiling::NumRegs]; @@ -832,7 +844,7 @@ void update_threats_accumulator_full(const FeatureTransformer& featu for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) { auto* accTile = - reinterpret_cast(&accumulator.accumulation[Perspective][j * Tiling::TileHeight]); + reinterpret_cast(&accumulator.accumulation[perspective][j * Tiling::TileHeight]); for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = vec_zero(); @@ -865,7 +877,7 @@ void update_threats_accumulator_full(const FeatureTransformer& featu for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) { auto* accTilePsqt = reinterpret_cast( - &accumulator.psqtAccumulation[Perspective][j * Tiling::PsqtTileHeight]); + &accumulator.psqtAccumulation[perspective][j * Tiling::PsqtTileHeight]); for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = vec_zero_psqt(); @@ -888,21 +900,21 @@ void update_threats_accumulator_full(const FeatureTransformer& featu #else for (IndexType j = 0; j < Dimensions; ++j) - accumulator.accumulation[Perspective][j] = 0; + accumulator.accumulation[perspective][j] = 0; for (std::size_t k = 0; k < PSQTBuckets; ++k) - accumulator.psqtAccumulation[Perspective][k] = 0; + accumulator.psqtAccumulation[perspective][k] = 0; for (const auto index : active) { const IndexType offset = Dimensions * index; for (IndexType j = 0; j < Dimensions; ++j) - accumulator.accumulation[Perspective][j] += + accumulator.accumulation[perspective][j] += featureTransformer.threatWeights[offset + j]; for (std::size_t k = 0; k < PSQTBuckets; ++k) - accumulator.psqtAccumulation[Perspective][k] += + accumulator.psqtAccumulation[perspective][k] += featureTransformer.threatPsqtWeights[index * PSQTBuckets + k]; } diff --git a/src/nnue/nnue_accumulator.h b/src/nnue/nnue_accumulator.h index c0a912f58..181412b43 100644 --- a/src/nnue/nnue_accumulator.h +++ b/src/nnue/nnue_accumulator.h @@ -176,21 +176,24 @@ class AccumulatorStack { template [[nodiscard]] std::array, MaxSize>& mut_accumulators() noexcept; - template - void evaluate_side(const Position& pos, + template + void evaluate_side(Color perspective, + const Position& pos, const FeatureTransformer& featureTransformer, AccumulatorCaches::Cache& cache) noexcept; - template - [[nodiscard]] std::size_t find_last_usable_accumulator() const noexcept; + template + [[nodiscard]] std::size_t find_last_usable_accumulator(Color perspective) const noexcept; - template - void forward_update_incremental(const Position& pos, + template + void forward_update_incremental(Color perspective, + const Position& pos, const FeatureTransformer& featureTransformer, const std::size_t begin) noexcept; - template - void backward_update_incremental(const Position& pos, + template + void backward_update_incremental(Color perspective, + const Position& pos, const FeatureTransformer& featureTransformer, const std::size_t end) noexcept;