From df01cb7ed3c92ec65a0a8d8c6ed870bc664c27bb Mon Sep 17 00:00:00 2001 From: Carlos Esparza Date: Thu, 9 Apr 2026 21:44:44 +0200 Subject: [PATCH] Avoid branching before `ValueList::push_back` Instead of checking whether a threat index is valid and then writing to a vector if it isn't, we can instead always write to the buffer of the vector, and only increase the size of the vector if the index is valid. This saves some branch mispredictions. passed STC: https://tests.stockfishchess.org/tests/view/69ceb1689f7a7e3fdfc9a44b LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 205760 W: 53109 L: 52561 D: 100090 Ptnml(0-2): 603, 22552, 56076, 22992, 657 local speedtest shows ``` Result of 100 runs (cycles) =========================== base (...ockfish.orig) = 296886 +/- 1645 test (...kfish.df0822) = 298862 +/- 1662 speedup % = +0.67 +/- 0.19 [95% CI; t-statistic] p(speedup > 0) = 1.0000 p(speedup > .5%) = 0.9562 CPU: 16 x Intel(R) Core(TM) Ultra 9 185H Hyperthreading: on ``` closes https://github.com/official-stockfish/Stockfish/pull/6703 No functional change --- src/misc.h | 6 ++++++ src/nnue/features/full_threats.cpp | 24 ++++++++---------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/misc.h b/src/misc.h index d1c368fdd..d69f7ef38 100644 --- a/src/misc.h +++ b/src/misc.h @@ -201,6 +201,12 @@ class ValueList { assert(size_ < MaxSize); values_[size_++] = value; } + // pushes back value if value < max + void push_back_if_lt(const T& value, const T& max) { + assert(size_ < MaxSize); + values_[size_] = value; + size_ += (value < max); + } const T* begin() const { return values_; } const T* end() const { return values_ + size_; } const T& operator[](int index) const { return values_[index]; } diff --git a/src/nnue/features/full_threats.cpp b/src/nnue/features/full_threats.cpp index 6cae5d0ed..a62a664e0 100644 --- a/src/nnue/features/full_threats.cpp +++ b/src/nnue/features/full_threats.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -236,8 +235,7 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos, Piece attacked = pos.piece_on(to); IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); - if (index < Dimensions) - active.push_back(index); + active.push_back_if_lt(index, Dimensions); } while (attacks_right) @@ -247,8 +245,7 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos, Piece attacked = pos.piece_on(to); IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); - if (index < Dimensions) - active.push_back(index); + active.push_back_if_lt(index, Dimensions); } // Set of pawns which are prevented from movement by a pawn in front of them @@ -261,8 +258,7 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos, assert(type_of(attacked) == PAWN); IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); - if (index < Dimensions) - active.push_back(index); + active.push_back_if_lt(index, Dimensions); } } else @@ -279,8 +275,7 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos, IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); - if (index < Dimensions) - active.push_back(index); + active.push_back_if_lt(index, Dimensions); } } } @@ -342,13 +337,10 @@ void FullThreats::append_changed_indices(Color perspective, auto& insert = add ? added : removed; const IndexType index = make_index(perspective, attacker, from, to, attacked, ksq); - if (index < Dimensions) - { - if (prefetchBase) - prefetch( - prefetchBase + static_cast(index) * prefetchStride); - insert.push_back(index); - } + if (prefetchBase) + prefetch(reinterpret_cast( + reinterpret_cast(prefetchBase) + index * prefetchStride)); + insert.push_back_if_lt(index, Dimensions); } }