Update nnue architecture to SFNNv16 and net nn-89cb98a217f7.nnue

Failed STC (https://tests.stockfishchess.org/tests/view/6a4f36355529b8472df7ff7e):
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 144768 W: 38003 L: 38051 D: 68714
Ptnml(0-2): 521, 17154, 37050, 17170, 489

Passed LTC (https://tests.stockfishchess.org/tests/view/6a501dad5529b8472df80103):
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 189888 W: 49613 L: 48984 D: 91291
Ptnml(0-2): 122, 20406, 53256, 21041, 119

Passed VLTC (https://tests.stockfishchess.org/tests/view/6a52892c5529b8472df80481):
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 46124 W: 12156 L: 11865 D: 22103
Ptnml(0-2): 12, 4523, 13696, 4824, 7

Passed VVLTC (https://tests.stockfishchess.org/tests/view/6a566a285529b8472df80b84):
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 44698 W: 11805 L: 11507 D: 21386
Ptnml(0-2): 9, 3819, 14395, 4117, 9

This PR adds pawn pair features, a new set of features that is indexed by pairs of pawns occupying the same or adjacent files (hence "3-wide"). Because these are a superset of pawn–pawn interactions in threat inputs (including the recently added pawn-pusher inputs), those are removed. HalfKA features remain unchanged.

Pawn-pair features were invented by Jonathan for Pawnocchio, based on his observation that in a net trained on *all* pairs of pawns, the most important pawn pairs were those differing by at most one file.

sscg13 made the necessary changes to the trainer (https://github.com/official-stockfish/nnue-pytorch/pull/502) and initial changes to inference. The slowdown was originally far too large (some 10%); following major optimizations from Jonathan and a bit from me, the slowdown is small enough for a comfortable LTC pass; on my machine I get a 3.5% slowdown overall. I expect there are further "easy" speedups in the new code, so this gap should narrow a bit.

Nettest PR: https://github.com/vondele/nettest/pull/359

closes https://github.com/official-stockfish/Stockfish/pull/6982

Bench: 2718396

Co-Authored-By: anematode <timothy.herchen@gmail.com>
Co-Authored-By: Jonathan Hallström <lmj.hallstrom@gmail.com>
This commit is contained in:
sscg13
2026-07-20 11:06:41 +02:00
committed by Joost VandeVondele
co-authored by anematode Jonathan Hallström
parent 4d75fd4f70
commit f4bcd40409
16 changed files with 440 additions and 135 deletions
+14 -23
View File
@@ -817,8 +817,7 @@ bool Position::gives_check(Move m) const {
void Position::do_move(Move m,
StateInfo& newSt,
bool givesCheck,
DirtyPiece& dp,
DirtyThreats& dts,
Dirties& dirties,
const TranspositionTable* tt = nullptr,
const SharedHistories* history = nullptr) {
@@ -840,6 +839,13 @@ void Position::do_move(Move m,
++st->rule50;
++st->pliesFromNull;
auto& dpps = dirties.dirtyPawnPairs;
auto& dts = dirties.dirtyThreats;
auto& dp = dirties.dirtyPiece;
dpps.before[WHITE] = pieces(WHITE, PAWN);
dpps.before[BLACK] = pieces(BLACK, PAWN);
Color us = sideToMove;
Color them = ~us;
Square from = m.from_sq();
@@ -1065,6 +1071,9 @@ void Position::do_move(Move m,
assert(pos_is_ok());
dpps.after[WHITE] = pieces(WHITE, PAWN);
dpps.after[BLACK] = pieces(BLACK, PAWN);
assert(dp.pc != NO_PIECE);
assert(!(bool(captured) || m.type_of() == CASTLING) ^ (dp.remove_sq != SQ_NONE));
assert(dp.from != SQ_NONE);
@@ -1238,32 +1247,14 @@ void Position::update_piece_threats(Piece pc,
Bitboard threatened = attacks_bb(pc, s, occupied) & occupiedNoK;
Bitboard incoming_threats = PseudoAttacks[KNIGHT][s] & knights;
// Compute both incoming and outgoing pawn threats. Incoming pawn pushers are only
// added if 'pc' is a pawn.
Bitboard pawnThreats = 0;
if (type_of(pc) == PAWN)
{
Bitboard whiteAttacks = PawnPushOrAttacks[WHITE][s];
Bitboard blackAttacks = PawnPushOrAttacks[BLACK][s];
threatened |= (color_of(pc) == WHITE ? whiteAttacks : blackAttacks) & pieces(PAWN);
pawnThreats = whiteAttacks & blackPawns;
pawnThreats |= blackAttacks & whitePawns;
}
else
{
pawnThreats =
if (type_of(pc) == KNIGHT || type_of(pc) == ROOK)
incoming_threats |=
(attacks_bb<PAWN>(s, WHITE) & blackPawns) | (attacks_bb<PAWN>(s, BLACK) & whitePawns);
}
if (type_of(pc) == PAWN || type_of(pc) == KNIGHT || type_of(pc) == ROOK)
incoming_threats |= pawnThreats;
switch (type_of(pc))
{
case PAWN :
threatened &= pieces(PAWN, KNIGHT, ROOK);
threatened &= pieces(KNIGHT, ROOK);
break;
case BISHOP :
case ROOK :