mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Improve Threats Speed
Passed STC: LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 23168 W: 6132 L: 5845 D: 11191 Ptnml(0-2): 77, 2405, 6325, 2708, 69 https://tests.stockfishchess.org/tests/view/69148c3c7ca8781852331831 ``` Result of 50 runs ================== base (./stockfish.master ) = 985641 +/- 4249 test (./stockfish.patch ) = 1038567 +/- 5679 diff = +52926 +/- 4473 speedup = +0.0537 P(speedup > 0) = 1.0000 CPU: 16 x AMD Ryzen 9 3950X 16-Core Processor Hyperthreading: on ``` closes https://github.com/official-stockfish/Stockfish/pull/6415 No functional change
This commit is contained in:
committed by
Joost VandeVondele
parent
7ac8e62219
commit
3ae7684714
@@ -58,6 +58,35 @@ 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)
|
||||
{
|
||||
@@ -129,32 +158,8 @@ void init_threat_offsets() {
|
||||
template<Color Perspective>
|
||||
IndexType
|
||||
FullThreats::make_index(Piece attacker, Square from, Square to, Piece attacked, Square ksq) {
|
||||
from = (Square) (int(from) ^ OrientTBL[Perspective][ksq]);
|
||||
to = (Square) (int(to) ^ OrientTBL[Perspective][ksq]);
|
||||
|
||||
if (Perspective == BLACK)
|
||||
{
|
||||
attacker = ~attacker;
|
||||
attacked = ~attacked;
|
||||
}
|
||||
|
||||
auto piecePairData = index_lut1[attacker][attacked];
|
||||
|
||||
// Some threats imply the existence of the corresponding ones in the opposite
|
||||
// direction. We filter them here to ensure only one such threat is active.
|
||||
|
||||
// In the below addition, the 2nd lsb gets set iff either the pair is always excluded,
|
||||
// or the pair is semi-excluded and from < to. By using an unsigned compare, the following
|
||||
// sequence can use an add-with-carry instruction.
|
||||
bool less_than = static_cast<uint8_t>(from) < static_cast<uint8_t>(to);
|
||||
if ((piecePairData.excluded_pair_info() + less_than) & 2)
|
||||
return Dimensions;
|
||||
|
||||
IndexType index =
|
||||
piecePairData.feature_index_base() + offsets[attacker][from] + index_lut2[attacker][from][to];
|
||||
|
||||
sf_assume(index != Dimensions);
|
||||
return index;
|
||||
return make_index_with_orientation<Perspective>(attacker, from, to, attacked,
|
||||
OrientTBL[Perspective][ksq]);
|
||||
}
|
||||
|
||||
// Get a list of indices for active features in ascending order
|
||||
@@ -162,8 +167,9 @@ template<Color Perspective>
|
||||
void FullThreats::append_active_indices(const Position& pos, IndexList& active) {
|
||||
static constexpr Color order[2][2] = {{WHITE, BLACK}, {BLACK, WHITE}};
|
||||
|
||||
Square ksq = pos.square<KING>(Perspective);
|
||||
Bitboard occupied = pos.pieces();
|
||||
Square ksq = pos.square<KING>(Perspective);
|
||||
const int orientation = OrientTBL[Perspective][ksq];
|
||||
Bitboard occupied = pos.pieces();
|
||||
|
||||
for (Color color : {WHITE, BLACK})
|
||||
{
|
||||
@@ -187,7 +193,8 @@ 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<Perspective>(attacker, from, to, attacked, ksq);
|
||||
IndexType index = make_index_with_orientation<Perspective>(
|
||||
attacker, from, to, attacked, orientation);
|
||||
|
||||
if (index < Dimensions)
|
||||
active.push_back(index);
|
||||
@@ -198,7 +205,8 @@ 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<Perspective>(attacker, from, to, attacked, ksq);
|
||||
IndexType index = make_index_with_orientation<Perspective>(
|
||||
attacker, from, to, attacked, orientation);
|
||||
|
||||
if (index < Dimensions)
|
||||
active.push_back(index);
|
||||
@@ -215,8 +223,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<Perspective>(attacker, from, to, attacked, ksq);
|
||||
IndexType index = make_index_with_orientation<Perspective>(
|
||||
attacker, from, to, attacked, orientation);
|
||||
|
||||
if (index < Dimensions)
|
||||
active.push_back(index);
|
||||
@@ -243,7 +251,9 @@ void FullThreats::append_changed_indices(Square ksq,
|
||||
IndexList& added,
|
||||
FusedUpdateData* fusedData,
|
||||
bool first) {
|
||||
for (const auto dirty : diff.list)
|
||||
const int orientation = OrientTBL[Perspective][ksq];
|
||||
|
||||
for (const auto& dirty : diff.list)
|
||||
{
|
||||
auto attacker = dirty.pc();
|
||||
auto attacked = dirty.threatened_pc();
|
||||
@@ -282,9 +292,10 @@ void FullThreats::append_changed_indices(Square ksq,
|
||||
}
|
||||
}
|
||||
|
||||
IndexType index = make_index<Perspective>(attacker, from, to, attacked, ksq);
|
||||
const IndexType index =
|
||||
make_index_with_orientation<Perspective>(attacker, from, to, attacked, orientation);
|
||||
|
||||
if (index != Dimensions)
|
||||
if (index < Dimensions)
|
||||
(add ? added : removed).push_back(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,8 @@ struct AccumulatorUpdateContext {
|
||||
to_psqt_weight_vector(indices)...);
|
||||
}
|
||||
|
||||
void apply(typename FeatureSet::IndexList added, typename FeatureSet::IndexList removed) {
|
||||
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];
|
||||
|
||||
@@ -573,6 +574,21 @@ void update_accumulator_incremental(
|
||||
FeatureSet::template 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]));
|
||||
|
||||
targetAcc.computed[Perspective] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
auto updateContext =
|
||||
make_accumulator_update_context<Perspective>(featureTransformer, computed, target_state);
|
||||
|
||||
|
||||
+44
-27
@@ -1051,12 +1051,22 @@ inline void add_dirty_threat(
|
||||
|
||||
template<bool PutPiece, bool ComputeRay>
|
||||
void Position::update_piece_threats(Piece pc, Square s, DirtyThreats* const dts) {
|
||||
// Add newly threatened pieces
|
||||
Bitboard occupied = pieces();
|
||||
const Bitboard occupied = pieces();
|
||||
const Bitboard rookQueens = pieces(ROOK, QUEEN);
|
||||
const Bitboard bishopQueens = pieces(BISHOP, QUEEN);
|
||||
const Bitboard knights = pieces(KNIGHT);
|
||||
const Bitboard kings = pieces(KING);
|
||||
const Bitboard whitePawns = pieces(WHITE, PAWN);
|
||||
const Bitboard blackPawns = pieces(BLACK, PAWN);
|
||||
|
||||
Bitboard rAttacks = attacks_bb<ROOK>(s, occupied);
|
||||
Bitboard bAttacks = attacks_bb<BISHOP>(s, occupied);
|
||||
Bitboard qAttacks = rAttacks | bAttacks;
|
||||
const Bitboard rAttacks = attacks_bb<ROOK>(s, occupied);
|
||||
const Bitboard bAttacks = attacks_bb<BISHOP>(s, occupied);
|
||||
|
||||
Bitboard qAttacks = Bitboard(0);
|
||||
if constexpr (ComputeRay)
|
||||
qAttacks = rAttacks | bAttacks;
|
||||
else if (type_of(pc) == QUEEN)
|
||||
qAttacks = rAttacks | bAttacks;
|
||||
|
||||
Bitboard threatened;
|
||||
|
||||
@@ -1092,35 +1102,42 @@ void Position::update_piece_threats(Piece pc, Square s, DirtyThreats* const dts)
|
||||
add_dirty_threat<PutPiece>(dts, pc, threatened_pc, s, threatened_sq);
|
||||
}
|
||||
|
||||
Bitboard sliders = (pieces(ROOK, QUEEN) & rAttacks) | (pieces(BISHOP, QUEEN) & bAttacks);
|
||||
Bitboard sliders = (rookQueens & rAttacks) | (bishopQueens & bAttacks);
|
||||
|
||||
Bitboard incoming_threats = (attacks_bb<KNIGHT>(s, occupied) & pieces(KNIGHT))
|
||||
| (attacks_bb<PAWN>(s, WHITE) & pieces(BLACK, PAWN))
|
||||
| (attacks_bb<PAWN>(s, BLACK) & pieces(WHITE, PAWN))
|
||||
| (attacks_bb<KING>(s, occupied) & pieces(KING));
|
||||
|
||||
while (sliders)
|
||||
if constexpr (ComputeRay)
|
||||
{
|
||||
Square slider_sq = pop_lsb(sliders);
|
||||
Piece slider = piece_on(slider_sq);
|
||||
|
||||
Bitboard ray = RayPassBB[slider_sq][s] & ~BetweenBB[slider_sq][s];
|
||||
threatened = ray & qAttacks & occupied;
|
||||
|
||||
assert(!more_than_one(threatened));
|
||||
if (ComputeRay && threatened)
|
||||
while (sliders)
|
||||
{
|
||||
Square threatened_sq = lsb(threatened);
|
||||
Square slider_sq = pop_lsb(sliders);
|
||||
Piece slider = piece_on(slider_sq);
|
||||
|
||||
Piece threatened_pc = piece_on(threatened_sq);
|
||||
add_dirty_threat<!PutPiece>(dts, slider, threatened_pc, slider_sq, threatened_sq);
|
||||
const Bitboard ray = RayPassBB[slider_sq][s] & ~BetweenBB[slider_sq][s];
|
||||
const Bitboard discovered = ray & qAttacks & occupied;
|
||||
|
||||
assert(!more_than_one(discovered));
|
||||
if (discovered)
|
||||
{
|
||||
const Square threatened_sq = lsb(discovered);
|
||||
const Piece threatened_pc = piece_on(threatened_sq);
|
||||
add_dirty_threat<!PutPiece>(dts, slider, threatened_pc, slider_sq, threatened_sq);
|
||||
}
|
||||
|
||||
add_dirty_threat<PutPiece>(dts, slider, pc, slider_sq, s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (sliders)
|
||||
{
|
||||
Square slider_sq = pop_lsb(sliders);
|
||||
Piece slider = piece_on(slider_sq);
|
||||
add_dirty_threat<PutPiece>(dts, slider, pc, slider_sq, s);
|
||||
}
|
||||
|
||||
add_dirty_threat<PutPiece>(dts, slider, pc, slider_sq, s);
|
||||
}
|
||||
|
||||
// Add threats of sliders that were already threatening s,
|
||||
// sliders are already handled in the loop above
|
||||
Bitboard incoming_threats =
|
||||
(PseudoAttacks[KNIGHT][s] & knights) | (attacks_bb<PAWN>(s, WHITE) & blackPawns)
|
||||
| (attacks_bb<PAWN>(s, BLACK) & whitePawns) | (PseudoAttacks[KING][s] & kings);
|
||||
|
||||
while (incoming_threats)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user