Skip to content

v1.0.51

Choose a tag to compare

@github-actions github-actions released this 02 Aug 14:19
· 14 commits to main since this release

A speed release. The search is unchanged in almost every respect — it explores the same tree and reaches the same conclusions — it simply does so about 20% faster on a modern CPU. Two correctness fixes ride along.

Strength

~+30 Elo over v1.0.50, measured over 300 games at 30–45s + 0.5–1.0s increment.

Pairing W–L–D Elo
v1.0.51-rc1 vs v1.0.50 (match A) +34 −20 =46 +49 ±35
v1.0.51-rc1 vs v1.0.50 (match B) +32 −29 =39 +10 ±35
v1.0.51-rc2 vs v1.0.50 +32 −23 =45 +31 ±35
Pooled, 300 games 163.0/300 +30 ±20

The two rc1 measurements disagree sharply (+49 vs +10) despite being the same binaries at the same time control. Neither is wrong — that is what a ±35 error bar looks like at 100 games, and it is the reason the pooled figure is quoted rather than the best one. Pooling is legitimate here because the release candidates differ only by changes that leave the search tree identical.

+30 also happens to be what theory predicts from a ~22% speed gain, which is mild corroboration rather than coincidence.

Faster: the NNUE accumulator update

Every evaluated node updates the incrementally-maintained NNUE accumulator. That used to mean three or more full passes over a 1 KB structure: clone the parent, then one read-modify-write pass per changed feature. It is now a single fused pass that computes the child directly from the parent, with specialised kernels for the three shapes that actually occur (quiet move, capture, castling).

Asset v1.0.50 v1.0.51
-avx2 ~1.95M NPS ~2.38M NPS (+22%)
unsuffixed x86_64 ~1.97M NPS ~2.08M NPS (+5.7%)

Note the v1.0.50 column: baseline and AVX2 were the same speed. Before this change the engine got no benefit from AVX2 at all, because nothing in the hot path vectorised enough to use it. The fused loop is what unlocks the wide registers, which is why the gain is so lopsided between the two builds.

Three smaller speed changes are included on the same principle — the quiescence search no longer evaluates positions whose score it provably discards, losing captures are rejected before the move is made rather than after, and check status is passed from parent to child instead of recomputed. Each was verified to leave the fixed-depth node count bit-identical.

Portability: the default download was crippled

The unsuffixed linux-x86_64 and windows-x86_64 assets were compiled for plain x86-64 — no POPCNT, no SSE4, no AVX. They are now built for x86-64-v2 (SSE4.2 + POPCNT), which has been universal since 2008 and remains portable for any realistic user.

If your CPU is Haswell (2013) or later, download the -avx2 build: on this release it is roughly 15% faster again than the v2 baseline.

Correctness

KBB-vs-K and KBN-vs-K were scored as draws. insufficient_material derived its minor-piece count from the bishop bitboards only, and the surviving condition was unconditionally true for any pawnless four-man position — so two bishops, or bishop and knight, against a lone king all evaluated as insufficient material. Since the draw check runs at every node past ply 6 and a bishop+knight mate takes around 33 moves, no mate was ever findable inside the horizon. The engine could not convert those endings, and would trade into them a piece down believing the result was drawn. Now decided by per-side material: two knights remain a draw, bishop pair and bishop+knight do not.

Measured at depth 12: KBN-vs-K went from cp 0 to cp 67, KBB-vs-K from cp 0 to cp 198.

Known gaps

  • The KBB/KBN scores above are modest because the network itself undervalues those endings. Removing the false draw is a precondition for converting them, not a complete solution.
  • The singular-extension fix that was prepared for this release is not included. It works — it reduces depth-14 node counts by 1.5% — but it also causes the search to overrun its soft time limit (2.1× versus a 2× budget) because the extension activates abruptly at depth 13 and the time manager's linear cost prediction cannot anticipate the jump. That is the failure class that caused time forfeits in v1.0.48, so it is held back until paired with a mid-iteration time guard.
  • No per-change Elo measurement exists. At 100 games per pairing the resolution is roughly ±35 Elo, which cannot separate individual changes of this size; the pooled 300-game figure above is the only strength claim made here.