Commit Graph
30 Commits
Author SHA1 Message Date
anematodeandDisservin 8132dbcb5a split affine_transform on VNNI as well
```
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 184544 W: 47990 L: 47474 D: 89080
Ptnml(0-2): 551, 20238, 50206, 20698, 579
```

Torom measured

```
sf_base =  2538696 +/-   2915 (95%)
sf_test =  2546510 +/-   3011 (95%)
diff    =     7814 +/-   4146 (95%)
speedup = 0.30782% +/- 0.163% (95%)
```

I get something similar. The benefit would be larger if we ever decide
to further increase the L2 size I think

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

No functional change
2026-04-02 20:30:33 +02:00
anematodeandDisservin d173a0655d Speedup splat_moves on avx512icl
STC
```
LLR: 5.45 (-2.94,2.94) <0.00,2.00>
Total: 612192 W: 158602 L: 157260 D: 296330
Ptnml(0-2): 1634, 67783, 166027, 68911, 1741
```

@Torom measured:
```
sf_base =  2380902 +/-   1016 (95%)
sf_test =  2391426 +/-   1065 (95%)
diff    =    10524 +/-   1336 (95%)
speedup = 0.44203% +/- 0.056% (95%)
```

I've verified that `_mm512_slli_epi16(v, 0)` gets optimized out in GCC
9+ and clang 4+. Added constants to types.h so that people messing
around with the layout of `Move` don't have to know about this part of
the code.

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

No functional change
2026-03-18 20:49:20 +01:00
anematodeandJoost VandeVondele b3a810a1c4 Fix avx512icl update_piece_threats bug
Thanks to MinetaS for discovering this and finding the culprit commit,
specific to this architecture. 9f42980 was subtly incorrect, leading to
spurious wrong benches on avx512icl. Because this piece of code has twice been
the source of wrong benches, I also added a brief comment explaining why it
needs to be this way, and added a sample position to bench.

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

Bench: 2288704
2026-03-07 22:28:06 +01:00
anematodeandJoost VandeVondele 4c0878cb0b skip setting threatByLesser[KING]
It doesn't make sense for a king to move to a square threatened by a lesser
piece, since that move would be illegal.

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

No functional change
2026-02-28 12:07:38 +01:00
anematodeandJoost VandeVondele b808fd3d55 avoid modify_and_replicate for first load
We call modify_and_replicate in load_networks, but this is quite inefficient.

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

No functional change
2026-02-13 07:06:33 +01:00
anematodeandJoost VandeVondele 0d26c61ff2 fix return type of vmovl_high_s8
also add -flax-vector-conversions=none to the build

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

No functional change
2026-02-04 17:32:48 +01:00
anematodeandDisservin 253aaefbc0 Fix compilation on BSD/macOS
fixes github.com/official-stockfish/Stockfish/issues/6571

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

No functional change
2026-01-28 20:28:27 +01:00
anematodeandJoost VandeVondele c0f245303b Make PGO builds deterministic again
some environment dependent execution (e.g. pid) were being std::hash'ed, and
net filenames put in unordered maps.  Also uses sprintf instead of
std::to_string.  Depending on precise content, this could lead to different
PGO'ed binaries. This is mitigated by using a basic hash function.

This also fixes a potential issue in net filename generation, in cases where
std::hash would use invocation dependent salt, which is not the cases today for
typical std libraries.

Closes https://github.com/official-stockfish/Stockfish/pull/6562

No functional change
2026-01-22 19:15:17 +01:00
anematodeandJoost VandeVondele f61d4317a3 use default signal handler after cleanup
With the current setup, on Linux, SIGILL (and SIGSEGV/SIGBUS etc., in the case
of a program bug) lead to no feedback if they occur after the signal handlers
are installed, they just exit silently. By invoking the default signal handler,
we can still get the appropriate feedback. This is particularly important for
feedback if someone downloads the wrong SF binary and runs it on Linux.

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

No functional change
2026-01-18 08:53:06 +01:00
anematodeandJoost VandeVondele 5b8b304ebd Skip munmap when exiting via a signal
avoid munmap of memory when exiting via signal, which avoids side effects such
as triggering asserts or (caught) segfaults while the process exists.

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

No functional change
2026-01-15 22:17:14 +01:00
Timothy HerchenandJoost VandeVondele eb5a65aeb0 Fix RelationCache on Windows 10 compiles
Windows 10 is missing the GroupMasks and GroupCount members, this breaks compiles on Windows 10.
Windows 11 builds, including the official ones, run fine on Windows 10/11.
To support developers/testers on Windows 10, fallback conditionally to the Windows 10 struct definition.

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

No functional change
2026-01-11 09:13:37 +01:00
anematodeandJoost VandeVondele b4d4eecfb2 Make shared history allocation aware of non-uniform cache access
Although shared history has been successful overall, it led to some speed
issues with large numbers of threads. Originally we just split by NUMA node,
but on systems with non-unified L3 caches (most AMD workstation and server
CPUs, and some Intel E-core based server CPUs), this can still lead to a speed
penalty at the default config. Thus, we decided to further subdivide the shared
history based on the L3 cache structure.

Based on this test, the original SPRTs, and speed experiments, we decided that
grouping L3 domains to reach 32 threads per SharedHistories was a reasonable
balance for affected systems – but we may revisit this in the future. See the
PR for full details.

In an extreme case, a single-socket EPYC 9755 configured with 1 numa domain per socket,
the nps increases from:
Nodes/second               : 182827480
to
Nodes/second               : 229118365

In many cases, when L3 caches are shared between many threads, or when several
numa nodes are already configured per socket, this patch does not influence the
default. This default setting can adjusted with the existing NumaPolicy option.

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

No functional change.
2026-01-10 15:46:01 +01:00
anematodeandJoost VandeVondele 8be6b14218 Network loading refactoring
closes https://github.com/official-stockfish/Stockfish/pull/6523

No functional change
2026-01-06 12:02:37 +01:00
anematodeandJoost VandeVondele 593eeaf24c simplify find_nnz a bit
This code path is never taken for vector sizes >= 512, so we can simplify it.

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

No functional change
2026-01-01 16:08:03 +01:00
anematodeandJoost VandeVondele aeb3bf33a9 port get_changed_pieces to ARM NEON
passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 71968 W: 18833 L: 18489 D: 34646
Ptnml(0-2): 192, 7310, 20643, 7640, 199
https://tests.stockfishchess.org/tests/view/69509e5c572093c1986d7a0a

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

No functional change
2026-01-01 16:04:43 +01:00
Timothy HerchenandDisservin 44d5467bbe Remove -Wstack-usage on (apple) clang
Clang pretends to be GCC, but is enraged by `-Wstack-usage`:

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

No functional change
2025-12-28 14:59:26 +01:00
969285fa5d Shared pawn history
[Passed STC SMP](https://tests.stockfishchess.org/tests/view/694e506c572093c1986d7276):
```
LLR: 2.97 (-2.94,2.94) <0.00,2.00>
Total: 14992 W: 3924 L: 3653 D: 7415
Ptnml(0-2): 20, 1547, 4090, 1820, 19
```

[Passed LTC SMP](https://tests.stockfishchess.org/tests/live_elo/694ead61572093c1986d7365):
```
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 41146 W: 10654 L: 10342 D: 20150
Ptnml(0-2): 17, 3999, 12225, 4319, 13
```

[Passed a sanity check STC SMP post-refactoring](https://tests.stockfishchess.org/tests/view/69503997572093c1986d763a):
```
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 46728 W: 12178 L: 11863 D: 22687
Ptnml(0-2): 82, 5093, 12685, 5436, 68
```

(The large gain of the first STC was probably a fluke, and this result
is more reasonable!)

After shared correction history, Viz suggested we try sharing other
histories, especially `pawnHistory`. As far as we're aware, sharing
history besides correction history (like Caissa does) is novel. The
implementation follows the same pattern as shared correction history –
the size of the history table is scaled with
`next_power_of_two(threadsInNumaNode)` and the entry is prefetched in
`do_move`.

A bit of refactoring was done to accommodate this new history. Note that
we prefetch `&history->pawn_entry(*this)[pc][to]` rather than
`&history->pawn_entry(*this)` because unlike the other entries, each
entry contains multiple cache lines.

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

Bench: 2503391

Co-authored-by: Michael Chaly <Vizvezdenec@gmail.com>
2025-12-28 14:59:09 +01:00
anematodeandDisservin 1a67ccc72e Share correction history between threads
We did quite a few tests because this is a pretty involved change with
unknown scaling behavior, but results are decent.

[STC 10+0.1 1th, non-regression](https://tests.stockfishchess.org/tests/live_elo/6941ce3b46f342e1ec210180)
```
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 83200 W: 21615 L: 21452 D: 40133
Ptnml(0-2): 247, 9064, 22844, 9169, 276
```

[STC 5+0.05 8th](https://tests.stockfishchess.org/tests/live_elo/693dc38346f342e1ec20f555)
```
LLR: 3.48 (-2.94,2.94) <0.00,2.00>
Total: 58536 W: 15067 L: 14688 D: 28781
Ptnml(0-2): 87, 6474, 15781, 6825, 101
```

[LTC 20+0.2 8th](https://tests.stockfishchess.org/tests/live_elo/693f2afb46f342e1ec20f847)
```
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 27716 W: 7211 L: 6925 D: 13580
Ptnml(0-2): 8, 2674, 8207, 2962, 7
```

[LTC 10+0.1 64th](https://tests.stockfishchess.org/tests/live_elo/694003aa46f342e1ec20fac4):
```
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 16918 W: 4439 L: 4182 D: 8297
Ptnml(0-2): 3, 1493, 5213, 1744, 6
```

[NUMA test, 5+0.05 256th](https://tests.stockfishchess.org/tests/view/6941ee4e46f342e1ec210203)
```
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 7124 W: 1910 L: 1678 D: 3536
Ptnml(0-2): 0, 560, 2211, 790, 1
```

[LTC 60+0.6 64th](https://tests.stockfishchess.org/tests/live_elo/6940a85346f342e1ec20fcde):
```
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 15504 W: 4045 L: 3826 D: 7633
Ptnml(0-2): 0, 1002, 5530, 1219, 1
```

Bonus (courtesy of Viz): The 1 double kill in this last test was master
blundering a cool mate in 3: https://lichess.org/jyNZuRl4

Basically the idea here is to share correction history between threads.
That way, T1 can use the correction values produced by T2, which already
searched positions with that pawn structure etc., so that T1 can search
more efficiently. The table size per thread is about the same, so we
shouldn't get a large increase in hash collisions; in fact, I'd expect a
lower collision rate overall.

Although I came up with and implemented the idea independently,
[Caissa](https://github.com/Witek902/Caissa) was the first engine to
implement corrhist sharing (and corrhist in the first place) – this idea
is not completely novel.

The table size is rounded to a power of two. In particular, it's `65536
* nextPowerOfTwo(threadCount)`. That way, the indexing operation becomes
an AND of the key bits with a mask, rather than something more expensive
(e.g., a `mul_hi64`-style approach or a modulo).

The updates are racy, like the TT, but because `entry` is hoisted into a
register, there's no risk of writing back a value that's out of the
designated range `[-D, D]`. Various attempts at rewriting using atomics
led to substantial slowdowns, so we begrudgingly ignored the functions
in thread sanitizer, but at some point we'd like to make this better.

We allocate one shared correction history per NUMA node, because the
penalty associated with crossing nodes is substantial – I get a 40% hit
with NPS=4 and 256 threads, which is intolerable. With separate tables
per NUMA node I get a 6% penalty for nodes per second, which isn't ideal
but apparently compensated for.

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

Bench: 2690604

Co-authored-by: Disservin <disservin.social@gmail.com>
2025-12-23 21:42:29 +01:00
Timothy HerchenandDisservin e0e6fdf094 Tweak nnue_accumulator indexing
```
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 92736 W: 24149 L: 23764 D: 44823
Ptnml(0-2): 280, 10056, 25334, 10395, 303
```

The use of `IndexType` in the loops is suboptimal because it requires
truncation to 32 bits, and thereby defeats some optimizations. Using
`size_t` for the loop body works nicely, and a signed index into the
index lists allows the compiler to assume the case `added.size() ==
UINT_MAX`, which would be an infinite loop, to not happen.

Passed STC
https://tests.stockfishchess.org/tests/live_elo/692fd98ab23dfeae38d01d98

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

No functional change
2025-12-21 15:43:32 +01:00
Timothy HerchenandDisservin a98c3f6878 Small threat-related cleanups
Remove a couple unused things, mark `noRaysContaining` as
`[[maybe_unused]]` (suggested by Viz) to silence a warning on GCC 10,
update a comment, and replace inline constants

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

No functional change
2025-12-21 15:43:32 +01:00
Timothy HerchenandJoost VandeVondele c109a88ebe fix missing condition
Fixes a bug in https://github.com/official-stockfish/Stockfish/pull/6453
https://github.com/official-stockfish/Stockfish/commit/abd835dcbc3a28481224f6253b00b7420d062513
The modifications to the DirtyThreats bitboards should only happen if PutPiece is true.
This somehow didn't affect bench at the default parameters.

Reference AVX2:
./stockfish.killdeer-fix.avx2 bench 64 1 23
Nodes searched  : 178140156
Nodes/second    : 1503152

before patch:
./stockfish.master.avx512icl  bench 64 1 23
Nodes searched  : 218349728
Nodes/second    : 1743450

after patch:
./stockfish.killdeer-fix.avx512icl bench 64 1 23
Nodes searched  : 178140156
Nodes/second    : 1727520

passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 39328 W: 10293 L: 10080 D: 18955
Ptnml(0-2): 113, 4306, 10629, 4487, 129
https://tests.stockfishchess.org/tests/view/692fb2d8b23dfeae38d01c81

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

Bench: 2912398
2025-12-03 12:32:29 +01:00
Timothy HerchenandJoost VandeVondele abd835dcbc Improve update_piece_threats
passed on avx512ICL:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 30240 W: 8026 L: 7726 D: 14488
Ptnml(0-2): 95, 3235, 8171, 3513, 106
https://tests.stockfishchess.org/tests/view/69281d9ab23dfeae38cfeeb8

passed on generic architectures:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 73184 W: 19183 L: 18821 D: 35180
Ptnml(0-2): 258, 7988, 19744, 8338, 264
https://tests.stockfishchess.org/tests/view/6928ba11b23dfeae38cff276

subsequent cleanups tested as:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 72480 W: 18678 L: 18502 D: 35300
Ptnml(0-2): 242, 7925, 19718, 8125, 230
https://tests.stockfishchess.org/tests/view/692a26adb23dfeae38cff566

We add an argument noRaysContaining, which skips all discoveries which contain
all bits in the argument; if the argument is from | to, then this will
eliminate the discovery. Separately, on AVX512ICL we can speed up the
computation of DirtyThreats by moving from a pop_lsb loop to a vector
extraction with vpcompressb. See PR for details.

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

No functional change
2025-12-01 17:26:50 +01:00
Timothy HerchenandDisservin 7c7c574e6b Fix msvc macro
closes https://github.com/official-stockfish/Stockfish/pull/6449

No functional change
2025-11-30 21:58:35 +01:00
Timothy HerchenandJoost VandeVondele b083049fe0 Use non-locking operations for nodes count and tbHits
fetch_add and friends must produce a locking instruction because they guarantee
consistency in the presence of multiple writers. Because only one thread ever
writes to nodes and tbHits, we may use relaxed load and store to emit regular
loads and stores (on both x86-64 and arm64), while avoiding undefined behavior
and miscounting nodes.

Credit must go to Arseniy Surkov of Reckless (codedeliveryservice) for
uncovering this performance gotcha.

failed yellow as a gainer on fishtest:
LLR: -2.95 (-2.94,2.94) <0.00,2.00>
Total: 219616 W: 57165 L: 57105 D: 105346
Ptnml(0-2): 732, 24277, 59720, 24357, 722
https://tests.stockfishchess.org/tests/view/69086abfea4b268f1fac2809

potential small speedup on large core system:
```
==== master ====
1 Nodes/second : 294269736
2 Nodes/second : 295217629
Average (over 2):  294743682
==== patch ====
1 Nodes/second : 299003603
2 Nodes/second : 298111320
Average (over 2):  298557461
```

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

No functional change
2025-11-17 13:24:32 +01:00
Timothy HerchenandJoost VandeVondele 229bd1e2e3 check for material key validity in tbprobe
During recent work on threat inputs, there was a hard-to-debug crash in tbprobe
caused by incorrectly computing st->materialKey. This PR adds correctness
checking to pos_is_ok and a faster check in tbprobe that will actually run in
CI (because pos_is_ok checking is disabled even in debug mode, for performance
purposes).

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

No functional change
2025-11-13 22:42:10 +01:00
Timothy HerchenandJoost VandeVondele fa4f05d3ef Don't copy around DirtyThreats
The contents of DirtyThreats gets memcpyed twice for each call to do_move.
(Return value optimization doesn't apply to the do_move function itself because
it constructs a std::pair, so it gets copied; and the calls to reset also
require a copy.) This patch inserts the dirty info in place.

Sometimes the caller of do_move ignores the DirtyThreats info, so we pass in
scratch objects. I found that stack-allocating these scratch objects was bad on
Fishtest, so I begrudgingly put them in the Position struct. Both templating
the do_move function on whether dirty threats are needed and putting a
null-check branch for each use of dirty threats were slowdowns locally. Of
course, nothing prevents a future attempt at cleaning this up.

passed STC
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 68448 W: 17770 L: 17418 D: 33260
Ptnml(0-2): 198, 7425, 18630, 7769, 202
https://tests.stockfishchess.org/tests/view/6914c01a7ca87818523318ba

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

No functional change
2025-11-13 22:17:03 +01:00
Timothy HerchenandJoost VandeVondele 6764561916 Improve index generation
The speedup seems to vary by machine.  The indexing function can be changed w/o needing to understand intrinsics.

Result of 100 runs
==================
base (...ish_baseline) =    1719637  +/- 3233
test (./stockfish    ) =    1734245  +/- 3534
diff                   =     +14608  +/- 4868

speedup        = +0.0085
P(speedup > 0) =  1.0000

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

No functional change
2025-11-01 10:42:42 +01:00
Timothy HerchenandJoost VandeVondele 3bb01ce7a9 prefetch earlier if checKEP is false
Only a modest amount of work happens between the transposition table prefetch
and the probe, so the probe still often stalls waiting for DRAM. The vast
majority of the time (in particular, if !checkEP), the key is known much
earlier in the do_move function and the latency can be better hidden.

passed STC SMP
https://tests.stockfishchess.org/tests/view/68f337c528e6d77fcffa066a
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 65256 W: 16806 L: 16462 D: 31988
Ptnml(0-2): 76, 7386, 17362, 7726, 78

but failed to gain STC
https://tests.stockfishchess.org/tests/view/68f3378328e6d77fcffa0665
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 109824 W: 28523 L: 28618 D: 52683
Ptnml(0-2): 311, 11799, 30788, 11702, 312

In local tests, the speedup grows with thread count

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

No functional change
2025-11-01 10:40:23 +01:00
b09339a420 Split accumulator 3-Way
Squeeze a tiny bit more juice from the original idea in #6336 which this is on top of.

https://tests.stockfishchess.org/tests/view/68dddd85fa806e2e8393c0b9
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 156320 W: 40925 L: 40447 D: 74948
Ptnml(0-2): 427, 17330, 42172, 17800, 431

4-way doesn't look to be better than this.
https://tests.stockfishchess.org/tests/view/68dde19efa806e2e8393c0c1

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

No functional change

Co-authored-by: M Stembera <m_stembera@yahoo.com>
2025-10-05 09:33:23 +02:00
Timothy HerchenandJoost VandeVondele 9b164d9520 Shave some instructions off a hot loop in affine transform
On x86, GCC generates highly suboptimal code for this loop in its old form,
about 2x as many instructions as necessary. This decreases throughput
especially in an SMT setting. Clang does a better job but this change still has
some improvement. Note that the std::ptrdiff_t type is not optional; using an
unsigned type brings back the bad assembly. (Not sure why, but it seems
reliable on all the GCC versions I tested.)

passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 44672 W: 11841 L: 11527 D: 21304
Ptnml(0-2): 165, 4625, 12415, 4993, 138
https://tests.stockfishchess.org/tests/view/68d8111efa806e2e8393b10e

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

No functional change
2025-09-28 21:04:29 +02:00