mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Simplify out double_inc_update
Passed STC https://tests.stockfishchess.org/tests/view/69e82e200e9667dd5a765631 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 115424 W: 29950 L: 29822 D: 55652 Ptnml(0-2): 318, 12712, 31544, 12800, 338 Passed AVX2-only STC https://tests.stockfishchess.org/tests/view/69e953080e9667dd5a7657c0 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 134720 W: 34773 L: 34665 D: 65282 Ptnml(0-2): 344, 14958, 36694, 14974, 390 Now that our L1 size is much smaller, the overhead of tracking diffs for `double_inc_update` is a larger share of the cost. Interestingly ces42 measured a -0.9% slowdown locally (avxvnni build). Meanwhile Torom and I find this branch to be 2% faster. I'm not sure exactly what's going on but more tests may be in order closes https://github.com/official-stockfish/Stockfish/pull/6776 No functional change
This commit is contained in:
committed by
Joost VandeVondele
parent
0e78190b72
commit
1a882efc7f
@@ -27,7 +27,6 @@
|
||||
#include "../misc.h"
|
||||
#include "../position.h"
|
||||
#include "../types.h"
|
||||
#include "features/half_ka_v2_hm.h"
|
||||
#include "nnue_architecture.h"
|
||||
#include "nnue_common.h"
|
||||
#include "nnue_feature_transformer.h" // IWYU pragma: keep
|
||||
@@ -39,23 +38,6 @@ using namespace SIMD;
|
||||
|
||||
namespace {
|
||||
|
||||
template<IndexType TransformedFeatureDimensions>
|
||||
void double_inc_update(Color perspective,
|
||||
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
|
||||
const Square ksq,
|
||||
const AccumulatorState<PSQFeatureSet>& middle_state,
|
||||
AccumulatorState<PSQFeatureSet>& target_state,
|
||||
const AccumulatorState<PSQFeatureSet>& computed);
|
||||
|
||||
template<IndexType TransformedFeatureDimensions>
|
||||
void double_inc_update(Color perspective,
|
||||
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
|
||||
const Square ksq,
|
||||
const AccumulatorState<ThreatFeatureSet>& middle_state,
|
||||
AccumulatorState<ThreatFeatureSet>& target_state,
|
||||
const AccumulatorState<ThreatFeatureSet>& computed,
|
||||
const DirtyPiece& dp2);
|
||||
|
||||
template<bool Forward, typename FeatureSet, IndexType TransformedFeatureDimensions>
|
||||
void update_accumulator_incremental(
|
||||
Color perspective,
|
||||
@@ -213,40 +195,6 @@ void AccumulatorStack::forward_update_incremental(
|
||||
|
||||
for (std::size_t next = begin + 1; next < size; next++)
|
||||
{
|
||||
if (next + 1 < size)
|
||||
{
|
||||
DirtyPiece& dp1 = mut_accumulators<PSQFeatureSet>()[next].diff;
|
||||
DirtyPiece& dp2 = mut_accumulators<PSQFeatureSet>()[next + 1].diff;
|
||||
|
||||
auto& accumulators = mut_accumulators<FeatureSet>();
|
||||
|
||||
if constexpr (std::is_same_v<FeatureSet, ThreatFeatureSet>)
|
||||
{
|
||||
if (dp2.remove_sq != SQ_NONE
|
||||
&& (accumulators[next].diff.threateningSqs & square_bb(dp2.remove_sq)))
|
||||
{
|
||||
double_inc_update(perspective, featureTransformer, ksq, accumulators[next],
|
||||
accumulators[next + 1], accumulators[next - 1], dp2);
|
||||
next++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<FeatureSet, PSQFeatureSet>)
|
||||
{
|
||||
if (dp1.to != SQ_NONE && dp1.to == dp2.remove_sq)
|
||||
{
|
||||
const Square captureSq = dp1.to;
|
||||
dp1.to = dp2.remove_sq = SQ_NONE;
|
||||
double_inc_update(perspective, featureTransformer, ksq, accumulators[next],
|
||||
accumulators[next + 1], accumulators[next - 1]);
|
||||
dp1.to = dp2.remove_sq = captureSq;
|
||||
next++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_accumulator_incremental<true>(perspective, featureTransformer, ksq,
|
||||
mut_accumulators<FeatureSet>()[next],
|
||||
accumulators<FeatureSet>()[next - 1]);
|
||||
@@ -487,87 +435,6 @@ auto make_accumulator_update_context(Color persp
|
||||
accumulatorFrom, accumulatorTo};
|
||||
}
|
||||
|
||||
template<IndexType TransformedFeatureDimensions>
|
||||
void double_inc_update(Color perspective,
|
||||
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
|
||||
const Square ksq,
|
||||
const AccumulatorState<PSQFeatureSet>& middle_state,
|
||||
AccumulatorState<PSQFeatureSet>& target_state,
|
||||
const AccumulatorState<PSQFeatureSet>& computed) {
|
||||
|
||||
assert(computed.acc<TransformedFeatureDimensions>().computed[perspective]);
|
||||
assert(!middle_state.acc<TransformedFeatureDimensions>().computed[perspective]);
|
||||
assert(!target_state.acc<TransformedFeatureDimensions>().computed[perspective]);
|
||||
|
||||
PSQFeatureSet::IndexList 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(perspective, ksq, target_state.diff, removed, added);
|
||||
|
||||
[[maybe_unused]] const int addedSize = added.ssize();
|
||||
[[maybe_unused]] const int removedSize = removed.ssize();
|
||||
|
||||
assert(addedSize == 1);
|
||||
assert(removedSize == 2 || removedSize == 3);
|
||||
|
||||
// Workaround compiler warning for uninitialized variables, replicated on
|
||||
// profile builds on windows with gcc 14.2.0.
|
||||
// Also helps with optimizations on some compilers.
|
||||
|
||||
sf_assume(addedSize == 1);
|
||||
sf_assume(removedSize == 2 || removedSize == 3);
|
||||
|
||||
auto updateContext =
|
||||
make_accumulator_update_context(perspective, featureTransformer, computed, target_state);
|
||||
|
||||
if (removedSize == 2)
|
||||
{
|
||||
updateContext.template apply<Add, Sub, Sub>(added[0], removed[0], removed[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateContext.template apply<Add, Sub, Sub, Sub>(added[0], removed[0], removed[1],
|
||||
removed[2]);
|
||||
}
|
||||
|
||||
target_state.acc<TransformedFeatureDimensions>().computed[perspective] = true;
|
||||
}
|
||||
|
||||
template<IndexType TransformedFeatureDimensions>
|
||||
void double_inc_update(Color perspective,
|
||||
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
|
||||
const Square ksq,
|
||||
const AccumulatorState<ThreatFeatureSet>& middle_state,
|
||||
AccumulatorState<ThreatFeatureSet>& target_state,
|
||||
const AccumulatorState<ThreatFeatureSet>& computed,
|
||||
const DirtyPiece& dp2) {
|
||||
|
||||
assert(computed.acc<TransformedFeatureDimensions>().computed[perspective]);
|
||||
assert(!middle_state.acc<TransformedFeatureDimensions>().computed[perspective]);
|
||||
assert(!target_state.acc<TransformedFeatureDimensions>().computed[perspective]);
|
||||
|
||||
ThreatFeatureSet::FusedUpdateData fusedData;
|
||||
|
||||
fusedData.dp2removed = dp2.remove_sq;
|
||||
|
||||
ThreatFeatureSet::IndexList removed, added;
|
||||
const auto* pfBase = &featureTransformer.threatWeights[0];
|
||||
auto pfStride = static_cast<IndexType>(TransformedFeatureDimensions);
|
||||
ThreatFeatureSet::append_changed_indices(perspective, ksq, middle_state.diff, removed, added,
|
||||
&fusedData, true, pfBase, pfStride);
|
||||
ThreatFeatureSet::append_changed_indices(perspective, ksq, target_state.diff, removed, added,
|
||||
&fusedData, false, pfBase, pfStride);
|
||||
|
||||
auto updateContext =
|
||||
make_accumulator_update_context(perspective, featureTransformer, computed, target_state);
|
||||
|
||||
updateContext.apply(added, removed);
|
||||
|
||||
target_state.acc<TransformedFeatureDimensions>().computed[perspective] = true;
|
||||
}
|
||||
|
||||
template<bool Forward, typename FeatureSet, IndexType TransformedFeatureDimensions>
|
||||
void update_accumulator_incremental(
|
||||
Color perspective,
|
||||
|
||||
+21
-38
@@ -860,13 +860,12 @@ void Position::do_move(Move m,
|
||||
Piece pc = piece_on(from);
|
||||
Piece captured = m.type_of() == EN_PASSANT ? make_piece(them, PAWN) : piece_on(to);
|
||||
|
||||
dp.pc = pc;
|
||||
dp.from = from;
|
||||
dp.to = to;
|
||||
dp.add_sq = SQ_NONE;
|
||||
dts.us = us;
|
||||
dts.prevKsq = square<KING>(us);
|
||||
dts.threatenedSqs = dts.threateningSqs = 0;
|
||||
dp.pc = pc;
|
||||
dp.from = from;
|
||||
dp.to = to;
|
||||
dp.add_sq = SQ_NONE;
|
||||
dts.us = us;
|
||||
dts.prevKsq = square<KING>(us);
|
||||
|
||||
assert(color_of(pc) == us);
|
||||
assert(captured == NO_PIECE || color_of(captured) == (m.type_of() != CASTLING ? them : us));
|
||||
@@ -1151,16 +1150,13 @@ void Position::undo_move(Move m) {
|
||||
assert(pos_is_ok());
|
||||
}
|
||||
|
||||
template<bool PutPiece>
|
||||
inline void add_dirty_threat(
|
||||
DirtyThreats* const dts, Piece pc, Piece threatened, Square s, Square threatenedSq) {
|
||||
if (PutPiece)
|
||||
{
|
||||
dts->threatenedSqs |= threatenedSq;
|
||||
dts->threateningSqs |= s;
|
||||
}
|
||||
|
||||
dts->list.push_back({pc, threatened, s, threatenedSq, PutPiece});
|
||||
inline void add_dirty_threat(DirtyThreats* const dts,
|
||||
bool putPiece,
|
||||
Piece pc,
|
||||
Piece threatened,
|
||||
Square s,
|
||||
Square threatenedSq) {
|
||||
dts->list.push_back({pc, threatened, s, threatenedSq, putPiece});
|
||||
}
|
||||
|
||||
#ifdef USE_AVX512ICL
|
||||
@@ -1198,8 +1194,9 @@ void write_multiple_dirties(const Position& p,
|
||||
}
|
||||
#endif
|
||||
|
||||
template<bool PutPiece, bool ComputeRay>
|
||||
template<bool ComputeRay>
|
||||
void Position::update_piece_threats(Piece pc,
|
||||
bool putPiece,
|
||||
Square s,
|
||||
DirtyThreats* const dts,
|
||||
[[maybe_unused]] Bitboard noRaysContaining) const {
|
||||
@@ -1226,11 +1223,11 @@ void Position::update_piece_threats(Piece pc,
|
||||
{
|
||||
const Square threatenedSq = lsb(discovered);
|
||||
const Piece threatenedPc = piece_on(threatenedSq);
|
||||
add_dirty_threat<!PutPiece>(dts, slider, threatenedPc, sliderSq, threatenedSq);
|
||||
add_dirty_threat(dts, !putPiece, slider, threatenedPc, sliderSq, threatenedSq);
|
||||
}
|
||||
|
||||
if (addDirectAttacks)
|
||||
add_dirty_threat<PutPiece>(dts, slider, pc, sliderSq, s);
|
||||
add_dirty_threat(dts, putPiece, slider, pc, sliderSq, s);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1270,27 +1267,13 @@ void Position::update_piece_threats(Piece pc,
|
||||
}
|
||||
|
||||
#ifdef USE_AVX512ICL
|
||||
if constexpr (PutPiece)
|
||||
{
|
||||
dts->threatenedSqs |= threatened;
|
||||
// A bit may only be set if that square actually produces a threat, so we
|
||||
// must guard setting the square accordingly
|
||||
dts->threateningSqs |= Bitboard(bool(threatened)) << s;
|
||||
}
|
||||
|
||||
DirtyThreat dt_template{pc, NO_PIECE, s, Square(0), PutPiece};
|
||||
DirtyThreat dt_template{pc, NO_PIECE, s, Square(0), putPiece};
|
||||
write_multiple_dirties<DirtyThreat::ThreatenedSqOffset, DirtyThreat::ThreatenedPcOffset>(
|
||||
*this, threatened, dt_template, dts);
|
||||
|
||||
Bitboard all_attackers = sliders | incoming_threats;
|
||||
|
||||
if constexpr (PutPiece)
|
||||
{
|
||||
dts->threatenedSqs |= Bitboard(bool(all_attackers)) << s; // same as above
|
||||
dts->threateningSqs |= all_attackers;
|
||||
}
|
||||
|
||||
dt_template = {NO_PIECE, pc, Square(0), s, PutPiece};
|
||||
dt_template = {NO_PIECE, pc, Square(0), s, putPiece};
|
||||
write_multiple_dirties<DirtyThreat::PcSqOffset, DirtyThreat::PcOffset>(*this, all_attackers,
|
||||
dt_template, dts);
|
||||
#else
|
||||
@@ -1302,7 +1285,7 @@ void Position::update_piece_threats(Piece pc,
|
||||
assert(threatenedSq != s);
|
||||
assert(threatenedPc);
|
||||
|
||||
add_dirty_threat<PutPiece>(dts, pc, threatenedPc, s, threatenedSq);
|
||||
add_dirty_threat(dts, putPiece, pc, threatenedPc, s, threatenedSq);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1328,7 +1311,7 @@ void Position::update_piece_threats(Piece pc,
|
||||
assert(srcSq != s);
|
||||
assert(srcPc != NO_PIECE);
|
||||
|
||||
add_dirty_threat<PutPiece>(dts, srcPc, pc, srcSq, s);
|
||||
add_dirty_threat(dts, putPiece, srcPc, pc, srcSq, s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+8
-7
@@ -195,8 +195,9 @@ class Position {
|
||||
void set_check_info() const;
|
||||
|
||||
// Other helpers
|
||||
template<bool PutPiece, bool ComputeRay = true>
|
||||
template<bool ComputeRay = true>
|
||||
void update_piece_threats(Piece pc,
|
||||
bool putPiece,
|
||||
Square s,
|
||||
DirtyThreats* const dts,
|
||||
Bitboard noRaysContaining = -1ULL) const;
|
||||
@@ -362,14 +363,14 @@ inline void Position::put_piece(Piece pc, Square s, DirtyThreats* const dts) {
|
||||
pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
|
||||
|
||||
if (dts)
|
||||
update_piece_threats<true>(pc, s, dts);
|
||||
update_piece_threats(pc, true, s, dts);
|
||||
}
|
||||
|
||||
inline void Position::remove_piece(Square s, DirtyThreats* const dts) {
|
||||
Piece pc = board[s];
|
||||
|
||||
if (dts)
|
||||
update_piece_threats<false>(pc, s, dts);
|
||||
update_piece_threats(pc, false, s, dts);
|
||||
|
||||
byTypeBB[ALL_PIECES] ^= s;
|
||||
byTypeBB[type_of(pc)] ^= s;
|
||||
@@ -384,7 +385,7 @@ inline void Position::move_piece(Square from, Square to, DirtyThreats* const dts
|
||||
Bitboard fromTo = from | to;
|
||||
|
||||
if (dts)
|
||||
update_piece_threats<false>(pc, from, dts, fromTo);
|
||||
update_piece_threats(pc, false, from, dts, fromTo);
|
||||
|
||||
byTypeBB[ALL_PIECES] ^= fromTo;
|
||||
byTypeBB[type_of(pc)] ^= fromTo;
|
||||
@@ -393,7 +394,7 @@ inline void Position::move_piece(Square from, Square to, DirtyThreats* const dts
|
||||
board[to] = pc;
|
||||
|
||||
if (dts)
|
||||
update_piece_threats<true>(pc, to, dts, fromTo);
|
||||
update_piece_threats(pc, true, to, dts, fromTo);
|
||||
}
|
||||
|
||||
inline void Position::swap_piece(Square s, Piece pc, DirtyThreats* const dts) {
|
||||
@@ -402,12 +403,12 @@ inline void Position::swap_piece(Square s, Piece pc, DirtyThreats* const dts) {
|
||||
remove_piece(s);
|
||||
|
||||
if (dts)
|
||||
update_piece_threats<false, false>(old, s, dts);
|
||||
update_piece_threats<false>(old, false, s, dts);
|
||||
|
||||
put_piece(pc, s);
|
||||
|
||||
if (dts)
|
||||
update_piece_threats<true, false>(pc, s, dts);
|
||||
update_piece_threats<false>(pc, true, s, dts);
|
||||
}
|
||||
|
||||
inline void Position::do_move(Move m, StateInfo& newSt, const TranspositionTable* tt = nullptr) {
|
||||
|
||||
@@ -329,8 +329,6 @@ struct DirtyThreats {
|
||||
DirtyThreatList list;
|
||||
Color us;
|
||||
Square prevKsq, ksq;
|
||||
|
||||
Bitboard threatenedSqs, threateningSqs;
|
||||
};
|
||||
|
||||
#define ENABLE_INCR_OPERATORS_ON(T) \
|
||||
|
||||
Reference in New Issue
Block a user