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
This commit is contained in:
Carlos Esparza
2025-11-17 13:34:45 +01:00
committed by Joost VandeVondele
parent b083049fe0
commit 2084d94266
7 changed files with 231 additions and 244 deletions
+9
View File
@@ -412,6 +412,15 @@ void move_to_front(std::vector<T>& 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)))
+41 -72
View File
@@ -58,35 +58,6 @@ constexpr std::array<Piece, 12> 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<Color Perspective>
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<unsigned>(from) < static_cast<unsigned>(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<Color Perspective>
IndexType
FullThreats::make_index(Piece attacker, Square from, Square to, Piece attacked, Square ksq) {
return make_index_with_orientation<Perspective>(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<unsigned>(from) < static_cast<unsigned>(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<Color Perspective>
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<KING>(Perspective);
const int orientation = OrientTBL[Perspective][ksq];
Square ksq = pos.square<KING>(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<Perspective>(
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<Perspective>(
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<Perspective>(
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<WHITE>(const Position& pos, IndexList& active);
template void FullThreats::append_active_indices<BLACK>(const Position& pos, IndexList& active);
template IndexType
FullThreats::make_index<WHITE>(Piece attkr, Square from, Square to, Piece attkd, Square ksq);
template IndexType
FullThreats::make_index<BLACK>(Piece attkr, Square from, Square to, Piece attkd, Square ksq);
// Get a list of indices for recently changed features
template<Color Perspective>
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<Perspective>(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<WHITE>(Square ksq,
const DiffType& diff,
IndexList& removed,
IndexList& added,
FusedUpdateData* fd,
bool first);
template void FullThreats::append_changed_indices<BLACK>(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];
+9 -6
View File
@@ -89,16 +89,19 @@ class FullThreats {
using IndexList = ValueList<IndexType, MaxActiveDimensions>;
using DiffType = DirtyThreats;
template<Color Perspective>
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<Color Perspective>
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<Color Perspective>
static void append_changed_indices(Square ksq,
static void append_changed_indices(Color perspective,
Square ksq,
const DiffType& diff,
IndexList& removed,
IndexList& added,
+17 -30
View File
@@ -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<Color Perspective>
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<Color Perspective>
void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active) {
Square ksq = pos.square<KING>(Perspective);
void HalfKAv2_hm::append_active_indices(Color perspective,
const Position& pos,
IndexList& active) {
Square ksq = pos.square<KING>(perspective);
Bitboard bb = pos.pieces();
while (bb)
{
Square s = pop_lsb(bb);
active.push_back(make_index<Perspective>(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<WHITE>(const Position& pos, IndexList& active);
template void HalfKAv2_hm::append_active_indices<BLACK>(const Position& pos, IndexList& active);
template IndexType HalfKAv2_hm::make_index<WHITE>(Square s, Piece pc, Square ksq);
template IndexType HalfKAv2_hm::make_index<BLACK>(Square s, Piece pc, Square ksq);
// Get a list of indices for recently changed features
template<Color Perspective>
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<Perspective>(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<Perspective>(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<Perspective>(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<Perspective>(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<WHITE>(Square ksq,
const DiffType& dp,
IndexList& removed,
IndexList& added);
template void HalfKAv2_hm::append_changed_indices<BLACK>(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);
}
+11 -7
View File
@@ -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<Color Perspective>
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<Color Perspective>
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<Color Perspective>
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.
+122 -110
View File
@@ -40,39 +40,43 @@ using namespace SIMD;
namespace {
template<Color Perspective, IndexType TransformedFeatureDimensions>
void double_inc_update(const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
template<IndexType TransformedFeatureDimensions>
void double_inc_update(Color perspective,
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
const Square ksq,
AccumulatorState<PSQFeatureSet>& middle_state,
AccumulatorState<PSQFeatureSet>& target_state,
const AccumulatorState<PSQFeatureSet>& computed);
template<Color Perspective, IndexType TransformedFeatureDimensions>
void double_inc_update(const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
template<IndexType TransformedFeatureDimensions>
void double_inc_update(Color perspective,
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
const Square ksq,
AccumulatorState<ThreatFeatureSet>& middle_state,
AccumulatorState<ThreatFeatureSet>& target_state,
const AccumulatorState<ThreatFeatureSet>& computed,
const DirtyPiece& dp2);
template<Color Perspective,
bool Forward,
template<bool Forward,
typename FeatureSet,
IndexType TransformedFeatureDimensions>
void update_accumulator_incremental(
Color perspective,
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
const Square ksq,
AccumulatorState<FeatureSet>& target_state,
const AccumulatorState<FeatureSet>& computed);
template<Color Perspective, IndexType Dimensions>
void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& featureTransformer,
template<IndexType Dimensions>
void update_accumulator_refresh_cache(Color perspective,
const FeatureTransformer<Dimensions>& featureTransformer,
const Position& pos,
AccumulatorState<PSQFeatureSet>& accumulatorState,
AccumulatorCaches::Cache<Dimensions>& cache);
template<Color Perspective, IndexType Dimensions>
void update_threats_accumulator_full(const FeatureTransformer<Dimensions>& featureTransformer,
template<IndexType Dimensions>
void update_threats_accumulator_full(Color perspective,
const FeatureTransformer<Dimensions>& featureTransformer,
const Position& pos,
AccumulatorState<ThreatFeatureSet>& accumulatorState);
}
@@ -143,71 +147,73 @@ void AccumulatorStack::evaluate(const Position& pos,
AccumulatorCaches::Cache<Dimensions>& cache) noexcept {
constexpr bool UseThreats = (Dimensions == TransformedFeatureDimensionsBig);
evaluate_side<WHITE, PSQFeatureSet>(pos, featureTransformer, cache);
evaluate_side<PSQFeatureSet>(WHITE, pos, featureTransformer, cache);
if (UseThreats)
evaluate_side<WHITE, ThreatFeatureSet>(pos, featureTransformer, cache);
evaluate_side<ThreatFeatureSet>(WHITE, pos, featureTransformer, cache);
evaluate_side<BLACK, PSQFeatureSet>(pos, featureTransformer, cache);
evaluate_side<PSQFeatureSet>(BLACK, pos, featureTransformer, cache);
if (UseThreats)
evaluate_side<BLACK, ThreatFeatureSet>(pos, featureTransformer, cache);
evaluate_side<ThreatFeatureSet>(BLACK, pos, featureTransformer, cache);
}
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
void AccumulatorStack::evaluate_side(const Position& pos,
template<typename FeatureSet, IndexType Dimensions>
void AccumulatorStack::evaluate_side(Color perspective,
const Position& pos,
const FeatureTransformer<Dimensions>& featureTransformer,
AccumulatorCaches::Cache<Dimensions>& cache) noexcept {
const auto last_usable_accum =
find_last_usable_accumulator<Perspective, FeatureSet, Dimensions>();
find_last_usable_accumulator<FeatureSet, Dimensions>(perspective);
if ((accumulators<FeatureSet>()[last_usable_accum].template acc<Dimensions>())
.computed[Perspective])
forward_update_incremental<Perspective, FeatureSet>(pos, featureTransformer,
.computed[perspective])
forward_update_incremental<FeatureSet>(perspective, pos, featureTransformer,
last_usable_accum);
else
{
if constexpr (std::is_same_v<FeatureSet, PSQFeatureSet>)
update_accumulator_refresh_cache<Perspective>(featureTransformer, pos,
update_accumulator_refresh_cache(perspective, featureTransformer, pos,
mut_latest<PSQFeatureSet>(), cache);
else
update_threats_accumulator_full<Perspective>(featureTransformer, pos,
update_threats_accumulator_full(perspective, featureTransformer, pos,
mut_latest<ThreatFeatureSet>());
backward_update_incremental<Perspective, FeatureSet>(pos, featureTransformer,
backward_update_incremental<FeatureSet>(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<Color Perspective, typename FeatureSet, IndexType Dimensions>
std::size_t AccumulatorStack::find_last_usable_accumulator() const noexcept {
template<typename FeatureSet, IndexType Dimensions>
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<FeatureSet>()[curr_idx].template acc<Dimensions>()).computed[Perspective])
if ((accumulators<FeatureSet>()[curr_idx].template acc<Dimensions>()).computed[perspective])
return curr_idx;
if (FeatureSet::requires_refresh(accumulators<FeatureSet>()[curr_idx].diff, Perspective))
if (FeatureSet::requires_refresh(accumulators<FeatureSet>()[curr_idx].diff, perspective))
return curr_idx;
}
return 0;
}
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
template<typename FeatureSet, IndexType Dimensions>
void AccumulatorStack::forward_update_incremental(
Color perspective,
const Position& pos,
const FeatureTransformer<Dimensions>& featureTransformer,
const std::size_t begin) noexcept {
assert(begin < accumulators<FeatureSet>().size());
assert((accumulators<FeatureSet>()[begin].template acc<Dimensions>()).computed[Perspective]);
assert((accumulators<FeatureSet>()[begin].template acc<Dimensions>()).computed[perspective]);
const Square ksq = pos.square<KING>(Perspective);
const Square ksq = pos.square<KING>(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<Perspective>(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,7 +242,7 @@ void AccumulatorStack::forward_update_incremental(
{
const Square captureSq = dp1.to;
dp1.to = dp2.remove_sq = SQ_NONE;
double_inc_update<Perspective>(featureTransformer, ksq, accumulators[next],
double_inc_update(perspective, featureTransformer, ksq, accumulators[next],
accumulators[next + 1], accumulators[next - 1]);
dp1.to = dp2.remove_sq = captureSq;
next++;
@@ -246,32 +251,33 @@ void AccumulatorStack::forward_update_incremental(
}
}
update_accumulator_incremental<Perspective, true>(featureTransformer, ksq,
update_accumulator_incremental<true>(perspective, featureTransformer, ksq,
mut_accumulators<FeatureSet>()[next],
accumulators<FeatureSet>()[next - 1]);
}
assert((latest<PSQFeatureSet>().acc<Dimensions>()).computed[Perspective]);
assert((latest<PSQFeatureSet>().acc<Dimensions>()).computed[perspective]);
}
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
void AccumulatorStack::backward_update_incremental(
template<typename FeatureSet, IndexType Dimensions>
void AccumulatorStack::backward_update_incremental(Color perspective,
const Position& pos,
const FeatureTransformer<Dimensions>& featureTransformer,
const std::size_t end) noexcept {
assert(end < accumulators<FeatureSet>().size());
assert(end < size);
assert((latest<FeatureSet>().template acc<Dimensions>()).computed[Perspective]);
assert((latest<FeatureSet>().template acc<Dimensions>()).computed[perspective]);
const Square ksq = pos.square<KING>(Perspective);
const Square ksq = pos.square<KING>(perspective);
for (std::int64_t next = std::int64_t(size) - 2; next >= std::int64_t(end); next--)
update_accumulator_incremental<Perspective, false>(featureTransformer, ksq,
update_accumulator_incremental<false>(perspective, featureTransformer, ksq,
mut_accumulators<FeatureSet>()[next],
accumulators<FeatureSet>()[next + 1]);
assert((accumulators<FeatureSet>()[end].template acc<Dimensions>()).computed[Perspective]);
assert((accumulators<FeatureSet>()[end].template acc<Dimensions>()).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<const typename VectorWrapper::type*>(rows)[i]...);
}
template<typename FeatureSet, Color Perspective, IndexType Dimensions>
template<typename FeatureSet, IndexType Dimensions>
struct AccumulatorUpdateContext {
Color perspective;
const FeatureTransformer<Dimensions>& featureTransformer;
const AccumulatorState<FeatureSet>& from;
AccumulatorState<FeatureSet>& to;
AccumulatorUpdateContext(const FeatureTransformer<Dimensions>& ft,
AccumulatorUpdateContext(Color persp,
const FeatureTransformer<Dimensions>& ft,
const AccumulatorState<FeatureSet>& accF,
AccumulatorState<FeatureSet>& accT) noexcept :
perspective{persp},
featureTransformer{ft},
from{accF},
to{accT} {}
@@ -330,22 +339,22 @@ struct AccumulatorUpdateContext {
};
fused_row_reduce<Vec16Wrapper, Dimensions, ops...>(
(from.template acc<Dimensions>()).accumulation[Perspective],
(to.template acc<Dimensions>()).accumulation[Perspective], to_weight_vector(indices)...);
(from.template acc<Dimensions>()).accumulation[perspective],
(to.template acc<Dimensions>()).accumulation[perspective], to_weight_vector(indices)...);
fused_row_reduce<Vec32Wrapper, PSQTBuckets, ops...>(
(from.template acc<Dimensions>()).psqtAccumulation[Perspective],
(to.template acc<Dimensions>()).psqtAccumulation[Perspective],
(from.template acc<Dimensions>()).psqtAccumulation[perspective],
(to.template acc<Dimensions>()).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<Dimensions>().accumulation[Perspective];
const auto toAcc = to.template acc<Dimensions>().accumulation[Perspective];
const auto fromAcc = from.template acc<Dimensions>().accumulation[perspective];
const auto toAcc = to.template acc<Dimensions>().accumulation[perspective];
const auto fromPsqtAcc = from.template acc<Dimensions>().psqtAccumulation[Perspective];
const auto toPsqtAcc = to.template acc<Dimensions>().psqtAccumulation[Perspective];
const auto fromPsqtAcc = from.template acc<Dimensions>().psqtAccumulation[perspective];
const auto toPsqtAcc = to.template acc<Dimensions>().psqtAccumulation[perspective];
#ifdef VECTOR
using Tiling = SIMDTiling<Dimensions, Dimensions, PSQTBuckets>;
@@ -469,31 +478,33 @@ struct AccumulatorUpdateContext {
}
};
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
auto make_accumulator_update_context(const FeatureTransformer<Dimensions>& featureTransformer,
template<typename FeatureSet, IndexType Dimensions>
auto make_accumulator_update_context(Color perspective,
const FeatureTransformer<Dimensions>& featureTransformer,
const AccumulatorState<FeatureSet>& accumulatorFrom,
AccumulatorState<FeatureSet>& accumulatorTo) noexcept {
return AccumulatorUpdateContext<FeatureSet, Perspective, Dimensions>{
featureTransformer, accumulatorFrom, accumulatorTo};
return AccumulatorUpdateContext<FeatureSet, Dimensions>{
perspective, featureTransformer, accumulatorFrom, accumulatorTo};
}
template<Color Perspective, IndexType TransformedFeatureDimensions>
void double_inc_update(const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
template<IndexType TransformedFeatureDimensions>
void double_inc_update(Color perspective,
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
const Square ksq,
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]);
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);
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);
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<TransformedFeatureDimensions>& f
sf_assume(removed.size() == 2 || removed.size() == 3);
auto updateContext =
make_accumulator_update_context<Perspective>(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<TransformedFeatureDimensions>& f
removed[2]);
}
target_state.acc<TransformedFeatureDimensions>().computed[Perspective] = true;
target_state.acc<TransformedFeatureDimensions>().computed[perspective] = true;
}
template<Color Perspective, IndexType TransformedFeatureDimensions>
void double_inc_update(const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
template<IndexType TransformedFeatureDimensions>
void double_inc_update(Color perspective,
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
const Square ksq,
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]);
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;
ThreatFeatureSet::append_changed_indices<Perspective>(ksq, middle_state.diff, removed, added,
ThreatFeatureSet::append_changed_indices(perspective, ksq, middle_state.diff, removed, added,
&fusedData, true);
ThreatFeatureSet::append_changed_indices<Perspective>(ksq, target_state.diff, removed, added,
ThreatFeatureSet::append_changed_indices(perspective, ksq, target_state.diff, removed, added,
&fusedData, false);
auto updateContext =
make_accumulator_update_context<Perspective>(featureTransformer, computed, target_state);
make_accumulator_update_context(perspective, featureTransformer, computed, target_state);
updateContext.apply(added, removed);
target_state.acc<TransformedFeatureDimensions>().computed[Perspective] = true;
target_state.acc<TransformedFeatureDimensions>().computed[perspective] = true;
}
template<Color Perspective,
bool Forward,
template<bool Forward,
typename FeatureSet,
IndexType TransformedFeatureDimensions>
void update_accumulator_incremental(
Color perspective,
const FeatureTransformer<TransformedFeatureDimensions>& featureTransformer,
const Square ksq,
AccumulatorState<FeatureSet>& target_state,
const AccumulatorState<FeatureSet>& computed) {
assert((computed.template acc<TransformedFeatureDimensions>()).computed[Perspective]);
assert(!(target_state.template acc<TransformedFeatureDimensions>()).computed[Perspective]);
assert((computed.template acc<TransformedFeatureDimensions>()).computed[perspective]);
assert(!(target_state.template acc<TransformedFeatureDimensions>()).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<Perspective>(ksq, target_state.diff, removed,
added);
FeatureSet::append_changed_indices(perspective, ksq, target_state.diff, removed, added);
else
FeatureSet::template append_changed_indices<Perspective>(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<TransformedFeatureDimensions>();
const auto& sourceAcc = computed.template acc<TransformedFeatureDimensions>();
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<Perspective>(featureTransformer, computed, target_state);
make_accumulator_update_context(perspective, featureTransformer, computed, target_state);
if constexpr (std::is_same_v<FeatureSet, ThreatFeatureSet>)
updateContext.apply(added, removed);
@@ -633,7 +643,7 @@ void update_accumulator_incremental(
}
}
(target_state.template acc<TransformedFeatureDimensions>()).computed[Perspective] = true;
(target_state.template acc<TransformedFeatureDimensions>()).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<Color Perspective, IndexType Dimensions>
void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& featureTransformer,
template<IndexType Dimensions>
void update_accumulator_refresh_cache(Color perspective,
const FeatureTransformer<Dimensions>& featureTransformer,
const Position& pos,
AccumulatorState<PSQFeatureSet>& accumulatorState,
AccumulatorCaches::Cache<Dimensions>& cache) {
using Tiling [[maybe_unused]] = SIMDTiling<Dimensions, Dimensions, PSQTBuckets>;
const Square ksq = pos.square<KING>(Perspective);
auto& entry = cache[ksq][Perspective];
const Square ksq = pos.square<KING>(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<Dimensions>& feat
while (removedBB)
{
Square sq = pop_lsb(removedBB);
removed.push_back(PSQFeatureSet::make_index<Perspective>(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<Perspective>(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<Dimensions>();
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<Dimensions>& feat
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{
auto* accTile =
reinterpret_cast<vec_t*>(&accumulator.accumulation[Perspective][j * Tiling::TileHeight]);
reinterpret_cast<vec_t*>(&accumulator.accumulation[perspective][j * Tiling::TileHeight]);
auto* entryTile = reinterpret_cast<vec_t*>(&entry.accumulation[j * Tiling::TileHeight]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
@@ -747,7 +758,7 @@ void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& feat
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
{
auto* accTilePsqt = reinterpret_cast<psqt_vec_t*>(
&accumulator.psqtAccumulation[Perspective][j * Tiling::PsqtTileHeight]);
&accumulator.psqtAccumulation[perspective][j * Tiling::PsqtTileHeight]);
auto* entryTilePsqt =
reinterpret_cast<psqt_vec_t*>(&entry.psqtAccumulation[j * Tiling::PsqtTileHeight]);
@@ -805,25 +816,26 @@ void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& 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<Color Perspective, IndexType Dimensions>
void update_threats_accumulator_full(const FeatureTransformer<Dimensions>& featureTransformer,
template<IndexType Dimensions>
void update_threats_accumulator_full(Color perspective,
const FeatureTransformer<Dimensions>& featureTransformer,
const Position& pos,
AccumulatorState<ThreatFeatureSet>& accumulatorState) {
using Tiling [[maybe_unused]] = SIMDTiling<Dimensions, Dimensions, PSQTBuckets>;
ThreatFeatureSet::IndexList active;
ThreatFeatureSet::append_active_indices<Perspective>(pos, active);
ThreatFeatureSet::append_active_indices(perspective, pos, active);
auto& accumulator = accumulatorState.acc<Dimensions>();
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<Dimensions>& featu
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{
auto* accTile =
reinterpret_cast<vec_t*>(&accumulator.accumulation[Perspective][j * Tiling::TileHeight]);
reinterpret_cast<vec_t*>(&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<Dimensions>& featu
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
{
auto* accTilePsqt = reinterpret_cast<psqt_vec_t*>(
&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<Dimensions>& 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];
}
+11 -8
View File
@@ -176,21 +176,24 @@ class AccumulatorStack {
template<typename T>
[[nodiscard]] std::array<AccumulatorState<T>, MaxSize>& mut_accumulators() noexcept;
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
void evaluate_side(const Position& pos,
template<typename FeatureSet, IndexType Dimensions>
void evaluate_side(Color perspective,
const Position& pos,
const FeatureTransformer<Dimensions>& featureTransformer,
AccumulatorCaches::Cache<Dimensions>& cache) noexcept;
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
[[nodiscard]] std::size_t find_last_usable_accumulator() const noexcept;
template<typename FeatureSet, IndexType Dimensions>
[[nodiscard]] std::size_t find_last_usable_accumulator(Color perspective) const noexcept;
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
void forward_update_incremental(const Position& pos,
template<typename FeatureSet, IndexType Dimensions>
void forward_update_incremental(Color perspective,
const Position& pos,
const FeatureTransformer<Dimensions>& featureTransformer,
const std::size_t begin) noexcept;
template<Color Perspective, typename FeatureSet, IndexType Dimensions>
void backward_update_incremental(const Position& pos,
template<typename FeatureSet, IndexType Dimensions>
void backward_update_incremental(Color perspective,
const Position& pos,
const FeatureTransformer<Dimensions>& featureTransformer,
const std::size_t end) noexcept;