mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Precompute moves and use magics index as compress mask on AVX512ICL
Passed STC https://tests.stockfishchess.org/tests/view/69f6df65b64b50e29dbed427 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 112224 W: 29195 L: 28782 D: 54247 Ptnml(0-2): 312, 12345, 30381, 12766, 308 Local speedup: ``` Result of 100 runs base (...kfish.master) = 2050387 +/- 5497 test (./stockfish ) = 2069598 +/- 4426 diff = +19211 +/- 7468 speedup = +0.0094 P(speedup > 0) = 1.0000 ``` closes https://github.com/official-stockfish/Stockfish/pull/6797 No functional change
This commit is contained in:
committed by
Joost VandeVondele
parent
ab8f901d25
commit
1554a2ca0b
@@ -281,6 +281,17 @@ inline int popcount(Bitboard b) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline constexpr int lsb_index64[64] = {
|
||||||
|
0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, 54, 58, 35, 52, 50, 42,
|
||||||
|
21, 44, 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43,
|
||||||
|
31, 22, 10, 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63};
|
||||||
|
|
||||||
|
constexpr int constexpr_lsb(uint64_t bb) {
|
||||||
|
assert(bb != 0);
|
||||||
|
constexpr uint64_t debruijn64 = 0x03F79D71B4CB0A89ULL;
|
||||||
|
return lsb_index64[((bb ^ (bb - 1)) * debruijn64) >> 58];
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the least significant bit in a non-zero bitboard.
|
// Returns the least significant bit in a non-zero bitboard.
|
||||||
inline Square lsb(Bitboard b) {
|
inline Square lsb(Bitboard b) {
|
||||||
assert(b);
|
assert(b);
|
||||||
|
|||||||
+85
-4
@@ -62,6 +62,76 @@ inline Move* splat_moves(Move* moveList, Square from, Bitboard to_bb) {
|
|||||||
return moveList + popcount(to_bb);
|
return moveList + popcount(to_bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rook/bishop, indexed by (Pt - BISHOP) and from sq
|
||||||
|
// Moves are provided in ascending order of the piece's attacks on an empty board
|
||||||
|
alignas(64) constexpr auto SliderMoves = []() {
|
||||||
|
std::array<std::array<std::array<Move, 16>, SQUARE_NB>, 2> arr{};
|
||||||
|
for (PieceType pt : {BISHOP, ROOK})
|
||||||
|
{
|
||||||
|
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
||||||
|
{
|
||||||
|
Bitboard bb = PseudoAttacks[pt][s];
|
||||||
|
int i = 0;
|
||||||
|
while (bb)
|
||||||
|
{
|
||||||
|
arr[pt - BISHOP][s][i++] = Move(s, Square(constexpr_lsb(bb)));
|
||||||
|
bb &= bb - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}();
|
||||||
|
|
||||||
|
// Knight/king analog of the above
|
||||||
|
alignas(64) constexpr auto KnightKingMoves = []() {
|
||||||
|
std::array<std::array<std::array<Move, 8>, SQUARE_NB>, 2> arr{};
|
||||||
|
for (PieceType pt : {KNIGHT, KING})
|
||||||
|
{
|
||||||
|
for (Square s = SQ_A1; s <= SQ_H8; ++s)
|
||||||
|
{
|
||||||
|
Bitboard bb = PseudoAttacks[pt][s];
|
||||||
|
int i = 0;
|
||||||
|
while (bb)
|
||||||
|
{
|
||||||
|
arr[pt == KING][s][i++] = Move(s, Square(constexpr_lsb(bb)));
|
||||||
|
bb &= bb - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}();
|
||||||
|
|
||||||
|
template<PieceType Pt>
|
||||||
|
inline Move*
|
||||||
|
splat_precomputed_moves(Move* moveList, Square from, Bitboard occupied, Bitboard target) {
|
||||||
|
static_assert(Pt != QUEEN && Pt != PAWN, "Unsupported piece type");
|
||||||
|
|
||||||
|
// The nth bit in the mask corresponds to the nth square in the piece's pseudo-attacks
|
||||||
|
uint32_t mask;
|
||||||
|
if constexpr (Pt == BISHOP || Pt == ROOK)
|
||||||
|
{
|
||||||
|
const Magic& magic = Magics[from][Pt - BISHOP];
|
||||||
|
|
||||||
|
mask = magic.attacks[magic.index(occupied)];
|
||||||
|
mask &= pext(target, magic.pseudoAttacks);
|
||||||
|
|
||||||
|
const __m256i moves =
|
||||||
|
*reinterpret_cast<const __m256i*>(SliderMoves[Pt - BISHOP][from].data());
|
||||||
|
_mm256_storeu_si256(reinterpret_cast<__m256i*>(moveList),
|
||||||
|
_mm256_maskz_compress_epi16(mask, moves));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = pext(target, PseudoAttacks[Pt][from]);
|
||||||
|
|
||||||
|
__m128i moves = *reinterpret_cast<const __m128i*>(KnightKingMoves[Pt == KING][from].data());
|
||||||
|
_mm_storeu_si128(reinterpret_cast<__m128i*>(moveList),
|
||||||
|
_mm_maskz_compress_epi16(mask, moves));
|
||||||
|
}
|
||||||
|
|
||||||
|
return moveList + popcount(mask);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
template<Direction offset>
|
template<Direction offset>
|
||||||
@@ -192,8 +262,15 @@ Move* generate_moves(const Position& pos, Move* moveList, Bitboard target) {
|
|||||||
|
|
||||||
while (bb)
|
while (bb)
|
||||||
{
|
{
|
||||||
Square from = pop_lsb(bb);
|
Square from = pop_lsb(bb);
|
||||||
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
|
#ifdef USE_AVX512ICL
|
||||||
|
if constexpr (Pt != QUEEN)
|
||||||
|
{
|
||||||
|
moveList = splat_precomputed_moves<Pt>(moveList, from, pos.pieces(), target);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
|
||||||
|
|
||||||
moveList = splat_moves(moveList, from, b);
|
moveList = splat_moves(moveList, from, b);
|
||||||
}
|
}
|
||||||
@@ -225,9 +302,13 @@ Move* generate_all(const Position& pos, Move* moveList) {
|
|||||||
moveList = generate_moves<Us, QUEEN>(pos, moveList, target);
|
moveList = generate_moves<Us, QUEEN>(pos, moveList, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitboard b = attacks_bb<KING>(ksq) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
|
Bitboard b = Type == EVASIONS ? ~pos.pieces(Us) : target;
|
||||||
|
|
||||||
moveList = splat_moves(moveList, ksq, b);
|
#ifdef USE_AVX512ICL
|
||||||
|
moveList = splat_precomputed_moves<KING>(moveList, ksq, 0ULL, b);
|
||||||
|
#else
|
||||||
|
moveList = splat_moves(moveList, ksq, attacks_bb<KING>(ksq) & b);
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
|
if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
|
||||||
for (CastlingRights cr : {Us & KING_SIDE, Us & QUEEN_SIDE})
|
for (CastlingRights cr : {Us & KING_SIDE, Us & QUEEN_SIDE})
|
||||||
|
|||||||
@@ -38,19 +38,6 @@
|
|||||||
|
|
||||||
namespace Stockfish::Eval::NNUE::Layers {
|
namespace Stockfish::Eval::NNUE::Layers {
|
||||||
|
|
||||||
#if (USE_SSSE3 | (USE_NEON >= 8))
|
|
||||||
static constexpr int lsb_index64[64] = {
|
|
||||||
0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, 54, 58, 35, 52, 50, 42,
|
|
||||||
21, 44, 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43,
|
|
||||||
31, 22, 10, 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63};
|
|
||||||
|
|
||||||
constexpr int constexpr_lsb(uint64_t bb) {
|
|
||||||
assert(bb != 0);
|
|
||||||
constexpr uint64_t debruijn64 = 0x03F79D71B4CB0A89ULL;
|
|
||||||
return lsb_index64[((bb ^ (bb - 1)) * debruijn64) >> 58];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Sparse input implementation
|
// Sparse input implementation
|
||||||
template<IndexType InDims, IndexType OutDims>
|
template<IndexType InDims, IndexType OutDims>
|
||||||
class AffineTransformSparseInput {
|
class AffineTransformSparseInput {
|
||||||
|
|||||||
Reference in New Issue
Block a user