mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Improve index generation
The speedup seems to vary by machine. The indexing function can be changed w/o needing to understand intrinsics. Result of 100 runs ================== base (...ish_baseline) = 1719637 +/- 3233 test (./stockfish ) = 1734245 +/- 3534 diff = +14608 +/- 4868 speedup = +0.0085 P(speedup > 0) = 1.0000 closes https://github.com/official-stockfish/Stockfish/pull/6366 No functional change
This commit is contained in:
committed by
Joost VandeVondele
parent
3bb01ce7a9
commit
6764561916
@@ -18,9 +18,9 @@
|
||||
|
||||
#include "nnue_accumulator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../bitboard.h"
|
||||
@@ -362,6 +362,29 @@ void update_accumulator_incremental(
|
||||
(target_state.acc<TransformedFeatureDimensions>()).computed[Perspective] = true;
|
||||
}
|
||||
|
||||
Bitboard get_changed_pieces(const Piece old[SQUARE_NB], const Piece new_[SQUARE_NB]) {
|
||||
#if defined(USE_AVX512) || defined(USE_AVX2)
|
||||
static_assert(sizeof(Piece) == 1);
|
||||
Bitboard same_bb = 0;
|
||||
for (int i = 0; i < 64; i += 32)
|
||||
{
|
||||
const __m256i old_v = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(old + i));
|
||||
const __m256i new_v = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(new_ + i));
|
||||
const __m256i cmp_equal = _mm256_cmpeq_epi8(old_v, new_v);
|
||||
const std::uint32_t equal_mask = _mm256_movemask_epi8(cmp_equal);
|
||||
same_bb |= static_cast<Bitboard>(equal_mask) << i;
|
||||
}
|
||||
return ~same_bb;
|
||||
#else
|
||||
Bitboard changed = 0;
|
||||
for (Square sq = SQUARE_ZERO; sq < SQUARE_NB; ++sq)
|
||||
{
|
||||
changed |= static_cast<Bitboard>(old[sq] != new_[sq]) << sq;
|
||||
}
|
||||
return changed;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<Color Perspective, IndexType Dimensions>
|
||||
void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& featureTransformer,
|
||||
const Position& pos,
|
||||
@@ -374,28 +397,23 @@ void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& feat
|
||||
auto& entry = cache[ksq][Perspective];
|
||||
FeatureSet::IndexList removed, added;
|
||||
|
||||
for (Color c : {WHITE, BLACK})
|
||||
{
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
{
|
||||
const Piece piece = make_piece(c, pt);
|
||||
const Bitboard oldBB = entry.byColorBB[c] & entry.byTypeBB[pt];
|
||||
const Bitboard newBB = pos.pieces(c, pt);
|
||||
Bitboard toRemove = oldBB & ~newBB;
|
||||
Bitboard toAdd = newBB & ~oldBB;
|
||||
const Bitboard changed_bb = get_changed_pieces(entry.pieces, pos.piece_array());
|
||||
Bitboard removed_bb = changed_bb & entry.pieceBB;
|
||||
Bitboard added_bb = changed_bb & pos.pieces();
|
||||
|
||||
while (toRemove)
|
||||
{
|
||||
Square sq = pop_lsb(toRemove);
|
||||
removed.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
while (toAdd)
|
||||
{
|
||||
Square sq = pop_lsb(toAdd);
|
||||
added.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
}
|
||||
while (removed_bb)
|
||||
{
|
||||
Square sq = pop_lsb(removed_bb);
|
||||
removed.push_back(FeatureSet::make_index<Perspective>(sq, entry.pieces[sq], ksq));
|
||||
}
|
||||
while (added_bb)
|
||||
{
|
||||
Square sq = pop_lsb(added_bb);
|
||||
added.push_back(FeatureSet::make_index<Perspective>(sq, pos.piece_on(sq), ksq));
|
||||
}
|
||||
|
||||
entry.pieceBB = pos.pieces();
|
||||
std::copy_n(pos.piece_array(), SQUARE_NB, entry.pieces);
|
||||
|
||||
auto& accumulator = accumulatorState.acc<Dimensions>();
|
||||
accumulator.computed[Perspective] = true;
|
||||
@@ -518,12 +536,6 @@ void update_accumulator_refresh_cache(const FeatureTransformer<Dimensions>& feat
|
||||
std::memcpy(accumulator.psqtAccumulation[Perspective], entry.psqtAccumulation,
|
||||
sizeof(int32_t) * PSQTBuckets);
|
||||
#endif
|
||||
|
||||
for (Color c : {WHITE, BLACK})
|
||||
entry.byColorBB[c] = pos.pieces(c);
|
||||
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
entry.byTypeBB[pt] = pos.pieces(pt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,8 +71,8 @@ struct AccumulatorCaches {
|
||||
struct alignas(CacheLineSize) Entry {
|
||||
BiasType accumulation[Size];
|
||||
PSQTWeightType psqtAccumulation[PSQTBuckets];
|
||||
Bitboard byColorBB[COLOR_NB];
|
||||
Bitboard byTypeBB[PIECE_TYPE_NB];
|
||||
Piece pieces[SQUARE_NB];
|
||||
Bitboard pieceBB;
|
||||
|
||||
// To initialize a refresh entry, we set all its bitboards empty,
|
||||
// so we put the biases in the accumulation, without any weights on top
|
||||
|
||||
+7
-4
@@ -91,10 +91,11 @@ class Position {
|
||||
Bitboard pieces(PieceTypes... pts) const;
|
||||
Bitboard pieces(Color c) const;
|
||||
template<typename... PieceTypes>
|
||||
Bitboard pieces(Color c, PieceTypes... pts) const;
|
||||
Piece piece_on(Square s) const;
|
||||
Square ep_square() const;
|
||||
bool empty(Square s) const;
|
||||
Bitboard pieces(Color c, PieceTypes... pts) const;
|
||||
Piece piece_on(Square s) const;
|
||||
const Piece* piece_array() const;
|
||||
Square ep_square() const;
|
||||
bool empty(Square s) const;
|
||||
template<PieceType Pt>
|
||||
int count(Color c) const;
|
||||
template<PieceType Pt>
|
||||
@@ -208,6 +209,8 @@ inline Piece Position::piece_on(Square s) const {
|
||||
return board[s];
|
||||
}
|
||||
|
||||
inline const Piece* Position::piece_array() const { return board; }
|
||||
|
||||
inline bool Position::empty(Square s) const { return piece_on(s) == NO_PIECE; }
|
||||
|
||||
inline Piece Position::moved_piece(Move m) const { return piece_on(m.from_sq()); }
|
||||
|
||||
Reference in New Issue
Block a user