mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Some more work on FullThreats::make_index
[Passed STC](https://tests.stockfishchess.org/tests/live_elo/691fc321acb6dbdf23d07e4b): ``` LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 215360 W: 55651 L: 55108 D: 104601 Ptnml(0-2): 520, 22399, 61290, 22960, 511 ``` This PR is on top of ces42's work so I'll rebase if that PR changes. Essentially, it comprises my adjustments to `make_index` that remained unmerged before threat inputs was finalized. The unsigned intermediate variables let us skip a bunch of useless sign extensions (because Square and Piece inherit from `int8_t`, and C/C++ semantics require narrow integers to be promoted to `int` before doing arithmetic on them). Additionally, by removing the special usage of `offsets[][64]` and `[65]` the indexing becomes more efficient. (This usage was a temporary hack from sscg anyway, so I think he'll like that it's gone.) Finally, the `sf_assume` condition was fixed so that it actually makes a difference to the compiler. The speedup is fairly nice locally (combining both ces42's and these changes): ``` Result of 100 runs ================== base (...kfish.master) = 1691982 +/- 1907 test (./stockfish ) = 1714349 +/- 1789 diff = +22367 +/- 2465 speedup = +0.0132 P(speedup > 0) = 1.0000 ``` closes https://github.com/official-stockfish/Stockfish/pull/6445 No functional change
This commit is contained in:
committed by
Disservin
parent
93f2d14d95
commit
f4244e13e4
@@ -32,7 +32,12 @@
|
|||||||
namespace Stockfish::Eval::NNUE::Features {
|
namespace Stockfish::Eval::NNUE::Features {
|
||||||
|
|
||||||
// Lookup array for indexing threats
|
// Lookup array for indexing threats
|
||||||
IndexType offsets[PIECE_NB][SQUARE_NB + 2];
|
IndexType offsets[PIECE_NB][SQUARE_NB];
|
||||||
|
|
||||||
|
struct HelperOffsets {
|
||||||
|
int cumulativePieceOffset, cumulativeOffset;
|
||||||
|
};
|
||||||
|
std::array<HelperOffsets, PIECE_NB> helper_offsets;
|
||||||
|
|
||||||
// Information on a particular pair of pieces and whether they should be excluded
|
// Information on a particular pair of pieces and whether they should be excluded
|
||||||
struct PiecePairData {
|
struct PiecePairData {
|
||||||
@@ -69,9 +74,9 @@ static void init_index_luts() {
|
|||||||
|
|
||||||
int map = FullThreats::map[attackerType - 1][attackedType - 1];
|
int map = FullThreats::map[attackerType - 1][attackedType - 1];
|
||||||
bool semi_excluded = attackerType == attackedType && (enemy || attackerType != PAWN);
|
bool semi_excluded = attackerType == attackedType && (enemy || attackerType != PAWN);
|
||||||
IndexType feature = offsets[attacker][65]
|
IndexType feature = helper_offsets[attacker].cumulativeOffset
|
||||||
+ (color_of(attacked) * (numValidTargets[attacker] / 2) + map)
|
+ (color_of(attacked) * (numValidTargets[attacker] / 2) + map)
|
||||||
* offsets[attacker][64];
|
* helper_offsets[attacker].cumulativePieceOffset;
|
||||||
|
|
||||||
bool excluded = map < 0;
|
bool excluded = map < 0;
|
||||||
index_lut1[attacker][attacked] = PiecePairData(excluded, semi_excluded, feature);
|
index_lut1[attacker][attacked] = PiecePairData(excluded, semi_excluded, feature);
|
||||||
@@ -116,8 +121,7 @@ void init_threat_offsets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offsets[pieceIdx][64] = cumulativePieceOffset;
|
helper_offsets[pieceIdx] = {cumulativePieceOffset, cumulativeOffset};
|
||||||
offsets[pieceIdx][65] = cumulativeOffset;
|
|
||||||
|
|
||||||
cumulativeOffset += numValidTargets[pieceIdx] * cumulativePieceOffset;
|
cumulativeOffset += numValidTargets[pieceIdx] * cumulativePieceOffset;
|
||||||
}
|
}
|
||||||
@@ -128,32 +132,30 @@ void init_threat_offsets() {
|
|||||||
// Index of a feature for a given king position and another piece on some square
|
// Index of a feature for a given king position and another piece on some square
|
||||||
inline sf_always_inline IndexType FullThreats::make_index(
|
inline sf_always_inline IndexType FullThreats::make_index(
|
||||||
Color perspective, Piece attacker, Square from, Square to, Piece attacked, Square ksq) {
|
Color perspective, Piece attacker, Square from, Square to, Piece attacked, Square ksq) {
|
||||||
const int orientation = OrientTBL[perspective][ksq];
|
const std::int8_t orientation = OrientTBL[ksq] ^ (56 * perspective);
|
||||||
from = Square(int(from) ^ orientation);
|
unsigned from_oriented = uint8_t(from) ^ orientation;
|
||||||
to = Square(int(to) ^ orientation);
|
unsigned to_oriented = uint8_t(to) ^ orientation;
|
||||||
|
|
||||||
std::int8_t swap = 8 * perspective;
|
std::int8_t swap = 8 * perspective;
|
||||||
attacker = Piece(attacker ^ swap);
|
unsigned attacker_oriented = attacker ^ swap;
|
||||||
attacked = Piece(attacked ^ swap);
|
unsigned attacked_oriented = attacked ^ swap;
|
||||||
|
|
||||||
const auto piecePairData = index_lut1[attacker][attacked];
|
const auto piecePairData = index_lut1[attacker_oriented][attacked_oriented];
|
||||||
|
|
||||||
const bool less_than = static_cast<unsigned>(from) < static_cast<unsigned>(to);
|
const bool less_than = from_oriented < to_oriented;
|
||||||
if ((piecePairData.excluded_pair_info() + less_than) & 2)
|
if ((piecePairData.excluded_pair_info() + less_than) & 2)
|
||||||
return FullThreats::Dimensions;
|
return FullThreats::Dimensions;
|
||||||
|
|
||||||
const IndexType index =
|
const IndexType index = piecePairData.feature_index_base()
|
||||||
piecePairData.feature_index_base() + offsets[attacker][from] + index_lut2[attacker][from][to];
|
+ offsets[attacker_oriented][from_oriented]
|
||||||
|
+ index_lut2[attacker_oriented][from_oriented][to_oriented];
|
||||||
sf_assume(index != FullThreats::Dimensions);
|
sf_assume(index < Dimensions);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a list of indices for active features in ascending order
|
// Get a list of indices for active features in ascending order
|
||||||
|
|
||||||
void FullThreats::append_active_indices(Color perspective, 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);
|
Square ksq = pos.square<KING>(perspective);
|
||||||
Bitboard occupied = pos.pieces();
|
Bitboard occupied = pos.pieces();
|
||||||
|
|
||||||
@@ -161,7 +163,7 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos,
|
|||||||
{
|
{
|
||||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||||
{
|
{
|
||||||
Color c = order[perspective][color];
|
Color c = Color(perspective ^ color);
|
||||||
Piece attacker = make_piece(c, pt);
|
Piece attacker = make_piece(c, pt);
|
||||||
Bitboard bb = pos.pieces(c, pt);
|
Bitboard bb = pos.pieces(c, pt);
|
||||||
|
|
||||||
@@ -268,16 +270,16 @@ void FullThreats::append_changed_indices(Color perspective,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const IndexType index = make_index(perspective, attacker, from, to, attacked, ksq);
|
auto& insert = add ? added : removed;
|
||||||
|
const IndexType index = make_index(perspective, attacker, from, to, attacked, ksq);
|
||||||
|
|
||||||
if (index < Dimensions)
|
if (index < Dimensions)
|
||||||
(add ? added : removed).push_back(index);
|
insert.push_back(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FullThreats::requires_refresh(const DiffType& diff, Color perspective) {
|
bool FullThreats::requires_refresh(const DiffType& diff, Color perspective) {
|
||||||
return perspective == diff.us
|
return perspective == diff.us && (int8_t(diff.ksq) & 0b100) != (int8_t(diff.prevKsq) & 0b100);
|
||||||
&& OrientTBL[diff.us][diff.ksq] != OrientTBL[diff.us][diff.prevKsq];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Stockfish::Eval::NNUE::Features
|
} // namespace Stockfish::Eval::NNUE::Features
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ namespace Stockfish::Eval::NNUE::Features {
|
|||||||
|
|
||||||
static constexpr int numValidTargets[PIECE_NB] = {0, 6, 12, 10, 10, 12, 8, 0,
|
static constexpr int numValidTargets[PIECE_NB] = {0, 6, 12, 10, 10, 12, 8, 0,
|
||||||
0, 6, 12, 10, 10, 12, 8, 0};
|
0, 6, 12, 10, 10, 12, 8, 0};
|
||||||
extern IndexType offsets[PIECE_NB][SQUARE_NB + 2];
|
|
||||||
void init_threat_offsets();
|
void init_threat_offsets();
|
||||||
|
|
||||||
class FullThreats {
|
class FullThreats {
|
||||||
@@ -48,23 +47,15 @@ class FullThreats {
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
// Orient a square according to perspective (rotates by 180 for black)
|
// Orient a square according to perspective (rotates by 180 for black)
|
||||||
static constexpr int OrientTBL[COLOR_NB][SQUARE_NB] = {
|
static constexpr std::int8_t OrientTBL[SQUARE_NB] = {
|
||||||
{ SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
|
||||||
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1 },
|
|
||||||
{ SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8,
|
|
||||||
SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8,
|
|
||||||
SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8,
|
|
||||||
SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8,
|
|
||||||
SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8,
|
|
||||||
SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8,
|
|
||||||
SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8,
|
|
||||||
SQ_A8, SQ_A8, SQ_A8, SQ_A8, SQ_H8, SQ_H8, SQ_H8, SQ_H8 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int map[PIECE_TYPE_NB-2][PIECE_TYPE_NB-2] = {
|
static constexpr int map[PIECE_TYPE_NB-2][PIECE_TYPE_NB-2] = {
|
||||||
|
|||||||
+2
-6
@@ -295,18 +295,14 @@ struct DirtyPiece {
|
|||||||
struct DirtyThreat {
|
struct DirtyThreat {
|
||||||
DirtyThreat() { /* don't initialize data */ }
|
DirtyThreat() { /* don't initialize data */ }
|
||||||
DirtyThreat(Piece pc, Piece threatened_pc, Square pc_sq, Square threatened_sq, bool add) {
|
DirtyThreat(Piece pc, Piece threatened_pc, Square pc_sq, Square threatened_sq, bool add) {
|
||||||
data = (add << 28) | (pc << 20) | (threatened_pc << 16) | (threatened_sq << 8) | (pc_sq);
|
data = (add << 31) | (pc << 20) | (threatened_pc << 16) | (threatened_sq << 8) | (pc_sq);
|
||||||
}
|
}
|
||||||
|
|
||||||
Piece pc() const { return static_cast<Piece>(data >> 20 & 0xf); }
|
Piece pc() const { return static_cast<Piece>(data >> 20 & 0xf); }
|
||||||
Piece threatened_pc() const { return static_cast<Piece>(data >> 16 & 0xf); }
|
Piece threatened_pc() const { return static_cast<Piece>(data >> 16 & 0xf); }
|
||||||
Square threatened_sq() const { return static_cast<Square>(data >> 8 & 0xff); }
|
Square threatened_sq() const { return static_cast<Square>(data >> 8 & 0xff); }
|
||||||
Square pc_sq() const { return static_cast<Square>(data & 0xff); }
|
Square pc_sq() const { return static_cast<Square>(data & 0xff); }
|
||||||
bool add() const {
|
bool add() const { return data >> 31; }
|
||||||
uint32_t b = data >> 28;
|
|
||||||
sf_assume(b == 0 || b == 1);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|||||||
Reference in New Issue
Block a user