Skip to content

High-throughput search and position hot-path optimization - #26

Merged
KnightStackSys merged 22 commits into
mainfrom
nps-performance
Oct 12, 2026
Merged

KnightStackSys merged 22 commits into
mainfrom
nps-performance

Conversation

@KnightStackSys

@KnightStackSys KnightStackSys commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Performance-only branch from current main focused on NPS and hot-path cost.

Search hot paths

  • throttle wall-clock polling to every ~1024 nodes instead of repeatedly per move
  • defer partner-in-check detection and HCE evaluation until NMP is otherwise eligible
  • generate tactical qsearch moves directly instead of generating all moves then filtering/copying
  • remove unused/repeated qsearch check calculations
  • merge quiet/capture failure scratch storage into one buffer
  • avoid value-initializing large per-node scratch arrays
  • at non-PV nodes, avoid sorting the entire move list; score cheaply and lazily select only the strongest first 16 moves as the search actually asks for them
  • defer non-PV givesCheck() work until a move is actually considered instead of evaluating check status for the whole move list up front
  • preserve the existing full-ordering path at PV nodes

Faster capture ordering

  • remove full four-player SEE from the move-ordering score for every generated capture
  • use cheap MVV/LVA plus capture history for capture and promotion ordering
  • keep SEE where it affects actual search decisions (seeGE pruning)
  • avoid pointless givesCheck() calls for captures/promotions when their ordering score does not consume the check bonus

Move generation / storage

  • make plain Move scratch buffers trivially default-initialized while preserving Move{} as the null move
  • avoid clearing the 512-entry MoveList backing array at construction
  • add direct capture/promotion/en-passant tactical generation for qsearch

14-bit compact sliding attacks

  • maintain compact occupancy for every rank, file and both diagonal families inside Position
  • use one universal 14 x 2^14 attack-mask table
  • expand 14-bit attack masks back to the 3x64 board through two 7-bit lookup tables
  • encode missing cross-board corner cells as permanent blockers, preventing diagonal attacks from jumping across board holes
  • use compact lookup attacks for normal move generation, tactical move generation, HCE mobility and current-position king/check detection
  • keep the original ray attack implementation for hypothetical occupancies used by SEE, givesCheck() and castling safety
  • randomized property tests cross-check lookup attacks against the original ray implementation before/after make, undo and null moves
  • benchmark reports ray vs compact-line queen attack throughput directly

Position / board hot paths

  • combine both enemy colors into a single slider attack calculation for arbitrary-occupancy isAttackedByEnemy / attackersToEnemy
  • fast-path castling-right updates for the common case where no king/rook is involved
  • skip unchanged castling/alive-state Zobrist work
  • use no-Zobrist/no-king-state board primitives during undo, then restore reversible state from StateInfo

SEE / TT hot paths

  • avoid zeroing the full SEE gain array on every invocation
  • use the captured piece already encoded in generated moves instead of rediscovering it from the board
  • avoid unnecessary capture-square lookup for normal SEE captures
  • stop clearing/default-initializing TTProbe output on every probe/miss; callers use the returned hit boolean

No pruning thresholds, LMR/NMP parameters, evaluation weights, or move legality rules are intentionally changed. Timer polling is intentionally coarser by up to roughly 1024 searched nodes.

The newest move-ordering changes are intentionally more aggressive and may alter node count/Elo, so benchmark both raw NPS and time-to-depth, then run an SPRT before merge.

@KnightStackSys

Copy link
Copy Markdown
Owner Author

This PR significantly improves IronPhoenix's search throughput through compact 14-bit sliding attack tables, faster move generation, reduced search overhead, cheaper capture ordering, lazy non-PV move picking, optimized SEE/TT hot paths, and faster make/undo operations.

@KnightStackSys
KnightStackSys marked this pull request as ready for review October 12, 2026 16:54
@KnightStackSys
KnightStackSys merged commit 3c85e50 into main Oct 12, 2026
2 checks passed
@KnightStackSys
KnightStackSys deleted the nps-performance branch October 12, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant