Compare commits

..

511 Commits

Author SHA1 Message Date
opelly27 f65a195ca4 Update evaluate.h 2025-02-19 10:18:39 -08:00
FauziAkram fa6c30af81 FutilityValue formula tweak
Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 29600 W: 7979 L: 7662 D: 13959
Ptnml(0-2): 138, 3446, 7324, 3745, 147
https://tests.stockfishchess.org/tests/view/67ac7dff52879dfd14d7e7da

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 49662 W: 12850 L: 12502 D: 24310
Ptnml(0-2): 41, 5354, 13689, 5710, 37
https://tests.stockfishchess.org/tests/view/67acc1b252879dfd14d7e81d

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

Bench: 2581469
2025-02-13 20:18:35 +01:00
Daniel Monroe d54240c50a Decrease lmr depth if static eval decreases a lot
This tweak originally had some more conditions which have been simplified away.

Passed STC
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 60064 W: 15797 L: 15439 D: 28828
Ptnml(0-2): 236, 7080, 15106, 7310, 300
https://tests.stockfishchess.org/tests/view/67a2af9cfedef70e42ac3325

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 76794 W: 19740 L: 19337 D: 37717
Ptnml(0-2): 61, 8327, 21236, 8694, 79
https://tests.stockfishchess.org/tests/view/67a2c904fedef70e42ac374d

Passed Non-Regression VVLTC scaling check
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 29046 W: 7581 L: 7389 D: 14076
Ptnml(0-2): 2, 2557, 9213, 2749, 2
https://tests.stockfishchess.org/tests/view/67a54b591c4a3ea87241cb83

Passed simplification STC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 212448 W: 55244 L: 55217 D: 101987
Ptnml(0-2): 932, 25283, 53707, 25430, 872
https://tests.stockfishchess.org/tests/view/67aaacb02554387b116f698f

Passed simplification LTC
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 185736 W: 47270 L: 47217 D: 91249
Ptnml(0-2): 141, 20568, 51394, 20627, 138
https://tests.stockfishchess.org/tests/view/67ab8efa133d55b1d3bc1397

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

Bench: 2512420
2025-02-13 20:17:26 +01:00
Nonlinear2 a4edacb87a Tweak the cutnode depth condition for TT cutoffs
Passed STC:
https://tests.stockfishchess.org/tests/view/67ab396ab5c93ee812d851f3
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 83648 W: 21964 L: 21571 D: 40113
Ptnml(0-2): 339, 9779, 21217, 10128, 361

Passed LTC:
https://tests.stockfishchess.org/tests/view/67ab9647133d55b1d3bc171e
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 68160 W: 17551 L: 17166 D: 33443
Ptnml(0-2): 62, 7353, 18870, 7728, 67

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

Bench: 3087275
2025-02-13 19:52:06 +01:00
Michael Chaly 9cc15b3049 Do more reductions for cut nodes without a tt move
Logic is somewhat similar to IIR but in LMR.
Usually things like reducing more in IIR scale badly but this patch does
this in LMR where reducing more for cutNodes is in general good, so I
believe there is no non-linear scaling.

Passed STC:
https://tests.stockfishchess.org/tests/view/67abc9aaa04df5eb8dbeb452
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 42304 W: 11223 L: 10892 D: 20189
Ptnml(0-2): 184, 4904, 10669, 5187, 208

Passed LTC:
https://tests.stockfishchess.org/tests/view/67abcd7ba04df5eb8dbeb96c
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 32334 W: 8386 L: 8074 D: 15874
Ptnml(0-2): 26, 3446, 8916, 3748, 31

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

Bench: 2612849
2025-02-13 19:49:54 +01:00
Stefan Geschwentner 7258567804 Refactor reduction rules
Refactor reduction rules so that all ttPv/Pv related stuff is in one
rule and the scaling becomes more clear. No functional change

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

No functional change
2025-02-13 19:46:53 +01:00
Daniel Monroe 3a0418c0d0 Simplify opponent worsening
Passed simplification STC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 57120 W: 14712 L: 14526 D: 27882
Ptnml(0-2): 53, 6241, 15796, 6407, 63
https://tests.stockfishchess.org/tests/view/67a26153eb183d11c659454d

Passed simplification LTC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 313452 W: 79893 L: 79973 D: 153586
Ptnml(0-2): 279, 35053, 86156, 34945, 293
https://tests.stockfishchess.org/tests/view/67a29fe0fedef70e42ac32ae

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

Bench: 2582245
2025-02-13 19:45:55 +01:00
Carlos Esparza e089f723d8 Remove two xors by setting the hash keys for unreachable squares to zero
performance before:
3.6714 +- 0.20%  Gcycles
3.6620 +- 0.12%  Gcycles
3.6704 +- 0.26%  Gcycles
3.6602 +- 0.27%  Gcycles
3.6799 +- 0.37%  Gcycles

after:
3.6540 +- 0.30%  Gcycles
3.6388 +- 0.25%  Gcycles
3.6557 +- 0.17%  Gcycles
3.6449 +- 0.15%  Gcycles
3.6460 +- 0.26%  Gcycles

(every line is a different `profile-build` and shows the number of
cycles needed for `./stockfish bench`, measured with `perf stat -r 10`)

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

No functional change
2025-02-13 19:44:53 +01:00
Shawn Xu d66e603070 Increase PCM bonus when cutOffCnt is low
Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 36832 W: 9763 L: 9438 D: 17631
Ptnml(0-2): 159, 4267, 9254, 4562, 174
https://tests.stockfishchess.org/tests/view/67a29dbafedef70e42ac329a

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 19728 W: 5124 L: 4839 D: 9765
Ptnml(0-2): 18, 2029, 5485, 2314, 18
https://tests.stockfishchess.org/tests/view/67a2a1abfedef70e42ac32b7

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

Bench: 3197798
2025-02-05 19:00:25 +01:00
Daniel Monroe 3dfbc5de25 Remove non-pawn material check in qsearch pruning
Passed simplification STC
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 47712 W: 12621 L: 12409 D: 22682
Ptnml(0-2): 224, 5349, 12480, 5597, 206
https://tests.stockfishchess.org/tests/view/67a1b4fb612069de394afc37

Passed rebased simplification LTC
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 188274 W: 47727 L: 47677 D: 92870
Ptnml(0-2): 171, 20429, 52867, 20519, 151
https://tests.stockfishchess.org/tests/view/67a2a761fedef70e42ac3300

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

bench 2654242
2025-02-05 18:56:12 +01:00
Disservin 4c6d2bf921 Show stdout/stderr in CI/CD tests
makes it easier to fix based on warnings shown with e.g. valgrind

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

No functional change
2025-02-05 18:52:28 +01:00
Disservin 2a5b41fd12 Fixes a wrongly combined merge conflict from the previous merge wave.
Passed STC:
https://tests.stockfishchess.org/tests/view/67a288aaeb183d11c65945f1
LLR: 2.99 (-2.94,2.94) <0.00,2.00>
Total: 51424 W: 13588 L: 13237 D: 24599
Ptnml(0-2): 223, 6039, 12860, 6344, 246

Passed LTC:
https://tests.stockfishchess.org/tests/view/67a28c0aeb183d11c6594609
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 54144 W: 13900 L: 13543 D: 26701
Ptnml(0-2): 42, 5881, 14870, 6236, 43

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

Bench: 2345723
2025-02-04 23:08:43 +01:00
Michael Chaly e852d9880a Reduce less for positions without tt move
Continuation of work on scaling.
In line with previous scaling patches this one massively reduces
reduction for moves that don't go thru lmr for position without a tt
move.

Passed VVLTC with STC bounds:
https://tests.stockfishchess.org/tests/view/679fd2450774dfd78deb12b2
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 74718 W: 19354 L: 19042 D: 36322
Ptnml(0-2): 5, 6724, 23595, 7024, 11

Passed VVLTC with LTC bounds:
https://tests.stockfishchess.org/tests/view/67a009930774dfd78deb2346
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 82638 W: 21587 L: 21212 D: 39839
Ptnml(0-2): 15, 7476, 25953, 7869, 6

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

Bench: 2887850
2025-02-04 21:37:11 +01:00
FauziAkram 67573218e1 VVLTC parameters tweak
Some notes:
- Both tests were conducted on top of #5848.
- Based on tuning suggestions, the extension for capturing the
  previously moved piece was removed/simplified. (Developers can attempt
  to reintroduce it post-merge if needed.)
- Initially, bonusScale = std::max(bonusScale, -2); was included but
  later removed in the second test upon Viz's request, however, it was
  nearly non-functional anyway.

Passed VVLTC under STC bounds:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 31508 W: 8153 L: 7895 D: 15460
Ptnml(0-2): 1, 2747, 10005, 2995, 6
https://tests.stockfishchess.org/tests/view/679fdc7a0774dfd78deb1350

Passed VVLTC under LTC bounds:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 55026 W: 14370 L: 14046 D: 26610
Ptnml(0-2): 7, 4957, 17262, 5279, 8
https://tests.stockfishchess.org/tests/view/679fec920774dfd78deb19b8

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

Bench: 2757788
2025-02-04 21:34:08 +01:00
Viren6 ec7f1d6229 Increment cutoffCnt less often after fail high
Only increment when extension is less than 2 or it's a PvNode.

Tested vs #5851.

Failed STC:
LLR: -2.97 (-2.94,2.94) <0.00,2.00>
Total: 360064 W: 94546 L: 94271 D: 171247
Ptnml(0-2): 1835, 42826, 90314, 43343, 1714
https://tests.stockfishchess.org/tests/view/679f79cc0774dfd78deb1112

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 443076 W: 113942 L: 113081 D: 216053
Ptnml(0-2): 480, 49076, 121579, 49909, 494
https://tests.stockfishchess.org/tests/view/679fa21b0774dfd78deb1178

Passed VLTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 187184 W: 48098 L: 47495 D: 91591
Ptnml(0-2): 59, 19036, 54792, 19653, 52
https://tests.stockfishchess.org/tests/view/679fb6000774dfd78deb11e8

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

Bench: 3018089
2025-02-04 21:30:54 +01:00
Michael Chaly 3b8bfeb38a Do less aggressive pruning for higher movecounts
Move part of heuristic that makes reduction less before pruning stage.

Passed STC:
https://tests.stockfishchess.org/tests/view/679fdf1b0774dfd78deb13b3
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 47136 W: 12484 L: 12146 D: 22506
Ptnml(0-2): 211, 5472, 11866, 5806, 213

Passed LTC:
https://tests.stockfishchess.org/tests/view/679fe6790774dfd78deb1753
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 100536 W: 25837 L: 25383 D: 49316
Ptnml(0-2): 103, 10990, 27622, 11456, 97

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

Bench: 3265587
2025-02-04 21:28:49 +01:00
Kenneth Lee 09623abbe8 Simplify cutoffCnt further
Based off [Simplify cutoffCnt](https://github.com/official-stockfish/Stockfish/commit/69be04d38e10003853e78e4aa2b32aa252a82850) commit

Original
[commit](https://github.com/kennethlee33/Stockfish/commit/a77a895c3b7460f86b11a3ddfe3528f5be1276b9)
adding extension condition seems to not be improving strength anymore

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 54176 W: 14331 L: 14125 D: 25720
Ptnml(0-2): 261, 6340, 13676, 6554, 257
https://tests.stockfishchess.org/tests/view/679edb7c0774dfd78deb0eed

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 267198 W: 68148 L: 68179 D: 130871
Ptnml(0-2): 232, 30051, 73055, 30038, 223
https://tests.stockfishchess.org/tests/view/679ef2c70774dfd78deb0f43

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

Bench: 3119355
2025-02-04 21:26:04 +01:00
Nonlinear2 9ed1725e78 Simplify bonusScale formula
Passed STC:
https://tests.stockfishchess.org/tests/view/679ea7bc0774dfd78deb0d68
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 47680 W: 12575 L: 12364 D: 22741
Ptnml(0-2): 179, 5589, 12139, 5708, 225

Passed LTC:
https://tests.stockfishchess.org/tests/view/679eb7760774dfd78deb0dbb
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 314220 W: 80110 L: 80189 D: 153921
Ptnml(0-2): 265, 35121, 86420, 35036, 268

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

Bench: 3161782
2025-02-04 21:24:06 +01:00
Nonlinear2 fccc6f624e Reduce full depth search twice
Passed STC:
https://tests.stockfishchess.org/tests/view/679f429e0774dfd78deb10a5
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 71584 W: 18905 L: 18529 D: 34150
Ptnml(0-2): 302, 8372, 18081, 8722, 315

Passed LTC:
https://tests.stockfishchess.org/tests/view/679f72a00774dfd78deb1102
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 353952 W: 91007 L: 90024 D: 172921
Ptnml(0-2): 375, 39163, 96921, 40138, 379

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

Bench: 3642363
2025-02-04 21:22:08 +01:00
Disservin c12dbdedd9 Disallow same option being added twice
Now exits during startup.

```
./stockfish
Stockfish dev-20250202-243c7c6a by the Stockfish developers (see AUTHORS file)
x1,5,0,10,0.5,0.0020
Option: "x1" was already added!
```

i.e. prevents and helps debug this case

```cpp
int x1 = 5;

TUNE(x1);
TUNE(x1);
```

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

No functional change
2025-02-04 21:18:01 +01:00
Shawn Xu 8c73472ac8 Simplify depth increase condition further
Passed Non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 51232 W: 13560 L: 13351 D: 24321
Ptnml(0-2): 183, 6075, 12920, 6226, 212
https://tests.stockfishchess.org/tests/view/679d7b2b0774dfd78deb043f

Passed Non-regression LTC (v. #5827):
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 172398 W: 44108 L: 44042 D: 84248
Ptnml(0-2): 122, 19207, 47489, 19245, 136
https://tests.stockfishchess.org/tests/view/679d7fb10774dfd78deb05d2

Passed Non-regression VLTC (v. #5827):
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 388540 W: 99314 L: 99464 D: 189762
Ptnml(0-2): 89, 40454, 113350, 40272, 105
https://tests.stockfishchess.org/tests/view/679da3be0774dfd78deb0ad4

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

Bench: 2688175
2025-02-04 21:11:37 +01:00
Guenther Demetz 2a1ab11ab0 Micro-optimization for SEE: remove a superfluous condition
This condition can never be true, it's superfluous.

It never triggers even with a bench 16 1 20 run.
To met the condition it would imply that the previous recapture was done
by a higher rated piece than a Queen.
This is only the case when the King recaptures and that's already
handled in line 1161: (return (attackers & ~pieces(stm)) ? res ^ 1).

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

No functional change
2025-02-04 21:11:05 +01:00
Robert Nurnberg @ elitebook d46c0b6f49 Add cursed win checks to CI matetrack tests
This PR adds a run for the `matecheck.py` script from the matetrack repo
with the option `--syzygy50MoveRule false`.

The new tests guard against a re-introduction of the bugs recently fixed
by https://github.com/official-stockfish/Stockfish/pull/5814.

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

No functional change
2025-02-02 13:54:04 +01:00
Kenneth Lee 9f0844c101 Simplify extensions depth increase condition
Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 42784 W: 11198 L: 10979 D: 20607
Ptnml(0-2): 166, 5024, 10822, 5185, 195
https://tests.stockfishchess.org/tests/view/6795b6f8f6281b7d7b1869d6

Failed LTC:
LLR: -2.95 (-2.94,2.94) <-1.75,0.25>
Total: 283614 W: 72046 L: 72587 D: 138981
Ptnml(0-2): 241, 32097, 77647, 31606, 216
https://tests.stockfishchess.org/tests/view/6795cbb6f6281b7d7b186a07

Passed VLTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 59678 W: 15387 L: 15211 D: 29080
Ptnml(0-2): 23, 6169, 17273, 6357, 17
https://tests.stockfishchess.org/tests/view/6795c6dbf6281b7d7b1869f9

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

Bench: 3088494
2025-02-02 13:52:16 +01:00
Disservin 65a9a391e9 Silence clang-format issue
No functional change
2025-02-02 13:49:54 +01:00
Michael Chaly dabffbceff Make pruning at ttpv nodes more aggressive
Continuation of work done by @FauziAkram and @Viren6 They had a series
of patches that decrease pruning for ttPv nodes - and it passed as a
gainer at lower time controls while revert passed as a gainer at higher
time controls.
So it's a logical continuation of this work that increases pruning for
ttPv nodes in hopes of scaling to longer TCs.

Fixed games STC:
https://tests.stockfishchess.org/tests/view/679ee3910774dfd78deb0efd
Elo: -4.98 ± 2.1 (95%) LOS: 0.0%
Total: 28584 W: 7229 L: 7639 D: 13716
Ptnml(0-2): 143, 3579, 7219, 3247, 104
nElo: -9.54 ± 4.0 (95%) PairsRatio: 0.90

Passed VVLTC with STC bounds:
https://tests.stockfishchess.org/tests/view/679d21f70774dfd78deaf553
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 323282 W: 83729 L: 83105 D: 156448
Ptnml(0-2): 37, 29842, 101269, 30446, 47

Passed VVLTC with LTC bounds:
https://tests.stockfishchess.org/tests/view/679e7a970774dfd78deb0cd3
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 113712 W: 29485 L: 29051 D: 55176
Ptnml(0-2): 13, 10376, 35640, 10818, 9

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

Bench: 2964045
2025-02-02 13:47:52 +01:00
Shawn Xu 344e89275a Simplify Away Quadruple Extensions
Passed Non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 95856 W: 24551 L: 24404 D: 46901
Ptnml(0-2): 85, 10621, 26364, 10778, 80
https://tests.stockfishchess.org/tests/view/679a9aedae346be6da0eebd6

Passed Non-regression VLTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 157536 W: 40000 L: 39921 D: 77615
Ptnml(0-2): 43, 16416, 45775, 16487, 47
https://tests.stockfishchess.org/tests/view/679aed8f51037ccaf3e30fbf

Passed Non-regression VVLTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 51598 W: 13345 L: 13172 D: 25081
Ptnml(0-2): 0, 4735, 16162, 4896, 6
https://tests.stockfishchess.org/tests/view/679d368b0774dfd78deb0163

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

Bench: 2399312
2025-02-02 13:44:22 +01:00
Stefan Geschwentner c83ddd9e4b Tweak correction history factors
The values are taken from this tuning
https://tests.stockfishchess.org/tests/view/679c4e150774dfd78deaf376
which added also a new material correction history. The full tune
doesn't work but ignoring the new history results in this changes.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 102368 W: 27057 L: 26638 D: 48673
Ptnml(0-2): 394, 12031, 25949, 12382, 428
https://tests.stockfishchess.org/tess/view/679d2ca70774dfd78deaf796

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 55044 W: 14215 L: 13855 D: 26974
Ptnml(0-2): 43, 5956, 15172, 6300, 51
https://tests.stockfishchess.org/tests/view/679d30be0774dfd78deafda2

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

Bench: 3068583
2025-02-02 13:43:32 +01:00
Daniel Monroe 7690fac5cf Simp probcut disable condition
Disable probcut check when we the ttValue is not at least probCutBeta,
regardless of tt depth.

Passed simplification STC
LLR: 2.92 (-2.94,2.94) <-1.75,0.25>
Total: 60896 W: 16030 L: 15835 D: 29031
Ptnml(0-2): 220, 7164, 15507, 7315, 242
https://tests.stockfishchess.org/tests/view/679c0a3251037ccaf3e3141e

Passed simplification LTC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 76644 W: 19557 L: 19392 D: 37695
Ptnml(0-2): 50, 8486, 21104, 8613, 69
https://tests.stockfishchess.org/tests/view/679c380b0774dfd78deaf35c

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

Bench: 3543770
2025-02-02 13:39:47 +01:00
Michael Chaly 40e0486d02 Make IIR for PvNodes less aggressive
In line with previous experiments on improving scaling of IIR.
Now it disables IIR for pv nodes with depth <= 2, so disallowing for it
to perform a qsearch dive.

Fixed games STC:
https://tests.stockfishchess.org/tests/view/679ae6a951037ccaf3e30fb3
Elo: -10.36 ± 2.5 (95%) LOS: 0.0%
Total: 20020 W: 4902 L: 5499 D: 9619
Ptnml(0-2): 128, 2653, 4976, 2194, 59

Passed VVLTC with STC bounds:
https://tests.stockfishchess.org/tests/view/67954f2e406a4efe9eb7d266
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 196758 W: 50725 L: 50258 D: 95775
Ptnml(0-2): 21, 18153, 61564, 18620, 21

Passed VVLTC with LTC bounds:
https://tests.stockfishchess.org/tests/view/6795a26bf6281b7d7b18698b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 323092 W: 83679 L: 82857 D: 156556
Ptnml(0-2): 48, 29475, 101659, 30335, 29

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

Bench: 3464332
2025-02-02 13:37:47 +01:00
Daniel Monroe 5ef1f2b132 Refactor prior reduction
Make index of reduction consistent with rest of Stack

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

No functional change
2025-02-02 13:36:58 +01:00
Carlos Esparza 7684b6e4d8 Don't increase rule50 when doing null moves
also prefetch a bit earlier while we're at it

passed STC: https://tests.stockfishchess.org/tests/view/678c0860f4dc0a8b4ae8cf58
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 67328 W: 17608 L: 17418 D: 32302
Ptnml(0-2): 256, 7905, 17156, 8087, 260

passed LTC: https://tests.stockfishchess.org/tests/view/678c1a56f4dc0a8b4ae8cfb1
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 340896 W: 86577 L: 86685 D: 167634
Ptnml(0-2): 291, 38325, 93332, 38201, 299

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

Bench: 1910281
2025-02-02 13:35:48 +01:00
Shawn Xu 4a77fb213f Clean up corrhist
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 89056 W: 23225 L: 23067 D: 42764
Ptnml(0-2): 292, 9688, 24470, 9726, 352
https://tests.stockfishchess.org/tests/view/679816b2ae346be6da0ee8e7

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

Bench: 1767398
2025-02-02 13:33:35 +01:00
FauziAkram f50d52aa7f No Ply Restriction in the condition that limits the depth extension to a certain point
No Ply Restriction in the condition that limits the depth extension to a
certain point.

Passed again LTC rebased:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 195108 W: 49916 L: 49872 D: 95320
Ptnml(0-2): 170, 21846, 53464, 21918, 156
https://tests.stockfishchess.org/tests/view/6795542a406a4efe9eb7d361

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

Bench: 1767398
2025-01-26 22:53:34 +01:00
Robert Nurnberg @ elitebook c180163540 Update fastchess CI Version
This PR updates the fastchess version used as part of the CI to the one
used on fishtest, see
https://github.com/official-stockfish/fishtest/pull/2180.

Also change the name/repo from fast-chess to fastchess.

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

No functional change
2025-01-26 22:45:33 +01:00
Daniel Monroe ebdc7ba2da Refactor prior countermove bonus
Passed simplification STC
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 155424 W: 40252 L: 40159 D: 75013
Ptnml(0-2): 511, 18655, 39328, 18666, 552
https://tests.stockfishchess.org/tests/view/6794084fe96bfb672ad18d90

Passed rebased simplification LTC
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 103944 W: 26567 L: 26427 D: 50950
Ptnml(0-2): 69, 11640, 28418, 11772, 73
https://tests.stockfishchess.org/tests/view/67955c9a406a4efe9eb7d7e4

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

Bench: 1839554
2025-01-26 22:43:02 +01:00
Nonlinear2 a016abd698 Decrease all stats malus according to move count
Passed STC:
https://tests.stockfishchess.org/tests/view/6794c4634f7de645171fb341
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 28096 W: 7412 L: 7106 D: 13578
Ptnml(0-2): 97, 3194, 7148, 3524, 85

Passed LTC:
https://tests.stockfishchess.org/tests/view/6794ea13406a4efe9eb7d06b
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 58086 W: 15049 L: 14684 D: 28353
Ptnml(0-2): 27, 6344, 15957, 6667, 48

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

Bench: 1711170
2025-01-26 22:42:41 +01:00
Martin Novák 831cb01cea Remove major corrhist
Remove major correction history and slightly increase all other
correction weights.

Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 50080 W: 13171 L: 12959 D: 23950
Ptnml(0-2): 196, 5998, 12462, 6166, 218
https://tests.stockfishchess.org/tests/live_elo/67954526406a4efe9eb7d176

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 51504 W: 13188 L: 12995 D: 25321
Ptnml(0-2): 54, 5658, 14128, 5865, 47
https://tests.stockfishchess.org/tests/live_elo/67954961406a4efe9eb7d251

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

Bench: 2081366
2025-01-26 22:41:00 +01:00
FauziAkram 69be04d38e Simplify cutoffCnt
Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 235872 W: 61156 L: 61155 D: 113561
Ptnml(0-2): 843, 28269, 59658, 28376, 790
https://tests.stockfishchess.org/tests/view/6794dd3e4f7de645171fb380

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 61494 W: 15644 L: 15462 D: 30388
Ptnml(0-2): 61, 6822, 16788, 7026, 50
https://tests.stockfishchess.org/tests/view/6794f86a406a4efe9eb7d093

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

Bench: 2168937
2025-01-26 22:39:32 +01:00
Daniel Monroe 27e747d1d7 Simplify futility margin in lmr for quiets.
Replace the "low bestValue condition" with whether there is a best move.

Passed Simplification STC
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 102560 W: 26517 L: 26367 D: 49676
Ptnml(0-2): 328, 12223, 26036, 12357, 336
https://tests.stockfishchess.org/tests/view/679310e4ca18a2c66da02af8

Passed Simplification LTC
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 66942 W: 17130 L: 16953 D: 32859
Ptnml(0-2): 52, 7459, 18290, 7600, 70
https://tests.stockfishchess.org/tests/view/679459a3e96bfb672ad18ddf

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

Bench: 1438043
2025-01-25 20:59:33 +01:00
Stefan Geschwentner 1b31e266b0 Consider more nodes as ttPv nodes.
Remove depth condition in propagation rule for ttPv state from a node to
it childs.

Because this change marks more nodes as ttPv, we have a time sensitive
ttPv reduction rule and the STC snd LTC seems to show bad scaling. So i
have also submitted a VLTC non-regression to check the scaling at higher
time control.

The results gives a little indication that we have perhaps good scaling
with more ttPv nodes so that could be further explored.

Passed non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 82528 W: 21627 L: 21453 D: 39448
Ptnml(0-2): 317, 9809, 20891, 9877, 370
https://tests.stockfishchess.org/tests/view/678e608cd63764e34db49ad7

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 310440 W: 78879 L: 78956 D: 152605
Ptnml(0-2): 255, 34915, 84938, 34876, 236
https://tests.stockfishchess.org/tests/view/678fab89ac8f8f5496155f3c

Passed non-regression VLTC for scaling verification:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 59496 W: 15158 L: 14983 D: 29355
Ptnml(0-2): 15, 6039, 17470, 6204, 20
https://tests.stockfishchess.org/tests/view/6794bd1f4f7de645171fb33b

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

Bench: 1829507
2025-01-25 20:56:14 +01:00
Shawn Xu 889fed448c Better nonpawn indexing
Improves indexing scheme, by noting that both sides are likely to access the same non_pawn_index nearby.

LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 75936 W: 19905 L: 19554 D: 36477
Ptnml(0-2): 190, 7863, 21554, 8128, 233
https://tests.stockfishchess.org/tests/view/67904d0cfc8c306ba6cea332

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

No functional change

Co-authored-by: Andrew Grant <andrew.github@grantnet.us>
2025-01-25 20:53:53 +01:00
Viren6 435ba3dbb5 Revert "Moving up the if position is or has been on the PV reduction"
Passed VVLTC 1:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 68362 W: 17830 L: 17523 D: 33009
Ptnml(0-2): 9, 6253, 21347, 6566, 6
https://tests.stockfishchess.org/tests/view/6790271cfc8c306ba6cea2c1

Passed VVLTC 2:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 113256 W: 29158 L: 28721 D: 55377
Ptnml(0-2): 13, 10521, 35122, 10960, 12
https://tests.stockfishchess.org/tests/view/678d3e47d63764e34db491a3

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

bench 1943998
2025-01-25 20:51:31 +01:00
Robert Nurnberg @ elitebook 6c7c5c7e47 Do not change TB cursed wins to draws if requested
If Syzygy50MoveRule is false, do not calls to is_draw() need to be guarded.
Also fixes a TB rootmove ranking issue in this case.

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

No functional change
2025-01-25 20:42:50 +01:00
pkrisz99 75b75bc16a Add improving to a condition of NMP
This patch makes one of the conditions for null-move pruning depend on whether we're improving. Keep in mind that it relies on the "classical" definiton, rather than the refined one.

Passed STC: https://tests.stockfishchess.org/tests/view/678d5267d63764e34db49720
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 38976 W: 10296 L: 9974 D: 18706
Ptnml(0-2): 135, 4504, 9902, 4798, 149

Passed LTC: https://tests.stockfishchess.org/tests/view/678d5891d63764e34db49731
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 275772 W: 70655 L: 69836 D: 135281
Ptnml(0-2): 217, 30615, 75394, 31452, 208

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

Bench: 2475787
2025-01-25 20:41:37 +01:00
Shawn Xu d606311e55 Fix undefined behavior
From cppreference: "It is undefined behavior to read from the member of the
union that wasn't most recently written. Many compilers implement, as a
non-standard language extension, the ability to read inactive members of a
union."

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

no functional change
2025-01-25 20:33:43 +01:00
FauziAkram aa894c0f93 Comments Tweak
* Remove from comments, hardcoded exact values for parameters that are subject to tuning.
* Remove the Elo worth, as they are now completely outdated, making them irrelevant and potentially misleading.
* Consolidated scaling-related comments into a single section for clarity. Used asterisks (*) to highlight parameters significantly affected by scaling, given their separation in the code.

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

No functional change
2025-01-25 20:29:40 +01:00
Nonlinear2 4975b2bc6f Increase prior countermove bonus if TT move
Passed STC:
https://tests.stockfishchess.org/tests/view/678c4c8bf4dc0a8b4ae8db5c
LLR: 2.97 (-2.94,2.94) <0.00,2.00>
Total: 273408 W: 71089 L: 70415 D: 131904
Ptnml(0-2): 937, 32466, 69229, 33130, 942

Passed LTC:
https://tests.stockfishchess.org/tests/view/678ccabdf4dc0a8b4ae8dd7a
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 148614 W: 38138 L: 37584 D: 72892
Ptnml(0-2): 97, 16450, 40689, 16944, 127

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

Bench: 1582867
2025-01-25 20:27:11 +01:00
Stefan Geschwentner 59c578ad28 Add move count based reduction.
Do less reduction which is linear increasing with move count (factor = 64).

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 191488 W: 49982 L: 49432 D: 92074
Ptnml(0-2): 731, 22523, 48614, 23217, 659
https://tests.stockfishchess.org/tests/view/678d0b29d63764e34db4904b

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 90582 W: 23150 L: 22717 D: 44715
Ptnml(0-2): 73, 9936, 24822, 10405, 55
https://tests.stockfishchess.org/tests/view/678d347cd63764e34db4916f

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

Bench: 1803474
2025-01-25 20:23:33 +01:00
Shawn Xu e7367cef0f Clean up pack reordering
closes https://github.com/official-stockfish/Stockfish/pull/5802

no functional change
2025-01-25 20:17:39 +01:00
mstembera 18b3465a86 Generate lookup indices at compile time.
Credit to @Disservin: the constexpr lsb is just the De Bruijn bitscan with the xor from the cpw https://www.chessprogramming.org/BitScan

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

No functional change
2025-01-25 20:12:38 +01:00
Shawn Xu 62ecdfe82c simplify accumulator updates
After #5759 accumulator updates are strictly on a per-move basis. Therefore, the generic code for updating multiple moves at once is no longer needed.

Passed Non-regression STC:
LLR: 3.00 (-2.94,2.94) <-1.75,0.25>
Total: 81696 W: 21204 L: 21039 D: 39453
Ptnml(0-2): 210, 8431, 23416, 8566, 225
https://tests.stockfishchess.org/tests/view/67823a24a31c4c13e83518a8

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

no functional change
2025-01-25 20:09:09 +01:00
Joost VandeVondele 8e3e22b3d4 Replace depth increase condition with !opponentWorsening
Passed simplification STC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 220544 W: 57417 L: 57399 D: 105728
Ptnml(0-2): 816, 26554, 55540, 26520, 842
https://tests.stockfishchess.org/tests/view/678970e38082388fa0cbfe02

Passed simplification LTC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 132600 W: 33868 L: 33760 D: 64972
Ptnml(0-2): 126, 14770, 36390, 14898, 116
https://tests.stockfishchess.org/tests/view/678accabc00c743bc9e9fc7f

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

bench 1632964
2025-01-18 21:33:17 +01:00
Daniel Monroe f00d91f8ac Refine probcut
Allow probcut for depth 3 and disable deeper verification search when it would simply repeat the qsearch.

Passed STC
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 283232 W: 74450 L: 73760 D: 135022
Ptnml(0-2): 1052, 33780, 71349, 34296, 1139
https://tests.stockfishchess.org/tests/view/67843b58460e2910c51ddcc6

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 339654 W: 86845 L: 85893 D: 166916
Ptnml(0-2): 298, 37734, 92802, 38704, 289
https://tests.stockfishchess.org/tests/view/678aa722c00c743bc9e9face

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

bench 1288648
2025-01-18 21:27:42 +01:00
Shawn Xu 738ac2a100 tuned TM values
Tuned 70k games at 240+2.4 th 2: https://tests.stockfishchess.org/tests/view/6783b1b16ddf09c0b4b703f5

Failed STC:
LLR: -2.93 (-2.94,2.94) <0.00,2.00>
Total: 491872 W: 128260 L: 127804 D: 235808
Ptnml(0-2): 1579, 55449, 131572, 55609, 1727
https://tests.stockfishchess.org/tests/view/6785a045460e2910c51de4b8

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 154824 W: 39315 L: 38874 D: 76635
Ptnml(0-2): 110, 15809, 45147, 16222, 124
https://tests.stockfishchess.org/tests/view/678ac722c00c743bc9e9fc35

Passed VLTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 77404 W: 19825 L: 19452 D: 38127
Ptnml(0-2): 18, 7262, 23765, 7643, 14
https://tests.stockfishchess.org/tests/view/678b2a98c00c743bc9ea048c

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

No functional change
2025-01-18 21:24:01 +01:00
FauziAkram c94bcf62e4 Moving up the if position is or has been on the PV reduction
Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 29664 W: 7880 L: 7570 D: 14214
Ptnml(0-2): 93, 3487, 7390, 3741, 121
https://tests.stockfishchess.org/tests/view/678ac957c00c743bc9e9fc3f

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 81354 W: 20903 L: 20487 D: 39964
Ptnml(0-2): 66, 9003, 22123, 9419, 66
https://tests.stockfishchess.org/tests/view/678ad359c00c743bc9e9fcfa

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

Bench: 1414638
2025-01-18 21:18:48 +01:00
mstembera 329c267e25 Optimize find_nnz() by reducing the size of lookup_indices
https://tests.stockfishchess.org/tests/view/67896b688082388fa0cbfdee
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 452800 W: 118213 L: 117300 D: 217287
Ptnml(0-2): 1638, 50255, 121864, 50842, 1801

It's faster to shrink lookup_indices[] to 8 bit and zero extend to 16 bit using _mm_cvtepu8_epi16() than to read the larger 16 bit version. I suspect that having the constants available at compile time isn't too valuable and can be simplified back to generating at initialization time since this version also almost passed. https://tests.stockfishchess.org/tests/view/67863057460e2910c51de7e0 I will try that as a follow up.

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

No functional change
2025-01-18 21:13:12 +01:00
Michael Chaly 7701d0b3c4 Introduce one more continuation history
This one is counter counter counter history - with really low update value and divided by 3 in movepicker unlike the other ones.

Passed STC:
https://tests.stockfishchess.org/tests/view/67861495460e2910c51de720
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 44352 W: 11699 L: 11370 D: 21283
Ptnml(0-2): 156, 5098, 11361, 5383, 178

Passed LTC:
https://tests.stockfishchess.org/tests/view/6786e89e3b8f206a2696b646
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 432660 W: 110355 L: 109207 D: 213098
Ptnml(0-2): 381, 48214, 118039, 49268, 428

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

Bench: 1491837
2025-01-18 21:04:55 +01:00
Nonlinear2 b392ac76db Increase history bonus of TT moves
Passed STC:
https://tests.stockfishchess.org/tests/view/678807653b8f206a2696b78b
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 42208 W: 11113 L: 10783 D: 20312
Ptnml(0-2): 148, 4919, 10651, 5227, 159

Passed LTC:
https://tests.stockfishchess.org/tests/view/6788a8463b8f206a2696b956
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 122886 W: 31454 L: 30952 D: 60480
Ptnml(0-2): 105, 13567, 33619, 14025, 127

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

Bench: 1760081
2025-01-18 21:02:04 +01:00
FauziAkram 165ace194f Remove the cap from maxscale for x moves in y seconds TC
Passed STC 40/10:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 48800 W: 13044 L: 12835 D: 22921
Ptnml(0-2): 229, 5457, 12863, 5578, 273
https://tests.stockfishchess.org/tests/view/67862dae460e2910c51de7c9

Passed LTC 40/40:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 141296 W: 36110 L: 36014 D: 69172
Ptnml(0-2): 222, 14350, 41440, 14382, 254
https://tests.stockfishchess.org/tests/view/678799903b8f206a2696b6f8

Passed STC 80/8:
LLR: 2.99 (-2.94,2.94) <-1.75,0.25>
Total: 155120 W: 41442 L: 41346 D: 72332
Ptnml(0-2): 953, 17232, 41102, 17312, 961
https://tests.stockfishchess.org/tests/view/678aca4dc00c743bc9e9fc47

Passed LTC 80/60:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 93950 W: 24042 L: 23904 D: 46004
Ptnml(0-2): 80, 9020, 28627, 9178, 70
https://tests.stockfishchess.org/tests/view/678af705c00c743bc9e9fe94

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

No functional change
2025-01-18 20:58:41 +01:00
ppigazzini 4423c8eefa Return stockfish-macos-m1-apple-silicon.tar
https://github.com/[ppigazzini/stockfish-downloader now uses the official SF script for POSIX systems.

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

No functional change
2025-01-18 20:56:23 +01:00
Shawn Xu ccbd060b01 simplify razoring
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 93056 W: 24215 L: 24054 D: 44787
Ptnml(0-2): 364, 11085, 23470, 11244, 365
https://tests.stockfishchess.org/tests/view/67883a5d3b8f206a2696b804

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 66564 W: 16971 L: 16794 D: 32799
Ptnml(0-2): 56, 7403, 18192, 7570, 61
https://tests.stockfishchess.org/tests/view/6789ffa78082388fa0cbfe95

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

bench 1500649
2025-01-18 20:54:55 +01:00
Disservin 132b90df04 Update CI to Ubuntu 22.04 from 20.04
fixes #5756
closes https://github.com/official-stockfish/Stockfish/pull/5786

No functional change
2025-01-18 20:52:07 +01:00
Daniel Monroe a944f08225 retroactive reduction decrease if eval improves
If the previous reduction was large but the static eval improves then increase the search depth. This patch looks at the next node when calculating the reduction, something I don't think has been done before and which can probably used for further elo gaining patches.

Passed STC
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 55936 W: 14813 L: 14462 D: 26661
Ptnml(0-2): 220, 6565, 14094, 6822, 267
https://tests.stockfishchess.org/tests/view/67845b70460e2910c51ddcff

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 189468 W: 48411 L: 47773 D: 93284
Ptnml(0-2): 180, 20801, 52131, 21445, 177
https://tests.stockfishchess.org/tests/view/6784e2cb460e2910c51ddf86

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

bench: 1512884
2025-01-18 20:50:04 +01:00
FauziAkram 69ec5dcbfc Remove the type of moved piece from the evasion capture movepick formula
In the move generation the moves are generated in the order pawns, knight, bishops, rooks, queens and king.
This follows increasing type_of(pos.moved_piece(m)) term, so in master a capturing was sorted after a capturing rook if the same piece was captured in evasion.
Because we use a stable sorting method (stable means the order of elements with the same value are not changed) and generate the moves in the above order we do'nt need the removed term.

Passed STC:
LLR: 2.98 (-2.94,2.94) <-1.75,0.25>
Total: 170560 W: 44222 L: 44148 D: 82190
Ptnml(0-2): 569, 18792, 46488, 18858, 573
https://tests.stockfishchess.org/tests/view/678530ee460e2910c51de21d

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

No functional change
2025-01-18 20:44:04 +01:00
pb00067 56000827af Simplify common hint for parent position
Removes function hint_common_access_for_perspective together with it's comments,
which weren't accurate anymore since merge of #5576

https://tests.stockfishchess.org/tests/view/6784c9cd460e2910c51dde39
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 295104 W: 76702 L: 76765 D: 141637
Ptnml(0-2): 1031, 32135, 81249, 32140, 997

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

No functional change
2025-01-18 20:35:46 +01:00
Disservin 4c2241089d Remove addition of 1ms to all timestamps
The +1 was a quick fix to avoid the division by zero, a more correct approach is to use 1ms as the minimum reported timestamp to avoid a division by zero.
Later timestamps no longer include an additional 1ms.

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

No functional change
2025-01-18 20:32:00 +01:00
Disservin 675319b45d Fix Path to AUTHORS in CONTRIBUTING
closes https://github.com/official-stockfish/Stockfish/pull/5777

No functional change
2025-01-18 20:30:44 +01:00
Daniel Monroe 5868b4cb58 remove eval== staticeval check in fut pruning
Simplify corrplexity in futility margin
Don't check that staticEval == eval when applying the corrplexity-based adjustment in futility pruning.

Passed Simplification STC
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 121760 W: 31640 L: 31512 D: 58608
Ptnml(0-2): 349, 14400, 31289, 14458, 384
https://tests.stockfishchess.org/tests/view/6780c4109168c8bf30927777

Passed Simplification LTC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 134772 W: 34245 L: 34140 D: 66387
Ptnml(0-2): 94, 14869, 37350, 14984, 89
https://tests.stockfishchess.org/tests/view/6782d6ea6ddf09c0b4b6dd36

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

Bench: 1487627
2025-01-18 20:25:59 +01:00
mstembera 3104cd72d5 Fix initialization of TTData.
https://tests.stockfishchess.org/tests/view/6757757686d5ee47d9541de9
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 151200 W: 39396 L: 39306 D: 72498
Ptnml(0-2): 445, 16404, 41781, 16556, 414

Discussed in more detail here #5766

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

No functional change
2025-01-18 20:23:10 +01:00
Carlos Esparza aaafaaecf2 prefetch in do_move()
this allows removing Position::key_after()

STC
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 24960 W: 6556 L: 6336 D: 12068
Ptnml(0-2): 59, 2554, 7056, 2730, 81

LTC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 115080 W: 29319 L: 29204 D: 56557
Ptnml(0-2): 51, 10736, 35864, 10825, 64

STC with 2MB hash
LLR: 3.04 (-2.94,2.94) <-1.75,0.25>
Total: 182176 W: 46998 L: 46932 D: 88246
Ptnml(0-2): 526, 19711, 50544, 19785, 522

LTC with 8MB hash
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 441180 W: 111557 L: 111746 D: 217877
Ptnml(0-2): 229, 39698, 140929, 39501, 233

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

bench: 1379150
2025-01-18 20:19:53 +01:00
FauziAkram c085670b84 Increase the depth margin
Tested at VVLTC against the passed patches.

Test 1 against PR5764
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 167260 W: 43053 L: 42521 D: 81686
Ptnml(0-2): 7, 15272, 52542, 15800, 9
https://tests.stockfishchess.org/tests/view/6782ef196ddf09c0b4b6e780

Test 2 against PR5765
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 300012 W: 77364 L: 76771 D: 145877
Ptnml(0-2): 22, 27555, 94256, 28154, 19
https://tests.stockfishchess.org/tests/view/678366446ddf09c0b4b7028c

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

Bench: 1379150
2025-01-12 21:36:39 +01:00
Viren6 e2612f9a29 Introduce Correction History Quad Extensions
Also modifies the double and triple extension margins with the correction history adjustment.

STC Elo Estimate:
Elo: -4.40 ± 1.4 (95%) LOS: 0.0%
Total: 60000 W: 15230 L: 15990 D: 28780
Ptnml(0-2): 264, 7495, 15168, 6883, 190
nElo: -8.48 ± 2.8 (95%) PairsRatio: 0.91
https://tests.stockfishchess.org/tests/view/6783a3786ddf09c0b4b703a1

Passed 1st VVLTC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 35736 W: 9354 L: 9088 D: 17294
Ptnml(0-2): 4, 3191, 11212, 3457, 4
https://tests.stockfishchess.org/tests/view/6783a3336ddf09c0b4b7039b

Passed 2nd VVLTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 36394 W: 9515 L: 9225 D: 17654
Ptnml(0-2): 1, 3271, 11364, 3559, 2
https://tests.stockfishchess.org/tests/view/678395e26ddf09c0b4b70345

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

Bench: 1567166
2025-01-12 21:36:39 +01:00
Muzhen Gaming 93edf7a74c VVLTC Search Tune
Values were tuned with 118k VVLTC games.

Tested against #5764.

Passed VVLTC 1st sprt:
https://tests.stockfishchess.org/tests/view/678331226ddf09c0b4b6fd78
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 43556 W: 11219 L: 10942 D: 21395
Ptnml(0-2): 2, 3975, 13549, 4248, 4

Passed VVLTC 2nd sprt:
https://tests.stockfishchess.org/tests/view/67834aa06ddf09c0b4b6fe34
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 37150 W: 9577 L: 9285 D: 18288
Ptnml(0-2): 2, 3344, 11593, 3632, 4

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

Bench: 1258128
2025-01-12 21:36:31 +01:00
Michael Chaly 8b32e4825f Make IIR less aggressive
This patch is an elo gaining simplification which gains elo at longer time controls.
Patch disallows IIR for cutNodes with existing tt moves as well as makes
IIR for pv nodes less aggressive, basiclally confirming suspected
scaling patterns for this heuristic.

Result of 50k games STC run:
https://tests.stockfishchess.org/tests/view/678304676ddf09c0b4b6f9f9
Elo: -2.93 ± 1.6 (95%) LOS: 0.0%
Total: 50000 W: 12718 L: 13140 D: 24142
Ptnml(0-2): 189, 6087, 12835, 5735, 154
nElo: -5.71 ± 3.0 (95%) PairsRatio: 0.94

Passed VVLTC SPRT with STC bounds:
https://tests.stockfishchess.org/tests/view/6782eb1a6ddf09c0b4b6e6b0
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 150292 W: 38868 L: 38458 D: 72966
Ptnml(0-2): 19, 13890, 46907, 14322, 8

Passed VVLTC SPRT with LTC bounds:
https://tests.stockfishchess.org/tests/view/6782d8d96ddf09c0b4b6df18
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 153388 W: 39791 L: 39285 D: 74312
Ptnml(0-2): 13, 13924, 48311, 14436, 10

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

Bench: 1507606
2025-01-12 21:25:36 +01:00
mstembera b84c8807a3 Optimize attackers_to()
https://tests.stockfishchess.org/tests/view/6782decb6ddf09c0b4b6e1b0
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 105920 W: 27571 L: 27181 D: 51168
Ptnml(0-2): 284, 10808, 30403, 11164, 301

- If we only need to know if attackers exist we can skip some
  calculations.
- Also calculating slider/magic attackers first is better because the
  double lookup is slow due to memory latency.
- I also included a couple of very minor cleanups in search that
  probably don't warrant their own PR but I can open separately if
  that's better.

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

No functional change
2025-01-12 21:24:44 +01:00
Shawn Xu 921361829a Simplify away capthist bonus in Probcut
The explicit bonus has been obsoleted with the introduction of #5695

Passed Non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 132832 W: 34519 L: 34403 D: 63910
Ptnml(0-2): 430, 15754, 33931, 15872, 429
https://tests.stockfishchess.org/tests/view/678158c49168c8bf30927834

Passed Non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 123492 W: 31426 L: 31309 D: 60757
Ptnml(0-2): 79, 13705, 34051, 13842, 69
https://tests.stockfishchess.org/tests/view/6782b07e6ddf09c0b4b6dbb7

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

Bench: 1180439
2025-01-12 21:23:29 +01:00
Shawn Xu 8d517bddff Simplify accumulator updates
AMD Ryzen 5 7600X
```
sf_base =  1902646 +/-   2114 (95%)
sf_test =  1920873 +/-   2515 (95%)
diff    =    18227 +/-   3067 (95%)
speedup = 0.95800% +/- 0.161% (95%)
```

Ryzen 9 5950X
```
sf_base =  1413387 +/-   3592 (95%)
sf_test =  1437893 +/-   3355 (95%)
diff    =    24505 +/-   4669 (95%)
speedup = 1.73380% +/- 0.330% (95%)
```

Intel Core i7-6700K
```
sf_base =   912476 +/-   1863 (95%)
sf_test =   921864 +/-   2042 (95%)
diff    =     9388 +/-   3333 (95%)
speedup = 1.02893% +/- 0.365% (95%)
```

Raspberry Pi 5
```
sf_base =   260993 +/-   1508 (95%)
sf_test =   262912 +/-   1746 (95%)
diff    =     1918 +/-   1221 (95%)
speedup = 0.73504% +/- 0.468% (95%)
```

Passed Non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 23072 W: 6041 L: 5813 D: 11218
Ptnml(0-2): 61, 2435, 6319, 2657, 64
https://tests.stockfishchess.org/tests/view/6780a0ca9168c8bf30927757

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

No functional change
2025-01-12 21:21:53 +01:00
Shawn Xu 28c07fb456 Simplify Probcut Condition
Rebased and properly guarded #5720

Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 179616 W: 45764 L: 45706 D: 88146
Ptnml(0-2): 125, 19665, 50162, 19739, 117
https://tests.stockfishchess.org/tests/view/677590531a2f267f20548b82

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 445728 W: 113467 L: 113682 D: 218579
Ptnml(0-2): 331, 49226, 123900, 49141, 266
https://tests.stockfishchess.org/tests/view/67734f351a2f267f205489d9

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

Bench: 1180421
2025-01-12 21:18:39 +01:00
Disservin ea71a08843 Improve Instrumented Python Testing Script
For betting debugging and earlier stop in case of termination, like in
https://github.com/official-stockfish/Stockfish/pull/5754#issuecomment-2576120357

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

No functional change
2025-01-12 21:18:08 +01:00
Maxim Masiutin d49fd9090b Add .gitattributes for script LE
closes https://github.com/official-stockfish/Stockfish/pull/5753

No functional change
2025-01-12 21:16:32 +01:00
pb00067 c88a5b3950 Simplify away hint for common parent position at probcut
Since it's introduction at probcut step the nnue network has changed
substantially and now it no longer seems useful.

Passed non-regression test at STC
https://tests.stockfishchess.org/tests/view/675fe27986d5ee47d9542d86
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 118656 W: 30732 L: 30609 D: 57315
Ptnml(0-2): 319, 12767, 33049, 12858, 335

N.B.: It may be useful to reintroduce it here at probcut if we know that
a node that was cut away previously now has to be explored. Exploring
new ground will deliver no tt-hits so in this case the hint for common
parent position might be useful.

No functional change
2025-01-12 21:15:35 +01:00
Shawn Xu 403a5e100b Simplify Fail-Low Bonus
Passed Non-regression STC:
LLR: 2.92 (-2.94,2.94) <-1.75,0.25>
Total: 66592 W: 17426 L: 17239 D: 31927
Ptnml(0-2): 208, 7812, 17109, 7919, 248
https://tests.stockfishchess.org/tests/view/6774e1711a2f267f20548b22

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 179616 W: 45764 L: 45706 D: 88146
Ptnml(0-2): 125, 19665, 50162, 19739, 117
https://tests.stockfishchess.org/tests/view/677590531a2f267f20548b82

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

Bench: 1310158
2025-01-12 21:14:11 +01:00
Shawn Xu 5370c3035e Refactor Stats Array
* Limit use of `StatsEntry` wrapper to arithmetic types
* Generalize `Stats` to `MultiArray` by discarding the template parameter `D`
* Allow `MultiArray::fill` to take any type assignable to element type
* Remove now-unused operator overloads on `StatsEntry`

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

No functional change
2025-01-12 21:13:14 +01:00
Shawn Xu c47e6fcf84 Small cleanup of nnue_feature_transformer.h
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 285760 W: 73716 L: 73768 D: 138276
Ptnml(0-2): 777, 30775, 79851, 30677, 800
https://tests.stockfishchess.org/tests/view/676f78681a2f267f205485aa

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

No functional change
2025-01-12 21:11:59 +01:00
Shawn Xu d1a1ff4f17 Simplify Razoring
Passed Non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 95584 W: 24906 L: 24750 D: 45928
Ptnml(0-2): 285, 11227, 24632, 11343, 305
https://tests.stockfishchess.org/tests/view/675e0ed286d5ee47d95429ee

Passed Non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 191292 W: 48637 L: 48589 D: 94066
Ptnml(0-2): 97, 21061, 53276, 21121, 91
https://tests.stockfishchess.org/tests/view/675f08c686d5ee47d9542be3

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

Bench: 1286274
2025-01-12 21:11:27 +01:00
sscg13 7858f9dfdc Use same pawn value in both nets when doing material scaling of eval
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 221312 W: 57291 L: 57274 D: 106747
Ptnml(0-2): 760, 26152, 56841, 26117, 786
https://tests.stockfishchess.org/tests/view/676e2a101a2f267f20548453

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 176808 W: 45084 L: 45023 D: 86701
Ptnml(0-2): 112, 19418, 49286, 19473, 115
https://tests.stockfishchess.org/tests/view/676f424d1a2f267f2054857f

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

Bench: 1121800
2025-01-12 21:09:58 +01:00
Daniel Monroe c76c179361 Remove non-functional std::min()
closes https://github.com/official-stockfish/Stockfish/pull/5749

No functional change
2025-01-06 00:48:05 +01:00
Daniel Monroe 1611b9c940 Corrplexity for futility pruning
Add corrhist-based term to futility margin

Inspired by a recent patch of Shawn Xu, this tweak increases the margin
over beta needed to futility prune based on the correction history, with
an offset.

Passed STC
LLR: 2.97 (-2.94,2.94) <0.00,2.00>
Total: 545504 W: 141957 L: 140885 D: 262662
Ptnml(0-2): 1829, 64226, 139551, 65336, 1810
https://tests.stockfishchess.org/tests/view/67634a8386d5ee47d95439db

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 125994 W: 32199 L: 31695 D: 62100
Ptnml(0-2): 97, 13742, 34798, 14280, 80
https://tests.stockfishchess.org/tests/view/6765cf9986d5ee47d9544217

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

Bench: 999324
2025-01-06 00:46:30 +01:00
Shawn Xu 5488dd2f91 Update Copyright Year
closes https://github.com/official-stockfish/Stockfish/pull/5747

No functional change
2025-01-06 00:45:28 +01:00
Shawn Xu 00da3ff463 Cleanup stats entry
Prevents potential issue caused by publicly inheriting from STL container types

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

No functional change
2025-01-06 00:44:25 +01:00
Shawn Xu 5cf6f99177 Remove some incorrectly marked const qualifiers
closes https://github.com/official-stockfish/Stockfish/pull/5744

No functional change
2025-01-06 00:43:49 +01:00
Shawn Xu 78b5733939 Simplify post-lmr conthist bonus
Passed Non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 49184 W: 12735 L: 12528 D: 23921
Ptnml(0-2): 134, 5746, 12647, 5909, 156
https://tests.stockfishchess.org/tests/view/6765cd2e86d5ee47d954420e

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 177270 W: 45227 L: 45166 D: 86877
Ptnml(0-2): 132, 19498, 49302, 19583, 120
https://tests.stockfishchess.org/tests/view/676721fd86d5ee47d9544489

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

Bench: 1042099
2025-01-06 00:43:37 +01:00
Michael Chaly 03e4cde729 Allow Pv nodes at certain conditions to spawn zero window searches deeper than default
In current case it's allowed if there is no best move.

Passed STC:
https://tests.stockfishchess.org/tests/view/67640fd586d5ee47d9543d5a
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 392480 W: 102038 L: 101192 D: 189250
Ptnml(0-2): 1303, 46287, 100253, 47055, 1342

Passed LTC:
https://tests.stockfishchess.org/tests/view/67671a4686d5ee47d9544476
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 128616 W: 32941 L: 32433 D: 63242
Ptnml(0-2): 84, 13997, 35634, 14513, 80

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

Bench: 1095871
2025-01-06 00:40:05 +01:00
mstembera f656fdfa9a Simplify Zobrist keys for captures
The Zobrist keys for NO_PIECE are 0 so no need to special case captures.
Also the TranspositionTable reference passed to do_null_move() can be
const.

STC Simplification:
https://tests.stockfishchess.org/tests/view/6764a79a86d5ee47d9544005
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 114240 W: 29654 L: 29523 D: 55063
Ptnml(0-2): 329, 12360, 31620, 12473, 338

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

No functional change
2024-12-22 15:29:42 +01:00
Michael Chaly 79261bec59 Simplify away reductions adjustment for multithreaded search
Seem to no longer bring measurable benefit.

Passed STC SMP simplification:
https://tests.stockfishchess.org/tests/view/6753561a86d5ee47d954151f
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 38000 W: 9864 L: 9656 D: 18480
Ptnml(0-2): 53, 4177, 10320, 4409, 41

Passed LTC SMP simplification:
https://tests.stockfishchess.org/tests/view/6753d75f86d5ee47d9541669
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 258674 W: 66314 L: 66335 D: 126025
Ptnml(0-2): 77, 26957, 75303, 26910, 90

Passed 16 threads LTC simplification:
https://tests.stockfishchess.org/tests/view/675a066286d5ee47d9542296
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 221804 W: 56950 L: 56936 D: 107918
Ptnml(0-2): 34, 21491, 67839, 21503, 35

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

Bench: 1294909
2024-12-22 15:28:15 +01:00
Disservin 4bc2a24245 Workaround for clang-format bug
closes https://github.com/official-stockfish/Stockfish/pull/5728

No functional change
2024-12-22 15:27:40 +01:00
Shawn Xu e7e78aa09e Adjust LMR with correction history
A positive constant increase in base reduction is applied to counter the
decrease in average reduction from this tweak.

Passed STC:
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 109216 W: 28415 L: 27989 D: 52812
Ptnml(0-2): 310, 12848, 27911, 13184, 355
https://tests.stockfishchess.org/tests/view/6760bb0e86d5ee47d9542f26

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 66918 W: 17073 L: 16694 D: 33151
Ptnml(0-2): 33, 7175, 18666, 7550, 35
https://tests.stockfishchess.org/tests/view/6761e10f86d5ee47d95431fa

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

Bench: 1294909
2024-12-22 15:26:39 +01:00
FauziAkram a04b07265f Make reductionScale smoother
Making the second part of the formula smoother, changing it to a linear
function, increasing steadily as reductionScale increases and at the
same time, it should be a little bit simpler, therefore the
simplification bounds.

Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 83040 W: 21493 L: 21322 D: 40225
Ptnml(0-2): 252, 9848, 21209, 9899, 312
https://tests.stockfishchess.org/tests/view/6762145486d5ee47d9543242

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 230124 W: 58485 L: 58478 D: 113161
Ptnml(0-2): 175, 25620, 63484, 25589, 194
https://tests.stockfishchess.org/tests/view/6762d4ef86d5ee47d9543367

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

Bench: 1204658
2024-12-22 15:24:09 +01:00
Shawn Xu 6075e787d0 Add CI test with glibcxx assertions enabled
Re: https://github.com/official-stockfish/Stockfish/pull/5721#pullrequestreview-2504542601

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

No functional change
2024-12-22 15:20:25 +01:00
Disservin 2dc47e4345 Cleanup Evaluate Calls
Makes code a bit easier to read as well.

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

No functional change
2024-12-22 15:19:53 +01:00
Shawn Xu 77ec878ffa Prevent out of bounds access of dbg info arrays
closes https://github.com/official-stockfish/Stockfish/pull/5721

No functional change
2024-12-22 15:19:13 +01:00
Daniel Monroe ba145332c9 Remove time reduction for recaptures
Passed simplification STC
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 54016 W: 14098 L: 13902 D: 26016
Ptnml(0-2): 165, 5797, 14919, 5931, 196
https://tests.stockfishchess.org/tests/view/6758a90486d5ee47d954201e

Passed simplification LTC
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 296940 W: 75631 L: 75689 D: 145620
Ptnml(0-2): 145, 28928, 90384, 28866, 147
https://tests.stockfishchess.org/tests/view/6758df7a86d5ee47d9542091

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

Bench: 1148169
2024-12-22 15:17:55 +01:00
Shawn Xu e770b55f7f Remove Extraneous Parenthesis
No longer needed after
https://github.com/official-stockfish/Stockfish/pull/5667.

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

No functional change
2024-12-22 15:17:33 +01:00
Disservin 1776448917 Move Embedded Net Data out of Anon Namespace
fixes https://github.com/official-stockfish/Stockfish/issues/5714

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

No functional change
2024-12-22 15:16:07 +01:00
Disservin f414d490bc Update Incbin Library
No functional change
2024-12-22 15:16:01 +01:00
Shawn Xu b822fdf2f2 Tune histories
Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 268736 W: 70080 L: 69421 D: 129235
Ptnml(0-2): 831, 31795, 68460, 32448, 834
https://tests.stockfishchess.org/tests/view/6750778886d5ee47d9540e7c

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 505356 W: 129145 L: 127868 D: 248343
Ptnml(0-2): 307, 54901, 140959, 56230, 281
https://tests.stockfishchess.org/tests/view/675367de86d5ee47d9541536

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

Bench: 1148169
2024-12-22 15:14:22 +01:00
Nonlinear2 cf10644d6e Fix duplicate code (#5711)
closes https://github.com/official-stockfish/Stockfish/pull/5711

No functional change
2024-12-08 22:24:29 +01:00
mstembera a8b6bf1b1a Small Major/Minor piece key simplification/optimization.
closes https://github.com/official-stockfish/Stockfish/pull/5710

No functional change
2024-12-08 19:58:34 +01:00
Michael Chaly afaf3a0f2a Refine statscore for captures
Continuation of previous attempts there.
Now instead of using capture history with a static offset also add the
value of the captured piece in the same way at it is used in movepicker.

Passed STC:
https://tests.stockfishchess.org/tests/view/674aa3d386d5ee47d95404aa
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 116480 W: 30433 L: 29999 D: 56048
Ptnml(0-2): 361, 13720, 29662, 14118, 379

Passed LTC:
https://tests.stockfishchess.org/tests/view/674c4b2d86d5ee47d954073f
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 133542 W: 34365 L: 33847 D: 65330
Ptnml(0-2): 78, 14585, 36934, 15089, 85

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

Bench: 934447
2024-12-08 19:57:59 +01:00
xu-shawn e8d2ba194a Add Leela Data Attribution
closes https://github.com/official-stockfish/Stockfish/pull/5705

No functional change
2024-12-08 19:56:01 +01:00
Shawn Xu 6a8478c6ad Simplify Prior Capture Countermove Bonus
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 184032 W: 47626 L: 47568 D: 88838
Ptnml(0-2): 590, 21808, 47238, 21714, 666
https://tests.stockfishchess.org/tests/view/67412c7686d5ee47d953f743

Passed Non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 169218 W: 43395 L: 43323 D: 82500
Ptnml(0-2): 302, 18567, 46791, 18655, 294
https://tests.stockfishchess.org/tests/view/6743b7e086d5ee47d953f9a6

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

Bench: 1130692
2024-12-08 19:55:10 +01:00
Carlos Esparza 1f9404434d Simplify picking of evasion moves
Sort evasions before we start returning them in next_move() (just like
every other kind of move) instead of looking for the biggest element on
every call to next_move(). The bench number changes because the old
method is not equivalent to a stable sort.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 132064 W: 34318 L: 34204 D: 63542
Ptnml(0-2): 392, 15522, 34106, 15604, 408
https://tests.stockfishchess.org/tests/view/6743fee086d5ee47d953f9ca

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 97542 W: 24899 L: 24757 D: 47886
Ptnml(0-2): 63, 10646, 27193, 10824, 45
https://tests.stockfishchess.org/tests/view/674509cd86d5ee47d953fb96

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

Bench: 1094825
2024-12-08 19:54:18 +01:00
pb00067 713000c517 Same weight for black and white nonPawnCorrection history
Since we don't have color dependent parameters in NNUE eval, it also has
no sense IMO to have color dependent parameters in correction histories.

Ideally a fixed depth search on a single thread should be determistic,
so delivering the same result (move) if we just flip colors on the
board.

Patch replaces 2 parameters (122 and 185) with just one value 154 (= the avg of the two).

Passed STC-non regression
https://tests.stockfishchess.org/tests/view/6740a63286d5ee47d953f656
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 122336 W: 31499 L: 31372 D: 59465
Ptnml(0-2): 336, 14535, 31301, 14658, 338

Passed LTC-non regression
https://tests.stockfishchess.org/tests/view/67419bae86d5ee47d953f7b6
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 101400 W: 25870 L: 25731 D: 49799
Ptnml(0-2): 78, 11109, 28166, 11290, 57

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

Bench: 1215483
2024-12-08 19:52:16 +01:00
FauziAkram d5a36a3c92 Simplify probCutBeta formula
After recent changes to the improving definition, seems like there is no
need anymore to keep opponentWorsening in the probCutBeta formula.

Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 214272 W: 55566 L: 55541 D: 103165
Ptnml(0-2): 620, 25540, 54817, 25513, 646
https://tests.stockfishchess.org/tests/view/6735243d86d5ee47d953eaea

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 126708 W: 32329 L: 32216 D: 62163
Ptnml(0-2): 68, 13986, 35123, 14119, 58
https://tests.stockfishchess.org/tests/view/67393cf686d5ee47d953ef99

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

Bench: 983067
2024-12-08 19:49:01 +01:00
Nonlinear2 da82942b54 Add functions to check for decisive scores
Thanks to peregrineshahin and robbyrobbyrob for their suggestions.

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

No functional change
2024-12-08 19:48:49 +01:00
Nonlinear2 57e06be71f Add functions to check for decisive scores
Thanks to peregrineshahin and robbyrobbyrob for their suggestions.

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

No functional change
2024-12-08 19:47:02 +01:00
Daniel Monroe 70bb317afe Bonus for a prior capture that causes a fail low.
This tweak adds a bonus equal to twice the stat_bonus for the current depth for a prior capture that caused a fail high, similar to the prior countermove bonus we currently have.

Passed STC
https://tests.stockfishchess.org/tests/view/673bc14b86d5ee47d953f1f2
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 105824 W: 27538 L: 27118 D: 51168
Ptnml(0-2): 358, 12370, 27024, 12814, 346

Passed LTC
https://tests.stockfishchess.org/tests/view/673ccbff86d5ee47d953f2d9
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 134502 W: 34340 L: 33820 D: 66342
Ptnml(0-2): 102, 14634, 37229, 15214, 72

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

Bench: 1107054
2024-12-08 19:46:07 +01:00
Daniel Monroe 55905e562a Simplify movepick coefficients
This commit sets movepick weights for all continuation histories to 1
and doubles the weight for the main history, inspired by a recent tune.

Passed STC
https://tests.stockfishchess.org/tests/view/6735151a86d5ee47d953eaa2
LLR: 2.92 (-2.94,2.94) <-1.75,0.25>
Total: 29984 W: 7840 L: 7612 D: 14532
Ptnml(0-2): 85, 3511, 7571, 3741, 84

Passed LTC
https://tests.stockfishchess.org/tests/view/673667a986d5ee47d953ec78
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 26268 W: 6726 L: 6510 D: 13032
Ptnml(0-2): 16, 2797, 7288, 3021, 12

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

Bench: 1130293
2024-12-08 19:45:48 +01:00
Shawn Xu b7f17346e5 Fix Sanitizer Tests
closes https://github.com/official-stockfish/Stockfish/pull/5692

No functional change
2024-11-22 23:41:34 +01:00
Daniel Monroe fb6be17ad4 Simplify statscore at captures
Simplify statscores for captures, setting them to 0

A recent tweak of Vizvezdenec finds substantial elo gain from giving
captures a separate statscore, which is used mainly for reductions. The
idea is that the old combination of quiet histories was inappropriate
and that a value based on the capture history is more suitable. This
simplification sets the statscore for captures to 0, suggesting that the
elo gain came from rectifying the quiet history/capture mismatch.

Passed STC (against a slightly older version of Viz's patch)
https://tests.stockfishchess.org/tests/view/673ac6e286d5ee47d953f0ec
LR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 57312 W: 14872 L: 14672 D: 27768
Ptnml(0-2): 152, 6761, 14649, 6923, 171

Passed LTC (against Viz's newest patch)
https://tests.stockfishchess.org/tests/view/673cd00686d5ee47d953f2db
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 88236 W: 22510 L: 22358 D: 43368
Ptnml(0-2): 70, 9530, 24745, 9724, 49

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

Bench: 959947
2024-11-22 23:34:15 +01:00
Shawn Xu 4fcd78ceb4 Simplify Probcut Bonus
Passed STC:
LLR: 2.99 (-2.94,2.94) <-1.75,0.25>
Total: 172288 W: 44656 L: 44580 D: 83052
Ptnml(0-2): 507, 20650, 43782, 20670, 535
https://tests.stockfishchess.org/tests/view/673b74f986d5ee47d953f1a3

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 94596 W: 24098 L: 23953 D: 46545
Ptnml(0-2): 57, 10322, 26393, 10471, 55
https://tests.stockfishchess.org/tests/view/673d191886d5ee47d953f337

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

Bench: 1031022
2024-11-22 23:31:34 +01:00
Michael Chaly cd3c13a883 Further tweak statscore for captures
Even lower offset.

Passed STC:
https://tests.stockfishchess.org/tests/view/673a66d786d5ee47d953f070
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 63776 W: 16570 L: 16216 D: 30990
Ptnml(0-2): 178, 7371, 16478, 7641, 220

Passed LTC:
https://tests.stockfishchess.org/tests/view/673b2e2a86d5ee47d953f14b
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 156960 W: 39999 L: 39435 D: 77526
Ptnml(0-2): 96, 16965, 43803, 17511, 105

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

Bench: 867931
2024-11-22 23:29:37 +01:00
Guenther Demetz d29c8bd5d4 Rewrite of 'Adjust correction history' condition
Current condition is convoluted and hard to understand because of
several negations. Also added 2 comments to make the concept behind the
condition better understandable.

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

No functional change
2024-11-22 23:24:15 +01:00
FauziAkram 0282edc0b0 Simplify bonus formula
Give full bonus instead of half.

Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 23872 W: 6254 L: 6018 D: 11600
Ptnml(0-2): 80, 2691, 6152, 2939, 74
https://tests.stockfishchess.org/tests/view/673b709686d5ee47d953f19d

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 42894 W: 10924 L: 10725 D: 21245
Ptnml(0-2): 30, 4592, 12011, 4777, 37
https://tests.stockfishchess.org/tests/view/673bb50386d5ee47d953f1eb

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

Bench: 836558
2024-11-22 23:23:42 +01:00
Michael Chaly f129bf0de9 Tweak statscore for captures
Followup of a recent patch that separated statscore for captures and non-captures.
Lower value that we subtract from statscore if a move is a capture.

Passed STC:
https://tests.stockfishchess.org/tests/view/67385b6786d5ee47d953eeba
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 50592 W: 13223 L: 12888 D: 24481
Ptnml(0-2): 154, 5853, 12931, 6220, 138

Passed LTC:
https://tests.stockfishchess.org/tests/view/6739056e86d5ee47d953ef3f
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 23598 W: 6155 L: 5862 D: 11581
Ptnml(0-2): 16, 2466, 6543, 2757, 17

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

Bench: 771180
2024-11-22 23:12:43 +01:00
Michael Chaly 82b092ca48 Adjust statscore for captures
Instead of using quiet histories use capture history with a different
offset.

Passed STC:
https://tests.stockfishchess.org/tests/view/6731d5cc86d5ee47d953e719
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 428896 W: 111160 L: 110269 D: 207467
Ptnml(0-2): 1220, 50296, 110534, 51169, 1229

Passed LTC:
https://tests.stockfishchess.org/tests/view/6733d9fd86d5ee47d953e962
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 105882 W: 26918 L: 26458 D: 52506
Ptnml(0-2): 66, 11430, 29482, 11904, 59

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

Bench: 840721
2024-11-13 20:35:02 +01:00
Disservin 49138b8c33 Fix CI Docker Buildx
closes https://github.com/official-stockfish/Stockfish/pull/5678

No functional change
2024-11-13 20:35:02 +01:00
FauziAkram ce2d9e27ea Simplify big-net reevaluation
Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 37408 W: 9699 L: 9477 D: 18232
Ptnml(0-2): 130, 4326, 9577, 4534, 137
https://tests.stockfishchess.org/tests/view/672ffd8086d5ee47d953e633

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 151062 W: 38087 L: 37999 D: 74976
Ptnml(0-2): 63, 16686, 41958, 16748, 76
https://tests.stockfishchess.org/tests/view/673087aa86d5ee47d953e66b

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

Bench: 848812
2024-11-13 20:35:02 +01:00
Linmiao Xu 070db8b3a1 Update default main net to nn-1c0000000000.nnue
Found by updating 489 L2 weights with values found from around
31k / 60k spsa games.

Spsa was configured to use 60k games, down from 120k games in:
https://github.com/official-stockfish/Stockfish/pull/5459

623 spsa params:
L2 weights from `nn-1cedc0ffeeee.nnue` where 24 <= |value| <= 30
A: 3000, alpha: 0.602, gamma: 0.101
weights: [-127, 127], c_end = 6

Passed STC:
https://tests.stockfishchess.org/tests/view/6728d61e86d5ee47d953dcaf
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 187168 W: 48642 L: 48107 D: 90419
Ptnml(0-2): 558, 21888, 48213, 22311, 614

Passed LTC:
https://tests.stockfishchess.org/tests/view/672b018f86d5ee47d953de98
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 235074 W: 59924 L: 59202 D: 115948
Ptnml(0-2): 131, 25467, 65610, 26207, 122

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

Bench: 898850
2024-11-13 20:35:02 +01:00
Nonlinear2 43e100ae06 Use cutnode as TT Cutoff Condition
At low enough depths, fail high with TT only when expected cutnode.

Passed STC:
https://tests.stockfishchess.org/tests/view/6726357b86d5ee47d953da8c
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 41184 W: 10873 L: 10551 D: 19760
Ptnml(0-2): 131, 4728, 10554, 5046, 133

Passed LTC:
https://tests.stockfishchess.org/tests/view/6727326a86d5ee47d953db30
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 270888 W: 69040 L: 68243 D: 133605
Ptnml(0-2): 180, 29385, 75485, 30246, 148

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

Bench: 805776
2024-11-13 20:35:02 +01:00
Muzhen Gaming 3d084e9164 VVLTC Search Tune
A single tuning run of 190k games was conducted:
https://tests.stockfishchess.org/tests/view/670f3e3786d5ee47d953c554.

Passed VVLTC 1st sprt:
https://tests.stockfishchess.org/tests/view/672344dc86d5ee47d953d8c3
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 56768 W: 14615 L: 14323 D: 27830
Ptnml(0-2): 3, 5152, 17789, 5430, 10

Passed VVLTC 2nd sprt (rebased):
https://tests.stockfishchess.org/tests/view/6726d83786d5ee47d953db03
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 57884 W: 14885 L: 14554 D: 28445
Ptnml(0-2): 5, 5300, 17999, 5635, 3

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

Bench: 920336
2024-11-13 20:34:53 +01:00
Shawn Xu cc5c67c564 Introduce Fractional LMR
Tuning Run (90k Games):
https://tests.stockfishchess.org/tests/view/67202b1c86d5ee47d953d442

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 241024 W: 62616 L: 62001 D: 116407
Ptnml(0-2): 716, 28231, 62015, 28822, 728
https://tests.stockfishchess.org/tests/view/6725196786d5ee47d953d9f2

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 92532 W: 23678 L: 23246 D: 45608
Ptnml(0-2): 45, 9981, 25797, 10383, 60
https://tests.stockfishchess.org/tests/view/6727d3cb86d5ee47d953db9d

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

Bench: 1066071
2024-11-13 20:12:47 +01:00
mstembera f77bac3dca Remove stale Cache::clear() method
closes https://github.com/official-stockfish/Stockfish/pull/5666

No functional change
2024-11-13 20:11:03 +01:00
FauziAkram 54cf226604 Revert VLTC regression from #5634
https://tests.stockfishchess.org/tests/view/671bf61b86d5ee47d953cf23

And thanks to @xu-shawn for suggesting running a VLTC regress test since
depth modifications affect scaling. Also, the LTC was showing a slight
regress after 680+k games  ~= -0.34 , for reference:
https://tests.stockfishchess.org/tests/view/67042b1f86d5ee47d953be7c

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

Bench: 1307308
2024-11-13 20:09:13 +01:00
Michael Chaly ecf5646f6e Refine definition of improving
This patch also allows improving flag to be true if static evaluation of
the position is good enough.

Passed STC:
https://tests.stockfishchess.org/tests/view/6720906086d5ee47d953d4d0
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 34816 W: 9172 L: 8858 D: 16786
Ptnml(0-2): 113, 3988, 8887, 4312, 108

Passed LTC:
https://tests.stockfishchess.org/tests/view/6721162686d5ee47d953d597
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 145374 W: 37118 L: 36574 D: 71682
Ptnml(0-2): 91, 15875, 40212, 16417, 92

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

Bench: 1518856
2024-11-13 20:08:14 +01:00
Shawn Xu c2611efe5c Move history code to a separate header
Since no correction histories are ever used inside Movepick, and many
existing histories are closely integrated into search, it might be more
logical to separate them into their own header. PR based on #5650

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

No functional change
2024-11-13 20:07:15 +01:00
mstembera 16fee2a7da Cleanup TT::hashfull()
closes https://github.com/official-stockfish/Stockfish/pull/5651

No functional change
2024-11-13 20:06:49 +01:00
MinetaS 24c57793e1 Remove moveCountPruning in search.cpp
The definition of moveCountPruning may cause confusion by implying that
the variable is unconstrained. However, once it is set to true, it
should not be reset to false, otherwise it would break the internal
logic of MovePicker.

Several patches have overlooked this constraint. For example:
https://tests.stockfishchess.org/tests/view/671e7c0486d5ee47d953d226
https://tests.stockfishchess.org/tests/view/66a1de7b4ff211be9d4eccea

The implementation approach was suggested by Disservin.

Passed non-regression STC:
LLR: 3.02 (-2.94,2.94) <-1.75,0.25>
Total: 180672 W: 47072 L: 47006 D: 86594
Ptnml(0-2): 536, 19482, 50247, 19522, 549
https://tests.stockfishchess.org/tests/view/6720df6f86d5ee47d953d542

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

No functional change
2024-10-31 10:08:34 +01:00
FauziAkram 8681d3c2b3 Simplify Time Management Formula
Decreasing the number of operations
Passed STC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 38880 W: 10038 L: 9823 D: 19019
Ptnml(0-2): 92, 4334, 10395, 4505, 114
https://tests.stockfishchess.org/tests/view/67112bf586d5ee47d953c6be

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 242844 W: 61425 L: 61431 D: 119988
Ptnml(0-2): 145, 25175, 70797, 25151, 154
https://tests.stockfishchess.org/tests/view/6712387486d5ee47d953c737

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

Bench: 1281912
2024-10-31 10:07:24 +01:00
Shawn Xu 4a9c980f3b Template Corrhist
Avoids duplication of `using ... = Stats<int16_t,
CORRECTION_HISTORY_LIMIT, COLOR_NB, CORRECTION_HISTORY_SIZE>;`

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

No functional change

Co-authored-by: Disservin <disservin.social@gmail.com>
2024-10-31 09:27:12 +01:00
Michael Chaly 8ef403c786 Small cleanup for stats adjustments
After some simplifications bonuses and maluses are the same for quiet
and non-quiet moves so it makes no sense to use quietMoveBonus/Malus,
instead use just bonus/malus.

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

No functional change
2024-10-31 09:26:00 +01:00
Disservin c15113554f Speedup Makefile on Windows
The Makefile is notoriously slow on windows, because of new processes
being spawned I believe. This pr improves it a little bit for the help
and config-sanity targets, with the latter also improving `make -j
build` because it depends on that. On the same machine ubuntu (wsl) is
more than 3 times faster, if there are other improvements we can make
I'd be happy to hear about them. Ultimately
https://github.com/official-stockfish/Stockfish/pull/5543 also aims to
improve this I believe, but it will take some additional time before
that lands.

```
make config-sanity:

    patch: 6.199s
    master: 12.738s

make help:

    patch: 3.1s
    master: 11.49s

make -j build:

    patch: 36s
    master: 43.25s

make -j build:

    master ubuntu: 10s
```

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

No functional change
2024-10-31 09:25:59 +01:00
FauziAkram 2ce47573b4 Remove -stat_malus(newDepth)
Passed STC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 92544 W: 23940 L: 23778 D: 44826
Ptnml(0-2): 286, 10936, 23638, 11154, 258
https://tests.stockfishchess.org/tests/view/670c3d6986d5ee47d953c30b

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 43164 W: 10986 L: 10786 D: 21392
Ptnml(0-2): 27, 4713, 11905, 4907, 30
https://tests.stockfishchess.org/tests/view/670eda3d86d5ee47d953c51d

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

Bench: 1281912
2024-10-31 09:25:59 +01:00
FauziAkram b325b2c348 Simplify bestValue formula
Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 45888 W: 12051 L: 11841 D: 21996
Ptnml(0-2): 123, 5356, 11807, 5504, 154
https://tests.stockfishchess.org/tests/view/670bb89086d5ee47d953c2d8

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 51336 W: 13021 L: 12830 D: 25485
Ptnml(0-2): 34, 5594, 14227, 5773, 40
https://tests.stockfishchess.org/tests/view/670c587f86d5ee47d953c31b

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

Bench: 1192999
2024-10-31 09:25:59 +01:00
FauziAkram 7f386d109e Remove material corrHist
Passed STC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 80832 W: 21150 L: 20975 D: 38707
Ptnml(0-2): 283, 9531, 20598, 9736, 268
https://tests.stockfishchess.org/tests/view/670302fe86d5ee47d953bd68

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 46008 W: 11621 L: 11423 D: 22964
Ptnml(0-2): 30, 5072, 12606, 5262, 34
https://tests.stockfishchess.org/tests/view/6704074686d5ee47d953be53

Passed LTC Rebased:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 95814 W: 24340 L: 24195 D: 47279
Ptnml(0-2): 71, 10497, 26602, 10690, 47
https://tests.stockfishchess.org/tests/view/670ae1ac86d5ee47d953c262

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

Bench: 1119774
2024-10-31 09:25:56 +01:00
Taras Vuk bf2a0d5392 Simplify internal iterative reductions
Passed STC:
LLR: 2.92 (-2.94,2.94) <-1.75,0.25>
Total: 138656 W: 36182 L: 36074 D: 66400
Ptnml(0-2): 523, 16422, 35310, 16570, 503
https://tests.stockfishchess.org/tests/view/6702beb386d5ee47d953bd41

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 680844 W: 172021 L: 172480 D: 336343
Ptnml(0-2): 492, 76259, 187419, 75720, 532
https://tests.stockfishchess.org/tests/view/67042b1f86d5ee47d953be7c

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

Bench: 1169252
2024-10-31 09:13:35 +01:00
FauziAkram 2f3e6198e8 Simplify optimism divisor.
Passed STC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 139360 W: 36143 L: 36033 D: 67184
Ptnml(0-2): 436, 16456, 35778, 16582, 428
https://tests.stockfishchess.org/tests/view/66fc49c786d5ee47d953b94e

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 257748 W: 65163 L: 65184 D: 127401
Ptnml(0-2): 173, 28471, 71611, 28442, 177
https://tests.stockfishchess.org/tests/view/66ff01ae86d5ee47d953bb54

Passed LTC against rebased version:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 53610 W: 13691 L: 13501 D: 26418
Ptnml(0-2): 52, 5942, 14605, 6176, 30
https://tests.stockfishchess.org/tests/view/670a9c5c86d5ee47d953c231

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

Bench: 1282078
2024-10-31 09:12:34 +01:00
Linmiao Xu 656b2cb645 Update default main net to nn-1cedc0ffeeee.nnue
Created by setting output weights (256) and biases (8) of the previous main net
nn-1111cefa1111.nnue to values found with spsa after 38k / 120k games at 120+1.2
using the same method as:
https://github.com/official-stockfish/Stockfish/pull/5459

nn-1111cefa1111.nnue -> nn-1cedc0ffeeee.nnue
  # weights changed: 185
  mean: 0.0703 +/- 2.53
  min: -6
  max:  6

Passed STC:
https://tests.stockfishchess.org/tests/view/6703589b86d5ee47d953bda1
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 101984 W: 26690 L: 26275 D: 49019
Ptnml(0-2): 375, 11944, 25926, 12385, 362

Passed LTC:
https://tests.stockfishchess.org/tests/view/670542d286d5ee47d953befa
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 106224 W: 27079 L: 26618 D: 52527
Ptnml(0-2): 71, 11508, 29487, 11981, 65

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

Bench: 1351413
2024-10-31 09:12:20 +01:00
Michael Chaly 9766db8139 Make low ply history size fixed
Size of low ply history should always be the same, so ensure it.

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

No functional change
2024-10-12 16:40:55 +02:00
Shawn Xu b261df970d Fix majorPieceKey Updates
Passed STC:
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 476160 W: 124285 L: 123311 D: 228564
Ptnml(0-2): 1662, 56266, 121219, 57302, 1631
https://tests.stockfishchess.org/tests/view/66ea3dc186d5ee47d953ae07

Failed Yellow LTC:
LLR: -2.94 (-2.94,2.94) <0.50,2.50>
Total: 230634 W: 58525 L: 58295 D: 113814
Ptnml(0-2): 113, 25301, 64299, 25451, 153
https://tests.stockfishchess.org/tests/view/66f1825e86d5ee47d953b2ec

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 112344 W: 28590 L: 28462 D: 55292
Ptnml(0-2): 71, 12439, 31039, 12537, 86
https://tests.stockfishchess.org/tests/view/6707474486d5ee47d953bfe3

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

Bench: 1283457
2024-10-12 16:40:49 +02:00
Nonlinear2 aaadbe0572 Introduce mean squared score for delta adjustments
This patch introduces the value `meanSquaredScore`, which makes the
initial delta sensitive to unstable iterative deepening scores.

Passed STC:
https://tests.stockfishchess.org/tests/view/66fed74286d5ee47d953bb42
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 71104 W: 18635 L: 18262 D: 34207
Ptnml(0-2): 234, 8365, 17993, 8714, 246

Passed LTC:
https://tests.stockfishchess.org/tests/view/6700088e86d5ee47d953bbe9
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 212544 W: 54238 L: 53560 D: 104746
Ptnml(0-2): 120, 23093, 59172, 23763, 124

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

Bench: 1395505
2024-10-12 16:40:37 +02:00
Mathias Parnaudeau d4358ddba7 Add autodetection of ppc64 architectures
That allows 'make -j profile-build' work on ppc64 architectures, setting the use of
the appropriate SIMD extension, Altivec or VSX.
For VSX, gcc allows to map SSE2 intrinsics and get benefit of the existing SIMD code.

On PowerMac G5, using altivec provides a performance improvement of 30%.
On Talos 2, using vsx provides a performance improvement of 120%.

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

No functional change
2024-10-12 16:30:44 +02:00
mstembera 76923bb6fe Optimize magics
Reduce the size of the Magics table by half on modern cpu's and lay it
out to match our access pattern. Namely we typically access the magics
for the same square for both bishop and rook back to back so we want
those to be in the same cache line.

https://tests.stockfishchess.org/tests/view/6701c9b386d5ee47d953bcf4
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 121664 W: 31931 L: 31497 D: 58236
Ptnml(0-2): 395, 13658, 32322, 14032, 425

A similar patch minus the size reduction finished yellow
https://tests.stockfishchess.org/tests/view/6695f03f4ff211be9d4ec16c
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 310688 W: 80940 L: 80746 D: 149002
Ptnml(0-2): 1119, 35032, 82846, 35230, 1117

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

No functional change
2024-10-12 16:30:44 +02:00
FauziAkram 9a21e3e996 Simplify bestvalue formula
Passed STC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 163680 W: 42689 L: 42605 D: 78386
Ptnml(0-2): 619, 19555, 41386, 19683, 597
https://tests.stockfishchess.org/tests/view/66f9451386d5ee47d953b7d9

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 96498 W: 24582 L: 24438 D: 47478
Ptnml(0-2): 62, 10642, 26718, 10744, 83
https://tests.stockfishchess.org/tests/view/66fd765786d5ee47d953ba1c

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

Bench: 1309815
2024-10-12 16:30:44 +02:00
mstembera 3348603770 Simplify previous #5608
https://github.com/official-stockfish/Stockfish/pull/5608

STC: https://tests.stockfishchess.org/tests/view/66fb1bab86d5ee47d953b8cc
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 25536 W: 6797 L: 6560 D: 12179
Ptnml(0-2): 93, 2953, 6460, 3148, 114

LTC https://tests.stockfishchess.org/tests/view/66fb690e86d5ee47d953b8eb
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 225114 W: 57200 L: 57188 D: 110726
Ptnml(0-2): 197, 25076, 61995, 25096, 193

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

Bench: 1570076
2024-10-12 16:30:44 +02:00
Disservin dce72913fe Temporarily fix clang-format mismatch
closes https://github.com/official-stockfish/Stockfish/pull/5620

No functional change
2024-10-12 16:30:44 +02:00
Linmiao Xu e046c4ef0d Simplify evaluation scaling
Set digits in adjusted eval params all to 7.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/66fc493d86d5ee47d953b94c
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 57696 W: 15098 L: 14898 D: 27700
Ptnml(0-2): 205, 6784, 14678, 6968, 213

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/66fd4b9386d5ee47d953b9d5
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 93786 W: 23868 L: 23721 D: 46197
Ptnml(0-2): 55, 10322, 25993, 10467, 56

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

Bench: 1277182
2024-10-12 16:30:44 +02:00
Ömer Faruk Tutkun 6592b13d56 Introduce Continuation Correction History
Continuation correction history uses last 2 move to correct static eval.

ContCorrHist first introduced by @martinnovaak in
Motor(https://github.com/martinnovaak/motor/pull/162). Earlier ideas
using last move to correct eval is introduced by @MinusKelvin in
Ice4(https://github.com/MinusKelvin/ice4/commit/45daf7d9ea64ea4efaf0d2b4e99f53e12e08c838)

Passed STC:

LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 310144 W: 81267 L: 80538 D: 148339
Ptnml(0-2): 1160, 36607, 78834, 37286, 1185
https://tests.stockfishchess.org/tests/view/66f96cbc86d5ee47d953b7f7

Passed LTC:

LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 97470 W: 24892 L: 24447 D: 48131
Ptnml(0-2): 63, 10631, 26915, 11050, 76
https://tests.stockfishchess.org/tests/view/66fd59bc86d5ee47d953b9ea

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

Bench: 1143382
2024-10-12 16:30:44 +02:00
Taras Vuk 81c1d31084 Decrease probCutBeta based on opponentWorsening
Passed STC:
LLR: 2.97 (-2.94,2.94) <0.00,2.00>
Total: 62112 W: 16305 L: 15947 D: 29860
Ptnml(0-2): 203, 7226, 15856, 7552, 219
https://tests.stockfishchess.org/tests/view/66f85fc986d5ee47d953b71e

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 129552 W: 33223 L: 32710 D: 63619
Ptnml(0-2): 94, 14250, 35573, 14767, 92
https://tests.stockfishchess.org/tests/view/66f93fef86d5ee47d953b7d2

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

bench: 1511354
2024-10-04 08:35:08 +02:00
Michael Chaly 7ac745a736 Refactor root history into low ply history
This patch changes root history to low ply history - butterfly history for plies < 4.
Doubles weight of this history for root, latter plies have lesser effect.

Passed STC:
https://tests.stockfishchess.org/tests/view/66f77d2386d5ee47d953b65d
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 180992 W: 47362 L: 46830 D: 86800
Ptnml(0-2): 554, 21499, 45928, 21891, 624

Passed LTC:
https://tests.stockfishchess.org/tests/view/66fb557986d5ee47d953b8e5
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 42462 W: 11013 L: 10682 D: 20767
Ptnml(0-2): 33, 4518, 11795, 4855, 30

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

Bench 1264335
2024-10-04 08:32:21 +02:00
Linmiao Xu 0186904f53 Remove evaluation grain
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/66fa345a86d5ee47d953b86e
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 39776 W: 10528 L: 10306 D: 18942
Ptnml(0-2): 134, 4674, 10063, 4870, 147

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/66facfb886d5ee47d953b8a8
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 64230 W: 16484 L: 16305 D: 31441
Ptnml(0-2): 38, 7195, 17483, 7348, 51

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

bench 1013135
2024-10-04 08:29:09 +02:00
Linmiao Xu 2b9154882a Tweak 7 eval params
Values found from 120k / 120k spsa games at 30+0.3

Passed STC:
https://tests.stockfishchess.org/tests/view/66ecd7ce86d5ee47d953b003
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 241312 W: 62994 L: 62373 D: 115945
Ptnml(0-2): 754, 28684, 61280, 29063, 875

Passed LTC:
https://tests.stockfishchess.org/tests/view/66f1f3a286d5ee47d953b331
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 304896 W: 77580 L: 76709 D: 150607
Ptnml(0-2): 198, 33413, 84360, 34274, 203

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

bench 1173651
2024-10-01 21:02:44 +02:00
Taras Vuk c85f802185 Tweak ttCapture reduction
More reduction at shallow depth for quiet moves when ttMove is a capture.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 365728 W: 95896 L: 95090 D: 174742
Ptnml(0-2): 1283, 43133, 93262, 43867, 1319
https://tests.stockfishchess.org/tests/view/66edd35986d5ee47d953b0d5

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 200526 W: 51197 L: 50540 D: 98789
Ptnml(0-2): 119, 21952, 55462, 22613, 117
https://tests.stockfishchess.org/tests/view/66f405dc86d5ee47d953b460

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

bench: 1269487
2024-10-01 20:59:17 +02:00
Shawn Xu d6043970bd Make Correction History Size Uniform
Passed Non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 207232 W: 53834 L: 53802 D: 99596
Ptnml(0-2): 695, 24486, 53200, 24562, 673
https://tests.stockfishchess.org/tests/view/66e9f5a886d5ee47d953ada1

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 99120 W: 25264 L: 25123 D: 48733
Ptnml(0-2): 66, 10803, 27675, 10956, 60
https://tests.stockfishchess.org/tests/view/66ed7ebc86d5ee47d953b056

Passed Non-regression LTC vs #5606:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 208950 W: 53049 L: 53019 D: 102882
Ptnml(0-2): 111, 23232, 57760, 23260, 112
https://tests.stockfishchess.org/tests/view/66f1843886d5ee47d953b2f2

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

bench 1575189
2024-09-28 18:01:31 +02:00
peregrineshahin 56444ce1f7 Push expected cutting late moves up in the move ordering.
since the passing of the LMR verification is coming from a relatively late move
this means we have wasted some time trying/picking other moves, and it would
make sense to push it up in the move ordering for future positions not to be as
late.

Passed STC:
https://tests.stockfishchess.org/tests/view/66f0f69186d5ee47d953b2aa
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 34144 W: 9024 L: 8709 D: 16411
Ptnml(0-2): 137, 3875, 8732, 4192, 136

Passed LTC:
https://tests.stockfishchess.org/tests/view/66f1d84a86d5ee47d953b325
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 62808 W: 16054 L: 15684 D: 31070
Ptnml(0-2): 24, 6725, 17555, 7057, 43

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

bench: 1452807
2024-09-28 18:01:31 +02:00
Tomasz Sobczyk 3ac75cd27d Add a standardized benchmark command speedtest.
`speedtest [threads] [hash_MiB] [time_s]`. `threads` default to system concurrency. `hash_MiB` defaults to `threads*128`. `time_s` defaults to 150.

Intended to be used with default parameters, as a stable hardware benchmark.

Example:
```
C:\dev\stockfish-master\src>stockfish.exe speedtest
Stockfish dev-20240928-nogit by the Stockfish developers (see AUTHORS file)
info string Using 16 threads
Warmup position 3/3
Position 258/258
===========================
Version                    : Stockfish dev-20240928-nogit
Compiled by                : g++ (GNUC) 13.2.0 on MinGW64
Compilation architecture   : x86-64-vnni256
Compilation settings       : 64bit VNNI BMI2 AVX2 SSE41 SSSE3 SSE2 POPCNT
Compiler __VERSION__ macro : 13.2.0
Large pages                : yes
User invocation            : speedtest
Filled invocation          : speedtest 16 2048 150
Available processors       : 0-15
Thread count               : 16
Thread binding             : none
TT size [MiB]              : 2048
Hash max, avg [per mille]  :
    single search          : 40, 21
    single game            : 631, 428
Total nodes searched       : 2099917842
Total search time [s]      : 153.937
Nodes/second               : 13641410
```

-------------------------------

Small unrelated tweaks:
 - Network verification output is now handled as a callback.
 - TT hashfull queries allow specifying maximum entry age.

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

No functional change
2024-09-28 18:01:26 +02:00
Nonlinear2 aff1f67997 simplify see pruning in qsearch
passed non-regression STC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 34880 W: 9193 L: 8968 D: 16719
Ptnml(0-2): 103, 4047, 8935, 4232, 123
https://tests.stockfishchess.org/tests/view/66ee83bd86d5ee47d953b15b

passed non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 69126 W: 17529 L: 17357 D: 34240
Ptnml(0-2): 41, 7507, 19285, 7699, 31
https://tests.stockfishchess.org/tests/view/66ef3e0386d5ee47d953b1d3

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

Bench: 1339840
2024-09-28 17:22:33 +02:00
Joost VandeVondele ae420e735f Tweak Correction histories
tune parameters some more, adjust scores updated for each history

passed STC:
https://tests.stockfishchess.org/tests/view/66ea569186d5ee47d953ae48
LLR: 2.92 (-2.94,2.94) <0.00,2.00>
Total: 36288 W: 9660 L: 9344 D: 17284
Ptnml(0-2): 110, 4207, 9220, 4471, 136

passed LTC:
https://tests.stockfishchess.org/tests/view/66ea9b4e86d5ee47d953ae6f
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 241446 W: 61748 L: 61010 D: 118688
Ptnml(0-2): 173, 26211, 67202, 26979, 158

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

Bench: 1677953
2024-09-28 17:17:44 +02:00
FauziAkram 5d0bb5976e Removed ROOK threatenedByPawn
Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 56608 W: 14788 L: 14588 D: 27232
Ptnml(0-2): 162, 6763, 14313, 6845, 221
https://tests.stockfishchess.org/tests/view/66e83f9c86d5ee47d953ab1d

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 175758 W: 44501 L: 44438 D: 86819
Ptnml(0-2): 125, 19489, 48601, 19526, 138
https://tests.stockfishchess.org/tests/view/66e882d486d5ee47d953ab8a

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

bench: 1241271
2024-09-28 17:17:14 +02:00
Wencey Wang 93869d5d0a Fix native arch builds on loongarch64
Adds support for LSX and LASX

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

No functional change
2024-09-28 17:12:12 +02:00
Shawn Xu 60351b9df9 Introduce Various Correction histories
This patch introduces three additional correction histories, namely,
Major Piece Correction History, Minor Piece Correction History, and
Non-Pawn Correction History.

Introduced by @mcthouacbb in Sirius
(https://github.com/mcthouacbb/Sirius) chess engine. The Major Piece
Correction History is indexed by side-to-move and the Zobrist key
representing the position of the King, Rook, and Queen of both sides.
Likewise, the Minor Piece Correction History is indexed by side-to-move
and the Zobrist key representing the position of the King, Knight, and
Bishop of both sides.

Also See:
https://github.com/mcthouacbb/Sirius/commit/97b85bbaac88ff5a0f63e28776027dd3de77164e
https://github.com/mcthouacbb/Sirius/commit/3099cdef2f13e29805654b5f8153e6ecd5853195

Introduced by @zzzzz151 in Starzix (https://github.com/zzzzz151/Starzix)
chess engine. Non-Pawn correction history consists of side-to-move, side
of Zobrist key, and a Zobrist key representing of the position of all
non-pawn pieces of **one side**. The non-pawn correction values for both
key sides are then summed.

Also See:
https://github.com/zzzzz151/Starzix/commit/34911772f178c27b3a239dda0acb79c397c3a2f0
https://github.com/zzzzz151/Starzix/commit/33e0df8dd2db1d4775974ab12e3390154697f47a

The weights on the final correction value of the above correction
histories, as well as existing correction histories, are then tuned in
two separate SPSA sessions, totaling 75k games.

SPSA1:
https://tests.stockfishchess.org/tests/view/66e5243886d5ee47d953a86b
(Stopped early due to some weights reaching the maximum value)

SPSA2:
https://tests.stockfishchess.org/tests/view/66e6a26f86d5ee47d953a965

Also thanks to @martinnovaak, (Motor
https://github.com/martinnovaak/motor author) for insights and
suggestions.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 23328 W: 6197 L: 5901 D: 11230
Ptnml(0-2): 82, 2582, 6041, 2876, 83
https://tests.stockfishchess.org/tests/view/66e8787b86d5ee47d953ab6f

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 10626 W: 2826 L: 2560 D: 5240
Ptnml(0-2): 4, 1054, 2941, 1300, 14
https://tests.stockfishchess.org/tests/view/66e8ab2386d5ee47d953aba8

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

Bench: 1011161
2024-09-17 21:01:43 +02:00
Michael Chaly 240a5b1c72 Introduce separate butterfly history table for sorting root moves
Idea of this patch comes from the fact that current history heuristics
are mostly populated by low depth entries since our stat bonus reaches
maximum value at depth 5-6 and number of low depth nodes is much bigger
than number of high depth nodes. But it doesn't make a whole lost of
sense to use this low-depth centered histories to sort moves at root.
Current patch introduces special history table that is used exclusively
at root, it remembers which quiet moves were good and which quiet moves
were not good there and uses this information for move ordering.

Passed STC:
https://tests.stockfishchess.org/tests/view/66dda74adc53972b68218cc9
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 127680 W: 33579 L: 33126 D: 60975
Ptnml(0-2): 422, 15098, 32391, 15463, 466

Passed LTC:
https://tests.stockfishchess.org/tests/view/66dead2adc53972b68218d34
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 381978 W: 96958 L: 95923 D: 189097
Ptnml(0-2): 277, 42165, 105089, 43162, 296

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

Bench: 1611283
2024-09-17 20:54:02 +02:00
Shawn Xu 5ce7f866a5 Simplify Fail Low Bonus
Passed Non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 302528 W: 78190 L: 78264 D: 146074
Ptnml(0-2): 1029, 35797, 77551, 35993, 894
https://tests.stockfishchess.org/tests/view/66dcebdedc53972b68218c7e

Passed Non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 122754 W: 31025 L: 30907 D: 60822
Ptnml(0-2): 74, 13597, 33908, 13733, 65
https://tests.stockfishchess.org/tests/view/66e0c38686d5ee47d953a481

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

Bench: 1646373
2024-09-17 20:50:30 +02:00
Muzhen Gaming 224c147bd6 VVLTC Search Tune
Tuned with 115k games at VVLTC:
https://tests.stockfishchess.org/tests/view/66c80e09bf8c9d8780fda62a

Passed VVLTC 1st sprt:
https://tests.stockfishchess.org/tests/view/66d69ade9de3e7f9b33d14f9
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 54270 W: 13935 L: 13647 D: 26688
Ptnml(0-2): 2, 4907, 17032, 5189, 5

Passed VVLTC 2nd sprt:
https://tests.stockfishchess.org/tests/view/66dcf9c1dc53972b68218c84
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 136696 W: 34941 L: 34462 D: 67293
Ptnml(0-2): 8, 12659, 42535, 13138, 8

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

Bench: 1644273
2024-09-17 20:47:24 +02:00
Disservin a06e7004c1 Port instrumented testing to python
Since an unknown amount of time the instrumented CI has been a bit
flawed, explained here
https://github.com/official-stockfish/Stockfish/issues/5185. It also
experiences random timeout issues where restarting the workflow fixes it
or very long run times (more than other workflows) and is not very
portable.

The intention of this commit is to port the instrumented.sh to python
which also works on other operating systems. It should also be
relatively easy for beginners to add new tests to assert stockfish's
output and to run it.
From the source directory the following command can be run.

`python3 ../tests/instrumented.py --none ./stockfish`

A test runner will go over the test suites and run the test cases.

All instrumented tests should have been ported over.
The required python version for this is should be 3.7 (untested) + the
requests package, testing.py includes some infrastructure code which
setups the testing.

fixes https://github.com/official-stockfish/Stockfish/issues/5185
closes https://github.com/official-stockfish/Stockfish/pull/5583

No functional change
2024-09-17 20:24:17 +02:00
MinetaS f677aee28b Fix net downloading script
The recent commit introduced a bug in the net downloading script that
the file is not downloaded correctly and the content is redirected to
stdout.

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

No functional change
2024-09-10 23:00:41 +02:00
Nonlinear2 d8e49cdbdd Remove the moveCount increase in the LMR condition.
Passed non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 87104 W: 22630 L: 22464 D: 42010
Ptnml(0-2): 316, 10295, 22132, 10525, 284
https://tests.stockfishchess.org/tests/view/66dccd00dc53972b68218c60

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 94050 W: 23869 L: 23722 D: 46459
Ptnml(0-2): 49, 10400, 25985, 10537, 54
https://tests.stockfishchess.org/tests/view/66dd69c7dc53972b68218ca5

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

Bench: 1281840
2024-09-10 22:59:27 +02:00
MinetaS 6de2587236 Remove statScore condition in NMP
Eliminate the condition that is nearly 100% likelihood of being true.

Passed non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 208832 W: 54053 L: 54022 D: 100757
Ptnml(0-2): 753, 24987, 52901, 25026, 749
https://tests.stockfishchess.org/tests/view/66cddb50bf8c9d8780fdabaf

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 154344 W: 39132 L: 39047 D: 76165
Ptnml(0-2): 115, 17231, 42403, 17300, 123
https://tests.stockfishchess.org/tests/view/66cfafe39de3e7f9b33d1050

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

Bench: 1393697
2024-09-10 22:58:47 +02:00
MinetaS 2680c9c799 Small speedup in incremental accumulator updates
Instead of updating at most two accumulators, update all accumluators
during incremental updates. Tests have shown that this change yields a
small speedup of at least 0.5%, and up to 1% with shorter TC.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 54368 W: 14179 L: 13842 D: 26347
Ptnml(0-2): 173, 6122, 14262, 6449, 178
https://tests.stockfishchess.org/tests/view/66db038a9de3e7f9b33d1ad9

Passed 5+0.05:
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 55040 W: 14682 L: 14322 D: 26036
Ptnml(0-2): 303, 6364, 13856, 6664, 333
https://tests.stockfishchess.org/tests/view/66dbc325dc53972b68218ba7

Passed non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 57390 W: 14555 L: 14376 D: 28459
Ptnml(0-2): 37, 5876, 16683, 6069, 30
https://tests.stockfishchess.org/tests/view/66dbc30adc53972b68218ba5

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

No functional change
2024-09-09 18:02:32 +02:00
Disservin effa246071 Use optional for the engine path
- A small quality of file change is to change the type of engine path
  from a string to an optional string, skips the binary directory
  lookup, which is commonly disabled by people who create wasm builds or
  include stockfish as a library.

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

No functional change
2024-09-09 18:02:32 +02:00
Michael Chaly a8cb002038 Simplify ttmove reduction
Remove condition that clamps reductions for tt move.

Passed STC:
https://tests.stockfishchess.org/tests/view/66d5f1239de3e7f9b33d14b0
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 91136 W: 23805 L: 23646 D: 43685
Ptnml(0-2): 334, 10328, 24066, 10525, 315

Passed LTC:
https://tests.stockfishchess.org/tests/view/66d7c5889de3e7f9b33d1721
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 139242 W: 35130 L: 35030 D: 69082
Ptnml(0-2): 78, 15200, 38986, 15258, 99

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

Bench: 1268715
2024-09-09 18:02:32 +02:00
xu-shawn d7e3a708d4 Remove ARCH=... from README.md
closes https://github.com/official-stockfish/Stockfish/pull/5570

No functional change
2024-09-09 18:02:32 +02:00
MinetaS 1b310cc87e Export and clean up net downloading script
Fixes https://github.com/official-stockfish/Stockfish/issues/5564

This patch extracts the net downloading script in Makefile into an
external script file. Also the script is moderately rewritten for
improved readability and speed.

* Use wget preferentially over curl, as curl is known to have slight
  overhead.
* Use command instead of hash to check if command exists. Reportedly,
  hash always returns zero in some POSIX shells even when the command
  fails.
* Command existence checks (wget/curl, sha256sum) are performed only
  once at the beginning.
* Each of common patterns is encapsulated in a function
  (get_nnue_filename, validate_network).
* Print out error/warning messages to stderr.

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

No functional change

Co-authored-by: Disservin <disservin.social@gmail.com>
2024-09-09 18:02:27 +02:00
xu-shawn 66a7965b0f Copy scripts directory in distributed packages
closes https://github.com/official-stockfish/Stockfish/pull/5571

No functional change
2024-09-09 17:54:27 +02:00
Daniel Monroe e74452ae44 Reduce on ttcaptures if not capture
Tweak ttcapture reduction.
Reduce on ttcaptures only if the current move is a capture

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 94912 W: 24896 L: 24492 D: 45524
Ptnml(0-2): 301, 11197, 24087, 11539, 332
https://tests.stockfishchess.org/tests/view/66cd2264bf8c9d8780fdab34

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 60738 W: 15465 L: 15096 D: 30177
Ptnml(0-2): 42, 6573, 16775, 6932, 47
https://tests.stockfishchess.org/tests/view/66cf356d9de3e7f9b33d0fde

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

Bench: 1268700
2024-09-09 17:48:26 +02:00
Shawn Xu ddc9f48bc3 Introduce Material Correction History
Idea from Caissa (https://github.com/Witek902/Caissa) chess engine.

Add a secondary correction history indexed by the material key of a position.
The material key is the zobrist hash representing the number of pieces left in a
position.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 189472 W: 49360 L: 48813 D: 91299
Ptnml(0-2): 666, 22453, 47953, 22996, 668
https://tests.stockfishchess.org/tests/view/66cbddafbf8c9d8780fda9f1

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 224190 W: 57022 L: 56312 D: 110856
Ptnml(0-2): 197, 24723, 61540, 25443, 192
https://tests.stockfishchess.org/tests/view/66cd529bbf8c9d8780fdab4c

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

Bench: 1462697
2024-09-09 17:43:05 +02:00
FauziAkram 4fb04eb3df Simplify history bonus
After we recently added the disallowance for negative bonuses, it is no
longer necessary to keep the max comparison in the previous step.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 72000 W: 18820 L: 18637 D: 34543
Ptnml(0-2): 267, 8489, 18276, 8730, 238
https://tests.stockfishchess.org/tests/view/66ce132cbf8c9d8780fdabe7

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 67452 W: 17136 L: 16961 D: 33355
Ptnml(0-2): 35, 7489, 18519, 7632, 51
https://tests.stockfishchess.org/tests/view/66cf6ad49de3e7f9b33d1010

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

Bench: 1147012
2024-09-09 17:34:31 +02:00
Disservin f4ba7ce67a Restore development
closes https://github.com/official-stockfish/Stockfish/pull/5580

No functional change
2024-09-09 17:21:14 +02:00
Joost VandeVondele e0bfc4b69b Stockfish 17
Official release version of Stockfish 17

Bench: 1484730

---

Stockfish 17

Today we have the pleasure to announce a new major release of Stockfish. As
always, you can freely download it at https://stockfishchess.org/download and
use it in the GUI of your choice.

Don’t forget to join our Discord server[1] to get in touch with the community
of developers and users of the project!

*Quality of chess play*

In tests against Stockfish 16, this release brings an Elo gain of up to 46
points[2] and wins up to 4.5 times more game pairs[3] than it loses. In
practice, high-quality moves are now found in less time, with a user upgrading
from Stockfish 14 being able to analyze games at least 6 times[4] faster with
Stockfish 17 while maintaining roughly the same quality.

During this development period, Stockfish won its 9th consecutive first place
in the main league of the Top Chess Engine Championship (TCEC)[5], and the 24th
consecutive first place in the main events (bullet, blitz, and rapid) of the
Computer Chess Championship (CCC)[6].

*Update highlights*

*Improved engine lines*

This release introduces principal variations (PVs) that are more informative
for mate and decisive table base (TB) scores. In both cases, the PV will
contain all moves up to checkmate. For mate scores, the PV shown is the best
variation known to the engine at that point, while for table base wins, it
follows, based on the TB, a sequence of moves that preserves the game outcome
to checkmate.

*NUMA performance optimization*

For high-end computers with multiple CPUs (typically a dual-socket architecture
with 100+ cores), this release automatically improves performance with a
`NumaPolicy` setting that optimizes non-uniform memory access (NUMA).  Although
typical consumer hardware will not benefit, speedups of up to 2.8x[7] have been
measured.

*Shoutouts*

*ChessDB*

During the past 1.5 years, hundreds of cores have been continuously running
Stockfish to grow a database of analyzed positions. This chess cloud
database[8] now contains well over 45 billion positions, providing excellent
coverage of all openings and commonly played lines. This database is already
integrated into GUIs such as En Croissant[9] and Nibbler[10], which access it
through the public API.

*Leela Chess Zero*

Generally considered to be the strongest GPU engine, it continues to provide
open data which is essential for training our NNUE networks. They released
version 0.31.1[11] of their engine a few weeks ago, check it out!

*Website redesign*

Our website has undergone a redesign in recent months, most notably in our home
page[12], now featuring a darker color scheme and a more modern aesthetic,
while still maintaining its core identity. We hope you'll like it as much as we
do!

*Thank you*

The Stockfish project builds on a thriving community of enthusiasts (thanks
everybody!) who contribute their expertise, time, and resources to build a free
and open-source chess engine that is robust, widely available, and very strong.

We would like to express our gratitude for the 11k stars[13] that light up our
GitHub project! Thank you for your support and encouragement – your recognition
means a lot to us.

We invite our chess fans to join the Fishtest testing framework[14] to
contribute compute resources needed for development. Programmers can contribute
to the project either directly to Stockfish[15] (C++), to Fishtest[16] (HTML,
CSS, JavaScript, and Python), to our trainer nnue-pytorch[17] (C++ and Python),
or to our website[18] (HTML, CSS/SCSS, and JavaScript).

The Stockfish team

[1] https://discord.gg/GWDRS3kU6R
[2] https://tests.stockfishchess.org/tests/view/66d738ba9de3e7f9b33d159a
[3] https://tests.stockfishchess.org/tests/view/66d738f39de3e7f9b33d15a0
[4] https://github.com/official-stockfish/Stockfish/wiki/Useful-data#equivalent-time-odds-and-normalized-game-pair-elo
[5] https://en.wikipedia.org/wiki/Stockfish_(chess)#Top_Chess_Engine_Championship
[6] https://en.wikipedia.org/wiki/Stockfish_(chess)#Chess.com_Computer_Chess_Championship
[7] https://github.com/official-stockfish/Stockfish/pull/5285
[8] https://chessdb.cn/queryc_en/
[9] https://encroissant.org/
[10] https://github.com/rooklift/nibbler
[11] https://github.com/LeelaChessZero/lc0/releases/tag/v0.31.1
[12] https://stockfishchess.org/
[13] https://github.com/official-stockfish/Stockfish/stargazers
[14] https://github.com/official-stockfish/fishtest/wiki/Running-the-worker
[15] https://github.com/official-stockfish/Stockfish
[16] https://github.com/official-stockfish/fishtest
[17] https://github.com/official-stockfish/nnue-pytorch
[18] https://github.com/official-stockfish/stockfish-web
2024-09-06 16:53:45 +02:00
Joost VandeVondele 38e0cc7b90 Update Top CPU Contributors
to the status as of Aug 31st 2024.

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

No functional change
2024-09-03 17:53:23 +02:00
Robert Nurnberg @ elitebook 2054add23c Update the WDL model
updates the internal WDL model, using data from 2.6M games played by the revisions since 9fb5832.

https://github.com/official-stockfish/Stockfish/pull/5565

No functional change
2024-09-03 17:53:23 +02:00
Joost VandeVondele ab00c24c7e Fix some of the tests
due to https://github.com/official-stockfish/Stockfish/issues/5185 some CI tests are skipped.
This patch fixes a few tests that need updating.

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

No functional change
2024-09-03 17:48:58 +02:00
FauziAkram 451044202a Simpler formula for ss->cutoffCnt update
closes https://github.com/official-stockfish/Stockfish/pull/5548

No functional change
2024-08-28 09:35:21 +02:00
Taras Vuk 54def6f7eb rename !(PvNode || cutNode) to allNode
Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 108992 W: 28178 L: 28039 D: 52775
Ptnml(0-2): 356, 12428, 28762, 12621, 329
https://tests.stockfishchess.org/tests/view/66c73a51bf8c9d8780fda532

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

No functional change
2024-08-28 09:34:09 +02:00
Tomasz Sobczyk a0597b1281 Forcibly split NUMA nodes on Windows
split by processor groups due to Window's thread scheduler issues.

fixes #5551
closes https://github.com/official-stockfish/Stockfish/pull/5552

No functional change
2024-08-28 08:52:24 +02:00
Taras Vuk 9fb58328e3 Tweak late move extensions
Allow late move extensions only for PV and cut nodes.

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 44512 W: 11688 L: 11355 D: 21469
Ptnml(0-2): 167, 5180, 11229, 5513, 167
https://tests.stockfishchess.org/tests/view/66c0509d4ff211be9d4ef10e

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 152970 W: 39026 L: 38466 D: 75478
Ptnml(0-2): 102, 16792, 42164, 17298, 129
https://tests.stockfishchess.org/tests/view/66c0994d21503a509c13b2b6

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

bench: 1484730
2024-08-20 21:37:25 +02:00
Shawn Xu d275bf9643 Introduce Fail Low History Bonus
When a node fails low, give TT move a small bonus 1/4 of normal value.

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 92384 W: 24094 L: 23691 D: 44599
Ptnml(0-2): 323, 10852, 23465, 11203, 349
https://tests.stockfishchess.org/tests/view/66be80794ff211be9d4eed68

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 114660 W: 29260 L: 28778 D: 56622
Ptnml(0-2): 97, 12506, 31653, 12966, 108
https://tests.stockfishchess.org/tests/view/66bf63ee4ff211be9d4eeef0

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

bench 1463003
2024-08-20 21:34:19 +02:00
Nonlinear2 6cf7f300ac Simplify stand pat adjustement
Remove && !PvNode condition for stand pat adjustement in quiescence search.

Passed non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 108544 W: 28228 L: 28085 D: 52231
Ptnml(0-2): 389, 12902, 27554, 13031, 396
https://tests.stockfishchess.org/tests/view/66bb402e4ff211be9d4ee688

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 193014 W: 48796 L: 48751 D: 95467
Ptnml(0-2): 188, 21481, 53116, 21542, 180
https://tests.stockfishchess.org/tests/view/66bc78774ff211be9d4ee88f

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

Bench 1787360
2024-08-20 21:31:33 +02:00
Shawn Xu 87814d2fb8 Simplify doShallowerSearch
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 242336 W: 62657 L: 62663 D: 117016
Ptnml(0-2): 941, 28949, 61418, 28895, 965
https://tests.stockfishchess.org/tests/view/66bc13c34ff211be9d4ee794

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 128100 W: 32503 L: 32390 D: 63207
Ptnml(0-2): 106, 14319, 35113, 14380, 132
https://tests.stockfishchess.org/tests/view/66bdbb304ff211be9d4eec5d

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

bench 1586246
2024-08-20 21:27:58 +02:00
Shawn Xu 175021721c Simplify bestMove promotion
Passed Non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 216768 W: 56240 L: 56217 D: 104311
Ptnml(0-2): 794, 24900, 56956, 24957, 777
https://tests.stockfishchess.org/tests/view/66bc11324ff211be9d4ee78b

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 44970 W: 11391 L: 11199 D: 22380
Ptnml(0-2): 44, 4596, 13002, 4810, 33
https://tests.stockfishchess.org/tests/view/66bdbb1b4ff211be9d4eec5a

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

bench: 1613043
2024-08-20 21:24:04 +02:00
Linmiao Xu 5d81071953 Update default main net to nn-1111cefa1111.nnue
Created from 2 distinct spsa tunes of the latest main net (nn-31337bea577c.nnue)
and applying the params to the prior main net (nn-e8bac1c07a5a.nnue). This
effectively reverts the modifications to output weights and biases in
https://github.com/official-stockfish/Stockfish/pull/5509

SPSA:
A: 6000, alpha: 0.602, gamma: 0.101

1st - 437 feature transformer biases where values are < 25
54k / 120k games at 180+1.8
https://tests.stockfishchess.org/tests/view/66af98ac4ff211be9d4edad0
nn-808259761cca.nnue

2nd - 208 L2 weights where values are zero
112k / 120k games at 180+1.8
https://tests.stockfishchess.org/tests/view/66b0c3074ff211be9d4edbe5
nn-a56cb8c3d477.nnue

When creating the above 2 nets (nn-808259761cca.nnue, nn-a56cb8c3d477.nnue),
spsa params were unintentionally applied to nn-e8bac1c07a5a.nnue rather
than nn-31337bea577c.nnue due to an issue in a script that creates nets
by applying spsa results to base nets.

Since they both passed STC and were neutral or slightly positive at LTC,
they were combined to see if the elo from each set of params was additive.

The 2 nets can be merged on top of nn-e8bac1c07a5a.nnue with:
https://github.com/linrock/nnue-tools/blob/90942d3/spsa/combine_nnue.py
```
python3 combine_nnue.py \
  nn-e8bac1c07a5a.nnue \
  nn-808259761cca.nnue \
  nn-a56cb8c3d477.nnue
```

Merging yields nn-87caa003fc6a.nnue which was renamed to nn-1111cefa1111.nnue
with an updated nnue-namer around 10x faster than before by:
- using a prefix trie for efficient prefix matches
- modifying 4 non-functional bytes near the end of the file instead of 2
https://github.com/linrock/nnue-namer

Thanks to @MinetaS for pointing out in #nnue-dev what the non-functional bytes are:
  L3 is 32, 4 bytes for biases, 32 bytes for weights. (fc_2)
  So -38 and -37 are technically -2 and -1 of fc_1 (type AffineTransform<30, 32>)
  And since InputDimension is padded to 32 there are total 32 of 2 adjacent bytes padding.
  So yes, it's non-functional whatever values are there.
  It's possible to tweak bytes at -38 - 32 * N and -37 - 32 * N given N = 0 ... 31

The net renamed with the new method passed non-regression STC vs. the original net:
https://tests.stockfishchess.org/tests/view/66c0f0a821503a509c13b332

To print the spsa params with nnue-pytorch:
```
import features
from serialize import NNUEReader

feature_set = features.get_feature_set_from_name("HalfKAv2_hm")

with open("nn-31337bea577c.nnue", "rb") as f:
    model = NNUEReader(f, feature_set).model

c_end = 16
for i,ft_bias in enumerate(model.input.bias.data[:3072]):
    value = int(ft_bias * 254)
    if abs(value) < 25:
        print(f"ftB[{i}],{value},-1024,1024,{c_end},0.0020")

c_end = 6
for i in range(8):
    for j in range(32):
        for k in range(30):
            value = int(model.layer_stacks.l2.weight.data[32 * i + j, k] * 64)
            if value == 0:
                print(f"twoW[{i}][{j}][{k}],{value},-127,127,{c_end},0.0020")
```

New params found with the same method as:
https://github.com/official-stockfish/Stockfish/pull/5459

Passed STC:
https://tests.stockfishchess.org/tests/view/66b4d4464ff211be9d4edf6e
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 136416 W: 35753 L: 35283 D: 65380
Ptnml(0-2): 510, 16159, 34416, 16597, 526

Passed LTC:
https://tests.stockfishchess.org/tests/view/66b76e814ff211be9d4ee1cc
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 159336 W: 40753 L: 40178 D: 78405
Ptnml(0-2): 126, 17497, 43864, 18038, 143

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

bench 1613043
2024-08-20 20:59:36 +02:00
FauziAkram 4995792a6c Simplify cutnode reduction formula
Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 137994 W: 34705 L: 34603 D: 68686
Ptnml(0-2): 124, 15371, 37903, 15477, 122
https://tests.stockfishchess.org/tests/view/66aeb74b4ff211be9d4eda10

Passed LTC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 131456 W: 34148 L: 34031 D: 63277
Ptnml(0-2): 506, 15571, 33465, 15672, 514
https://tests.stockfishchess.org/tests/view/66ae258b4ff211be9d4ed95d

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

Bench: 1261995
2024-08-20 20:57:07 +02:00
Shawn Xu a75717ede1 Simplify Post-LMR Continuation History Updates
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 55520 W: 14625 L: 14420 D: 26475
Ptnml(0-2): 247, 6522, 14007, 6747, 237
https://tests.stockfishchess.org/tests/view/66ad40874ff211be9d4ed8f7

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 216168 W: 54561 L: 54540 D: 107067
Ptnml(0-2): 196, 24212, 59244, 24239, 193
https://tests.stockfishchess.org/tests/view/66aeac954ff211be9d4eda03

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

bench 1418263
2024-08-20 20:51:39 +02:00
Shawn Xu bc80ece6c7 Improve Comments for Pairwise Multiplication Optimization
closes https://github.com/official-stockfish/Stockfish/pull/5524

no functional change
2024-08-20 20:47:46 +02:00
Disservin d626af5c3a Fix failing CI for MacOS 13 GCC 11
closes https://github.com/official-stockfish/Stockfish/pull/5540

No functional change
2024-08-20 20:44:55 +02:00
Shawn Xu ae9e55cf53 Simplify Cutnode Reduction
Passed Non-regression STC:
LR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 143968 W: 37439 L: 37333 D: 69196
Ptnml(0-2): 521, 17228, 36456, 17182, 597
https://tests.stockfishchess.org/tests/view/66a73f9f4ff211be9d4ed27f

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 198954 W: 50384 L: 50345 D: 98225
Ptnml(0-2): 201, 22360, 54347, 22337, 232
https://tests.stockfishchess.org/tests/view/66a906e94ff211be9d4ed423

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

bench 1277466
2024-08-03 09:42:54 +02:00
MinetaS b976f0a101 Move DotProd code into optimized affine layer
This patch moves the DotProd code into the propagation function which
has sequential access optimization. To prove the speedup, the comparison
is done without the sparse layer. With the sparse layer the effect is
marginal (GCC 0.3%, LLVM/Clang 0.1%).

For both tests, binary is compiled with GCC 14.1. Each test had 50 runs.

Sparse layer included:
```
speedup        = +0.0030
P(speedup > 0) =  1.0000
```

Sparse layer excluded:
```
speedup        = +0.0561
P(speedup > 0) =  1.0000
```

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

No functional change
2024-08-03 09:42:03 +02:00
Tomasz Sobczyk 8e560c4fd3 Replicate network weights only to used NUMA nodes
On a system with multiple NUMA nodes, this patch avoids unneeded replicated
(e.g. 8x for a single threaded run), reducting memory use in that case.

Lazy initialization forced before search.

Passed STC:
https://tests.stockfishchess.org/tests/view/66a28c524ff211be9d4ecdd4
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 691776 W: 179429 L: 179927 D: 332420
Ptnml(0-2): 2573, 79370, 182547, 78778, 2620

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

No functional change
2024-08-03 09:41:37 +02:00
Shawn Xu 2343f71f3f Remove Killers
The removal of killers on line 1774 resulted in a substantial decrease
in pre-LMR history average, so a negative history fill is applied to
counter it.

Passed Non-regression STC (vs #5513):
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 21984 W: 5886 L: 5645 D: 10453
Ptnml(0-2): 80, 2492, 5628, 2691, 101
https://tests.stockfishchess.org/tests/view/66a095894ff211be9d4ecb9d

Passed Non-regression LTC (vs #5513):
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 95430 W: 24141 L: 23995 D: 47294
Ptnml(0-2): 97, 10537, 26298, 10689, 94
https://tests.stockfishchess.org/tests/view/66a11c8d4ff211be9d4ecbf8

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

Bench: 1660869
2024-07-28 22:22:50 +02:00
Stéphane Nicolet af802da65b Clean up comments for movepicker
Remove references to checks in MovePicker comments. Follow-up for
https://github.com/official-stockfish/Stockfish/pull/5498

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

No functional change
2024-07-28 22:21:03 +02:00
Michael Chaly 607c3e404f Remove unneeded depth tracking in qsearch
Since simplification of quiet checks in qsearch this depth isn't used by
any function at all apart movepicker, which also doesn't use passed
qsearch depth in any way, so can be removed. No functional change.

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

No functional change
2024-07-28 22:18:33 +02:00
Shawn Xu 85893ac1cd Simplify Away Killer Condition in Cutnode LMR
Passed Non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 42944 W: 11240 L: 11024 D: 20680
Ptnml(0-2): 159, 5056, 10825, 5274, 158
https://tests.stockfishchess.org/tests/view/669c13384ff211be9d4ec69f

Passed Non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 163548 W: 41366 L: 41289 D: 80893
Ptnml(0-2): 109, 18246, 45007, 18283, 129
https://tests.stockfishchess.org/tests/view/669cb1254ff211be9d4ec73a

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

Bench: 1178570
2024-07-28 22:13:47 +02:00
Linmiao Xu b55217fd02 Update default main net to nn-31337bea577c.nnue
Created by updating output weights (256) and biases (8)
of the previous main net with values found with spsa around
101k / 120k games at 140+1.4.

264 spsa params: output weights and biases in nn-e8bac1c07a5a.nnue
A: 6000, alpha: 0.602, gamma: 0.101
weights: [-127, 127], c_end = 6
biases: [-8192, 8192], c_end = 64

Among the 264 params, 189 weights and all 8 biases were changed.

Changes in the weights:
- mean: -0.111 +/- 3.57
- range: [-8, 8]

Found with the same method as:
https://github.com/official-stockfish/Stockfish/pull/5459

Due to the original name (nn-ea8c9128c325.nnue) being too similar
to the previous main net (nn-e8bac1c07a5a.nnue) and creating confusion,
it was renamed by making non-functional changes to the .nnue file
the same way as past nets with:
https://github.com/linrock/nnue-namer

To verify that bench is the same and view the modified non-functional bytes:
```
echo -e "setoption name EvalFile value nn-ea8c9128c325.nnue\nbench" | ./stockfish
echo -e "setoption name EvalFile value nn-31337bea577c.nnue\nbench" | ./stockfish

cmp -l nn-ea8c9128c325.nnue nn-31337bea577c.nnue

diff <(xxd nn-ea8c9128c325.nnue) <(xxd nn-31337bea577c.nnue)
```

Passed STC:
https://tests.stockfishchess.org/tests/view/669564154ff211be9d4ec080
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 57280 W: 15139 L: 14789 D: 27352
Ptnml(0-2): 209, 6685, 14522, 6995, 229

Passed LTC:
https://tests.stockfishchess.org/tests/view/669694204ff211be9d4ec1b4
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 63030 W: 16093 L: 15720 D: 31217
Ptnml(0-2): 47, 6766, 17516, 7139, 47

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

bench 1371485
2024-07-23 19:34:27 +02:00
Michael Chaly 836154acb5 Introduce pre-qsearch ttmove extensions at pv nodes
The idea is that we are about to dive into qsearch (next search depth is <= 0)
but since we have the move in transposition table we should extend that move
and evaluate it with more precise search - because branch seems important.

Passed STC:
https://tests.stockfishchess.org/tests/view/6699d2564ff211be9d4ec488
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 83104 W: 21789 L: 21401 D: 39914
Ptnml(0-2): 293, 9748, 21128, 10044, 339

Passed LTC:
https://tests.stockfishchess.org/tests/view/669b3f1a4ff211be9d4ec602
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 136098 W: 34636 L: 34111 D: 67351
Ptnml(0-2): 105, 14882, 37550, 15407, 105

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

bench 1526129
2024-07-23 19:24:00 +02:00
Shawn Xu 985b9fd7b0 Remove Killer Heuristic In Move Ordering
Passed Non-regression STC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 80480 W: 20979 L: 20802 D: 38699
Ptnml(0-2): 279, 9610, 20337, 9683, 331
https://tests.stockfishchess.org/tests/view/669c12c14ff211be9d4ec69b

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 77988 W: 19788 L: 19624 D: 38576
Ptnml(0-2): 66, 8605, 21481, 8783, 59
https://tests.stockfishchess.org/tests/view/669d628a4ff211be9d4ec7a8

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

bench 1367740
2024-07-23 19:24:00 +02:00
Linmiao Xu 1e2f051103 Replace simple eval with psqt in re-eval condition
As a result, re-eval depends only on smallnet outputs
so an extra call to simple eval can be removed.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/669743054ff211be9d4ec232
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 214912 W: 55801 L: 55777 D: 103334
Ptnml(0-2): 746, 24597, 56760, 24593, 760

https://github.com/official-stockfish/Stockfish/pull/5501

Bench: 1440277
2024-07-23 19:24:00 +02:00
Shahin M. Shahin bb4b01e306 Fix TB guard
even if beta is below TB range, once we return probcutBeta with beta + 390 we
can return wrong TB value, and guard against ttData.value being `VALUE_NONE`

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

bench: 1440277
2024-07-23 19:24:00 +02:00
FauziAkram 986173264f Adding LowestElo and HighestElo constants
These values represent the lowest Elo rating in the skill level calculation,
and the highest one, but it's not clear from the code where these values come
from other than the comment.  This should improve code readability and
maintainability. It makes the purpose of the values clear and allows for easy
modification if the Elo range for skill level calculation changes in the
future.  Moved the Skill struct definition from search.cpp to search.h header
file to define the Search::Skill struct, making it accessible from other files.

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

No functional change
2024-07-23 19:23:57 +02:00
FauziAkram a2ba3e3362 Bonus Simplification
This tune removes completely a recently added term.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 61376 W: 16046 L: 15693 D: 29637
Ptnml(0-2): 207, 7132, 15665, 7469, 215
https://tests.stockfishchess.org/tests/view/669512b94ff211be9d4ebffb

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 100662 W: 25474 L: 25020 D: 50168
Ptnml(0-2): 64, 11092, 27581, 11514, 80
https://tests.stockfishchess.org/tests/view/66955f194ff211be9d4ec06a

Passed LTC#2:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 28056 W: 7128 L: 6909 D: 14019
Ptnml(0-2): 18, 3084, 7620, 3273, 33
https://tests.stockfishchess.org/tests/view/669a541a4ff211be9d4ec52b

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

bench: 1619438
2024-07-23 18:01:14 +02:00
Dubslow 703f17975b Remove QS_CHECKS movepick stage
Passed STC: https://tests.stockfishchess.org/tests/view/669597cf4ff211be9d4ec147
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 199072 W: 52100 L: 52058 D: 94914
Ptnml(0-2): 829, 23679, 50406, 23865, 757

Passed LTC: https://tests.stockfishchess.org/tests/view/66988f5f4ff211be9d4ec33e
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 119778 W: 30420 L: 30299 D: 59059
Ptnml(0-2): 106, 13293, 32957, 13440, 93

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

Bench 1499842
2024-07-23 17:56:52 +02:00
Joost VandeVondele e57fba7fc9 Fix TB PV extension and MultiPV
in the case of MultiPV, the first move of the Nth multiPV could actually turn a
winning position in a losing one, so don't attempt to correct it. Instead,
always perform the first move without correction.

Fixes #5505

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

No functional change
2024-07-23 17:51:30 +02:00
Joost VandeVondele 1fb4dc2e0f Enable syzygy in the matetrack action
now checks correctness of PV lines with TB score.

uses 3-4-5 man table bases, downloaded from lichess,
which are cached with the appropriate action.

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

No functional change
2024-07-23 17:49:07 +02:00
Michael Chaly a8401e803d Adjust bonus to move that caused a fail low
This is an elo gainer and simultaneously a minor logical fix to bonuses that caused a fail low.
It increases maximum of statscore based subtraction - but disallows negative bonuses.

Passed STC:
https://tests.stockfishchess.org/tests/view/66955e6f4ff211be9d4ec063
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 44640 W: 11805 L: 11472 D: 21363
Ptnml(0-2): 166, 5178, 11335, 5439, 202

Passed LTC:
https://tests.stockfishchess.org/tests/view/66963fde4ff211be9d4ec190
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 72288 W: 18478 L: 18082 D: 35728
Ptnml(0-2): 50, 7919, 19825, 8285, 65

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

Bench: 1477054
2024-07-19 08:41:38 +02:00
Linmiao Xu c2837769e0 Avoid calculating nnue complexity twice
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6697459d4ff211be9d4ec236
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 146848 W: 38289 L: 38189 D: 70370
Ptnml(0-2): 503, 16665, 39046, 16649, 561

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

No functional change
2024-07-19 08:40:23 +02:00
Shahin M. Shahin c8d8e362fc Try nullmoves only on cutnodes
since master only tries nullmoves on cutNodes already with 99.0224% of the
cases running bench, We can try null moves at 100% of cutNodes and achieve such
simplification, by making passing false already equivalent to passing !cutNode

This is a more correct form of PR #5482

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/66941c044ff211be9d4ebf5f
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 153216 W: 39856 L: 39764 D: 73596
Ptnml(0-2): 590, 18174, 38979, 18284, 581

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6694e5cd4ff211be9d4ebfdf
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 67842 W: 17178 L: 17004 D: 33660
Ptnml(0-2): 52, 7437, 18759, 7631, 42

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

bench: 1345400

Co-Authored-By: FauziAkram <11150271+fauziakram@users.noreply.github.com>
2024-07-19 08:38:13 +02:00
Dubslow 27042fe949 Linearize corrHist
Passed STC: https://tests.stockfishchess.org/tests/view/66919cdec6827afcdcee146f
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 130656 W: 33579 L: 33461 D: 63616
Ptnml(0-2): 394, 15548, 33318, 15682, 386

Passed VVLTC: https://tests.stockfishchess.org/tests/view/6691acb2c6827afcdcee1645
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 160314 W: 40925 L: 40854 D: 78535
Ptnml(0-2): 12, 14754, 50551, 14831, 9

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

bench 1380295
2024-07-19 08:36:25 +02:00
yl25946 7bb45d05fa Replace ternary with std::min
equivalent and more readable.

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

No functional change
2024-07-19 08:34:02 +02:00
Guenther Demetz c755bc1a73 Simplify improving condition
if we were in check at our previous move we look back until we weren't
in check and take the staticEval of that position as reference.

Passed STC:
https://tests.stockfishchess.org/tests/view/668ba7b65034141ae5996665
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 74784 W: 19454 L: 19274 D: 36056
Ptnml(0-2): 260, 8874, 18952, 9038, 268

Passted LTC:
https://tests.stockfishchess.org/tests/view/668cb2db5034141ae599678b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 241488 W: 61166 L: 61171 D: 119151
Ptnml(0-2): 190, 27154, 66062, 27147, 191

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

bench: 1368313
2024-07-19 08:32:16 +02:00
Linmiao Xu e443b2459e Separate eval params for smallnet and main net
Values found with spsa around 80% of 120k games at 60+0.6:
https://tests.stockfishchess.org/tests/view/669205dac6827afcdcee3ea4

Passed STC:
https://tests.stockfishchess.org/tests/view/6692928b4ff211be9d4e98a9
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 313696 W: 81107 L: 80382 D: 152207
Ptnml(0-2): 934, 36942, 80363, 37683, 926

Passed LTC:
https://tests.stockfishchess.org/tests/view/6692aab54ff211be9d4e9915
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 228420 W: 57903 L: 57190 D: 113327
Ptnml(0-2): 131, 25003, 63243, 25688, 145

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

bench 1319322
2024-07-15 13:38:14 +02:00
Michael Chaly de2bf1a186 Remove quiet history pruning depth limit
This patch removes lmrDepth limit for quiet moves history based pruning.

Previously removal of this type of depth limits was considered bad because it
was performing bad for matetrack - but with this pruning heuristic this
shouldn't be that bad because it's "naturally" depth limited by history
threshold and should be completely disabled at depth >= 15 or so.  Also this
heuristic in previous years was known to scale non-linearly - bigger lmrDepth
thresholds were better at longer time controls and removing it completely
probably should scale pretty well.

Passed STC:
https://tests.stockfishchess.org/tests/view/6692b89b4ff211be9d4eab21
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 114464 W: 29675 L: 29545 D: 55244
Ptnml(0-2): 372, 12516, 31329, 12640, 375

Passed LTC:
https://tests.stockfishchess.org/tests/view/6692c4554ff211be9d4eab3d
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 67746 W: 17182 L: 17014 D: 33550
Ptnml(0-2): 28, 6993, 19652, 7183, 17

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

Bench: 1250388
2024-07-15 13:35:06 +02:00
MinetaS 2b37b151dd Use ValueList to represent searched moves array
This PR replaces a pair of array and size with existing ValueList class.
Removes two local variables in search and two parameters of
update_all_stats.

Passed non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 227040 W: 58472 L: 58463 D: 110105
Ptnml(0-2): 495, 23572, 65427, 23481, 545
https://tests.stockfishchess.org/tests/view/669299204ff211be9d4e98dc

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

No functional change
2024-07-15 13:30:47 +02:00
FauziAkram 7395d56832 bonus calculation for prior countermoves
Introduce a new term to the bonus calculation for prior countermoves

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 140896 W: 36545 L: 36079 D: 68272
Ptnml(0-2): 383, 16505, 36217, 16949, 394
https://tests.stockfishchess.org/tests/view/6691c73cc6827afcdcee1816

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 126660 W: 32089 L: 31587 D: 62984
Ptnml(0-2): 63, 13774, 35154, 14276, 63
https://tests.stockfishchess.org/tests/view/6691cdc4c6827afcdcee1930

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

bench: 1250388
2024-07-15 13:27:42 +02:00
Linmiao Xu 558abdbe8a Set best value to futility value after pruned quiet move
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6691592f5034141ae599c68d
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 278496 W: 71818 L: 71865 D: 134813
Ptnml(0-2): 865, 33311, 70978, 33194, 900

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/66918fca5034141ae599e761
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 202986 W: 51048 L: 51013 D: 100925
Ptnml(0-2): 107, 22552, 56133, 22601, 100

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

bench 1715206
2024-07-15 13:24:14 +02:00
Michael Chaly 930915de90 Decrease delta
Decrease delta in aspiration windows - both initial value and quadratic
function of previous best value.

Passed STC:
https://tests.stockfishchess.org/tests/view/6691a52ec6827afcdcee1569
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 55456 W: 14449 L: 14107 D: 26900
Ptnml(0-2): 174, 6416, 14193, 6784, 161

Passed LTC:
https://tests.stockfishchess.org/tests/view/6691aac1c6827afcdcee1625
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 107940 W: 27530 L: 27065 D: 53345
Ptnml(0-2): 52, 11787, 29840, 12226, 65

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

bench 1547707
2024-07-15 13:22:31 +02:00
MinetaS 563d268519 Simplify futility_move_count
This patch reverts changes from #4032 which was introduced as a speedup.
Modern compilers no longer use DIV/IDIV instructions, potentially making
the explicit branch perform worse. Since evaluations spend significantly
more time now, the impact of the speedup in search diminishes with old
compilers as well.

GCC 14.1.0 profile-build, x86-64-vnni512
```
.text:000000014010FEA9                 mov     ecx, [rsp+3FB8h+var_3F5C]
...
.text:000000014010FEBD                 mov     r10d, ecx
.text:000000014010FEC0                 imul    r10d, ecx
.text:000000014010FEC4                 mov     ecx, dword ptr [rsp+3FB8h+var_3F44+4]
.text:000000014010FEC8                 add     r10d, 3
.text:000000014010FECC                 mov     r11d, r10d
.text:000000014010FECF                 sar     r11d, 1
.text:000000014010FED2                 cmp     [rsp+3FB8h+var_3EE7], 0
.text:000000014010FEDA                 cmovnz  r11d, r10d
```

LLVM 18.1.18 profile-build, x86-64-vnni512
```
.text:0000000140001EDC                 mov     [rsp+40h+arg_E0], r13
.text:0000000140001EE4                 movsxd  rcx, r13d
.text:0000000140001EE7                 mov     rax, rcx
.text:0000000140001EEA                 mov     [rsp+40h+arg_B8], rcx
.text:0000000140001EF2                 imul    eax, eax
.text:0000000140001EF5                 add     eax, 3
.text:0000000140001EF8                 mov     ecx, [rsp+40h+arg_8C]
.text:0000000140001EFF                 shrx    eax, eax, ecx
.text:0000000140001F04                 mov     [rsp+40h+arg_190], rax
```

Passed non-regression STC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 109504 W: 28420 L: 28280 D: 52804
Ptnml(0-2): 355, 12326, 29273, 12420, 378
https://tests.stockfishchess.org/tests/view/6690dc095034141ae599c5fe

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

No functional change
2024-07-15 13:19:46 +02:00
Shawn Xu 024eb6f453 Unify Movepick Initializer
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 168704 W: 43524 L: 43455 D: 81725
Ptnml(0-2): 414, 17173, 49076, 17308, 381
https://tests.stockfishchess.org/tests/view/66904b7b5034141ae599a197

Passed Non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 120294 W: 30473 L: 30364 D: 59457
Ptnml(0-2): 40, 10974, 38032, 11039, 62
https://tests.stockfishchess.org/tests/view/66905b235034141ae599a223

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

bench 1459677
2024-07-15 13:18:37 +02:00
Shawn Xu 3df09c04d7 Simplify Away Refutation Stage
Simplify away killer stage to a constant bonus given to the killer move during
quiet move scoring.

Passed Non-regression STC (Against then-pending PR #5472):
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 106176 W: 27685 L: 27539 D: 50952
Ptnml(0-2): 410, 12765, 26637, 12821, 455
https://tests.stockfishchess.org/tests/view/668dd0835034141ae5999e8f

Passed Non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 92472 W: 23426 L: 23276 D: 45770
Ptnml(0-2): 55, 10376, 25215, 10544, 46
https://tests.stockfishchess.org/tests/view/669019e45034141ae5999fd2

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

Bench 1459677
2024-07-15 13:15:35 +02:00
Andyson007 42aae5fe8b Fixed non UCI compliance
print `<empty>` and accept `<empty>` for UCI string options,
accepting empty strings as well. Internally use empty strings (`""`).

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

No functional change
2024-07-15 13:14:57 +02:00
yl25946 8d1e41458e removed second killer move
STC with movepicker rewrite:

LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 46656 W: 12208 L: 11995 D: 22453
Ptnml(0-2): 203, 5461, 11777, 5694, 193
https://tests.stockfishchess.org/tests/view/668d98a15034141ae5999e68

Earlier version passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 468896 W: 120999 L: 120054 D: 227843
Ptnml(0-2): 1207, 55209, 120639, 56218, 1175
https://tests.stockfishchess.org/tests/view/668b17d2cf91c430fca58630

Earlier version passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 550524 W: 139553 L: 139877 D: 271094
Ptnml(0-2): 333, 61646, 151616, 61346, 321
https://tests.stockfishchess.org/tests/view/668b2e04cf91c430fca586b1

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

bench 1234309

Co-authored-by: rn5f107s2 <clemens.lerchl@gmail.com>
2024-07-11 07:29:49 +02:00
Joost VandeVondele 6135a0e2f8 Provide more info on found TB files
now uses the following format:

`info string Found 510 WDL and 510 DTZ tablebase files (up to 6-man).`

this clarifies exactly what has been found, as the difference matters,
e.g. for the PV extension of TB scores.

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

No functional change
2024-07-11 07:29:44 +02:00
Stéphane Nicolet 7e72b37e4c Clean up comments in code
- Capitalize comments
- Reformat multi-lines comments to equalize the widths of the lines
- Try to keep the width of comments around 85 characters
- Remove periods at the end of single-line comments

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

No functional change
2024-07-11 07:29:33 +02:00
Disservin 98a7bb4436 CI give correct permissions for the clang-format action
closes https://github.com/official-stockfish/Stockfish/pull/5470

No functional change
2024-07-11 07:21:04 +02:00
yl25946 362a77a345 Move Loop Consistency in Probcut
In probcut move loop, everything is enclosed within a large if statement. I've
changed it to guard clauses to stay consistent with other move loops.

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

No functional change
2024-07-09 18:54:12 +02:00
Linmiao Xu b209f14b1e Update default main net to nn-e8bac1c07a5a.nnue
Created by modifying L2 weights from the previous main net (nn-74f1d263ae9a.nnue)
with params found by spsa around 9k / 120k games at 120+1.2.

370 spsa params - L2 weights in nn-74f1d263ae9a.nnue where |val| >= 50
A: 6000, alpha: 0.602, gamma: 0.101
weights: [-127, 127], c_end = 6

To print the spsa params with nnue-pytorch:
```
import features
from serialize import NNUEReader

feature_set = features.get_feature_set_from_name("HalfKAv2_hm")
with open("nn-74f1d263ae9a.nnue", "rb") as f:
    model = NNUEReader(f, feature_set).model

c_end = 6
for i in range(8):
    for j in range(32):
        for k in range(30):
            value = int(model.layer_stacks.l2.weight[32 * i + j, k] * 64)
            if abs(value) >= 50:
                print(f"twoW[{i}][{j}][{k}],{value},-127,127,{c_end},0.0020")
```

Among the 370 params, 229 weights were changed.
  avg change: 0.0961 ± 1.67
  range: [-4, 3]

The number of weights changed, grouped by layer stack index,
shows more weights were modified in the lower piece count buckets:
[54, 52, 29, 23, 22, 18, 14, 17]

Found with the same method described in:
https://github.com/official-stockfish/Stockfish/pull/5459

Passed STC:
https://tests.stockfishchess.org/tests/view/668aec9a58083e5fd88239e7
LLR: 3.00 (-2.94,2.94) <0.00,2.00>
Total: 52384 W: 13569 L: 13226 D: 25589
Ptnml(0-2): 127, 6141, 13335, 6440, 149

Passed LTC:
https://tests.stockfishchess.org/tests/view/668af50658083e5fd8823a0b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 46974 W: 12006 L: 11668 D: 23300
Ptnml(0-2): 25, 4992, 13121, 5318, 31

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

bench 1300471
2024-07-09 18:49:28 +02:00
Shawn Xu 4880ed4ad1 Simplify Probcut Malus
Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 74880 W: 19261 L: 19083 D: 36536
Ptnml(0-2): 202, 8861, 19120, 9071, 186
https://tests.stockfishchess.org/tests/view/668a0966eca84f4d25864cba

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 263916 W: 66690 L: 66718 D: 130508
Ptnml(0-2): 125, 29348, 73040, 29320, 125
https://tests.stockfishchess.org/tests/view/668a17e3eca84f4d25864e91

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

bench 1331408
2024-07-09 18:44:39 +02:00
Stéphane Nicolet acd0a933ad Fix compilation on Apple
Always use the posix function posix_memalign() as aligned memory
allocator on Apple computers. This should allow to compile Stockfish
out of the box on all versions of Mac OS X.

Patch tested on the following systems (apart from the CI) :
  • Mac OS 10.9.6 (arch x86-64-sse41-popcnt) with gcc-10
  • Mac OS 10.13.6 (arch x86-64-bmi2) with gcc-10, gcc-14 and clang-11
  • Mac OS 14.1.1 (arch apple-silicon) with clang-15

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

No functional change
2024-07-09 18:42:21 +02:00
Michael Chaly eac2d080a3 Further simplify stat bonuses
Based on recent simplification by linrock Since it completely removed any
special bonuses based on values difference and made it flat stat_bonus(depth +
1) I got an idea that we might as well remove all (depth + 1) bonuses and make
them usual depth bonuses.  Also removes weird negative bonus for depth 1 as a
side effect.

Passed STC:
https://tests.stockfishchess.org/tests/view/6689d817eca84f4d25863746
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 18080 W: 4789 L: 4552 D: 8739
Ptnml(0-2): 46, 1987, 4727, 2244, 36

Passed LTC:
https://tests.stockfishchess.org/tests/view/6689daa4eca84f4d258639d7
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 109062 W: 27548 L: 27417 D: 54097
Ptnml(0-2): 58, 11983, 30293, 12164, 33

Passed direct LTC vs linrock patch:
https://tests.stockfishchess.org/tests/view/668a46f8eca84f4d25866fe9
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 100002 W: 25351 L: 25209 D: 49442
Ptnml(0-2): 54, 11119, 27529, 11229, 70

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

Bench 1175744
2024-07-09 18:41:36 +02:00
Joost VandeVondele 5d3517c601 Fix output for GUI
Fritz 19 can hang with the current way to provide output,
i.e. too much output in a short time for a mate / depth 245 found quickly.

fallout from 25361e514b

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

No functional change
2024-07-09 18:36:46 +02:00
Linmiao Xu 5752529cab Update default main net to nn-74f1d263ae9a.nnue
Created by setting output weights (256) and biases (8) of the previous main net
nn-ddcfb9224cdb.nnue to values found around 12k / 120k spsa games at 120+1.2

This used modified fishtest dev workers to construct .nnue files from
spsa params, then load them with EvalFile when running tests:
https://github.com/linrock/fishtest/tree/spsa-file-modified-nnue/worker

Inspired by researching loading spsa params from files:
https://github.com/official-stockfish/fishtest/pull/1926

Scripts for modifying nnue files and preparing params:
https://github.com/linrock/nnue-pytorch/tree/no-gpu-modify-nnue

spsa params:
  weights: [-127, 127], c_end = 6
  biases: [-8192, 8192], c_end = 64

Example of reading output weights and biases from the previous main net using
nnue-pytorch and printing spsa params in a format compatible with fishtest:

```
import features
from serialize import NNUEReader

feature_set = features.get_feature_set_from_name("HalfKAv2_hm")
with open("nn-ddcfb9224cdb.nnue", "rb") as f:
    model = NNUEReader(f, feature_set).model

c_end_weights = 6
c_end_biases = 64

for i in range(8):
    for j in range(32):
        value = round(int(model.layer_stacks.output.weight[i, j] * 600 * 16) / 127)
        print(f"oW[{i}][{j}],{value},-127,127,{c_end_weights},0.0020")

for i in range(8):
    value = int(model.layer_stacks.output.bias[i] * 600 * 16)
    print(f"oB[{i}],{value},-8192,8192,{c_end_biases},0.0020")
```

For more info on spsa tuning params in nets:
https://github.com/official-stockfish/Stockfish/pull/5149
https://github.com/official-stockfish/Stockfish/pull/5254

Passed STC:
https://tests.stockfishchess.org/tests/view/66894d64e59d990b103f8a37
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 32000 W: 8443 L: 8137 D: 15420
Ptnml(0-2): 80, 3627, 8309, 3875, 109

Passed LTC:
https://tests.stockfishchess.org/tests/view/6689668ce59d990b103f8b8b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 172176 W: 43822 L: 43225 D: 85129
Ptnml(0-2): 97, 18821, 47633, 19462, 75

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

bench 1120091
2024-07-09 18:35:23 +02:00
MinetaS cdb0b96e07 Clean up refutations array in MovePicker
This is a follow-up cleanup to a45c2bc34a.

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

No functional change
2024-07-09 18:34:00 +02:00
Linmiao Xu 4e9fded5a6 Larger bonus when updating quiet stats
Also removes unused arguments to update_all_stats to
fix compiler warnings about unused parameters.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6689a79a0fdd852d63cf52e9
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 26496 W: 6901 L: 6669 D: 12926
Ptnml(0-2): 62, 3094, 6715, 3304, 73

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6689a9960fdd852d63cf532d
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 41214 W: 10373 L: 10173 D: 20668
Ptnml(0-2): 11, 4491, 11412, 4673, 20

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

bench 1169958
2024-07-09 18:31:02 +02:00
Michael Chaly 75c8cb2c2f Adjust usage of previous statscore in bonus assignments
This patch adjusts usage of previous statscore for bonus assginments - allowing
it for any statscores and clamping it to wider range.

Passed STC:
https://tests.stockfishchess.org/tests/view/66892e76e59d990b103f6a91
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 431520 W: 111767 L: 110872 D: 208881
Ptnml(0-2): 1180, 51165, 110133, 52144, 1138

Passed LTC:
https://tests.stockfishchess.org/tests/view/66897176e59d990b103f9605
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 143184 W: 36463 L: 35929 D: 70792
Ptnml(0-2): 55, 15540, 39863, 16084, 50

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

bench 1330556
2024-07-09 18:29:09 +02:00
Linmiao Xu bb9b65408f Simplify improving deduction in futility margin
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/668981d4df142e108ffc9bb4
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 312672 W: 80280 L: 80363 D: 152029
Ptnml(0-2): 729, 37198, 80529, 37187, 693

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/668988c6df142e108ffca042
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 126042 W: 31971 L: 31857 D: 62214
Ptnml(0-2): 50, 13988, 34832, 14100, 51

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

bench 1100483
2024-07-09 18:28:06 +02:00
Shawn Xu 2d3ef434b4 Tweak LMR at Root
Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 328192 W: 84751 L: 84014 D: 159427
Ptnml(0-2): 758, 38802, 84253, 39511, 772
https://tests.stockfishchess.org/tests/view/6689203959cb3228a4759a49

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 56748 W: 14494 L: 14136 D: 28118
Ptnml(0-2): 19, 6089, 15803, 6441, 22
https://tests.stockfishchess.org/tests/view/66892d76e59d990b103f6626

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

Bench 1253593
2024-07-09 18:26:35 +02:00
Shawn Xu b79ac764ff Simplify in-check condition for Probcut-in-check
dont let your memes be dreams !?

Passed Non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 512000 W: 132193 L: 132497 D: 247310
Ptnml(0-2): 1600, 61170, 130704, 60986, 1540
https://tests.stockfishchess.org/tests/view/66838911c4f539faa03268a2

Passed Non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 380268 W: 95894 L: 96042 D: 188332
Ptnml(0-2): 193, 42861, 104180, 42701, 199
https://tests.stockfishchess.org/tests/view/6688d0550c9d7c1ab33ed5a8

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

Bench: 1130282
2024-07-09 18:24:40 +02:00
Shawn Xu b1f522930d Simplify Away Move Count Pruning Adjustment
Using Singular Search Result

Passed Non-regression STC:
LLR: 3.01 (-2.94,2.94) <-1.75,0.25>
Total: 62688 W: 16319 L: 16121 D: 30248
Ptnml(0-2): 196, 7317, 16104, 7547, 180
https://tests.stockfishchess.org/tests/view/66879bf51b527f04dd477ff9

Passed Non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 116502 W: 29504 L: 29379 D: 57619
Ptnml(0-2): 66, 12881, 32226, 13018, 60
https://tests.stockfishchess.org/tests/view/6688629e0c9d7c1ab33ed030

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

bench 1207930
2024-07-09 18:20:26 +02:00
Muzhen Gaming 4d6e1225bd Simplify ttPv reduction formula
This is a revert of 2046c92.
This patch is based on the fact that the ttPv reduction has proven non-linear scaling (as documented in the code, along with testing guidelines); however, the original patch had (erroneously) not been tested at VLTC or longer.

Simplification STC: https://tests.stockfishchess.org/tests/view/6689266e59cb3228a4759b28
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 100320 W: 25913 L: 25763 D: 48644
Ptnml(0-2): 270, 11842, 25750, 12064, 234

Simplification LTC: https://tests.stockfishchess.org/tests/view/66893103e59d990b103f6ab3
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 57078 W: 14466 L: 14282 D: 28330
Ptnml(0-2): 34, 6214, 15851, 6414, 26

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

Bench: 1124658
2024-07-06 18:00:09 +02:00
Muzhen Gaming 55cb235d47 Simplify internal iterative reductions
This is a revert of cc992e5.
This patch is based on consistent observations that decreasing depth more in IIR generally has a bad scaling behaviour (good at STC, bad at longer time controls).

Simplification STC: https://tests.stockfishchess.org/tests/view/6689266659cb3228a4759b26
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 96992 W: 24977 L: 24824 D: 47191
Ptnml(0-2): 251, 11497, 24851, 11642, 255

Simplification LTC: https://tests.stockfishchess.org/tests/view/668930ffe59d990b103f6ab1
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 35808 W: 9185 L: 8980 D: 17643
Ptnml(0-2): 25, 3776, 10101, 3973, 29

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

Bench: 1097766
2024-07-06 17:58:23 +02:00
Shawn Xu 24ab46c511 Non-functional Fixes & Updates
Fixes a missing default slot for dbg_extremes of, removes a extra newline, and
updates SE elo estimate from
https://tests.stockfishchess.org/tests/view/664ebd1e928b1fb18de4e4b7 while we
are at it.

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

No functional change
2024-07-06 17:56:31 +02:00
FauziAkram ec8288fe0d Simplify away eval in TM
Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 40160 W: 10523 L: 10309 D: 19328
Ptnml(0-2): 129, 4543, 10524, 4753, 131
https://tests.stockfishchess.org/tests/view/6685ab8b99271ae49479dbe9

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 195672 W: 49681 L: 49639 D: 96352
Ptnml(0-2): 112, 20976, 55597, 21060, 91
https://tests.stockfishchess.org/tests/view/6686f27a7092ade1206f7889

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

No functional change
2024-07-06 17:54:22 +02:00
Shawn Xu a45c2bc34a Simplify Away Countermove Heuristic
Passed Non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 977824 W: 252072 L: 252888 D: 472864
Ptnml(0-2): 2518, 117120, 250560, 116088, 2626
https://tests.stockfishchess.org/tests/view/6683452d95b0d1e881e81541

Passed Non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 81048 W: 20630 L: 20470 D: 39948
Ptnml(0-2): 36, 8915, 22464, 9071, 38
https://tests.stockfishchess.org/tests/view/66886b7b0c9d7c1ab33ed281

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

bench 1276784
2024-07-06 17:48:11 +02:00
Muzhen Gaming daa9e217ab VVLTC search tune
Passed VVLTC 1st sprt: https://tests.stockfishchess.org/tests/view/6688af640c9d7c1ab33ed327
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 16050 W: 4200 L: 3959 D: 7891
Ptnml(0-2): 0, 1383, 5018, 1624, 0

Passed VVLTC 2nd sprt: https://tests.stockfishchess.org/tests/view/6688e8900c9d7c1ab33efd60
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 44044 W: 11303 L: 10999 D: 21742
Ptnml(0-2): 1, 3973, 13772, 4273, 3

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

Bench: 992058
2024-07-06 17:45:58 +02:00
Stéphane Nicolet d212e663bb Introduction evaluation grain of 16 (and randomize)
This patch uses an evaluation grain of 16 in order to get more cutoffs in
the alpha-beta algorithm. For a discussion of the efficiency of alpha-beta
related to changes in the number of discrete values of terminal nodes, see
for instance section 9.1.2 of Judea Pearl's classical book "Heuristics" :

https://mat.uab.cat/~alseda/MasterOpt/Judea_Pearl-Heuristics_Intelligent_Search_Strategies_for_Computer_Problem_Solving.pdf

Moreover, we add a small (-1, +1) random component after the quantification
to help the search exploration a little bit. This is similar in spirit to
the (-1, +1) random component already present in the function draw_value()
to make Stockfish more robust in draw evaluations.

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 220960 W: 57249 L: 56668 D: 107043
Ptnml(0-2): 499, 26017, 56882, 26568, 514
https://tests.stockfishchess.org/tests/view/668907fb7edfb6f233f999f8

passed LTC :
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 48966 W: 12574 L: 12233 D: 24159
Ptnml(0-2): 14, 5233, 13654, 5562, 20
https://tests.stockfishchess.org/tests/view/6689105659cb3228a47598bf

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

bench: 1336007
2024-07-06 17:43:39 +02:00
Joost VandeVondele c40dd26cbc CI give creditials for the clang-format action
following up from earlier changes

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

No functional change
2024-07-06 17:42:23 +02:00
Joost VandeVondele 2cbc20e846 Correct and extend PV lines with decisive TB score
Currently (after #5407), SF has the property that any PV line with a decisive
TB score contains the corresponding TB position, with a score that correctly
identifies the depth at which TB are entered. The PV line that follows might
not preserve the game outcome, but can easily be verified and extended based on
TB information. This patch provides this functionality, simply extending the PV
lines on output, this doesn't affect search.

Indeed, if DTZ tables are available, search based PV lines that correspond to
decisive TB scores are verified to preserve game outcome, truncating the line
as needed. Subsequently, such PV lines are extended with a game outcome
preserving line until mate, as a possible continuation.  These lines are not
optimal mating lines, but are similar to what a user could produce on a website
like https://syzygy-tables.info/ clicking always the top ranked move, i.e.
minimizing or maximizing DTZ (with a simple tie-breaker for moves that have
identical DTZ), and are thus an just an illustration of how to game can be won.

A similar approach is already in established in
https://github.com/joergoster/Stockfish/tree/matefish2

This also contributes to addressing #5175 where SF can give an incorrect TB
win/loss for positions in TB with a movecounter that doesn't reflect optimal
play. While the full solution requires either TB generated differently, or a
search when ranking rootmoves, current SF will eventually find a draw in these
cases, in practice quite quickly, e.g.
`1kq5/q2r4/5K2/8/8/8/8/7Q w - - 96 1`
`8/8/6k1/3B4/3K4/4N3/8/8 w - - 54 106`

Gives the same results as master on an extended set of test positions from
https://github.com/mcostalba/Stockfish/commit/9173d29c414ddb8f4bec74e4db3ccbe664c66bf9
with the exception of the above mentioned fen where this commit improves.

With https://github.com/vondele/matetrack using 6men TB, all generated PVs verify:
```
Using ../Stockfish/src/stockfish.syzygyExtend on matetrack.epd with --nodes 1000000 --syzygyPath /chess/syzygy/3-4-5-6/WDL:/chess/syzygy/3-4-5-6/DTZ
Engine ID:     Stockfish dev-20240704-ff227954
Total FENs:    6555
Found mates:   3299
Best mates:    2582
Found TB wins: 568
```

As repeated DTZ probing could be slow a procedure (100ms+ on HDD, a few ms on
SSD), the extension is only done as long as the time taken is less than half
the `Move Overhead` parameter. For tournaments where these lines might be of
interest to the user, a suitable `Move Overhead` might be needed (e.g. TCEC has
1000ms already).

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

No functional change
2024-07-05 15:43:49 +02:00
Linmiao Xu 3c379e55d9 Update 7 stat bonus/malus params
Values found around 119k / 120k spsa games at 60+0.6:
https://tests.stockfishchess.org/tests/view/6683112a192114e61f92f87a

Passed STC:
https://tests.stockfishchess.org/tests/view/66838148c4f539faa0326897
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 40928 W: 10835 L: 10508 D: 19585
Ptnml(0-2): 139, 4802, 10254, 5131, 138

Passed LTC:
https://tests.stockfishchess.org/tests/view/668448a87a1863935cee42c6
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 29208 W: 7559 L: 7253 D: 14396
Ptnml(0-2): 17, 3118, 8019, 3442, 8

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

bench 1138753
2024-07-05 15:43:49 +02:00
Joost VandeVondele 25361e514b Output from a fix depth onward, instead of 3s.
To avoid output that depends on timing, output currmove and similar only from depth > 30
onward.  Current choice of 3s makes the output of the same search depending on
the system load, and doesn't always start at move 1. Depth 30 is nowadays
reached in a few seconds on most systems.

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

No functional change
2024-07-05 15:43:42 +02:00
Disservin 74a8fc0604 Use explicit action permissions in CI
Necessary modifications according to changes in the GitHub Action settings.

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

Follow up from the report by Yaron Avital (yaronav) earlier.

No functional change
2024-07-05 15:35:13 +02:00
Joost VandeVondele ee6fc7e38b CI: limit artifact uploads
do not upload some unneeded intermediate directories,
disable running authenticated git commands with the checkout action.

Thanks to Yaron A for the report.

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

No functional change
2024-07-03 13:45:14 +02:00
Shawn Xu b9ff5bb93b Implement dbg_extremes_of
An alternative to #5431, implements one function `dbg_extremes_of` to keep track
of min and max.

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

No functional change
2024-07-03 13:44:01 +02:00
Joost VandeVondele ad0f1fecda Move info strings once more
Follow up from #5404 ... current location leads to troubles with Aquarium GUI

Fixes #5430

Now prints the information on threads and available processors at the beginning
of search, where info about the networks is already printed (and is known to
work)

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

No functional change.
2024-07-03 13:39:31 +02:00
Shahin M. Shahin 6b7822119f Limit has_game_cycle() to only upcoming repetition
use the original algorithm according to the paper
http://web.archive.org/web/20201107002606/https://marcelk.net/2013-04-06/paper/upcoming-rep-v2.pdf,
which detects accurately if a position has an upcoming repetition. The 'no
progress' part of has_game_cycle has been removed, the function has been
renamed to upcoming_repetition to reflect this.

As a result of this fix, to the best of our knowledge, all PVs for completed
iterations that yield a mate or decisive table base score now end in mate or
contain a TB position, respectively.

passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6679fa1d0c2db3fa2dcecbf2
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 63584 W: 16666 L: 16472 D: 30446
Ptnml(0-2): 186, 7552, 16146, 7698, 210

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/667ac965e439ed1c7a9ca042
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 464574 W: 117493 L: 117729 D: 229352
Ptnml(0-2): 311, 52468, 126974, 52214, 320

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

bench: 1209805
2024-07-03 13:35:49 +02:00
Shawn Xu 69ad4667fb Do Capture History Updates In Probcut
This patch introduces history updates to probcut. Standard depth - 3 bonus and
maluses are given to the capture that caused fail high and previously searched
captures, respectively. Similar to #5243, a negative history fill is applied to
compensate for an increase in capture history average, thus improving the
scaling of this patch.

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 84832 W: 21941 L: 21556 D: 41335
Ptnml(0-2): 226, 9927, 21688, 10386, 189
https://tests.stockfishchess.org/tests/view/6682fab9389b9ee542b1d029

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 104298 W: 26469 L: 26011 D: 51818
Ptnml(0-2): 43, 11458, 28677, 11940, 31
https://tests.stockfishchess.org/tests/view/6682ff06389b9ee542b1d0a0

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

bench 1281351
2024-07-03 13:18:00 +02:00
Dubslow 6138a0fd0e Probcut in check no matter if pv or capture
Passed STC: https://tests.stockfishchess.org/tests/view/6681e9c8c1657e386d294cef
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 217824 W: 56149 L: 56129 D: 105546
Ptnml(0-2): 587, 25926, 55848, 25982, 569

Passed LTC: https://tests.stockfishchess.org/tests/view/6681fcb8c1657e386d294db1
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 357552 W: 90546 L: 90671 D: 176335
Ptnml(0-2): 207, 40064, 98362, 39933, 210

Each half of this also passed STC+LTC separately

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

bench 1227870
2024-07-01 20:07:03 +02:00
Linmiao Xu 843b6f7c98 Update some params for pruning at shallow depth
Values found around 82k / 120k spsa games at 60+0.6:
https://tests.stockfishchess.org/tests/view/6681aca4481148df247298bd

Passed STC:
https://tests.stockfishchess.org/tests/view/6681c795c1657e386d2948fa
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 145216 W: 37595 L: 37122 D: 70499
Ptnml(0-2): 375, 17122, 37185, 17507, 419

Passed LTC:
https://tests.stockfishchess.org/tests/view/6681d4eec1657e386d2949e0
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 154062 W: 39117 L: 38557 D: 76388
Ptnml(0-2): 67, 16874, 42608, 17396, 86

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

bench 996419
2024-07-01 20:04:13 +02:00
Linmiao Xu f6842a145c Simplify worsening deduction in futility margin
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/66817d46442423e547141226
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 345408 W: 89146 L: 89266 D: 166996
Ptnml(0-2): 954, 41317, 88286, 41189, 958

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/66818dbe1e90a146232d1f62
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 173214 W: 43821 L: 43755 D: 85638
Ptnml(0-2): 108, 19407, 47492, 19511, 89

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

bench 981017
2024-07-01 20:02:38 +02:00
FauziAkram 5deb262393 Simplify rm.averageScore calculation
Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 485056 W: 125222 L: 125497 D: 234337
Ptnml(0-2): 1384, 58197, 123614, 57976, 1357
https://tests.stockfishchess.org/tests/view/6681816d442423e54714133f

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 56622 W: 14301 L: 14115 D: 28206
Ptnml(0-2): 31, 6259, 15538, 6459, 24
https://tests.stockfishchess.org/tests/view/6681a9a5596d543edc677490

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

bench: 1171203
2024-07-01 20:01:05 +02:00
Shahin M. Shahin 38c5fc33e4 Increase reduction based on correct expectation
If the current node is not a cutNode then it means that the child is one in LMR
and the cutoff count is expected, so more reduction when the cutoffs are
expected

Passed STC:
https://tests.stockfishchess.org/tests/view/66815e791c5b344a34ca7090
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 64416 W: 16876 L: 16519 D: 31021
Ptnml(0-2): 150, 7670, 16264, 7921, 203

Passed LTC:
https://tests.stockfishchess.org/tests/view/668162f61c5b344a34ca725c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 78186 W: 19905 L: 19499 D: 38782
Ptnml(0-2): 55, 8561, 21437, 9003, 37

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

bench: 1161531
2024-07-01 19:58:13 +02:00
Michael Chaly 7b49f9dd70 Tweak multicut
This patch is an original patch by author of Altair
(https://github.com/Alex2262/AltairChessEngine) chess engine.

It allows to produce more aggressive multicut compared to master by changing
condition it needs to fulfil and also returns bigger value.  Also has applied
matetrack fix on top.

Passed STC:
https://tests.stockfishchess.org/tests/view/667223ab602682471b0650e2
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 50048 W: 13200 L: 12860 D: 23988
Ptnml(0-2): 181, 5822, 12679, 6160, 182

Passed LTC:
https://tests.stockfishchess.org/tests/view/6672f777602682471b06515d
LLR: 2.97 (-2.94,2.94) <0.50,2.50>
Total: 706380 W: 179707 L: 177981 D: 348692
Ptnml(0-2): 656, 79250, 191665, 80950, 669

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

bench 1148966
2024-07-01 19:56:38 +02:00
Daniel Monroe 91ec31dac4 Grade countermove bonus for low statscores
Passed STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 338592 W: 88396 L: 87627 D: 162569
Ptnml(0-2): 1161, 40201, 85788, 41000, 1146
https://tests.stockfishchess.org/tests/view/6679d40c0c2db3fa2dcecbcc

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 83526 W: 21429 L: 21010 D: 41087
Ptnml(0-2): 54, 9173, 22913, 9546, 77
https://tests.stockfishchess.org/tests/view/667c5f2980450dba965911fc

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

bench: 1489815
2024-07-01 19:53:45 +02:00
mstembera 90eca83e7f Simplify away a useless TTEntry::read()
Not needed when we don hit an entry.

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

No functional change
2024-07-01 19:50:32 +02:00
Taras Vuk 22a502ac74 Skip futility pruning if beta is below TB loss value
Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 77024 W: 20122 L: 19946 D: 36956
Ptnml(0-2): 278, 8754, 20277, 8920, 283
https://tests.stockfishchess.org/tests/view/66752d59602682471b0652f3

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 93114 W: 23623 L: 23477 D: 46014
Ptnml(0-2): 77, 9839, 26566, 10011, 64
https://tests.stockfishchess.org/tests/view/6676b3e1602682471b065395

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

bench: 1003441
2024-07-01 19:48:06 +02:00
Joost VandeVondele 66e6274d32 Fix typos in comments
closes https://github.com/official-stockfish/Stockfish/pull/5409

No functional change
2024-07-01 19:44:17 +02:00
FauziAkram b2a12917e2 Remove redundant inline
constexpr implies inline anyway

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

No functional change
2024-07-01 19:40:04 +02:00
Joost VandeVondele 5fbfd06171 Move info output afer uciok
fixes #5393 : an incompatibility with an older GUI (Chesspartner)
fixes #5396 : an incompatibility with an older GUI (Fritz9)

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

No functional change
2024-07-01 19:37:25 +02:00
FauziAkram cc992e5e4a Internal iterative reductions: decrease depth more
For PV nodes without a ttMove, we decrease depth.
But in this patch, additionally, if the current position is found in the TT, and the stored depth in the TT is greater than or equal to
the current search depth, we decrease the search depth even further.

Passed STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 84384 W: 22154 L: 21761 D: 40469
Ptnml(0-2): 292, 9972, 21315, 10277, 336
https://tests.stockfishchess.org/tests/view/666b0a4d602682471b064db6

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 92106 W: 23471 L: 23032 D: 45603
Ptnml(0-2): 79, 10155, 25154, 10578, 87
https://tests.stockfishchess.org/tests/view/666c423d602682471b064e56

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

bench: 1038234
2024-06-23 11:46:41 +02:00
Shawn Xu d5c130569b Simplify Bonus Formula In History Adjustment
Inspired by a discord message [1] from Vizvezdenec, this patch simplifies the
bonus adjustment bonus = bonus > 0 ? 2 * bonus : bonus / 2 to a constant
addition, maintaining bonus average at around 0 in regular bench. As cj5716
pointed in discord [2], the constant bonus can also be considered as factoring
tempo when calculating bonus, yielding a better value of the move.

[1] https://discord.com/channels/435943710472011776/882956631514689597/1243877089443188776
[2] https://discord.com/channels/435943710472011776/813919248455827515/1252277437249622077

Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 29984 W: 7908 L: 7677 D: 14399
Ptnml(0-2): 95, 3502, 7594, 3679, 122
https://tests.stockfishchess.org/tests/view/666f7210602682471b064fa2

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 170136 W: 43214 L: 43145 D: 83777
Ptnml(0-2): 158, 19185, 46311, 19258, 156
https://tests.stockfishchess.org/tests/view/666fb32e602682471b064fb5

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

bench 1438375
2024-06-23 11:41:48 +02:00
evqsx 8806a58ebf Simplify static exchange evaluation pruning formula
Passed STC: https://tests.stockfishchess.org/tests/view/666bda31602682471b064e1f
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 141696 W: 36932 L: 36826 D: 67938
Ptnml(0-2): 510, 16880, 35989, 16932, 537

Passed LTC: https://tests.stockfishchess.org/tests/view/666e6b67602682471b064f4b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 159504 W: 40552 L: 40471 D: 78481
Ptnml(0-2): 130, 18160, 43103, 18217, 142

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

bench: 1084115
2024-06-23 11:37:32 +02:00
Joost VandeVondele 5514690f8e CI/CD: play games
this action plays games under fast-chess with a `debug=yes` compiled binary.

It checks for triggered asserts in the code, or generally for engine disconnects.

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

No functional change
2024-06-23 11:35:50 +02:00
xoto10 2678606e8d Consider wider range of moves near leaves.
try to avoid missing good moves for opponent or engine, by updating bestMove
also when value == bestValue (i.e. value == alpha) under certain conditions.
In particular require this is at higher depth in the tree, leaving the logic
near the root unchanged, and only apply randomly. Avoid doing this near mate
scores, leaving mate PVs intact.

Passed SMP STC 6+0.06 th7 :
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 42040 W: 10930 L: 10624 D: 20486
Ptnml(0-2): 28, 4682, 11289, 4998, 23
https://tests.stockfishchess.org/tests/view/66608b00c340c8eed7757d1d

Passed SMP LTC 24+0.24 th7 :
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 73692 W: 18978 L: 18600 D: 36114
Ptnml(0-2): 9, 7421, 21614, 7787, 15
https://tests.stockfishchess.org/tests/view/666095e8c340c8eed7757d49

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

Bench 1205168
2024-06-23 11:29:02 +02:00
FauziAkram 2046c92ad4 Tweak the reduction formula
Tweak the reduction formula if position is or has been on the PV
Taking inspiration from an old Viren test.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 78528 W: 20607 L: 20225 D: 37696
Ptnml(0-2): 262, 9297, 19785, 9637, 283
https://tests.stockfishchess.org/tests/view/666339c70ff7cb4868d1fe24

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 138630 W: 35666 L: 35132 D: 67832
Ptnml(0-2): 118, 15345, 37835, 15919, 98
https://tests.stockfishchess.org/tests/view/66645dec0612cd151f9e77b0

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

Bench: 1134281
2024-06-15 12:13:59 +02:00
Dubslow ff10f4ac65 Fix readability of TTEntry occupancy check
Passed STC:
https://tests.stockfishchess.org/tests/view/66695b6a602682471b064cfc
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 107520 W: 28138 L: 27998 D: 51384
Ptnml(0-2): 373, 12257, 28358, 12401, 371

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

No functional change
2024-06-15 12:10:49 +02:00
Joost VandeVondele b01fdb596a Fix upperbound/lowerbound output in multithreaded case
In case a stop is received during multithreaded searches, the PV of the best
thread might be printed without the correct upperbound/lowerbound indicators.
This was due to the pvIdx variable being incremented after receiving the stop.

passed STC:
https://tests.stockfishchess.org/tests/view/666985da602682471b064d08
 LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 196576 W: 51039 L: 50996 D: 94541
Ptnml(0-2): 760, 22545, 51603, 22652, 728

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

Bench: 1160467
2024-06-15 12:08:29 +02:00
Joost VandeVondele 44cddbd962 Add matetrack to CI
verifies that all mate PVs printed for finished iterations (i.e. no lower or upper bounds),
are complete, i.e. of the expected length and ending in mate, and do not contain drawing
or illegal moves.

based on a set of 2000 positions and the code in https://github.com/vondele/matetrack

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

No functional change
2024-06-15 12:06:45 +02:00
Tomasz Sobczyk 7c0607d2d3 Fix printing of empty info strings.
Handle printing of `info string` in a single place.

Fixes #5386

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

No functional change
2024-06-15 12:04:16 +02:00
Joost VandeVondele 3d92950859 Limit depth after extensions to avoid asserts.
currently extensions can cause depth to exceed MAX_PLY.

This triggers the assert near line 542 in search when running a binary compiled with `debug=yes` on a testcase like:
```
position fen 7K/P1p1p1p1/2P1P1Pk/6pP/3p2P1/1P6/3P4/8 w - - 0 1
go nodes 1000000
```

passed STC
https://tests.stockfishchess.org/tests/view/6668a56a602682471b064c8d
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 143936 W: 37338 L: 37238 D: 69360
Ptnml(0-2): 514, 16335, 38149, 16477, 493

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

Bench: 1160467
2024-06-15 12:02:56 +02:00
Linmiao Xu 025da6a0d1 Give positional output more weight in nnue eval
This effectively reverts the removal of delta in:
https://github.com/official-stockfish/Stockfish/pull/5373

Passed STC:
https://tests.stockfishchess.org/tests/view/6664d41922234461cef58e6b
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 56448 W: 14849 L: 14500 D: 27099
Ptnml(0-2): 227, 6481, 14457, 6834, 225

Passed LTC:
https://tests.stockfishchess.org/tests/view/666587a1996b40829f4ee007
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 91686 W: 23402 L: 22963 D: 45321
Ptnml(0-2): 78, 10205, 24840, 10640, 80

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

bench 1160467
2024-06-12 09:17:04 +02:00
Disservin 7013a22b74 Move options into the engine
Move the engine options into the engine class, also avoid duplicated
initializations after startup.  UCIEngine needs to register an add_listener to
listen to all option changes and print these.  Also avoid a double
initialization of the TT, which was the case with the old state.

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

No functional change
2024-06-12 09:17:04 +02:00
Dubslow c8213ba0d0 Simplify TT interface and avoid changing TT info
This commit builds on the work and ideas of #5345, #5348, and #5364.

Place as much as possible of the TT implementation in tt.cpp, rather than in the
header.  Some commentary is added to better document the public interface.

Fix the search read-TT races, or at least contain them to within TT methods only.

Passed SMP STC: https://tests.stockfishchess.org/tests/view/666134ab91e372763104b443
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 512552 W: 132387 L: 132676 D: 247489
Ptnml(0-2): 469, 58429, 138771, 58136, 471

The unmerged version has bench identical to the other PR (see also #5348) and
therefore those same-functionality tests:

SMP LTC: https://tests.stockfishchess.org/tests/view/665c7021fd45fb0f907c214a
SMP LTC: https://tests.stockfishchess.org/tests/view/665d28a7fd45fb0f907c5495

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

bench 1205675
2024-06-12 09:17:04 +02:00
Joost VandeVondele 7e890fd048 Keep mate PVs intact.
do not return a cutoff value in razoring if that value is in the mate/tb range.

passed STC:
https://tests.stockfishchess.org/tests/view/666381880ff7cb4868d1fe58
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 130848 W: 34046 L: 33931 D: 62871
Ptnml(0-2): 429, 14968, 34524, 15065, 438

passed LTC:
https://tests.stockfishchess.org/tests/view/66643f120612cd151f9e7788
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 39702 W: 10157 L: 9959 D: 19586
Ptnml(0-2): 20, 4108, 11402, 4296, 25

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

Bench: 1174094
2024-06-12 09:03:32 +02:00
cj5716 e271059e08 Make repeated bench runs identical
fixes https://github.com/official-stockfish/Stockfish/issues/5376
closes https://github.com/official-stockfish/Stockfish/pull/5377

No functional changes
2024-06-08 23:40:22 +02:00
evqsx 4151c06b74 Remove the correction history bonus in null move search
Passed STC:
https://tests.stockfishchess.org/tests/view/666168e191e372763104c664
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 94848 W: 24708 L: 24550 D: 45590
Ptnml(0-2): 289, 11355, 24033, 11403, 344

Passed LTC:
https://tests.stockfishchess.org/tests/view/6661e73591e372763104c751
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 70452 W: 17849 L: 17679 D: 34924
Ptnml(0-2): 27, 7707, 19596, 7861, 35

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

Bench: 1174094
2024-06-08 23:39:46 +02:00
Dubslow 1c67b46caf Linearize corrHist
Passed STC: https://tests.stockfishchess.org/tests/view/6661fff88dd8f31ed3c5d819
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 17504 W: 4651 L: 4406 D: 8447
Ptnml(0-2): 71, 1975, 4384, 2282, 40

Passed LTC: https://tests.stockfishchess.org/tests/view/666205b48dd8f31ed3c61296
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 24522 W: 6313 L: 6094 D: 12115
Ptnml(0-2): 14, 2643, 6726, 2866, 12

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

Bench: 1237729
2024-06-08 23:35:00 +02:00
Dubslow 7d4ffa175c Remove delta from evaluation
Passed STC: https://tests.stockfishchess.org/tests/view/6660e49c6489614cdad14e29
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 188768 W: 48907 L: 48854 D: 91007
Ptnml(0-2): 584, 22571, 48005, 22656, 568

Passed LTC: https://tests.stockfishchess.org/tests/view/6660ff9791e372763104b38c
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 310680 W: 78651 L: 78727 D: 153302
Ptnml(0-2): 180, 34818, 85433, 34716, 193

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

Bench: 1214575
2024-06-08 23:34:03 +02:00
Tomasz Sobczyk f55239b2f3 NumaPolicy fixes and robustness improvements
1. Fix GetProcessGroupAffinity still not getting properly aligned memory
   sometimes.
2. Fix a very theoretically possible heap corruption if
   GetActiveProcessorGroupCount changes between calls.
3. Fully determine affinity on Windows 11 and Windows Server 2022. It
   should only ever be indeterminate in case of an error.
4. Separate isDeterminate for old and new API, as they are &'d together
   we still can end up with a subset of processors even if one API is
   indeterminate.
5. likely_used_old_api() that is based on actual affinity that's been
   detected
6. IMPORTANT: Gather affinities at startup, so that we only later use
   the affinites set at startup. Not only does this prevent us from our
   own calls interfering with detection but it also means subsequent
   setoption NumaPolicy calls should behave as expected.
7. Fix ERROR_INSUFFICIENT_BUFFER from GetThreadSelectedCpuSetMasks being
   treated like an error.

Should resolve
https://github.com/vondele/Stockfish/commit/02ff76630b358e5f958793cc93df0009d2da65a5#commitcomment-142790025

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

Bench: 1231853
2024-06-08 23:32:27 +02:00
FauziAkram e2be0aaf67 Tweak pruning formula
Tweak pruning formula, including a constant. I started from an old
yellow patch, if I'm not mistaken by Viz (Unfortunately I lost the link)
where he tried something similar.
I worked on it, trying different variations, until I came up with a good
configuration to pass.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 213120 W: 55351 L: 54778 D: 102991
Ptnml(0-2): 572, 25209, 54437, 25758, 584
https://tests.stockfishchess.org/tests/view/6660c9a7c340c8eed7758195

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 315324 W: 80176 L: 79284 D: 155864
Ptnml(0-2): 155, 34711, 87030, 35619, 147
https://tests.stockfishchess.org/tests/view/6660d7bb6489614cdad13d66

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

Bench: 1231853
2024-06-08 23:28:07 +02:00
rn5f107s2 5dda4037c7 Simplify razor changes
Remove razoring changes from
https://github.com/official-stockfish/Stockfish/pull/5360

The mentioned patch introduced the usage of futility_margin into
razoring alongside a tune to futility_margin. It seems the elo gained in
this patch comes from the tune of futility_margin and not the
introduction of futility_margin to razoring, so simplify it away here.

Passed Non-regression STC:
https://tests.stockfishchess.org/tests/view/66606581c340c8eed7757bc8
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 169056 W: 43922 L: 43848 D: 81286
Ptnml(0-2): 438, 20288, 43034, 20298, 470

Passed Non-regression LTC:
https://tests.stockfishchess.org/tests/view/66607764c340c8eed7757c58
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 157134 W: 39805 L: 39723 D: 77606
Ptnml(0-2): 74, 17444, 43461, 17502, 86

Passed rebased Non-regression LTC:
https://tests.stockfishchess.org/tests/view/6660c696c340c8eed77580c0
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 135984 W: 34427 L: 34324 D: 67233
Ptnml(0-2): 67, 15063, 37615, 15194, 53

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

Bench: 1150518
2024-06-08 23:10:59 +02:00
Disservin 66ed4312f2 Workaround the clang-format inconsistencies
closes https://github.com/official-stockfish/Stockfish/pull/5378

No functional change
2024-06-08 23:09:02 +02:00
R-Goc e6c83beed1 Change PGO type for clang
Change type of PGO in clang to IR which is recommended by LLVM/clang and
could result in a speedup.
https://github.com/llvm/llvm-project/issues/45668

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

No functional change
2024-06-08 23:05:56 +02:00
cj5716 5688b188cc Simplify evaluation constants
Passed STC (<0, 2> by accident):
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 346016 W: 89529 L: 88756 D: 167731
Ptnml(0-2): 1012, 41074, 88027, 41919, 976
https://tests.stockfishchess.org/tests/view/6659d6ecf426908fcc6b6929

Passed LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 89862 W: 22887 L: 22734 D: 44241
Ptnml(0-2): 45, 9999, 24694, 10144, 49
https://tests.stockfishchess.org/tests/view/665a6ebb062b2c3cf814fde8

Passed LTC (Rebased):
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 325500 W: 82734 L: 82826 D: 159940
Ptnml(0-2): 193, 36409, 89665, 36263, 220
https://tests.stockfishchess.org/tests/view/665bd39f44e8416a9cdc1909

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

Bench 961982
2024-06-05 21:49:29 +02:00
Disservin fb18caae7a Update clang-format to version 18
clang-format-18 is available in ubuntu noble(24.04), if you are on
a version lower than that you can use the update script from llvm.
https://apt.llvm.org/

Windows users should be able to download and use clang-format from
their release builds https://github.com/llvm/llvm-project/releases
or get the latest from msys2
https://packages.msys2.org/package/mingw-w64-x86_64-clang.

macOS users can resort to "brew install clang-format".

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

No functional change
2024-06-05 21:41:43 +02:00
Viren6 36eb9bc783 Use futility margin in razoring margin
Uses futilityMargin * depth to set the razoring margin. This retains the
quadratic depth scaling to preserve mate finding capabilities. This patch is
nice because it increases the elo sensitivity of the futility margin
heuristics.

Passed STC:
https://tests.stockfishchess.org/tests/view/665f9892fd11ae7170b4849c
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 39392 W: 10348 L: 10030 D: 19014
Ptnml(0-2): 99, 4585, 10009, 4905, 98

Passed LTC:
https://tests.stockfishchess.org/tests/view/665f9d2dfd11ae7170b484a8
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 107910 W: 27521 L: 27053 D: 53336
Ptnml(0-2): 73, 11835, 29670, 12305, 72

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

bench 1277173
2024-06-05 21:33:46 +02:00
Muzhen Gaming a08fcacb28 VVLTC search tune
Parameters were tuned with 199k games of VVLTC: https://tests.stockfishchess.org/tests/view/665c67e73542f91ad1c54fe2

Passed VVLTC 1st sprt: https://tests.stockfishchess.org/tests/view/665e9c83fd45fb0f907c837c
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 83494 W: 21546 L: 21219 D: 40729
Ptnml(0-2): 6, 7707, 25993, 8036, 5

Passed VVLTC 2nd sprt: https://tests.stockfishchess.org/tests/view/665f650bfd45fb0f907cb360
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 151056 W: 38796 L: 38295 D: 73965
Ptnml(0-2): 5, 13742, 47536, 14237, 8

https://github.com/official-stockfish/Stockfish/pull/5359

Bench: 1154524
2024-06-05 21:10:55 +02:00
mstembera 21ba32af6d Remove m512_hadd128x16_interleave()
This functionality is no longer used anywhere.

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

No functional change
2024-06-05 21:07:07 +02:00
Tomasz Sobczyk 02ff76630b Add NumaPolicy "hardware" option that bypasses current processor affinity.
Can be used in case a GUI (e.g. ChessBase 17 see #5307) sets affinity to a
single processor group, but the user would like to use the full capabilities of
the hardware.  Improves affinity handling on Windows in case of multiple
available APIs and existing affinities.

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

No functional change
2024-06-05 21:01:45 +02:00
Gahtan Nahdi daaccd9fc9 Simplify smallnet threshold
remove pawncount

Passed STC non-reg:
https://tests.stockfishchess.org/tests/view/665e4548fd45fb0f907c80d5
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 60896 W: 15710 L: 15518 D: 29668
Ptnml(0-2): 149, 7145, 15660, 7353, 141

Passed LTC non-reg:
https://tests.stockfishchess.org/tests/view/665e4c52fd45fb0f907c815f
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 58068 W: 14773 L: 14590 D: 28705
Ptnml(0-2): 16, 6368, 16090, 6537, 23

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

Bench: 1343156
2024-06-05 20:59:56 +02:00
Disservin 4f53560d24 Accumulate nodes over all bench positions not just the last
closes https://github.com/official-stockfish/Stockfish/pull/5352

No functional change
2024-06-04 08:26:35 +02:00
Disservin 7f09d06b83 Properly initialize the TT in a multithreaded way again 2024-06-04 07:53:25 +02:00
Disservin ba06671aa9 Normalize some variable names and reuse existing logic
closes https://github.com/official-stockfish/Stockfish/pull/5346

No functional change
2024-06-03 23:28:23 +02:00
Dubslow 86b564055d Remove delta, adjusted, complexity from nnue code
...rather they're the consumer's concern whether to tweak the result or not.

Passed STC:
https://tests.stockfishchess.org/tests/view/665cea9ffd45fb0f907c53bd
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 69696 W: 18101 L: 17918 D: 33677
Ptnml(0-2): 195, 8171, 17929, 8362, 191

Passed LTC:
https://tests.stockfishchess.org/tests/view/665cf761fd45fb0f907c5406
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 63720 W: 16344 L: 16165 D: 31211
Ptnml(0-2): 32, 6990, 17625, 7193, 20

Non functional except for rounding issues of OutputScale changing bench.

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

Bench: 1378596
2024-06-03 23:27:58 +02:00
Dubslow 397f47a7a1 Adjust lowest depth constants to the natural place
Passed STC:
https://tests.stockfishchess.org/tests/view/665ce3f8fd45fb0f907c537f
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 282784 W: 73032 L: 73082 D: 136670
Ptnml(0-2): 680, 31845, 76364, 31851, 652

Recently when I overhauled these comments, Disservin asked why these
were so much lower: they're a relic from when we had a third QS stage at
-5. Now we don't, so fix these to the obvious place.

I was fairly sure it was nonfunctional but ran the nonreg to be double
sure.

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

Bench: 1057383
2024-06-03 23:20:02 +02:00
Gahtan Nahdi fe298953f8 Simplify smallnet threshold
Turns the quadratic threshold to a linear one

STC non-reg:
https://tests.stockfishchess.org/tests/view/665ba0b744e8416a9cdc188d
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 330432 W: 85351 L: 85454 D: 159627
Ptnml(0-2): 888, 39643, 84283, 39488, 914

LTC non-reg:
https://tests.stockfishchess.org/tests/view/665cd60ffd45fb0f907c4306
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 139146 W: 35194 L: 35093 D: 68859
Ptnml(0-2): 58, 15523, 38313, 15618, 61

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

Bench: 1057383
2024-06-03 23:18:36 +02:00
FauziAkram 924a843594 Simplify recapture extension
Simplifying the extension formula by removing the move == ttMove
condition.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 47328 W: 12324 L: 12117 D: 22887
Ptnml(0-2): 134, 5532, 12097, 5795, 106
https://tests.stockfishchess.org/tests/view/665ca5e6fd45fb0f907c41be

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 72126 W: 18378 L: 18209 D: 35539
Ptnml(0-2): 36, 7841, 20130, 8030, 26
https://tests.stockfishchess.org/tests/view/665cb276fd45fb0f907c41f9

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

Bench: 1399468
2024-06-03 23:17:09 +02:00
FauziAkram 3d6756769c Simplify continuation histories
Functional simplification.

Simplify continuation histories, therefore increasing the effect of
stats updates and movepicker bonuses for continuation history 3 plies
deep.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 229184 W: 59087 L: 59080 D: 111017
Ptnml(0-2): 554, 27248, 59002, 27213, 575
https://tests.stockfishchess.org/tests/view/665c7a09fd45fb0f907c223b

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 44532 W: 11419 L: 11223 D: 21890
Ptnml(0-2): 18, 4787, 12457, 4989, 15
https://tests.stockfishchess.org/tests/view/665c8842fd45fb0f907c23ec

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

Bench: 1326444
2024-06-03 23:12:13 +02:00
Disservin 00a28ae325 Add helpers for managing aligned memory
Previously, we had two type aliases, LargePagePtr and AlignedPtr, which
required manually initializing the aligned memory for the pointer.

The new helpers:

- make_unique_aligned
- make_unique_large_page

are now available for allocating aligned memory (with large pages). They
behave similarly to std::make_unique, ensuring objects allocated with
these functions follow RAII.

The old approach had issues with initializing non-trivial types or
arrays of objects. The evaluation function of the network is now a
unique pointer to an array instead of an array of unique pointers.

Memory related functions have been moved into memory.h

Passed High Hash Pressure Test Non-Regression STC:
https://tests.stockfishchess.org/tests/view/665b2b36586058766677cfd2
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 476992 W: 122426 L: 122677 D: 231889
Ptnml(0-2): 1145, 51027, 134419, 50744, 1161

Failed Normal Non-Regression STC:
https://tests.stockfishchess.org/tests/view/665b2997586058766677cfc8
LLR: -2.94 (-2.94,2.94) <-1.75,0.25>
Total: 877312 W: 225233 L: 226395 D: 425684
Ptnml(0-2): 2110, 94642, 246239, 93630, 2035

Probably a fluke since there shouldn't be a real slowndown and it has also
passed the high hash pressure test.

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

No functional change
2024-06-03 23:11:59 +02:00
Tomasz Sobczyk a2a7edf4c8 Fix GetProcessGroupAffinity call
`GetProcessGroupAffinity` appears to require 4 byte alignment for `GroupArray` memory.

See https://stackoverflow.com/q/78567676 for further information

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

No functional change
2024-06-03 08:54:24 +02:00
Joost VandeVondele 8aaae0367c Revert "Adjust return bonus from tt cutoffs at fail highs"
This reverts commit 783dfc2eb2.

could lead to a division by zero for:

ttValue = (ttValue * tte->depth() + beta) / (tte->depth() + 1)

as other threads can overwrite the tte with a QS depth of -1.

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

Bench: 1280020
2024-06-02 09:23:28 +02:00
Linmiao Xu c17d73c554 Simplify statScore divisor into a constant
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/665b392ff4a1fd0c208ea864
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 114752 W: 29628 L: 29495 D: 55629
Ptnml(0-2): 293, 13694, 29269, 13827, 293

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/665b588c11645bd3d3fac467
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 65322 W: 16549 L: 16373 D: 32400
Ptnml(0-2): 30, 7146, 18133, 7322, 30

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

bench 1241443
2024-06-01 20:17:38 +02:00
xoto10 b009c43254 Simplify tm, removing faster 1st move and 1.13 extraTime.
Passed STC 10+0.1 :
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 349760 W: 90112 L: 90231 D: 169417
Ptnml(0-2): 784, 37970, 97496, 37841, 789
https://tests.stockfishchess.org/tests/view/665aeee00223e235f05b7d21

Passed LTC 60+0.6 :
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 140082 W: 35463 L: 35370 D: 69249
Ptnml(0-2): 59, 13492, 42851, 13575, 64
https://tests.stockfishchess.org/tests/view/665b15e78da109e362924e5a

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

No functional change
2024-06-01 20:12:36 +02:00
MinetaS 180cab4438 Simplify 50 move rule dampening
Refactor the logic of 50 move rule dampening by removing a constant.

Passed non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 35232 W: 9214 L: 8992 D: 17026
Ptnml(0-2): 114, 4081, 8999, 4313, 109
https://tests.stockfishchess.org/tests/view/665a329013d08af3c1725610

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 38406 W: 9732 L: 9530 D: 19144
Ptnml(0-2): 14, 4132, 10708, 4336, 13
https://tests.stockfishchess.org/tests/view/665a370913d08af3c1725651

https://github.com/official-stockfish/Stockfish/pull/5327

Bench: 1059739
2024-06-01 20:09:47 +02:00
FauziAkram ec1cda1d81 Simplify histories movepick formula
Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 81440 W: 21100 L: 20929 D: 39411
Ptnml(0-2): 248, 9659, 20718, 9864, 231
https://tests.stockfishchess.org/tests/view/6659a8b7ea624d64ea5f3208

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 85758 W: 21763 L: 21607 D: 42388
Ptnml(0-2): 34, 9606, 23463, 9722, 54
https://tests.stockfishchess.org/tests/view/6659d7bff426908fcc6b692c

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

bench: 1280472
2024-06-01 20:08:08 +02:00
Joost VandeVondele b0870cf528 Avoid changing bestvalue
in the case the ttValue contains mate scores, do not return them as bestValue, since they are not proven.

passed STC
https://tests.stockfishchess.org/tests/view/665b1ea5586058766677cfa3
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 58912 W: 15319 L: 15130 D: 28463
Ptnml(0-2): 141, 6562, 15854, 6765, 134

passed LTC:
https://tests.stockfishchess.org/tests/view/665b2712586058766677cfc4
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 141666 W: 35976 L: 35879 D: 69811
Ptnml(0-2): 61, 15513, 39584, 15618, 57

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

Bench: 1336115
2024-06-01 20:04:30 +02:00
Michael Chaly 783dfc2eb2 Adjust return bonus from tt cutoffs at fail highs
This is reintroduction of the recently simplified logic - if positive tt cutoff
occurs return not a tt value but smth between it and beta.  Difference is that
instead of static linear combination there we use basically the same formula as
we do in the main search - with the only difference being using tt depth
instead of depth, which makes a lot of sense.

Passed STC:
https://tests.stockfishchess.org/tests/view/665b3a34f4a1fd0c208ea870
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 54944 W: 14239 L: 13896 D: 26809
Ptnml(0-2): 151, 6407, 14008, 6760, 146

Passed LTC:
https://tests.stockfishchess.org/tests/view/665b520011645bd3d3fac341
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 90540 W: 23070 L: 22640 D: 44830
Ptnml(0-2): 39, 9903, 24965, 10315, 48

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

bench 1381237
2024-06-01 20:02:09 +02:00
Linmiao Xu cb4a623119 Update default smallnet to nn-37f18f62d772.nnue
Created by training L1-128 from scratch with:
- skipping based on simple eval in the trainer, for compatibility with
  regular binpacks without requiring pre-filtering all binpacks
- minimum simple eval of 950, lower than 1000 previously
- usage of some hse-v1 binpacks with minimum simple eval 1000
- addition of hse-v6 binpacks with minimum simple eval 500
- permuting the FT with 10k positions from fishpack32.binpack
- torch.compile to speed up smallnet training

Training is significantly slower when using non-pre-filtered binpacks due to
the increased skipping required.

This net was reached at epoch 339.

```
experiment-name: 128--S1-hse-1k-T80-v6-unfilt-less-sf--se-gt950-no-wld-skip

training-dataset:
  /data/:
    - dfrc99-16tb7p.v2.min.binpack

  /data/hse-v1/:
    - leela96-filt-v2.min.high-simple-eval-1k.min-v2.binpack

    - test60-novdec2021-12tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.min-v2.binpack

    - test77-nov2021-2tb7p.no-db.min.high-simple-eval-1k.min-v2.binpack
    - test77-dec2021-16tb7p.no-db.min.high-simple-eval-1k.min-v2.binpack
    - test77-jan2022-2tb7p.high-simple-eval-1k.min-v2.binpack

    - test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.min-v2.binpack
    - test78-juntosep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.min-v2.binpack

    - test79-apr2022-16tb7p.min.high-simple-eval-1k.min-v2.binpack
    - test79-may2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.min-v2.binpack

    - test80-apr2022-16tb7p.min.high-simple-eval-1k.min-v2.binpack
    - test80-may2022-16tb7p.high-simple-eval-1k.min-v2.binpack
    - test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.min-v2.binpack
    - test80-jul2022-16tb7p.v6-dd.min.high-simple-eval-1k.min-v2.binpack
    - test80-sep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.min-v2.binpack
    - test80-nov2022-16tb7p-v6-dd.min.high-simple-eval-1k.min-v2.binpack

  /data/S11-mar2024/:
    - test80-2022-08-aug-16tb7p.v6-dd.min.binpack
    - test80-2022-10-oct-16tb7p.v6-dd.binpack
    - test80-2022-12-dec-16tb7p.min.binpack

    - test80-2023-01-jan-16tb7p.v6-sk20.min.binpack
    - test80-2023-02-feb-16tb7p.v6-sk20.min.binpack
    - test80-2023-03-mar-2tb7p.v6-sk16.min.binpack
    - test80-2023-04-apr-2tb7p.v6-sk16.min.binpack
    - test80-2023-05-may-2tb7p.v6.min.binpack
    - test80-2023-06-jun-2tb7p.binpack.min-v2.binpack
    - test80-2023-07-jul-2tb7p.binpack.min-v2.binpack
    - test80-2023-08-aug-2tb7p.v6.min.binpack
    - test80-2023-09-sep-2tb7p.binpack.hse-v6.binpack
    - test80-2023-10-oct-2tb7p.binpack.hse-v6.binpack
    - test80-2023-11-nov-2tb7p.binpack.hse-v6.binpack
    - test80-2023-12-dec-2tb7p.binpack.hse-v6.binpack

    - test80-2024-01-jan-2tb7p.binpack.hse-v6.binpack
    - test80-2024-02-feb-2tb7p.binpack.hse-v6.binpack
    - test80-2024-03-mar-2tb7p.binpack

wld-fen-skipping: False

nnue-pytorch-branch: linrock/nnue-pytorch/128-skipSimpleEval-lt950-torch-compile
engine-test-branch: linrock/Stockfish/L1-128-nolazy
engine-base-branch: linrock/Stockfish/L1-128
start-from-engine-test-net: False

num-epochs: 500
start-lambda: 1.0
end-lambda: 1.0
```

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Passed STC:
https://tests.stockfishchess.org/tests/view/66549c16a86388d5e27daff5
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 196608 W: 51254 L: 50697 D: 94657
Ptnml(0-2): 722, 23244, 49796, 23839, 703

Passed LTC:
https://tests.stockfishchess.org/tests/view/6658d1aa6b0e318cefa90122
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 122538 W: 31332 L: 30835 D: 60371
Ptnml(0-2): 69, 13407, 33811, 13922, 60

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

bench
2024-06-01 19:59:07 +02:00
rn5f107s2 b34a690cd4 MCP more after a bad singular search
The idea is, that if we have the information that the singular search failed low and therefore produced an upperbound score, we can use the score from singularsearch as approximate upperbound as to what bestValue our non ttMoves will produce. If this value is well below alpha, we assume that all non-ttMoves will score below alpha and therfore can skip more moves.
This patch also sets up variables for future patches wanting to use teh singular search result outside of singular extensions, in singularBound and singularValue, meaning further patches using this search result to affect various pruning techniques can be tried.

Passed STC:
https://tests.stockfishchess.org/tests/view/6658d13e6b0e318cefa90120
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 85632 W: 22112 L: 21725 D: 41795
Ptnml(0-2): 243, 10010, 21947, 10349, 267

Passed LTC:
https://tests.stockfishchess.org/tests/view/6658dd356b0e318cefa9016a
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 243978 W: 62014 L: 61272 D: 120692
Ptnml(0-2): 128, 26598, 67791, 27348, 124

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

bench 1397172
2024-06-01 19:58:20 +02:00
Linmiao Xu 0ef809ac71 Quadratic smallnet threshold with re-evaluation
The threshold now decreases more quickly as pawn count decreases,
using the smallnet more compared to before.

Combo of two eval patches:
https://tests.stockfishchess.org/tests/view/66576c5f6b0e318cefa8d26e
https://tests.stockfishchess.org/tests/view/664ced40830eb9f886616a77

Passed STC:
https://tests.stockfishchess.org/tests/view/66588c136b0e318cefa8ff21
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 112608 W: 29336 L: 28908 D: 54364
Ptnml(0-2): 344, 13223, 28718, 13699, 320

Passed LTC:
https://tests.stockfishchess.org/tests/view/6658c8786b0e318cefa900f5
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 108288 W: 27493 L: 27026 D: 53769
Ptnml(0-2): 54, 11821, 29930, 12282, 57

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

bench 1728074
2024-06-01 19:56:05 +02:00
FauziAkram de1ae4949d Tweak first picked move (ttMove) reduction rule
Tweak first picked move (ttMove) reduction rule:

Instead of always resetting the reduction to 0, we now only do so if the current reduction is less than 2.
If the current reduction is 2 or more, we decrease it by 2 instead.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 109504 W: 28340 L: 27919 D: 53245
Ptnml(0-2): 305, 12848, 28028, 13263, 308
https://tests.stockfishchess.org/tests/view/6658c2fa6b0e318cefa900c2

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 130410 W: 33248 L: 32738 D: 64424
Ptnml(0-2): 53, 14139, 36328, 14615, 70
https://tests.stockfishchess.org/tests/view/6658dd8a6b0e318cefa90173

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

bench: 1224588
2024-06-01 19:53:13 +02:00
Joost VandeVondele 54e74919d4 Fix cross from Linux to Windows
specifies Windows 7 required

https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170

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

No functional change
2024-05-30 23:07:25 +02:00
Tomasz Sobczyk c8375c2fbd On linux use sysfs instead of lscpu
Use sysfs (https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-devices-node)
to determine processor to NUMA node mapping.

Avoids problems on some machines with high core count where lscpu was showing high cpu utilization.

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

No functional change
2024-05-30 23:05:25 +02:00
Tomasz Sobczyk 86694b5914 Replace std::from_chars with std::stoull
the former was not widely supported, requiring newer compiler versions.

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

No functional change
2024-05-30 23:05:21 +02:00
Tomasz Sobczyk f1bb4164bf Fix process' processor affinity determination on Windows.
Specialize and privatize NumaConfig::get_process_affinity.
Only enable NUMA capability for 64-bit Windows.

Following #5307 and some more testing it was determined that the way affinity
was being determined on Windows was incorrect, based on incorrect assumptions
about GetNumaProcessorNodeEx.

This patch fixes the issue by attempting to retrieve the actual process'
processor affinity using Windows API. However one issue persists that is not
addressable due to limitations of Windows, and will have to be considered a
limitation. If affinities were set using SetThreadAffinityMask instead of
SetThreadSelectedCpuSetMasks and GetProcessGroupAffinity returns more than 1
group it is NOT POSSIBLE to determine the affinity programmatically on Windows.
In such case the implementation assumes no affinites are set and will consider
all processors available for execution.

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

No functional change
2024-05-30 23:05:16 +02:00
Disservin 596fb4842b NUMA: Fix concurrency counting for windows systems
If there is more than 1 processor group, std::thread::hardware_concurrency should not be used.

fixes #5307

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

No functional change
2024-05-30 23:05:01 +02:00
FauziAkram 02eae52833 Simplifying the malus for putting piece en prise formula
Simplifying the malus for putting piece en prise
formula by merging the minor pieces and pawns
(removing the pawn exclusion from the formula).

Passed STC:
https://tests.stockfishchess.org/tests/view/66578d9c6b0e318cefa8d441
LLR: 2.99 (-2.94,2.94) <-1.75,0.25>
Total: 314272 W: 80705 L: 80786 D: 152781
Ptnml(0-2): 873, 37577, 80366, 37398, 922

Passed LTC (before rebasing):
https://tests.stockfishchess.org/tests/view/6657b5ee6b0e318cefa8d6ab
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 117000 W: 29447 L: 29324 D: 58229
Ptnml(0-2): 47, 12877, 32535, 12988, 53

Passed LTC (also after rebasing):
https://tests.stockfishchess.org/tests/view/6658803d6b0e318cefa8fd99
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 244992 W: 61807 L: 61814 D: 121371
Ptnml(0-2): 125, 27420, 67414, 27411, 126

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

Bench: 1484840
2024-05-30 23:00:22 +02:00
Michael Chaly b280d2f065 Allow tt cutoffs for shallower depths in certain conditions
Current master allows tt cutoffs only when depth
from tt is strictly greater than current node
depth. This patch also allows them when it's equal
and if tt value is lower or equal to beta.

Passed STC:
https://tests.stockfishchess.org/tests/view/66578e2e6b0e318cefa8d447
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 26592 W: 6944 L: 6645 D: 13003
Ptnml(0-2): 67, 3039, 6795, 3318, 77

Passed LTC:
https://tests.stockfishchess.org/tests/view/6657f46b6b0e318cefa8d7e9
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 142572 W: 36315 L: 35776 D: 70481
Ptnml(0-2): 70, 15666, 39288, 16179, 83

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

Bench: 1368486
2024-05-30 22:54:23 +02:00
FauziAkram d1a71fdaa7 Functional simplification in the transposition table
Passed STC:
LLR: 2.98 (-2.94,2.94) <-1.75,0.25>
Total: 154848 W: 39838 L: 39750 D: 75260
Ptnml(0-2): 404, 16214, 44087, 16328, 391
https://tests.stockfishchess.org/tests/view/664892b088b8c6a2bbe430fc

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 68172 W: 17296 L: 17137 D: 33739
Ptnml(0-2): 23, 6349, 21185, 6504, 25
https://tests.stockfishchess.org/tests/view/6648aabfa0781149e383e526

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

Bench: 1623228
2024-05-30 22:53:20 +02:00
Viren6 a77a895c3b Add extension condition to cutoffCnt
Decrease cutoffCnt increment by 1 if extension is 2 or greater.

Passed STC:
https://tests.stockfishchess.org/tests/view/66577a696b0e318cefa8d34d
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 99200 W: 25703 L: 25297 D: 48200
Ptnml(0-2): 253, 11660, 25390, 12022, 275

Passed LTC:
https://tests.stockfishchess.org/tests/view/665787ab6b0e318cefa8d411
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 124530 W: 31659 L: 31161 D: 61710
Ptnml(0-2): 58, 13578, 34489, 14088, 52

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

bench 1623228
2024-05-30 14:34:24 +02:00
Robert Nurnberg @ elitebook a4ea183e78 Tweak and update the WDL model
This PR updates the internal WDL model, using data from 2.5M games played by SF-dev (3c62ad7).
Note that the normalizing constant has increased from 329 to 368.

Changes to the fitting procedure:

* the value for --materialMin was increased from 10 to 17: including data with less material leads to less accuracy for larger material count values
* the data was filtered to only include single thread LTC games at 60+0.6
* the data was filtered to only include games from master against patches that are (approximatively) within 5 nElo of master

For more information and plots of the model see PR#5309

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

No functional change
2024-05-30 14:29:31 +02:00
Linmiao Xu 35aff79843 Update default main net to nn-ddcfb9224cdb.nnue
Created by further tuning the spsa-tuned main net `nn-c721dfca8cd3.nnue`
with the same methods described in https://github.com/official-stockfish/Stockfish/pull/5254

This net was reached at 61k / 120k spsa games at 70+0.7 th 7:
https://tests.stockfishchess.org/tests/view/665639d0a86388d5e27dd259

Passed STC:
https://tests.stockfishchess.org/tests/view/6657d44e6b0e318cefa8d771
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 114688 W: 29775 L: 29344 D: 55569
Ptnml(0-2): 274, 13633, 29149, 13964, 324

Passed LTC:
https://tests.stockfishchess.org/tests/view/6657e1e46b0e318cefa8d7a6
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 88152 W: 22412 L: 21988 D: 43752
Ptnml(0-2): 56, 9560, 24409, 10006, 45

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

Bench: 1434678
2024-05-30 14:28:07 +02:00
FauziAkram 0ea6337ccf Remove Queen threatenedByMinor
Remove Queen threatenedByMinor from movepick

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 54432 W: 14053 L: 13855 D: 26524
Ptnml(0-2): 124, 6347, 14090, 6517, 138
https://tests.stockfishchess.org/tests/view/66578d036b0e318cefa8d43d

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 198168 W: 49979 L: 49940 D: 98249
Ptnml(0-2): 84, 21824, 55236, 21849, 91
https://tests.stockfishchess.org/tests/view/66579cf86b0e318cefa8d5b1

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

bench: 1342438
2024-05-30 14:21:28 +02:00
Linmiao Xu 5ab3fe6db8 Simplify blending eval with nnue complexity
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/66567377a86388d5e27dd89c
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 144000 W: 37443 L: 37338 D: 69219
Ptnml(0-2): 587, 17260, 36208, 17351, 594

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/66567f29a86388d5e27dd924
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 112326 W: 28550 L: 28421 D: 55355
Ptnml(0-2): 66, 12732, 30434, 12869, 62

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

bench 1554486
2024-05-30 14:18:39 +02:00
Shawn Xu 4a2291ed33 Simplify Away Quadruple Extension
Passed non-regression VVLTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 90792 W: 23155 L: 23018 D: 44619
Ptnml(0-2): 6, 8406, 28432, 8549, 3
https://tests.stockfishchess.org/tests/view/664ffa4ca86388d5e27d8e7a

Passed non-regression VLTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 288136 W: 72608 L: 72659 D: 142869
Ptnml(0-2): 38, 30258, 83525, 30211, 36
https://tests.stockfishchess.org/tests/view/66551609a86388d5e27db9ae

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

bench 1501735
2024-05-30 14:16:17 +02:00
xoto10 3c62ad7e07 Add compensation factor to adjust extra time according to time control
As stockfish nets and search evolve, the existing time control appears
to give too little time at STC, roughly correct at LTC, and too little
at VLTC+.

This change adds an adjustment to the optExtra calculation. This
adjustment is easy to retune and refine, so it should be easier to keep
up-to-date than the more complex calculations used for optConstant and
optScale.

Passed STC 10+0.1:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 169568 W: 43803 L: 43295 D: 82470
Ptnml(0-2): 485, 19679, 44055, 19973, 592
https://tests.stockfishchess.org/tests/view/66531865a86388d5e27da9fa

Yellow LTC 60+0.6:
LLR: -2.94 (-2.94,2.94) <0.50,2.50>
Total: 209970 W: 53087 L: 52914 D: 103969
Ptnml(0-2): 91, 19652, 65314, 19849, 79
https://tests.stockfishchess.org/tests/view/6653e38ba86388d5e27daaa0

Passed VLTC 180+1.8 :
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 85618 W: 21735 L: 21342 D: 42541
Ptnml(0-2): 15, 8267, 25848, 8668, 11
https://tests.stockfishchess.org/tests/view/6655131da86388d5e27db95f

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

Bench: 1212167
2024-05-29 19:04:57 +02:00
Shawn Xu ae7eef51fd Simplify Fail Low Bonus Formula
Tested against PR #5299

Passed Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 76352 W: 19797 L: 19619 D: 36936
Ptnml(0-2): 236, 9017, 19509, 9161, 253
https://tests.stockfishchess.org/tests/view/66564f60a86388d5e27dd307

Passed Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 114624 W: 28946 L: 28821 D: 56857
Ptnml(0-2): 59, 12675, 31714, 12810, 54
https://tests.stockfishchess.org/tests/view/6656543da86388d5e27dd329

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

Bench: 1212167
2024-05-29 19:01:50 +02:00
mstembera a2f4e988aa Fix MSVC NUMA compile issues
closes https://github.com/official-stockfish/Stockfish/pull/5298

No functional change
2024-05-29 19:00:37 +02:00
Shawn Xu c14297a483 Tune Fail Low Bonus
Fractional bonus idea is from @Ergodice on
[discord](https://discord.com/channels/435943710472011776/735707599353151579/1244039134499180614).
Values are tuned for 149k games at LTC.

SPSA tune:
https://tests.stockfishchess.org/tests/view/6652d5d5a86388d5e27da9d6

Failed STC:
LLR: -2.95 (-2.94,2.94) <0.00,2.00>
Total: 67424 W: 17364 L: 17528 D: 32532
Ptnml(0-2): 238, 8043, 17299, 7909, 223
https://tests.stockfishchess.org/tests/view/66551e1ba86388d5e27db9f9

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 146910 W: 37141 L: 36695 D: 73074
Ptnml(0-2): 84, 16201, 40441, 16643, 86
https://tests.stockfishchess.org/tests/view/66559949a86388d5e27dcc5d

Passed VLTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 27248 W: 6924 L: 6633 D: 13691
Ptnml(0-2): 5, 2744, 7835, 3035, 5
https://tests.stockfishchess.org/tests/view/66563f4da86388d5e27dd27a

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

Bench: 1390709
2024-05-29 18:58:38 +02:00
Stéphane Nicolet c7b80f6c8a Merge pawn count terms using their average
This simplification patch merges the pawn count terms in the eval
formula with the material term, updating the offset constant for
the nnue part of the formula from 34000 to 34300 because the average
pawn count in middlegame positions evaluated during search is around 8.

STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 138240 W: 35834 L: 35723 D: 66683
Ptnml(0-2): 527, 16587, 34817, 16626, 563
https://tests.stockfishchess.org/tests/view/6653f474a86388d5e27daaac

LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 454272 W: 114787 L: 115012 D: 224473
Ptnml(0-2): 246, 51168, 124553, 50903, 266
https://tests.stockfishchess.org/tests/view/6654f256a86388d5e27db131

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

Bench: 1279635
2024-05-29 18:57:32 +02:00
FauziAkram 41acbcae1a Simplifying malus for putting piece en prise formula
Patch author: @ehsanrashid

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 116192 W: 30229 L: 30094 D: 55869
Ptnml(0-2): 451, 13880, 29351, 13911, 503
https://tests.stockfishchess.org/tests/view/66510a40a86388d5e27da936

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 441312 W: 111009 L: 111220 D: 219083
Ptnml(0-2): 217, 49390, 121659, 49167, 223
https://tests.stockfishchess.org/tests/view/66530696a86388d5e27da9e3

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

Bench: 1987574
2024-05-29 18:55:30 +02:00
Tomasz Sobczyk a169c78b6d Improve performance on NUMA systems
Allow for NUMA memory replication for NNUE weights.  Bind threads to ensure execution on a specific NUMA node.

This patch introduces NUMA memory replication, currently only utilized for the NNUE weights. Along with it comes all machinery required to identify NUMA nodes and bind threads to specific processors/nodes. It also comes with small changes to Thread and ThreadPool to allow easier execution of custom functions on the designated thread. Old thread binding (WinProcGroup) machinery is removed because it's incompatible with this patch. Small changes to unrelated parts of the code were made to ensure correctness, like some classes being made unmovable, raw pointers replaced with unique_ptr. etc.

Windows 7 and Windows 10 is partially supported. Windows 11 is fully supported. Linux is fully supported, with explicit exclusion of Android. No additional dependencies.

-----------------

A new UCI option `NumaPolicy` is introduced. It can take the following values:
```
system - gathers NUMA node information from the system (lscpu or windows api), for each threads binds it to a single NUMA node
none - assumes there is 1 NUMA node, never binds threads
auto - this is the default value, depends on the number of set threads and NUMA nodes, will only enable binding on multinode systems and when the number of threads reaches a threshold (dependent on node size and count)
[[custom]] -
  // ':'-separated numa nodes
  // ','-separated cpu indices
  // supports "first-last" range syntax for cpu indices,
  for example '0-15,32-47:16-31,48-63'
```

Setting `NumaPolicy` forces recreation of the threads in the ThreadPool, which in turn forces the recreation of the TT.

The threads are distributed among NUMA nodes in a round-robin fashion based on fill percentage (i.e. it will strive to fill all NUMA nodes evenly). Threads are bound to NUMA nodes, not specific processors, because that's our only requirement and the OS can schedule them better.

Special care is made that maximum memory usage on systems that do not require memory replication stays as previously, that is, unnecessary copies are avoided.

On linux the process' processor affinity is respected. This means that if you for example use taskset to restrict Stockfish to a single NUMA node then the `system` and `auto` settings will only see a single NUMA node (more precisely, the processors included in the current affinity mask) and act accordingly.

-----------------

We can't ensure that a memory allocation takes place on a given NUMA node without using libnuma on linux, or using appropriate custom allocators on windows (https://learn.microsoft.com/en-us/windows/win32/memory/allocating-memory-from-a-numa-node), so to avoid complications the current implementation relies on first-touch policy. Due to this we also rely on the memory allocator to give us a new chunk of untouched memory from the system. This appears to work reliably on linux, but results may vary.

MacOS is not supported, because AFAIK it's not affected, and implementation would be problematic anyway.

Windows is supported since Windows 7 (https://learn.microsoft.com/en-us/windows/win32/api/processtopologyapi/nf-processtopologyapi-setthreadgroupaffinity). Until Windows 11/Server 2022 NUMA nodes are split such that they cannot span processor groups. This is because before Windows 11/Server 2022 it's not possible to set thread affinity spanning processor groups. The splitting is done manually in some cases (required after Windows 10 Build 20348). Since Windows 11/Server 2022 we can set affinites spanning processor group so this splitting is not done, so the behaviour is pretty much like on linux.

Linux is supported, **without** libnuma requirement. `lscpu` is expected.

-----------------

Passed 60+1 @ 256t 16000MB hash: https://tests.stockfishchess.org/tests/view/6654e443a86388d5e27db0d8
```
LLR: 2.95 (-2.94,2.94) <0.00,10.00>
Total: 278 W: 110 L: 29 D: 139
Ptnml(0-2): 0, 1, 56, 82, 0
```

Passed SMP STC: https://tests.stockfishchess.org/tests/view/6654fc74a86388d5e27db1cd
```
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 67152 W: 17354 L: 17177 D: 32621
Ptnml(0-2): 64, 7428, 18408, 7619, 57
```

Passed STC: https://tests.stockfishchess.org/tests/view/6654fb27a86388d5e27db15c
```
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 131648 W: 34155 L: 34045 D: 63448
Ptnml(0-2): 426, 13878, 37096, 14008, 416
```

fixes #5253
closes https://github.com/official-stockfish/Stockfish/pull/5285

No functional change
2024-05-28 18:34:15 +02:00
Disservin b0287dcb1c apply const to prefetch parameter
closes https://github.com/official-stockfish/Stockfish/pull/5296

No functional change
2024-05-28 18:31:06 +02:00
FauziAkram d0b9411b82 Tweak return value in futility pruning
Tweak the return value formula in futility pruning.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 60544 W: 15791 L: 15440 D: 29313
Ptnml(0-2): 193, 7024, 15520, 7309, 226
https://tests.stockfishchess.org/tests/view/6654ef22a86388d5e27db122

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 126426 W: 32317 L: 31812 D: 62297
Ptnml(0-2): 55, 13871, 34869, 14350, 68
https://tests.stockfishchess.org/tests/view/66550644a86388d5e27db649

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

bench: 1856147
2024-05-28 18:30:24 +02:00
Shawn Xu 5e98a4e43d Simplify Away TT Cutoff Return Value Adjustments
Passed Non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 198432 W: 51161 L: 51119 D: 96152
Ptnml(0-2): 772, 23670, 50273, 23746, 755
https://tests.stockfishchess.org/tests/view/66517b9ea86388d5e27da966

Passed Non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 234150 W: 59200 L: 59197 D: 115753
Ptnml(0-2): 126, 26200, 64404, 26235, 110
https://tests.stockfishchess.org/tests/view/6653a84da86388d5e27daa63

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

bench 1555200
2024-05-28 18:26:42 +02:00
Shahin M. Shahin 8e1f273c7d Remove rootDelta branch
This makes rootDelta logic easier to understand, recalculating the value
where it belongs so removes an unnecessary branch.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/664fc147a86388d5e27d8d8e
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 206016 W: 53120 L: 53089 D: 99807
Ptnml(0-2): 591, 20928, 59888, 21061, 540

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

No functional change
2024-05-26 20:32:41 +02:00
Linmiao Xu 8bc3fd3871 Lower smallnet threshold with tuned eval params
The smallnet threshold is now below the training data range
of the current smallnet (simple eval diff > 1k, nn-baff1edelf90.nnue)
when no pawns are on the board.

Params found with spsa at 93k / 120k games at 60+06:
https://tests.stockfishchess.org/tests/view/664fa166a86388d5e27d7d6b

Tuned on top of: https://github.com/official-stockfish/Stockfish/pull/5287

Passed STC:
https://tests.stockfishchess.org/tests/view/664fc8b7a86388d5e27d8dac
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 64672 W: 16731 L: 16371 D: 31570
Ptnml(0-2): 239, 7463, 16517, 7933, 184

Passed LTC:
https://tests.stockfishchess.org/tests/view/664fd5f9a86388d5e27d8dfe
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 210648 W: 53489 L: 52813 D: 104346
Ptnml(0-2): 102, 23129, 58164, 23849, 80

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

Bench: 1717838
2024-05-26 20:32:30 +02:00
Stéphane Nicolet 4d876275cf Simplify material weights in evaluation
This patch uses the same material weights for the nnue
amplification term and the optimism term in evaluate().

STC:
LLR: 2.99 (-2.94,2.94) <-1.75,0.25>
Total: 83360 W: 21489 L: 21313 D: 40558
Ptnml(0-2): 303, 9934, 21056, 10058, 329
https://tests.stockfishchess.org/tests/view/664eee69928b1fb18de500d9

LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 192648 W: 48675 L: 48630 D: 95343
Ptnml(0-2): 82, 21484, 53161, 21501, 96
https://tests.stockfishchess.org/tests/view/664fa17aa86388d5e27d7d6e

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

Bench: 1495602
2024-05-26 20:24:05 +02:00
Muzhen Gaming 61acbfc7d3 VVLTC search tune
Parameters were tuned in 2 stages:
1. 127k games at VVLTC:
   https://tests.stockfishchess.org/tests/view/6649f8dfb8fa20e74c39f52a.
2. 106k games at VVLTC:
   https://tests.stockfishchess.org/tests/view/664bfb77830eb9f886615a9d.

Passed VVLTC 1st sprt:
https://tests.stockfishchess.org/tests/view/664e8dd9928b1fb18de4e410
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 20466 W: 5340 L: 5093 D: 10033
Ptnml(0-2): 0, 1796, 6397, 2037, 3

Passed VVLTC 2nd sprt:
https://tests.stockfishchess.org/tests/view/664eb4aa928b1fb18de4e47d
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 15854 W: 4186 L: 3934 D: 7734
Ptnml(0-2): 1, 1367, 4938, 1621, 0

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

Bench: 1558110
2024-05-23 21:37:46 +02:00
Linmiao Xu 365aa85dce Remove material imbalance param when adjusting optimism
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/664d033d830eb9f886616aff
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 102144 W: 26283 L: 26135 D: 49726
Ptnml(0-2): 292, 12201, 25991, 12243, 345

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/664d5c00830eb9f886616cb3
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 250032 W: 63022 L: 63036 D: 123974
Ptnml(0-2): 103, 27941, 68970, 27871, 131

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

Bench: 1330940
2024-05-23 21:37:46 +02:00
Muzhen Gaming 72a345873d Revert "Reduce When TTValue is Above Alpha"
The patch regressed significantly at longer time controls. In
particular, the `depth--` behavior was predicted to scale badly based on
data from other variations of the patch.

Passed VVLTC 1st sprt:
https://tests.stockfishchess.org/tests/view/664d45cf830eb9f886616c7d
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 51292 W: 13242 L: 12954 D: 25096
Ptnml(0-2): 5, 4724, 15896, 5020, 1

Passed VVLTC 2nd sprt:
https://tests.stockfishchess.org/tests/view/664e641a928b1fb18de4e385
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 41884 W: 10933 L: 10634 D: 20317
Ptnml(0-2): 1, 3759, 13125, 4054, 3

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

Bench: 1503815
2024-05-23 21:37:46 +02:00
cj5716 c6a1e7fd42 Optimise pairwise multiplication
This speedup was first inspired by a comment by @AndyGrant on my recent
PR "If mullo_epi16 would preserve the signedness, then this could be
used to remove 50% of the max operations during the halfkp-pairwise
mat-mul relu deal."

That got me thinking, because although mullo_epi16 did not preserve the
signedness, mulhi_epi16 did, and so we could shift left and then use
mulhi_epi16, instead of shifting right after the mullo.

However, due to some issues with shifting into the sign bit, the FT
weights and biases had to be multiplied by 2 for the optimisation to
work.

Speedup on "Arch=x86-64-bmi2 COMP=clang", courtesy of @Torom
Result of 50 runs
base (...es/stockfish) =     962946  +/- 1202
test (...ise-max-less) =     979696  +/- 1084
diff                   =     +16750  +/- 1794

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

CPU: 4 x Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
Hyperthreading: on

Also a speedup on "COMP=gcc", courtesy of Torom once again
Result of 50 runs
base (...tockfish_gcc) =     966033  +/- 1574
test (...max-less_gcc) =     983319  +/- 1513
diff                   =     +17286  +/- 2515

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

CPU: 4 x Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
Hyperthreading: on

Passed STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 67712 W: 17715 L: 17358 D: 32639
Ptnml(0-2): 225, 7472, 18140, 7759, 260
https://tests.stockfishchess.org/tests/view/664c1d75830eb9f886616906

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

No functional change
2024-05-23 21:37:46 +02:00
Shawn Xu c39b98b9e3 Simplify Away History Updates in Multicut
Passed Non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 44896 W: 11600 L: 11388 D: 21908
Ptnml(0-2): 140, 5230, 11532, 5370, 176
https://tests.stockfishchess.org/tests/view/664cee31830eb9f886616a80

Passed Non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 56832 W: 14421 L: 14234 D: 28177
Ptnml(0-2): 37, 6251, 15643, 6458, 27
https://tests.stockfishchess.org/tests/view/664cfd4e830eb9f886616aa6

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

Bench: 1119412
2024-05-23 21:30:33 +02:00
Linmiao Xu 1dcffa6210 Comment about re-evaluating positions
While the smallNet bool is no longer used as of now,
setting it to false upon re-evaluation represents the
correct eval state.

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

No functional change
2024-05-23 21:30:24 +02:00
Viren6 6db47ed71a Addition of new scaling comments
This patch is intended to prevent patches like 9b90cd8 and the
subsequent reversion e3c9ed7 from happening again. Scaling behaviour of
the reduction adjustments in the non-linear scaling
section have been proven to >8 sigma:

STC: https://tests.stockfishchess.org/tests/view/6647b19f6dcff0d1d6b05d52
Elo: 4.28 ± 0.8 (95%) LOS: 100.0%
Total: 200000 W: 52555 L: 50094 D: 97351
Ptnml(0-2): 573, 22628, 51248, 24867, 684
nElo: 8.35 ± 1.5 (95%) PairsRatio: 1.10

VLTC: https://tests.stockfishchess.org/tests/view/6647b1b06dcff0d1d6b05d54
Elo: -1.48 ± 1.0 (95%) LOS: 0.2%
Total: 100000 W: 25009 L: 25436 D: 49555
Ptnml(0-2): 11, 10716, 28971, 10293, 9
nElo: -3.23 ± 2.2 (95%) PairsRatio: 0.96

The else if condition is moved to the non scaling section based on:
https://tests.stockfishchess.org/tests/view/664567a193ce6da3e93b3232 (It
has no proven scaling)

General comment improvements and removal of a redundant margin condition
have also been included.

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

No functional change
2024-05-23 21:29:36 +02:00
Dubslow ed79745bb9 Improve comments about DEPTH constants
Also "fix" movepicker to allow depths between CHECKS and NO_CHECKS,
which makes them easier to tweak (not that they get tweaked hardly ever)
(This was more beneficial when there was a third stage to DEPTH_QS, but
it's still an improvement now)

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

No functional change
2024-05-23 21:29:11 +02:00
Linmiao Xu c14b69790a Lower smallnet threshold with updated eval divisors
Params found after 30k spsa games at 60+0.6, with initial
values from 64k spsa games at 45+0.45

First spsa with 64k / 120k games at 45+0.45:
https://tests.stockfishchess.org/tests/view/664a561b5fc7b70b8817c663
https://tests.stockfishchess.org/tests/view/664ae88e830eb9f8866146f9

Second spsa with 30k / 120k games at 60+0.6:
https://tests.stockfishchess.org/tests/view/664be227830eb9f886615a36

Values found at 10k games at 60+0.6 also passed STC and LTC:
https://tests.stockfishchess.org/tests/view/664bf4bd830eb9f886615a72
https://tests.stockfishchess.org/tests/view/664c0905830eb9f886615abf

Passed STC:
https://tests.stockfishchess.org/tests/view/664c139e830eb9f886615af2
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 69408 W: 18216 L: 17842 D: 33350
Ptnml(0-2): 257, 8275, 17401, 8379, 392

Passed LTC:
https://tests.stockfishchess.org/tests/view/664cdaf7830eb9f886616a24
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 35466 W: 9075 L: 8758 D: 17633
Ptnml(0-2): 27, 3783, 9794, 4104, 25

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

bench 1301287
2024-05-21 22:06:17 +02:00
MinetaS c86ec8ec29 Remove cutoffCnt margin adjustment in razoring
Passed non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 65344 W: 16767 L: 16578 D: 31999
Ptnml(0-2): 198, 7557, 16987, 7718, 212
https://tests.stockfishchess.org/tests/view/664bd895830eb9f886615a26

Passed non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 35214 W: 8999 L: 8791 D: 17424
Ptnml(0-2): 16, 3804, 9760, 4010, 17
https://tests.stockfishchess.org/tests/view/664bead5830eb9f886615a52

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

Bench: 1296223
2024-05-21 08:46:12 +02:00
FauziAkram 87bad0c38a Refine Evaluation Scaling with Piece-Specific Weights
Refine Evaluation Scaling with Piece-Specific Weights, instead of the simplified npm method.
I took the initial idea from Viren6 , as he worked on it in September of last year.
I worked on it, and tuned it, and now it passed both tests.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 95712 W: 24731 L: 24325 D: 46656
Ptnml(0-2): 363, 11152, 24357, 11684, 300
https://tests.stockfishchess.org/tests/view/664b5493830eb9f886614af3

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 204480 W: 52167 L: 51501 D: 100812
Ptnml(0-2): 114, 22579, 56166, 23289, 92
https://tests.stockfishchess.org/tests/view/664b75dd830eb9f886614b44

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

Bench: 1384337
2024-05-21 08:44:59 +02:00
Shawn Xu f27a9be29c Reduce When TTValue is Above Alpha
Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 53376 W: 13818 L: 13476 D: 26082
Ptnml(0-2): 156, 6212, 13626, 6522, 172
https://tests.stockfishchess.org/tests/view/664aa261830eb9f8866145e5

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 393444 W: 100096 L: 99042 D: 194306
Ptnml(0-2): 191, 43516, 108248, 44582, 185
https://tests.stockfishchess.org/tests/view/664ab54f830eb9f88661463c

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

Bench: 1024562
2024-05-21 08:40:37 +02:00
Michael Chaly daf9787de1 Rescale pawn history updates
This patch is somewhat of a continuation of recent pawn history gainers.
It makes pawn history updates after search twice smaller. Since on average they make pawn history more negative offset is changed to lower value to remain average value approximately the same.

https://tests.stockfishchess.org/tests/view/664b3af9830eb9f886614aab
Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 170464 W: 44239 L: 43724 D: 82501
Ptnml(0-2): 523, 20278, 43128, 20767, 536

Passed LTC against pending PR :
https://tests.stockfishchess.org/tests/view/664b8c58830eb9f886614b64
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 98178 W: 25015 L: 24569 D: 48594
Ptnml(0-2): 48, 10769, 27005, 11223, 44

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

Bench: 1343175
2024-05-21 08:36:32 +02:00
FauziAkram b8ccaf038a Use same shuffling Constant for both nets
Passed STC:
https://tests.stockfishchess.org/tests/view/664a42b15fc7b70b8817aeef
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 87840 W: 22759 L: 22594 D: 42487
Ptnml(0-2): 335, 10351, 22324, 10634, 276

Passed LTC:
https://tests.stockfishchess.org/tests/view/664a46995fc7b70b8817af02
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 163122 W: 41443 L: 41367 D: 80312
Ptnml(0-2): 105, 18154, 44927, 18310, 65

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

bench: 1190174
2024-05-21 08:27:16 +02:00
Michael Chaly 0c797367a3 Update correction history in case of successful null move pruning
Since null move pruning uses the same position it makes some sense to try to update correction history there in case of fail high.
Update value is 4 times less than normal update.

Passed STC:
https://tests.stockfishchess.org/tests/view/664a011cae57c1758ac5b4dd
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 419360 W: 108390 L: 107505 D: 203465
Ptnml(0-2): 1416, 49603, 106724, 50554, 1383

Passed LTC:
https://tests.stockfishchess.org/tests/view/664a53d95fc7b70b8817c65b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 193518 W: 49076 L: 48434 D: 96008
Ptnml(0-2): 89, 21335, 53263, 21989, 83

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

bench 1301487
2024-05-21 08:17:20 +02:00
Linmiao Xu 4d88a63e60 Re-eval only if smallnet output flips from simple eval
Recent attempts to change the smallnet nnue re-eval
threshold did not show much elo difference:
https://tests.stockfishchess.org/tests/view/664a29bb25a9058c4d21d53c
https://tests.stockfishchess.org/tests/view/664a299925a9058c4d21d53a

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/664a3ea95fc7b70b8817aee2
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 22304 W: 5905 L: 5664 D: 10735
Ptnml(0-2): 67, 2602, 5603, 2783, 97

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/664a43d35fc7b70b8817aef4
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 37536 W: 9667 L: 9460 D: 18409
Ptnml(0-2): 25, 4090, 10321, 4317, 15

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

bench 1287409
2024-05-21 08:13:25 +02:00
Stefan Geschwentner 81e21a69f0 Simplify the recently introduced ply-based cmh bonus factor.
Replace it with a constant which is an approximation of the limit of the factor.

STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 120064 W: 30967 L: 30836 D: 58261
Ptnml(0-2): 421, 14238, 30608, 14319, 446
https://tests.stockfishchess.org/tests/view/6649d146b8fa20e74c39f4ad

LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 53856 W: 13719 L: 13530 D: 26607
Ptnml(0-2): 31, 5879, 14922, 6062, 34
https://tests.stockfishchess.org/tests/view/664a027fae57c1758ac5b4ee

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

Bench: 1355618
2024-05-21 08:11:17 +02:00
Michael Chaly 4a66a7c9ca Do more aggressive pawn history updates
Tweak of recent patch that made pawn history to update for move that caused a fail low - and setting up default value of it to -900.  This patch makes it more aggressive - twice bigger updates and default value -1100.

Passed STC:
https://tests.stockfishchess.org/tests/view/6648c5d4308cceea45533b5d
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 235200 W: 61090 L: 60476 D: 113634
Ptnml(0-2): 763, 27952, 59651, 28376, 858

Passed LTC:
https://tests.stockfishchess.org/tests/view/664a1008ae57c1758ac5b523
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 20076 W: 5193 L: 4908 D: 9975
Ptnml(0-2): 7, 2105, 5534, 2380, 12

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

Bench: 1590474
2024-05-21 08:07:22 +02:00
Stefan Geschwentner a3bb7e626d Tweak continuation history bonus dependent on ply.
This patch is based on following tuning https://tests.stockfishchess.org/tests/view/6648b2eb308cceea45533abe by only using the tuned factors for the continuation history.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 99904 W: 25865 L: 25457 D: 48582
Ptnml(0-2): 281, 11705, 25578, 12101, 287
https://tests.stockfishchess.org/tests/view/6648c136308cceea45533af8

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 36402 W: 9362 L: 9039 D: 18001
Ptnml(0-2): 20, 3952, 9951, 4241, 37
https://tests.stockfishchess.org/tests/view/6648ee3cb8fa20e74c39f3fd

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

Bench: 1917762
2024-05-21 08:04:44 +02:00
cj5716 27eb49a221 Simplify ClippedReLU
Removes some max calls

Some speedup stats, courtesy of @AndyGrant (albeit measured in an alternate implementation)
Dev  749240 nps
Base 748495 nps
Gain 0.100%
289936 games

STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 203040 W: 52213 L: 52179 D: 98648
Ptnml(0-2): 480, 20722, 59139, 20642, 537
https://tests.stockfishchess.org/tests/view/664805fe6dcff0d1d6b05f2c

closes #5261

No functional change
2024-05-21 07:58:16 +02:00
Viren6 2d32581623 Revert "Simplify Away Quadruple Extensions"
This reverts commit 4edd1a3

The unusual result of (combined) +12.0 +- 3.7 in the 2 VVLTC simplification SPRTs ran was the result of base having only 64MB of hash instead of 512MB (Asymmetric hash).
Vizvezdenec was the one to notice this.

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

bench 1404295

Co-Authored-By: Michael Chaly <26898827+Vizvezdenec@users.noreply.github.com>
2024-05-19 09:37:22 +02:00
Muzhen Gaming 99f1bacfd6 VVLTC search tune
Tuned with 85k games at VVLTC.

VVLTC 1st sprt: https://tests.stockfishchess.org/tests/view/6648b836308cceea45533ad7
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 14880 W: 3890 L: 3652 D: 7338
Ptnml(0-2): 0, 1255, 4694, 1489, 2

VVLTC 2nd sprt: https://tests.stockfishchess.org/tests/view/6648c34f308cceea45533b4f
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 24984 W: 6502 L: 6235 D: 12247
Ptnml(0-2): 1, 2178, 7867, 2445, 1

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

Bench: 1198142
2024-05-18 18:09:45 +02:00
Linmiao Xu 2694fce928 Simplify away adjustEval lambda
Now that only the shuffling constant differs between nets,
a lambda for adjusting eval is no longer needed.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/664806ca6dcff0d1d6b05f34
LLR: 2.99 (-2.94,2.94) <-1.75,0.25>
Total: 31552 W: 8175 L: 7959 D: 15418
Ptnml(0-2): 76, 3180, 9065, 3362, 93

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

No functional change
2024-05-18 18:08:39 +02:00
Shawn Xu 4edd1a389e Simplify Away Quadruple Extensions
serendipitous gainer

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 95472 W: 24176 L: 24031 D: 47265
Ptnml(0-2): 52, 10533, 26414, 10692, 45
https://tests.stockfishchess.org/tests/live_elo/6647fa596dcff0d1d6b05efa

Passed VVLTC 70+7 th 7:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 6772 W: 1793 L: 1583 D: 3396
Ptnml(0-2): 0, 502, 2172, 712, 0
https://tests.stockfishchess.org/tests/live_elo/6648277a6dcff0d1d6b05ffb

Passed VVLTC 70+7 th 7 (2x):
https://tests.stockfishchess.org/tests/view/66484c896dcff0d1d6b0619d
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 5424 W: 1469 L: 1254 D: 2701
Ptnml(0-2): 0, 394, 1710, 607, 1

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

Bench: 1441794
2024-05-18 09:32:21 +02:00
Linmiao Xu 99dfc63e03 Use one nnue pawn count multiplier
Switch to the value used by the main net.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6647e8096dcff0d1d6b05e96
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 51040 W: 13249 L: 13044 D: 24747
Ptnml(0-2): 139, 6029, 13016, 6160, 176

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6647f4a46dcff0d1d6b05eea
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 20460 W: 5195 L: 4972 D: 10293
Ptnml(0-2): 8, 2178, 5637, 2397, 10

https://github.com/official-stockfish/Stockfish/pull/5258

bench 1887462
2024-05-18 09:29:26 +02:00
Shawn Xu 285f1d2a66 Tweak NMP Formula
Passed STC:
LLR: 2.99 (-2.94,2.94) <0.00,2.00>
Total: 241728 W: 62440 L: 61811 D: 117477
Ptnml(0-2): 914, 28467, 61458, 29126, 899
https://tests.stockfishchess.org/tests/live_elo/6645992993ce6da3e93b5b99

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 167850 W: 42620 L: 42030 D: 83200
Ptnml(0-2): 82, 18412, 46354, 18988, 89
https://tests.stockfishchess.org/tests/live_elo/6647c5726dcff0d1d6b05dd3

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

Bench: 1636018
2024-05-18 09:26:42 +02:00
FauziAkram f5e15441b8 Early Exit in Bitboards::sliding_attack()
he original code checks for occupancy within the loop condition. By moving this check inside the loop and adding an early exit condition, we can avoid unnecessary iterations if a blocking piece is encountered.

Passed stc:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 127200 W: 33129 L: 32700 D: 61371
Ptnml(0-2): 424, 13243, 35826, 13694, 413
https://tests.stockfishchess.org/tests/view/664646006dcff0d1d6b05bca

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

No functional change
2024-05-18 09:24:23 +02:00
Linmiao Xu d92d1f3180 Move smallnet threshold logic into a function
Now that the smallnet threshold is no longer a constant,
use a function to organize it with other eval code.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/66459fa093ce6da3e93b5ba2
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 217600 W: 56281 L: 56260 D: 105059
Ptnml(0-2): 756, 23787, 59729, 23736, 792

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

No functional change
2024-05-18 09:21:00 +02:00
Linmiao Xu 1b7dea3f85 Update default main net to nn-c721dfca8cd3.nnue
Created by first retraining the spsa-tuned main net `nn-ae6a388e4a1a.nnue` with:
- using v6-dd data without bestmove captures removed
- addition of T80 mar2024 data
- increasing loss by 20% when Q is too high
- torch.compile changes for marginal training speed gains

And then SPSA tuning weights of epoch 899 following methods described in:
https://github.com/official-stockfish/Stockfish/pull/5149

This net was reached at 92k out of 120k steps in this 70+0.7 th 7 SPSA tuning run:
https://tests.stockfishchess.org/tests/view/66413b7df9f4e8fc783c9bbb
Thanks to @Viren6 for suggesting usage of:
- c value 4 for the weights
- c value 128 for the biases

Scripts for automating applying fishtest spsa params to exporting tuned .nnue are in:
https://github.com/linrock/nnue-tools/tree/master/spsa

Before spsa tuning, epoch 899 was nn-f85738aefa84.nnue
https://tests.stockfishchess.org/tests/view/663e5c893a2f9702074bc167

After initially training with max-epoch 800, training was resumed with max-epoch 1000.

```
experiment-name: 3072--S11--more-data-v6-dd-t80-mar2024--see-ge0-20p-more-loss-high-q-sk28-l8
nnue-pytorch-branch: linrock/nnue-pytorch/3072-r21-skip-more-wdl-see-ge0-20p-more-loss-high-q-torch-compile-more

start-from-engine-test-net: False
start-from-model: /data/config/apr2024-3072/nn-ae6a388e4a1a.nnue

early-fen-skipping: 28
training-dataset:
  /data/S11-mar2024/:
    - leela96.v2.min.binpack

    - test60-2021-11-12-novdec-12tb7p.v6-dd.min.binpack
    - test78-2022-01-to-05-jantomay-16tb7p.v6-dd.min.binpack

    - test80-2022-06-jun-16tb7p.v6-dd.min.binpack

    - test80-2022-08-aug-16tb7p.v6-dd.min.binpack
    - test80-2022-09-sep-16tb7p.v6-dd.min.binpack

    - test80-2023-01-jan-16tb7p.v6-sk20.min.binpack
    - test80-2023-02-feb-16tb7p.v6-sk20.min.binpack
    - test80-2023-03-mar-2tb7p.v6-sk16.min.binpack
    - test80-2023-04-apr-2tb7p.v6-sk16.min.binpack
    - test80-2023-05-may-2tb7p.v6.min.binpack

    # https://github.com/official-stockfish/Stockfish/pull/4782
    - test80-2023-06-jun-2tb7p.binpack
    - test80-2023-07-jul-2tb7p.binpack

    # https://github.com/official-stockfish/Stockfish/pull/4972
    - test80-2023-08-aug-2tb7p.v6.min.binpack
    - test80-2023-09-sep-2tb7p.binpack
    - test80-2023-10-oct-2tb7p.binpack

    # S9 new data: https://github.com/official-stockfish/Stockfish/pull/5056
    - test80-2023-11-nov-2tb7p.binpack
    - test80-2023-12-dec-2tb7p.binpack

    # S10 new data: https://github.com/official-stockfish/Stockfish/pull/5149
    - test80-2024-01-jan-2tb7p.binpack
    - test80-2024-02-feb-2tb7p.binpack

    # S11 new data
    - test80-2024-03-mar-2tb7p.binpack

  /data/filt-v6-dd/:
    - test77-dec2021-16tb7p-filter-v6-dd.binpack
    - test78-juntosep2022-16tb7p-filter-v6-dd.binpack
    - test79-apr2022-16tb7p-filter-v6-dd.binpack
    - test79-may2022-16tb7p-filter-v6-dd.binpack
    - test80-jul2022-16tb7p-filter-v6-dd.binpack
    - test80-oct2022-16tb7p-filter-v6-dd.binpack
    - test80-nov2022-16tb7p-filter-v6-dd.binpack

num-epochs: 1000

lr: 4.375e-4
gamma: 0.995
start-lambda: 0.8
end-lambda: 0.7
```

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move:
nn-epoch899.nnue : 4.6 +/- 1.4

Passed STC:
https://tests.stockfishchess.org/tests/view/6645454893ce6da3e93b31ae
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 95232 W: 24598 L: 24194 D: 46440
Ptnml(0-2): 294, 11215, 24180, 11647, 280

Passed LTC:
https://tests.stockfishchess.org/tests/view/6645522d93ce6da3e93b31df
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 320544 W: 81432 L: 80524 D: 158588
Ptnml(0-2): 164, 35659, 87696, 36611, 142

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

bench 1995552
2024-05-18 09:19:10 +02:00
Rak Laptudirm e0227a6272 Improve comment
closes https://github.com/official-stockfish/Stockfish/pull/5249

No functional change
2024-05-18 09:18:14 +02:00
Linmiao Xu 47597641dc Lower smallnet threshold linearly as pawn count decreases
Passed STC:
https://tests.stockfishchess.org/tests/view/6644f677324e96f42f89d894
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 377920 W: 97135 L: 96322 D: 184463
Ptnml(0-2): 1044, 44259, 97588, 44978, 1091

Passed LTC:
https://tests.stockfishchess.org/tests/view/664548af93ce6da3e93b31b3
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 169056 W: 42901 L: 42312 D: 83843
Ptnml(0-2): 58, 18538, 46753, 19115, 64

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

Bench: 1991750
2024-05-16 14:19:28 +02:00
Muzhen Gaming e3c9ed77aa Revert "Reduce more when improving and ttvalue is lower than alpha"
The patch regressed significantly at longer time controls.

Passed VLTC:
https://tests.stockfishchess.org/tests/view/6644c7a2bc537f5619453096
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 43336 W: 11177 L: 10884 D: 21275
Ptnml(0-2): 3, 4432, 12507, 4721, 5

Passed VVLTC:
https://tests.stockfishchess.org/tests/view/66450c974aa4fa9a83b6d0b0
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 32394 W: 8350 L: 8072 D: 15972
Ptnml(0-2): 2, 2798, 10317, 3080, 0

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

Bench: 1594188
2024-05-16 14:17:53 +02:00
Linmiao Xu 541406ab91 Use same nnue divisor for both nets
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6643ceeabc537f56194506f6
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 224800 W: 57910 L: 57896 D: 108994
Ptnml(0-2): 673, 26790, 57519, 26686, 732

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6643ff15bc537f5619451719
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 347658 W: 87574 L: 87688 D: 172396
Ptnml(0-2): 207, 39004, 95488, 38956, 174

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

Bench: 1804704
2024-05-16 14:16:54 +02:00
FauziAkram dcb0233784 Simplifying improving and worsening deduction formulas
Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 77696 W: 20052 L: 19878 D: 37766
Ptnml(0-2): 222, 9124, 19994, 9274, 234
https://tests.stockfishchess.org/tests/view/66440032bc537f561945171e

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 234414 W: 58874 L: 58871 D: 116669
Ptnml(0-2): 96, 26147, 64742, 26102, 120
https://tests.stockfishchess.org/tests/view/6644094cbc537f5619451735

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

Bench: 1336738
2024-05-15 16:27:03 +02:00
Linmiao Xu 1f3a0fda2e Use same eval divisor for both nets
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/66428f146577e9d2c8a29cf8
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 241024 W: 62173 L: 62177 D: 116674
Ptnml(0-2): 904, 28648, 61407, 28654, 899

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6643ae6f1f32a966da74977b
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 193710 W: 48762 L: 48717 D: 96231
Ptnml(0-2): 70, 21599, 53481, 21626, 79

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

Bench: 1700680
2024-05-15 16:26:00 +02:00
Stefan Geschwentner 9b90cd88f0 Reduce more when improving and ttvalue is lower than alpha
More reduction if position is improving but value from TT doesn't
exceeds alpha but the tt move is excluded.

This idea is based on following LMR condition tuning
https://tests.stockfishchess.org/tests/view/66423a1bf9f4e8fc783cba37
by using only three of the four largest terms P[3], P[18] and P[12].

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 27840 W: 7309 L: 7004 D: 13527
Ptnml(0-2): 85, 3219, 7018, 3502, 96
https://tests.stockfishchess.org/tests/view/6643dc1cbc537f56194508ba

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 191280 W: 48656 L: 48020 D: 94604
Ptnml(0-2): 78, 20979, 52903, 21589, 91
https://tests.stockfishchess.org/tests/view/6643e543bc537f5619451683

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

Bench: 1430835
2024-05-15 16:20:14 +02:00
mstembera 09dba1f080 Call adjustEval with correct parameters after rescore
Set smallNet to false after rescoring so we call adjustEval() w/ correct
parameters.

STC:
https://tests.stockfishchess.org/tests/view/664308687134c82f3f7a4003
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 146912 W: 37856 L: 37756 D: 71300
Ptnml(0-2): 566, 17562, 37122, 17618, 588

LTC:
https://tests.stockfishchess.org/tests/view/6643a0821f32a966da7485d6
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 390414 W: 98015 L: 98173 D: 194226
Ptnml(0-2): 162, 43555, 107929, 43401, 160

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

Bench: 1819318
2024-05-15 16:19:04 +02:00
Michael Chaly 9e45644c50 Add extra bonus to pawn history for a move that caused a fail low
Basically the same idea as it is for continuation/main history, but it
has some tweaks.
1) it has * 2 multiplier for bonus instead of full/half bonus - for
   whatever reason this seems to work better;
2) attempts with this type of big bonuses scaled somewhat poorly (or
   were unlucky at longer time controls), but after measuring the fact
   that average value of pawn history in LMR after adding this bonuses
   increased by substantial number (for multiplier 1,5 it increased by
   smth like 400~ from 8192 cap) attempts were made to make default pawn
   history negative to compensate it - and version with multiplier 2 and
   initial fill value -900 passed.

Passed STC:
https://tests.stockfishchess.org/tests/view/66424815f9f4e8fc783cba59
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 115008 W: 30001 L: 29564 D: 55443
Ptnml(0-2): 432, 13629, 28903, 14150, 390

Passed LTC:
https://tests.stockfishchess.org/tests/view/6642f5437134c82f3f7a3ffa
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 56448 W: 14432 L: 14067 D: 27949
Ptnml(0-2): 36, 6268, 15254, 6627, 39

Bench: 1857237
2024-05-15 16:15:15 +02:00
FauziAkram fa114266fa Add extra bonus for high-depth condition
Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 54208 W: 14058 L: 13717 D: 26433
Ptnml(0-2): 166, 6277, 13885, 6602, 174
https://tests.stockfishchess.org/tests/view/664136d8f9f4e8fc783c9b82

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 112548 W: 28492 L: 28018 D: 56038
Ptnml(0-2): 53, 12186, 31318, 12668, 49
https://tests.stockfishchess.org/tests/view/664143fef9f4e8fc783c9bf6

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

Bench: 1725980
2024-05-15 16:13:43 +02:00
xoto10 2682c2127d Use 5% less time on first move
Stockfish appears to take too much time on the first move of a game and
then not enough on moves 2,3,4... Probably caused by most of the factors
that increase time usually applying on the first move.

Attempts to give more time to the subsequent moves have not worked so
far, but this change to simply reduce first move time by 5% worked.

STC 10+0.1 :
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 78496 W: 20516 L: 20135 D: 37845
Ptnml(0-2): 340, 8859, 20456, 9266, 327
https://tests.stockfishchess.org/tests/view/663d47bf507ebe1c0e9200ba

LTC 60+0.6 :
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 94872 W: 24179 L: 23751 D: 46942
Ptnml(0-2): 61, 9743, 27405, 10161, 66
https://tests.stockfishchess.org/tests/view/663e779cbb28828150dd9089

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

Bench: 1876282
2024-05-15 16:09:30 +02:00
mstembera e608eab8dd Optimize update_accumulator_refresh_cache()
STC https://tests.stockfishchess.org/tests/view/664105df26ac5f9b286d30e6
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 178528 W: 46235 L: 45750 D: 86543
Ptnml(0-2): 505, 17792, 52142, 18363, 462

Combo of two yellow speedups
https://tests.stockfishchess.org/tests/view/6640abf9d163897c63214f5c
LLR: -2.93 (-2.94,2.94) <0.00,2.00>
Total: 355744 W: 91714 L: 91470 D: 172560
Ptnml(0-2): 913, 36233, 103384, 36381, 961

https://tests.stockfishchess.org/tests/view/6628ce073fe04ce4cefc739c
LLR: -2.93 (-2.94,2.94) <0.00,2.00>
Total: 627040 W: 162001 L: 161339 D: 303700
Ptnml(0-2): 2268, 72379, 163532, 73105, 2236

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

No functional change
2024-05-13 07:32:32 +02:00
Linmiao Xu 0b08953174 Re-evaluate some small net positions for more accurate evals
Use main net evals when small net evals hint that higher eval
accuracy may be worth the slower eval speeds. With Finny caches,
re-evals with the main net are less expensive than before.

Original idea by mstembera who I've added as co-author to this PR.

Based on reEval tests by mstembera:
https://tests.stockfishchess.org/tests/view/65e69187b6345c1b934866e5
https://tests.stockfishchess.org/tests/view/65e863aa0ec64f0526c3e991

A few variants of this patch also passed LTC:
https://tests.stockfishchess.org/tests/view/663d2108507ebe1c0e91f407
https://tests.stockfishchess.org/tests/view/663e388c3a2f9702074bc152

Passed STC:
https://tests.stockfishchess.org/tests/view/663dadbd1a61d6377f190e2c
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 92320 W: 23941 L: 23531 D: 44848
Ptnml(0-2): 430, 10993, 22931, 11349, 457

Passed LTC:
https://tests.stockfishchess.org/tests/view/663ef48b2948bf9aa698690c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 98934 W: 24907 L: 24457 D: 49570
Ptnml(0-2): 48, 10952, 27027, 11382, 58

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

bench 1876282

Co-Authored-By: mstembera <5421953+mstembera@users.noreply.github.com>
2024-05-13 07:30:18 +02:00
Linmiao Xu 53f363041c Simplify npm constants when adjusting eval
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/663d0c4f507ebe1c0e91ec8d
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 162784 W: 41987 L: 41906 D: 78891
Ptnml(0-2): 520, 19338, 41591, 19427, 516

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/663d20fd507ebe1c0e91f405
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 457242 W: 115022 L: 115250 D: 226970
Ptnml(0-2): 271, 51566, 125179, 51330, 275

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

Bench: 2238216
2024-05-13 07:25:22 +02:00
Michael Chaly d3f081ed8a Adjust standpat return value in qsearch
Instead of returning value itself return value between it and beta for non pv nodes - analogous to what we do after actual search there.

Passed STC:
https://tests.stockfishchess.org/tests/view/663cb1b4c0b75d7f7b98188e
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 131552 W: 34131 L: 33673 D: 63748
Ptnml(0-2): 420, 15446, 33600, 15876, 434

Passed LTC:
https://tests.stockfishchess.org/tests/view/663cda5dc0b75d7f7b981c6f
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 282798 W: 71658 L: 70833 D: 140307
Ptnml(0-2): 112, 31187, 77979, 32006, 115

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

Bench: 1606672
2024-05-13 07:22:11 +02:00
Muzhen Gaming 813c5aa532 VVLTC search tune
Tuned at 111k games of VVLTC.

Passed VVLTC 1st sprt: https://tests.stockfishchess.org/tests/view/664090c6d163897c63214324
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 83046 W: 21071 L: 20747 D: 41228
Ptnml(0-2): 2, 7574, 26048, 7896, 3

Passed VVLTC 2nd sprt: https://tests.stockfishchess.org/tests/view/6640cb2abaa6260a5688dc17
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 68630 W: 17620 L: 17270 D: 33740
Ptnml(0-2): 4, 6242, 21471, 6596, 2

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

Bench: 1752471
2024-05-13 07:20:03 +02:00
Shawn Xu 540545d127 simplify away quietCheckEvasions pruning
simplifies away the pruning of quiet evasion moves in quiescent search.

Passed STC:
LLR: 2.98 (-2.94,2.94) <-1.75,0.25>
Total: 343520 W: 88356 L: 88470 D: 166694
Ptnml(0-2): 1061, 40073, 89706, 39759, 1161
https://tests.stockfishchess.org/tests/view/663c7ddfc0b75d7f7b980f3b

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 168744 W: 42454 L: 42384 D: 83906
Ptnml(0-2): 75, 18678, 46782, 18776, 61
https://tests.stockfishchess.org/tests/view/663ce34fc0b75d7f7b981ed9

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

bench 3681552
2024-05-13 07:16:59 +02:00
xu-shawn b8812138e8 Fix usage of abs vs std::abs
closes https://github.com/official-stockfish/Stockfish/pull/5229

no functional change
2024-05-13 07:15:25 +02:00
Shawn Xu c43425b0b1 Simplify Away Negative Extension
This patch simplifies away the negative extension applied when the value returned by the transposition table is assumed to fail low over the value of reduced search.

Passed STC:
LLR: 2.99 (-2.94,2.94) <-1.75,0.25>
Total: 248736 W: 64293 L: 64302 D: 120141
Ptnml(0-2): 925, 29833, 62831, 29884, 895
https://tests.stockfishchess.org/tests/view/663bee3bca93dad645f7f64a

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 254970 W: 64289 L: 64308 D: 126373
Ptnml(0-2): 110, 28428, 70422, 28421, 104
https://tests.stockfishchess.org/tests/view/663c11f0c0b75d7f7b97d4bb

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

Bench: 2353057
2024-05-09 09:02:57 +02:00
FauziAkram 574ad14b32 Simplify depth formula based on score improvement
Simplify depth formula based on score improvement.
This idea was first tried by cj5716

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 347104 W: 89683 L: 89804 D: 167617
Ptnml(0-2): 1357, 38824, 93307, 38711, 1353
https://tests.stockfishchess.org/tests/view/66378edf9819650825aa75d0

Passed LTC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 63000 W: 15851 L: 15694 D: 31455
Ptnml(0-2): 22, 5396, 20499, 5569, 14
https://tests.stockfishchess.org/tests/view/663c04e5c0b75d7f7b97d461

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

Bench: 2691699

Co-Authored-By: cj5716 <125858804+cj5716@users.noreply.github.com>
2024-05-09 09:00:32 +02:00
Michael Chaly 23439e4096 Remove conthist 3 from moves loop pruning
Followup to previous gainer that made it twice less impactful there - this patch removes it entirely as a simplification.

Passed STC:
https://tests.stockfishchess.org/tests/view/6637aa7e9819650825aa93e0
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 26208 W: 6930 L: 6694 D: 12584
Ptnml(0-2): 113, 2997, 6652, 3225, 117

Passed LTC:
https://tests.stockfishchess.org/tests/view/66383cba493aaaf4b7ea90c2
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 67866 W: 17294 L: 17118 D: 33454
Ptnml(0-2): 46, 7627, 18415, 7795, 50

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

Bench: 2691699
2024-05-09 08:56:36 +02:00
Michael Chaly 3b4ddf4ae6 Simplify away conthist 3 from statscore
Following previous elo gainer that gained by making conthist 3 less important in pruning this patch simplifies away this history from calculation of statscore.

Passed STC:
https://tests.stockfishchess.org/tests/view/6637aa7e9819650825aa93e0
LLR: 3.00 (-2.94,2.94) <-1.75,0.25>
Total: 35392 W: 9352 L: 9120 D: 16920
Ptnml(0-2): 141, 4145, 8888, 4385, 137

Passed LTC:
https://tests.stockfishchess.org/tests/view/66383cd8493aaaf4b7ea90c5
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 33948 W: 8714 L: 8503 D: 16731
Ptnml(0-2): 39, 3701, 9270, 3938, 26

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

Bench: 2508571
2024-05-09 08:52:06 +02:00
FauziAkram 9d6dab06a8 simplify moveCountPruning
no (significant) speedup upon renewed testing

Passed stc:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 88992 W: 22779 L: 22633 D: 43580
Ptnml(0-2): 137, 8706, 26681, 8818, 154
https://tests.stockfishchess.org/tests/view/6636c4844b68b70d85800dae

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

No functional change.
2024-05-09 08:48:29 +02:00
MinetaS 2dbb44e28d Fix nodestime
1. The current time management system utilizes limits.inc and
limits.time, which can represent either milliseconds or node count,
depending on whether the nodestime option is active. There have been
several modifications which brought Elo gain for typical uses (i.e.
real-time matches), however some of these changes overlooked such
distinction. This patch adjusts constants and multiplication/division to
more accurately simulate real TC conditions when nodestime is used.

2. The advance_nodes_time function has a bug that can extend the time
limit when availableNodes reaches exact zero. This patch fixes the bug
by initializing the variable to -1 and make sure it does not go below
zero.

3. elapsed_time function is newly introduced to print PV in the UCI
output based on real time. This makes PV output more consistent with the
behavior of trivial use cases.

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

No functional changes
2024-05-09 08:42:56 +02:00
rn5f107s2 db147fe258 IIR on cutnodes if there is a ttMove but the ttBound is upper
If there is an upper bound stored in the transposition table, but we still have a ttMove, the upperbound indicates that the last time the ttMove was tried, it failed low. This fail low indicates that the ttMove may not be good, so this patch introduces a depth reduction of one for cutnodes with such ttMoves.

Passed STC:
https://tests.stockfishchess.org/tests/view/663be4d1ca93dad645f7f45f
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 139424 W: 35900 L: 35433 D: 68091
Ptnml(0-2): 425, 16357, 35743, 16700, 487

Passed LTC:
https://tests.stockfishchess.org/tests/view/663bec95ca93dad645f7f5c8
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 129690 W: 32902 L: 32390 D: 64398
Ptnml(0-2): 63, 14304, 35610, 14794, 74

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

bench 2257437
2024-05-09 08:38:04 +02:00
Michael Chaly d1b8d8bab3 Refactor quiet moves pruning in qsearch
Make it formula more in line with what we use in search - current formula is more or less the one we used years ago for search but since then it was remade, this patch remakes qsearch formula to almost exactly the same as we use in search - with sum of conthist 0, 1 and pawn structure history.

Passed STC:
https://tests.stockfishchess.org/tests/view/6639c8421343f0cb16716206
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 84992 W: 22414 L: 22019 D: 40559
Ptnml(0-2): 358, 9992, 21440, 10309, 397

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 119136 W: 30407 L: 29916 D: 58813
Ptnml(0-2): 46, 13192, 32622, 13641, 67

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

Bench: 2138659
2024-05-09 08:33:07 +02:00
FauziAkram 3bdfa0fb4a Depth dependent statscore based reductions
Test a modification of Fawzi's PR #5223, against that PR.

parameters locally tuned with nevergrad4sf.

passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 1047424 W: 271478 L: 269649 D: 506297
Ptnml(0-2): 3851, 124543, 265290, 125982, 4046
https://tests.stockfishchess.org/tests/view/663b0889ca93dad645f7c58c

passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 796236 W: 201712 L: 199825 D: 394699
Ptnml(0-2): 361, 88381, 218778, 90206, 392
https://tests.stockfishchess.org/tests/view/663be6adca93dad645f7f509

https://github.com/official-stockfish/Stockfish/pull/5228

Bench: 3346224
2024-05-09 08:29:33 +02:00
FauziAkram 2d5e248f58 Tweak reduction formula based on depth
The idea came to me by checking for trends from the megafauzi tunes, since the values of the divisor for this specific formula were as follows:
stc: 15990
mtc: 16117
ltc: 14805
vltc: 12719
new vltc passed by Muzhen: 12076

This shows a clear trend related to time control, the higher it is, the lower the optimum value for the divisor seems to be.
So I tried a simple formula, using educated guesses based on some calculations, tests show it works pretty fine, and it can still be further tuned at VLTC in the future to scale even better.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 431360 W: 110791 L: 109898 D: 210671
Ptnml(0-2): 1182, 50846, 110698, 51805, 1149
https://tests.stockfishchess.org/tests/view/663770409819650825aa269f

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 114114 W: 29109 L: 28625 D: 56380
Ptnml(0-2): 105, 12628, 31101, 13124, 99
https://tests.stockfishchess.org/tests/view/66378c099819650825aa73f6

https://github.com/official-stockfish/Stockfish/pull/5223

bench: 2273551
2024-05-09 08:26:35 +02:00
Muzhen Gaming 070e564c38 VVLTC search tune
This patch is the result of two tuning stages:
1. ~32k games at 60+0.6 th8:
   https://tests.stockfishchess.org/tests/view/662d9dea6115ff6764c7f817
2. ~193k games at 80+0.8 th6, based on PR #5211:
   https://tests.stockfishchess.org/tests/view/663587e273559a8aa857ca00.
   Based on extensive VVLTC tuning and testing both before and after
   #5211, it is observed that introduction of new extensions positively
   affected the search tune results.

Passed VVLTC 70+0.7 th7 1st sprt: https://tests.stockfishchess.org/tests/view/6636c6f04b68b70d85801409
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 18566 W: 4864 L: 4620 D: 9082
Ptnml(0-2): 0, 1608, 5827, 1844, 4

Passed VVLTC 70+0.7 th7 2nd sprt: https://tests.stockfishchess.org/tests/view/6636d4b84b68b70d85802ab7
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 43142 W: 11141 L: 10838 D: 21163
Ptnml(0-2): 4, 3915, 13427, 4224, 1

Passed VVLTC 70+0.7 3rd sprt: https://tests.stockfishchess.org/tests/view/66376b4f9819650825aa230b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 40322 W: 10374 L: 10076 D: 19872
Ptnml(0-2): 1, 3660, 12544, 3952, 4

The first two sprts were run against passed #5211. The third sprt was
run against latest master.

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

Bench: 2180675
2024-05-05 15:11:53 +02:00
cj5716 61f12a4c38 Simplify accumulator refreshes
Passed Non-Regression STC:
https://tests.stockfishchess.org/tests/view/6631f5d5d01fb9ac9bcdc7d0
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 57472 W: 14979 L: 14784 D: 27709
Ptnml(0-2): 185, 6486, 15192, 6695, 178

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

No functional change
2024-05-05 15:11:37 +02:00
Michael Chaly f161261245 Adjust history usage in moves loop pruning
After experiments with conthist 5 addition failed really bad divions by 2 passed as a gainer.

Passed STC:
https://tests.stockfishchess.org/tests/view/6636d7114b68b70d858035ce
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 35936 W: 9287 L: 8976 D: 17673
Ptnml(0-2): 81, 4129, 9234, 4446, 78

Passed LTC:
https://tests.stockfishchess.org/tests/view/6636ddb64b68b70d858040a8
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 82428 W: 21035 L: 20622 D: 40771
Ptnml(0-2): 29, 8985, 22775, 9394, 31

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

Bench: 2309253
2024-05-05 13:06:22 +02:00
cj5716 6da1590de0 Some history fixes and tidy-up
This adds the functions `update_refutations` and `update_quiet_histories` to better distinguish the two. `update_quiet_stats` now just calls both of these functions.

The functional side of this patch is two-fold:
1. Stop refutations being updated when we carry out multicut
2. Update pawn history every time we update other quiet histories

Yellow STC:
LLR: -2.95 (-2.94,2.94) <0.00,2.00>
Total: 238976 W: 61506 L: 61415 D: 116055
Ptnml(0-2): 846, 28628, 60456, 28705, 853
https://tests.stockfishchess.org/tests/view/66321b5ed01fb9ac9bcdca83

However, it passed in <-1.75, 0.25> bounds:
$ python3 sprt.py --wins 61506 --losses 61415 --draws 116055 --elo0 -1.75 --elo1 0.25
ELO: 0.132 +- 0.998 [-0.865, 1.13]
LLR: 4.15 [-1.75, 0.25] (-2.94, 2.94)
H1 Accepted

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 399126 W: 100730 L: 100896 D: 197500
Ptnml(0-2): 116, 44328, 110843, 44158, 118
https://tests.stockfishchess.org/tests/view/66357b0473559a8aa857ba6f

closes #5215

Bench 2370967
2024-05-05 13:04:37 +02:00
FauziAkram d712ed38d1 Simplify shuffling and optimism divisors to constants
Shuffling divisor and Optimism divisors passed STC & LTC separately:
shuf STC: https://tests.stockfishchess.org/tests/view/66356316b4e9bdbc7228b995
shuf LTC: https://tests.stockfishchess.org/tests/view/6635815a73559a8aa857c1dc
opt STC: https://tests.stockfishchess.org/tests/view/66356326b4e9bdbc7228b9a0
opt LTC: https://tests.stockfishchess.org/tests/view/663615c673559a8aa8589f8a

And then passed LTC together:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 178278 W: 45039 L: 44979 D: 88260
Ptnml(0-2): 43, 19776, 49460, 19798, 62
https://tests.stockfishchess.org/tests/view/66363f19cdb7cf5da64e22a3

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

Bench: 2198243
2024-05-05 13:02:42 +02:00
Viren6 741aaf8a38 Introduce Quadruple Extensions
This patch introduces quadruple extensions, with the new condition of not ttPv. It also generalises all margins, so that extensions can still occur if conditions are only partially fulfilled, but with a stricter margin.

Failed STC:
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 16096 W: 3984 L: 4228 D: 7884
Ptnml(0-2): 72, 2067, 4002, 1847, 60
https://tests.stockfishchess.org/tests/view/66316422d01fb9ac9bcdbdcd

Passed VVLTC 1:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 96660 W: 24550 L: 24210 D: 47900
Ptnml(0-2): 5, 8776, 30426, 9120, 3
https://tests.stockfishchess.org/tests/view/66361f2c74fa3f41ef2ee091

Passed VVLTC 2:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 80546 W: 20495 L: 20120 D: 39931
Ptnml(0-2): 6, 7477, 24929, 7858, 3
https://tests.stockfishchess.org/tests/view/66350cf739ba8e443112b3fa

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

bench 2233743
2024-05-05 12:53:58 +02:00
Michael Chaly 351a2e22dd Add extra bonuses to some moves that forced a fail low
The previous patch on this idea was giving bonuses to this moves if best value of search is far below current static evaluation.
This patch does similar thing but adds extra bonus when best value of search is far below static evaluation before previous move.

Passed STC:
https://tests.stockfishchess.org/tests/view/66355fc819566d64b481d6a4
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 454144 W: 116575 L: 115656 D: 221913
Ptnml(0-2): 1060, 53410, 117215, 54325, 1062

Passed LTC:
https://tests.stockfishchess.org/tests/view/6635c61a73559a8aa858012d
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 136578 W: 34858 L: 34335 D: 67385

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

Bench: 1614825
2024-05-05 12:42:30 +02:00
cj5716 8ee9905d8b Remove PSQT-only mode
Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 94208 W: 24270 L: 24112 D: 45826
Ptnml(0-2): 286, 11186, 24009, 11330, 293
https://tests.stockfishchess.org/tests/view/6635ddd773559a8aa8582826

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 114960 W: 29107 L: 28982 D: 56871
Ptnml(0-2): 37, 12683, 31924, 12790, 46
https://tests.stockfishchess.org/tests/view/663604a973559a8aa85881ed

closes #5214

Bench 1653939
2024-05-05 12:36:20 +02:00
Disservin be026bdcb2 Clear Workers after changing the network
ensures internal state (e.g. accumulator cache) is consistent with network

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

No functional change
2024-05-05 12:30:28 +02:00
mstembera be142337d8 Accumulator cache bugfix and cleanup
STC:
https://tests.stockfishchess.org/tests/view/663068913a05f1bf7a511dc2
LLR: 2.98 (-2.94,2.94) <-1.75,0.25>
Total: 70304 W: 18211 L: 18026 D: 34067
Ptnml(0-2): 232, 7966, 18582, 8129, 243

1) Fixes a bug introduced in
   https://github.com/official-stockfish/Stockfish/pull/5194. Only one
   psqtOnly flag was used for two perspectives which was causing
   wrong entries to be cleared and marked.
2) The finny caches should be cleared like histories and not at the
   start of every search.

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

No functional change
2024-05-01 14:17:32 +02:00
cj5716 6a9b8a0c7b Optimise NNUE Accumulator updates
Passed STC:
https://tests.stockfishchess.org/tests/view/662e3c6a5e9274400985a741
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 86176 W: 22284 L: 21905 D: 41987
Ptnml(0-2): 254, 9572, 23051, 9963, 248

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

No functional change
2024-05-01 14:10:57 +02:00
Ciekce eb20de36c0 Avoid unnecessary creation of accumulator cache
Saves a (currently) 800 KB allocation and deallocation when running
`eval`, not particularly significant and zero impact on play but not
necessary either.

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

No functional change
2024-05-01 14:10:57 +02:00
Dubslow 5d72032559 Use capture history to better judge which sacrifices to explore
This idea has been bouncing around a while. @Vizvezdenec tried it a
couple years ago in Stockfish without results, but its recent arrival in
Ethereal inspired him and thence me to try it afresh in Stockfish.

(Also factor out the now-common code with futpruning for captures.)

STC:
https://tests.stockfishchess.org/tests/view/662355bc3fe04ce4cefc18ac
LLR: 2.92 (-2.94,2.94) <0.00,2.00>
Total: 45760 W: 11970 L: 11640 D: 22150
Ptnml(0-2): 124, 5371, 11625, 5571, 189

LTC:
https://tests.stockfishchess.org/tests/view/662dda396115ff6764c817c9
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 243828 W: 62042 L: 61287 D: 120499
Ptnml(0-2): 211, 27202, 66329, 27965, 207

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

Bench: 1480008
2024-05-01 14:10:50 +02:00
Stefan Geschwentner 0fe6428645 More reduction at cut nodes which are not a former PV node
But the tt move and first killer are excluded.

This idea is based on following LMR condition tuning
https://tests.stockfishchess.org/tests/view/66228bed3fe04ce4cefc0c71 by
using only the two largest terms P[0] and P[1].

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 173248 W: 45091 L: 44565 D: 83592
Ptnml(0-2): 693, 20534, 43673, 21002, 722
https://tests.stockfishchess.org/tests/view/6629603b3fe04ce4cefc7d37

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 722394 W: 183231 L: 181487 D: 357676
Ptnml(0-2): 462, 80650, 197252, 82348, 485
https://tests.stockfishchess.org/tests/view/662cbe45d46f72253dcff7bf

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

Bench: 1619613
2024-04-28 21:46:45 +02:00
Stefan Geschwentner 48a3b7c0ee Simplify non-pawn material divisor to a constant
Passed STC:
https://tests.stockfishchess.org/tests/view/662942603fe04ce4cefc7aba
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 272832 W: 70456 L: 70497 D: 131879
Ptnml(0-2): 1020, 32619, 69154, 32628, 995

Passed LTC:
https://tests.stockfishchess.org/tests/view/662dfe3b6115ff6764c829eb
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 100254 W: 25446 L: 25303 D: 49505
Ptnml(0-2): 121, 11292, 27166, 11419, 129

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

Bench: 1544645
2024-04-28 21:43:46 +02:00
cj5716 834e8ff619 Penalise the TT move in multicut
Passed STC:
LLR: 2.99 (-2.94,2.94) <0.00,2.00>
Total: 185504 W: 48079 L: 47533 D: 89892
Ptnml(0-2): 716, 21866, 46988, 22520, 662
https://tests.stockfishchess.org/tests/view/662d9e1d6115ff6764c7f83d

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 75612 W: 19351 L: 18948 D: 37313
Ptnml(0-2): 46, 8363, 20592, 8752, 53
https://tests.stockfishchess.org/tests/view/662dc9dc6115ff6764c80fea

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

Bench: 1415435
2024-04-28 21:36:34 +02:00
mstembera a129c0695b Combine remove and add in update_accumulator_refresh_cache()
Combine remove and add in update_accumulator_refresh_cache().
Move remove before add to match other parts of the code.

STC:
https://tests.stockfishchess.org/tests/view/662d96dc6115ff6764c7f4ca
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 364032 W: 94421 L: 93624 D: 175987
Ptnml(0-2): 1261, 41983, 94811, 42620, 1341

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

Bench: 1836777
2024-04-28 21:35:48 +02:00
mstembera 940a3a7383 Cache small net w/ psqtOnly support
Caching the small net in the same way as the big net allows them to
share the same code path and completely removes
update_accumulator_refresh().

STC:
https://tests.stockfishchess.org/tests/view/662bfb5ed46f72253dcfed85
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 151712 W: 39252 L: 39158 D: 73302
Ptnml(0-2): 565, 17474, 39683, 17570, 564

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

Bench: 1836777
2024-04-28 21:30:19 +02:00
Joost VandeVondele bc45cbc820 Output some basic info about the used networks
Adds size in memory as well as layer sizes as in

info string NNUE evaluation using nn-ae6a388e4a1a.nnue (132MiB, (22528, 3072, 15, 32, 1))
info string NNUE evaluation using nn-baff1ede1f90.nnue (6MiB, (22528, 128, 15, 32, 1))

For example, the size in MiB is useful to keep the fishtest memory sizes up-to-date,
the L1-L3 sizes give a useful hint about the architecture used.

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

No functional change
2024-04-28 21:27:28 +02:00
Disservin 3502c8ae42 Fix missing initialization of AccumulatorCaches in Eval::trace
Add a constructor to `AccumulatorCaches` instead of just calling
`clear(networks)` to prevent similar issues from appearing in the
future.

fixes https://github.com/official-stockfish/Stockfish/issues/5190

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

No functional change
2024-04-28 21:26:36 +02:00
xoto10 886ed90ec3 Use less time on recaptures
Credit for the idea goes to peregrine on discord.

Passed STC 10+0.1:
https://tests.stockfishchess.org/tests/view/662652623fe04ce4cefc48cf
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 75712 W: 19793 L: 19423 D: 36496
Ptnml(0-2): 258, 8487, 20023, 8803, 285

Passed LTC 60+0.6:
https://tests.stockfishchess.org/tests/view/6627495e3fe04ce4cefc59b6
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 49788 W: 12743 L: 12404 D: 24641
Ptnml(0-2): 29, 5141, 14215, 5480, 29

The code was updated slightly and tested for non-regression against the
original code at STC:

LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 41952 W: 10912 L: 10698 D: 20342
Ptnml(0-2): 133, 4825, 10835, 5061, 122
https://tests.stockfishchess.org/tests/view/662d84f56115ff6764c7e438

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

Bench: 1836777
2024-04-28 21:26:25 +02:00
gab8192 49ef4c935a Implement accumulator refresh table
For each thread persist an accumulator cache for the network, where each
cache contains multiple entries for each of the possible king squares.
When the accumulator needs to be refreshed, the cached entry is used to more
efficiently update the accumulator, instead of rebuilding it from scratch.
This idea, was first described by Luecx (author of Koivisto) and
is commonly referred to as "Finny Tables".

When the accumulator needs to be refreshed, instead of filling it with
biases and adding every piece from scratch, we...

1. Take the `AccumulatorRefreshEntry` associated with the new king bucket
2. Calculate the features to activate and deactivate (from differences
   between bitboards in the entry and bitboards of the actual position)
3. Apply the updates on the refresh entry
4. Copy the content of the refresh entry accumulator to the accumulator
   we were refreshing
5. Copy the bitboards from the position to the refresh entry, to match
   the newly updated accumulator

Results at STC:
https://tests.stockfishchess.org/tests/view/662301573fe04ce4cefc1386
(first version)
https://tests.stockfishchess.org/tests/view/6627fa063fe04ce4cefc6560
(final)

Non-Regression between first and final:
https://tests.stockfishchess.org/tests/view/662801e33fe04ce4cefc660a

STC SMP:
https://tests.stockfishchess.org/tests/view/662808133fe04ce4cefc667c

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

No functional change
2024-04-24 18:38:20 +02:00
FauziAkram fcba524793 Tune Search Parameters
Parameters Tune, adding also another tunable parameter (npmDiv) to be
variable for different nets (bignet, smallnet, psqtOnly smallnet). P.s:
The changed values are only the parameters where there is agreement
among the different time controls, so in other words, the tunings are
telling us that changing these specific values to this specific
direction is good in all time controls, so there shouldn't be a high
risk of regressing at longer time controls.

Passed STC:
LLR: 2.97 (-2.94,2.94) <0.00,2.00>
Total: 39552 W: 10329 L: 9999 D: 19224
Ptnml(0-2): 156, 4592, 9989, 4844, 195
https://tests.stockfishchess.org/tests/view/661be9a0bd68065432a088c0

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 56394 W: 14439 L: 14078 D: 27877
Ptnml(0-2): 30, 6152, 15480, 6497, 38
https://tests.stockfishchess.org/tests/view/661c746296961e72eb565406

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

Bench: 1836777
2024-04-24 18:24:01 +02:00
Disservin ddd250b9d6 Restore NPS output for Perft
Previously it was possible to also get the node counter after running a bench with perft, i.e.
`./stockfish bench 1 1 5 current perft`, caused by a small regression from the uci refactoring.

```
Nodes searched: 4865609

===========================
Total time (ms) : 18
Nodes searched  : 4865609
Nodes/second    : 270311611
````

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

No functional change
2024-04-24 18:20:55 +02:00
cj5716 d47aa639bd Tweak TT aging and replacement strategies
We change the definition of "age" from "age of this position" to "age of this TT entry".
In this way, despite being on the same position, when we save into TT, we always prefer the new entry as compared to the old one.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 152256 W: 39597 L: 39110 D: 73549
Ptnml(0-2): 556, 17562, 39398, 18063, 549
https://tests.stockfishchess.org/tests/view/6620faee3fe04ce4cefbf215

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 51564 W: 13242 L: 12895 D: 25427
Ptnml(0-2): 24, 5464, 14463, 5803, 28
https://tests.stockfishchess.org/tests/view/66231ab53fe04ce4cefc153e

closes #5184

Bench 1479416
2024-04-21 14:50:04 +02:00
Disservin 56a9cc512e Move ALSR change to CI Workflow file
It makes more sense to not (potentially) change the developers alsr entropy setting to make the test run through. This should be an active choice even if the test then might fail locally for them.

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

No functional change
2024-04-21 14:49:11 +02:00
Joost VandeVondele 1a8de45b8c Improve CI
the recent refactoring has shown some limitations of our testing, hence we add a couple of more tests including:
* expected mate score
* expected mated score
* expected in TB win score
* expected in TB loss score
* expected info line output
* expected info line output (wdl)

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

No functional change
2024-04-21 14:46:01 +02:00
Robert Nurnberg @ elitebook 6fc7da44ad update the WDL model
The patch only changes the displayed cp and wdl values.

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

No functional change
2024-04-21 14:40:02 +02:00
Gahtan Nahdi d0e72c19fa fix clang compiler warning for avx512 build
Initialize variable in constexpr function to get rid of clang compiler warning for avx512 build.

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

Non-functional change
2024-04-21 14:38:16 +02:00
Michael Chaly 9021a61807 Trivial cleanup
Make naming and declaration of futilityValue in search consistent between different places.

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

No functional change.
2024-04-21 14:35:54 +02:00
Disservin d3fc1d835e Refactor elapsed time checks in search
Small improvement of the elapsed time usage in search, makes the code easier to read overall.
Also Search::Worker::iterative_deepening() now only checks the elapsed time once, instead of 3 times in a row.

Non Regression STC:
https://tests.stockfishchess.org/tests/view/6617005d5a4693796d965c3c
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 61024 W: 16002 L: 15806 D: 29216
Ptnml(0-2): 243, 6874, 16102, 7030, 263

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

No functional change
2024-04-21 14:35:01 +02:00
Disservin 432995ad82 Update outdated comments
closes https://github.com/official-stockfish/Stockfish/pull/5158

No functional change
2024-04-21 14:32:26 +02:00
Disservin c55ae376f6 Fix wrong sign for 200 TB score
Fix another case of 9032c6cbe7

*    TB values can have a distance of 0, mainly when we are in a tb position but haven't found mate.
*    Add a missing whitespace to UCIEngine::on_update_no_moves()

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

No functional change
2024-04-13 22:05:19 +02:00
Disservin 4912f5b0b5 Remove duplicated Position object in UCIEngine
Also fixes searchmoves.

Drop the need of a Position object in uci.cpp.

A side note, it is still required for the static functions,
but these should be moved to a different namespace/class
later on, since sf kinda relies on them.

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

No functional change
2024-04-12 19:37:39 +02:00
Shahin M. Shahin 14f6eab07d Fix some more UCI output
further fall-out of the refactoring, fixes:

* the position object in UCI is not never getting updated if position token is used
* duplicate string of " wdl "

See also:

https://discord.com/channels/435943710472011776/1032922913499783169/1228227522945351690
https://discord.com/channels/435943710472011776/813919248455827515/1228288106449338398

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

No functional change

Co-Authored-By: disservin <45608332+disservin@users.noreply.github.com>
2024-04-12 18:11:54 +02:00
Robert Nurnberg @ elitebook e58b3b4665 Fix wrong mate sign
introduced yesterday by the UCI refactoring 9032c6cbe

fixes #5166
closes https://github.com/official-stockfish/Stockfish/pull/5167

No functional change
2024-04-12 09:30:34 +02:00
FauziAkram 249eec6715 Simplify the depth-dependent part of the best value adjustment formula in main search
Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 139648 W: 36171 L: 36061 D: 67416
Ptnml(0-2): 545, 16685, 35282, 16739, 573
https://tests.stockfishchess.org/tests/view/660d953b8ff4a059828d625d

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 222894 W: 56519 L: 56505 D: 109870
Ptnml(0-2): 112, 25145, 60971, 25055, 164
https://tests.stockfishchess.org/tests/view/660fd4afbfeb43334bf7d558

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

bench: 1479416
2024-04-11 22:47:40 +02:00
gab8192 d6bdcec52c Remove an useless assignment
The assignment (ss + 1)->excludedMove = Move::none() can be simplified away because when that line is reached, (ss + 1)->excludedMove is always already none. The only moment stack[x]->excludedMove is modified, is during singular search, but it is reset to none right after the singular search is finished.

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

No functional change
2024-04-11 22:43:00 +02:00
Disservin de2244284b Remove COMPILER from Makefile
The same functionality is available by using COMPCXX and having another variable which does the same is just confusing.
There was only one mention on Stockfish Wiki about this which has been changed to COMPCXX.

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

No functional change
2024-04-11 22:41:35 +02:00
mstembera 94484db6e8 Avoid permuting inputs during transform()
Avoid permuting inputs during transform() and instead do it once at load time.
Affects AVX2 and newer Intel architectures only.

https://tests.stockfishchess.org/tests/view/661306613eb00c8ccc0033c7
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 108480 W: 28319 L: 27898 D: 52263
Ptnml(0-2): 436, 12259, 28438, 12662, 445

speedups measured such as e.g.

```
Result of 100 runs
==================
base (./stockfish.master       ) =    1241128  +/- 3757
test (./stockfish.patch        ) =    1247713  +/- 3689
diff                             =      +6585  +/- 2583

speedup        = +0.0053
P(speedup > 0) =  1.0000
```

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

No functional change
2024-04-11 22:38:38 +02:00
Muzhen Gaming 1adf8e1ae6 VVLTC search tune
Parameters were tuned in 3 stages:

* Using an earlier L1-3072 net, and with triple extension margin manually set to 0: https://tests.stockfishchess.org/tests/view/65ffdf5d0ec64f0526c544f2 (~30k games)
* Continue tuning, but with the previous master net (L1-2560). https://tests.stockfishchess.org/tests/view/660663f00ec64f0526c59c41 (~27k games)
* Starting with the parameters from step 2, use the current L1-3072 net, and allow the triple extension margin to be tuned starting from 0: https://tests.stockfishchess.org/tests/view/660c16b8216a13d9498e7536 (40k games)

Passed VVLTC 1st sprt: https://tests.stockfishchess.org/tests/view/66115eacbfeb43334bf7eddd
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 27138 W: 7045 L: 6789 D: 13304
Ptnml(0-2): 1, 2421, 8471, 2673, 3

Passed VVLTC 2nd sprt: https://tests.stockfishchess.org/tests/view/661483623eb00c8ccc0049c1
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 26242 W: 6807 L: 6535 D: 12900
Ptnml(0-2): 0, 2353, 8143, 2625, 0

STC Elo estimate: https://tests.stockfishchess.org/tests/view/66175ca55a4693796d96608c
Elo: -10.53 ± 2.4 (95%) LOS: 0.0%
Total: 21584 W: 5294 L: 5948 D: 10342
Ptnml(0-2): 102, 2937, 5363, 2293, 97
nElo: -19.99 ± 4.7 (95%) PairsRatio: 0.79

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

Bench: 1381387
2024-04-11 22:23:52 +02:00
Disservin 9032c6cbe7 Transform search output to engine callbacks
Part 2 of the Split UCI into UCIEngine and Engine refactor.
This creates function callbacks for search to use when an update should occur.
The benching in uci.cpp for example does this to extract the total nodes
searched.

No functional change
2024-04-05 21:03:58 +02:00
Disservin 299707d2c2 Split UCI into UCIEngine and Engine
This is another refactor which aims to decouple uci from stockfish. A new engine
class manages all engine related logic and uci is a "small" wrapper around it.

In the future we should also try to remove the need for the Position object in
the uci and replace the options with an actual options struct instead of using a
map. Also convert the std::string's in the Info structs a string_view.

closes #5147

No functional change
2024-04-04 00:15:17 +02:00
Viren6 0716b845fd Update NNUE architecture to SFNNv9 and net nn-ae6a388e4a1a.nnue
Part 1: PyTorch Training, linrock

Trained with a 10-stage sequence from scratch, starting in May 2023:
https://github.com/linrock/nnue-tools/blob/master/exp-sequences/3072-10stage-SFNNv9.yml

While the training methods were similar to the L1-2560 training sequence,
the last two stages introduced min-v2 binpacks,
where bestmove capture and in-check position scores were not zeroed during minimization,
for compatibility with skipping SEE >= 0 positions and future research.

Training data can be found at:
https://robotmoon.com/nnue-training-data

This net was tested at epoch 679 of the 10th training stage:
https://tests.stockfishchess.org/tests/view/65f32e460ec64f0526c48dbc

Part 2: SPSA Training, Viren6

The net was then SPSA tuned.
This consisted of the output weights (32 * 8) and biases (8)
as well as the L3 biases (32 * 8) and L2 biases (16 * 8), totalling 648 params in total.

The SPSA tune can be found here:
https://tests.stockfishchess.org/tests/view/65fc33ba0ec64f0526c512e3

With the help of Disservin , the initial weights were extracted with:
https://github.com/Viren6/Stockfish/tree/new228

The net was saved with the tuned weights using:
https://github.com/Viren6/Stockfish/tree/new241

Earlier nets of the SPSA failed STC compared to the base 3072 net of part 1:
https://tests.stockfishchess.org/tests/view/65ff356e0ec64f0526c53c98
Therefore it is suspected that the SPSA at VVLTC has
added extra scaling on top of the scaling of increasing the L1 size.

Passed VVLTC 1:
https://tests.stockfishchess.org/tests/view/6604a9020ec64f0526c583da
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 53042 W: 13554 L: 13256 D: 26232
Ptnml(0-2): 12, 5147, 15903, 5449, 10

Passed VVLTC 2:
https://tests.stockfishchess.org/tests/view/660ad1b60ec64f0526c5dd23
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 17506 W: 4574 L: 4315 D: 8617
Ptnml(0-2): 1, 1567, 5362, 1818, 5

STC Elo estimate:
https://tests.stockfishchess.org/tests/view/660b834d01aaec5069f87cb0
Elo: -7.66 ± 3.8 (95%) LOS: 0.0%
Total: 9618 W: 2440 L: 2652 D: 4526
Ptnml(0-2): 80, 1281, 2261, 1145, 42
nElo: -13.94 ± 6.9 (95%) PairsRatio: 0.87

closes https://tests.stockfishchess.org/tests/view/660b834d01aaec5069f87cb0

bench 1823302

Co-Authored-By: Linmiao Xu <lin@robotmoon.com>
2024-04-02 08:49:48 +02:00
Joost VandeVondele c964942da2 Avoid a note related to an ABI change
current master triggers a gcc note:
parameter passing for argument of type 'std::pair<double, double>' when C++17 is enabled changed to match C++14 in GCC 10.1

while this is inconsequential, and just informative  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111516 we can easily avoid it.

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

No functional change
2024-03-30 12:38:02 +01:00
Disservin ec598b380d Improve prerelease creation workflow
In the last couple of months we sometimes saw duplicated prereleases uploaded to GitHub, possibly due to some racy behavior when concurrent jobs create a prerelease. This now creates an empty prerelease at the beginning of the CI and the binaries are later just attached to this one.

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

No functional change
2024-03-29 13:13:07 +01:00
Joost VandeVondele 68d58d94da Fix usage of abs vs std::abs
close https://github.com/official-stockfish/Stockfish/pull/5143

No functional change
2024-03-29 13:12:20 +01:00
Shawn Xu e13e4cfb83 Simplify NMP Condition
Remove eval >= ss->staticEval condition for Null Move Pruning.

Passed non-regression STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 44000 W: 11420 L: 11202 D: 21378
Ptnml(0-2): 174, 5243, 10978, 5401, 204
https://tests.stockfishchess.org/tests/live_elo/6603ee490ec64f0526c57984

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 82956 W: 20978 L: 20818 D: 41160
Ptnml(0-2): 54, 9353, 22499, 9523, 49
https://tests.stockfishchess.org/tests/live_elo/660464b50ec64f0526c5804d

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

Bench 1759189
2024-03-29 10:18:40 +01:00
Michael Chaly 0ef5d05102 Adjust best value after a pruned quiet move
Logic somewhat similar to how we adjust best value after pruned captures
in qsearch, but in search this patch does it after pruned quiet moves
and also to not full scale of futility value but to smth in between
best value and futility value.

Passed STC:
https://tests.stockfishchess.org/tests/view/6601cf900ec64f0526c55c30
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 59936 W: 15722 L: 15369 D: 28845
Ptnml(0-2): 182, 7097, 15112, 7340, 237

Passed LTC:
https://tests.stockfishchess.org/tests/view/66029b2d0ec64f0526c566f1
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 118362 W: 29953 L: 29460 D: 58949
Ptnml(0-2): 68, 13159, 32249, 13622, 83

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

bench 1772608
2024-03-29 10:15:17 +01:00
xoto10 e636f73ab8 Vary time use with eval
Adjust time use depending on the current eval.

Passed STC :
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 101696 W: 26651 L: 26238 D: 48807
Ptnml(0-2): 400, 11602, 26459, 11959, 428
https://tests.stockfishchess.org/tests/live_elo/660187a50ec64f0526c557f6

Passed LTC :
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 60648 W: 15550 L: 15187 D: 29911
Ptnml(0-2): 40, 6356, 17171, 6715, 42
https://tests.stockfishchess.org/tests/live_elo/660298ed0ec64f0526c566d0

Values were found using two tunes with the final values taken from the ltc tune after 62k games :
stc - https://tests.stockfishchess.org/tests/view/65fb526b0ec64f0526c50694
ltc - https://tests.stockfishchess.org/tests/view/65fd36e60ec64f0526c5214b

Ideas for future work;

  * tune these values with the other TM adjustments
  * try narrower bands
  * calculate adjustment for exact eval by interpolation

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

No functional change
2024-03-29 10:09:42 +01:00
Gahtan Nahdi ed24e3a0a6 Remove material imbalance from nnue eval
Passed non-reg STC:
https://tests.stockfishchess.org/tests/view/65fdf11f0ec64f0526c52b57
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 76480 W: 19893 L: 19712 D: 36875
Ptnml(0-2): 339, 9107, 19157, 9308, 329

Passed non-reg LTC:
https://tests.stockfishchess.org/tests/view/65fee22e0ec64f0526c53885
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 150948 W: 38078 L: 37988 D: 74882
Ptnml(0-2): 111, 16997, 41148, 17127, 91

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

Bench: 2103324
2024-03-26 18:17:00 +01:00
FauziAkram d49b3738bc Tweak the stats bonus and malus
For depth 1 we don't have a negative score anymore.

Passed STC:
https://tests.stockfishchess.org/tests/view/65fb055c0ec64f0526c5024f
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 117120 W: 30468 L: 30023 D: 56629
Ptnml(0-2): 526, 13759, 29539, 14216, 520

Passed LTC:
https://tests.stockfishchess.org/tests/view/65fdca4b0ec64f0526c5293f
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 54816 W: 13955 L: 13595 D: 27266
Ptnml(0-2): 30, 6046, 14897, 6404, 31

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

Bench: 1876428
2024-03-26 18:17:00 +01:00
Disservin 7998570414 Add functionality to export small net
Usage
```
export_net <filenameBigNet> <filenameSmallNet>
```

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

No functional change
2024-03-26 18:17:00 +01:00
mstembera 5001d49f42 Update nnue_feature_transformer.h
Unroll update_accumulator_refresh to process two
active indices simultaneously.

The compiler might not unroll effectively because
the number of active indices isn't known at
compile time.

STC https://tests.stockfishchess.org/tests/view/65faa8850ec64f0526c4fca9
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 130464 W: 33882 L: 33431 D: 63151
Ptnml(0-2): 539, 14591, 34501, 15082, 519

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

No functional change
2024-03-26 18:06:49 +01:00
Muzhen Gaming d99f89506b VVLTC search tune
This set of parameters was derived from 3 tuning attempts:

    https://tests.stockfishchess.org/tests/view/65d19ab61d8e83c78bfd8436 (80+0.8 x8, ~40k games)
    Then tuned with one of linrock's early L1-3072 nets:
    https://tests.stockfishchess.org/tests/view/65def7b04b19edc854ebdec8 (VVLTC, ~36k games)
    Starting from the result of this tuning, the parameters were then tuned with the current master net:
    https://tests.stockfishchess.org/tests/view/65f11c420ec64f0526c46fc4 (VVLTC, ~45k games)

Additionally, at the start of the third tuning phase, 2 parameters were manually changed:

    Notably, the triple extension margin was decreased from 78 to 22. This idea was given by Vizvezdenec:
    https://tests.stockfishchess.org/tests/view/65f0a2360ec64f0526c46752.
    The PvNode extension margin was also adjusted from 50 to 40.

This tune also differs from previous tuning attempts by tuning the evaluation thresholds for smallnet and psqt-only.
The former was increased through the tuning, and this is hypothesized to scale better at VVLTC,
although there is not much evidence of it.

Passed VVLTC 1st sprt: https://tests.stockfishchess.org/tests/view/65f6761d0ec64f0526c4be88
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 44688 W: 11421 L: 11140 D: 22127
Ptnml(0-2): 1, 4170, 13722, 4449, 2

Passed VVLTC 2nd sprt: https://tests.stockfishchess.org/tests/view/65fa31a30ec64f0526c4f611
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 27450 W: 7057 L: 6778 D: 13615
Ptnml(0-2): 4, 2545, 8346, 2828, 2

STC Elo estimate: https://tests.stockfishchess.org/tests/view/65fd3e540ec64f0526c521ae
Elo: -7.84 ± 1.8 (95%) LOS: 0.0%
Total: 40000 W: 9899 L: 10802 D: 19299
Ptnml(0-2): 203, 5221, 10025, 4378, 173
nElo: -14.91 ± 3.4 (95%) PairsRatio: 0.84

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

Bench: 1876107
2024-03-22 16:44:06 +01:00
Disservin 7e427639ce Add cmath header to movepick.h
No functional change
2024-03-20 16:36:18 +01:00
Gahtan Nahdi 8e61d70499 Remove reduction increase on repetition
Passed non-reg STC:
https://tests.stockfishchess.org/tests/view/65f89ae30ec64f0526c4e0ff
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 173568 W: 45005 L: 44936 D: 83627
Ptnml(0-2): 684, 19878, 45628, 19873, 721

Passed non-reg LTC:
https://tests.stockfishchess.org/tests/view/65fa0f370ec64f0526c4f42d
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 21138 W: 5432 L: 5216 D: 10490
Ptnml(0-2): 13, 2107, 6112, 2325, 12

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

Bench: 2109005
2024-03-20 16:29:35 +01:00
Gahtan Nahdi 1a6c22c511 Evaluation adjustment for different eval types
Gives different eval scaling parameters for the three different types
of evaluation (bignet, smallnet, psqtOnly).

Passed STC:
https://tests.stockfishchess.org/tests/view/65f4b0020ec64f0526c4a3bd
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 168064 W: 43507 L: 42987 D: 81570
Ptnml(0-2): 662, 19871, 42445, 20393, 661

Passed LTC:
https://tests.stockfishchess.org/tests/view/65f6be1a0ec64f0526c4c361
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 162564 W: 41188 L: 40604 D: 80772
Ptnml(0-2): 120, 18112, 44216, 18732, 102

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

Bench: 2113576
2024-03-20 16:29:35 +01:00
Robert Nurnberg 9b92ada935 Base WDL model on material count and normalize evals dynamically
This PR proposes to change the parameter dependence of Stockfish's
internal WDL model from full move counter to material count. In addition
it ensures that an evaluation of 100 centipawns always corresponds to a
50% win probability at fishtest LTC, whereas for master this holds only
at move number 32. See also
https://github.com/official-stockfish/Stockfish/pull/4920 and the
discussion therein.

The new model was fitted based on about 340M positions extracted from
5.6M fishtest LTC games from the last three weeks, involving SF versions
from e67cc979fd (SF 16.1) to current
master.

The involved commands are for
[WDL_model](https://github.com/official-stockfish/WDL_model) are:
```
./updateWDL.sh --firstrev e67cc979fd
python scoreWDL.py updateWDL.json --plot save --pgnName update_material.png --momType "material" --momTarget 58 --materialMin 10 --modelFitting optimizeProbability
```

The anchor `58` for the material count value was chosen to be as close
as possible to the observed average material count of fishtest LTC games
at move 32 (`43`), while not changing the value of
`NormalizeToPawnValue` compared to the move-based WDL model by more than
1.

The patch only affects the displayed cp and wdl values.

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

No functional change
2024-03-20 16:29:35 +01:00
Disservin 117e08c264 Fix header name in Makefile
No functional change
2024-03-20 16:29:35 +01:00
Disservin 134e6d7bb4 Consistent use of anonymous namespace
Also change `bindThisThread` to match the current code style for function naming.

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

No functional change
2024-03-20 16:15:37 +01:00
Michael Chaly ed60460004 Clamp history bonus to stats range
Before, one always had to keep track of the bonus one assigns to a history to stop
the stats from overflowing. This is a quality of life improvement. Since this would often go unnoticed during benching.

Passed non-regression bounds:
https://tests.stockfishchess.org/tests/view/65ef2af40ec64f0526c44cbc
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 179232 W: 46513 L: 46450 D: 86269
Ptnml(0-2): 716, 20323, 47452, 20432, 693

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

No functional change
2024-03-20 16:14:00 +01:00
Disservin fb07281f55 Fix false positives from ThreadSanitizer
Since Linux Kernel 6.5 we are getting false positives from the ci,
lower the ALSR entropy to disable ALSR, which works as a temporary
workaround.

https://github.com/google/sanitizers/issues/1716
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2056762

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

No functional change
2024-03-14 22:14:11 +01:00
cj5716 abd82396a1 Make effort part of RootMove struct
Also includes several small cleanups.

Passed STC:
https://tests.stockfishchess.org/tests/view/65f15cfe0ec64f0526c473a0
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 71136 W: 18456 L: 18273 D: 34407
Ptnml(0-2): 311, 8014, 18708, 8251, 284

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

No functional change
2024-03-14 22:13:14 +01:00
Lemmy 23493de082 Sudden Death - Improve TM
Due to the 50 estimated move horizon, once a sudden death game got below
1 second, the time allocation for optimumTime would go into the negative
and SF would start instamoving.

To counter this, once limits.time is below 1 second, the move horizon
will start decreasing, at a rate of 1 move per 20ms. This was just what
seemed a reasonable rate of decay.

Fishtest sudden death TC 5+0
https://tests.stockfishchess.org/tests/live_elo/65ee2cdf0ec64f0526c43bbb
LLR: 2.99 (-2.94,2.94) <0.00,2.00>
Total: 3348 W: 1070 L: 727 D:1551
Ptnml(0-2): 46, 277, 738, 514, 99

Fishtest SD TC 10+0
https://tests.stockfishchess.org/tests/live_elo/65ee401e0ec64f0526c43cf7
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 3780 W: 1097 L: 808 D: 1875
Ptnml(0-2): 11, 353, 919, 550, 57

Neutral Non-Regression STC 10+0.1
https://tests.stockfishchess.org/tests/live_elo/65ee45ff0ec64f0526c43d68
LLR: 2.95 (-2.94,2.94) <-1.75, 0.25>
Total: 123616 W: 32054 L: 31927 D:59635
Ptnml(0-2): 493, 14323, 32105, 14338, 549

Neutral Non-Regression LTC 60+0.6
https://tests.stockfishchess.org/tests/live_elo/65ef1eec0ec64f0526c44bc4
LLR: 2.95 (-2.94,2.94) <-1.75, 0.25>
Total: 130482 W: 32961 L: 32855 D:64666
Ptnml(0-2): 88, 13412, 38123, 13542, 76

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

Bench: 2002517
2024-03-14 22:12:53 +01:00
Michael Chaly ee2ee6bdc4 Give more bonuses to quiet move that caused a fail low
Give extra bonus if search result is far below static evaluation of
position.

Passed STC:
https://tests.stockfishchess.org/tests/view/65edf1250ec64f0526c43787
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 90816 W: 23713 L: 23307 D: 43796
Ptnml(0-2): 401, 10725, 22742, 11147, 393

Passed LTC:
https://tests.stockfishchess.org/tests/view/65ef5ed70ec64f0526c450af
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 66618 W: 16950 L: 16565 D: 33103
Ptnml(0-2): 35, 7372, 18139, 7699, 64

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

Bench: 2002517
2024-03-14 22:08:48 +01:00
Disservin 55df0ee009 Fix Raspberry Pi Compilation
Reported by @Torom over discord.

> dev build fails on Raspberry Pi 5 with clang

```
clang++ -o stockfish benchmark.o bitboard.o evaluate.o main.o misc.o movegen.o movepick.o position.o search.o thread.o timeman.o tt.o uci.o ucioption.o tune.o tbprobe.o nnue_misc.o half_ka_v2_hm.o network.o  -fprofile-instr-generate -latomic -lpthread  -Wall -Wcast-qual -fno-exceptions -std=c++17 -fprofile-instr-generate  -pedantic -Wextra -Wshadow -Wmissing-prototypes -Wconditional-uninitialized -DUSE_PTHREADS -DNDEBUG -O3 -funroll-loops -DIS_64BIT -DUSE_POPCNT -DUSE_NEON=8 -march=armv8.2-a+dotprod -DUSE_NEON_DOTPROD -DGIT_SHA=627974c9 -DGIT_DATE=20240312 -DARCH=armv8-dotprod -flto=full
/tmp/lto-llvm-e9300e.o: in function `_GLOBAL__sub_I_network.cpp':
ld-temp.o:(.text.startup+0x704c): relocation truncated to fit: R_AARCH64_LDST64_ABS_LO12_NC against symbol `gEmbeddedNNUEBigEnd' defined in .rodata section in /tmp/lto-llvm-e9300e.o
/usr/bin/ld: ld-temp.o:(.text.startup+0x704c): warning: one possible cause of this error is that the symbol is being referenced in the indicated code as if it had a larger alignment than was declared where it was defined
ld-temp.o:(.text.startup+0x7068): relocation truncated to fit: R_AARCH64_LDST64_ABS_LO12_NC against symbol `gEmbeddedNNUESmallEnd' defined in .rodata section in /tmp/lto-llvm-e9300e.o
/usr/bin/ld: ld-temp.o:(.text.startup+0x7068): warning: one possible cause of this error is that the symbol is being referenced in the indicated code as if it had a larger alignment than was declared where it was defined
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [Makefile:1051: stockfish] Error 1
make[2]: Leaving directory '/home/torsten/chess/Stockfish_master/src'
make[1]: *** [Makefile:1058: clang-profile-make] Error 2
make[1]: Leaving directory '/home/torsten/chess/Stockfish_master/src'
make: *** [Makefile:886: profile-build] Error 2
```

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

No functional change
2024-03-12 19:09:50 +01:00
FauziAkram 627974c99f Search + Eval + Movepick Tune
Passed STC:
https://tests.stockfishchess.org/tests/view/65ef15220ec64f0526c44b04
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 24480 W: 6459 L: 6153 D: 11868
Ptnml(0-2): 101, 2798, 6184, 3008, 149

Passed LTC:
https://tests.stockfishchess.org/tests/view/65ef4bac0ec64f0526c44f50
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 53316 W: 13561 L: 13203 D: 26552
Ptnml(0-2): 27, 5925, 14408, 6259, 39

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

Bench: 1715522
2024-03-12 16:47:11 +01:00
FauziAkram daa3ef9148 Simplify increaseDepth to boolean expression
Non-functional Simplification, maintaining the same logic as before. Big thanks
to @peregrineshahin for helping with the code.

Passed non-regression bounds:
https://tests.stockfishchess.org/tests/view/65ec93860ec64f0526c42375
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 101088 W: 26196 L: 26047 D: 48845
Ptnml(0-2): 405, 11580, 26473, 11633, 453

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

No functional change
2024-03-12 16:43:10 +01:00
Disservin 1a26d698de Refactor Network Usage
Continuing from PR #4968, this update improves how Stockfish handles network
usage, making it easier to manage and modify networks in the future.

With the introduction of a dedicated Network class, creating networks has become
straightforward. See uci.cpp:
```cpp
NN::NetworkBig({EvalFileDefaultNameBig, "None", ""}, NN::embeddedNNUEBig)
```

The new `Network` encapsulates all network-related logic, significantly reducing
the complexity previously required to support multiple network types, such as
the distinction between small and big networks #4915.

Non-Regression STC:
https://tests.stockfishchess.org/tests/view/65edd26c0ec64f0526c43584
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 33760 W: 8887 L: 8661 D: 16212
Ptnml(0-2): 143, 3795, 8808, 3961, 173

Non-Regression SMP STC:
https://tests.stockfishchess.org/tests/view/65ed71970ec64f0526c42fdd
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 59088 W: 15121 L: 14931 D: 29036
Ptnml(0-2): 110, 6640, 15829, 6880, 85

Compiled with `make -j profile-build`
```
bash ./bench_parallel.sh ./stockfish ./stockfish-nnue 13 50

sf_base =  1568540 +/-   7637 (95%)
sf_test =  1573129 +/-   7301 (95%)
diff    =     4589 +/-   8720 (95%)
speedup = 0.29260% +/- 0.556% (95%)
```

Compiled with `make -j build`
```
bash ./bench_parallel.sh ./stockfish ./stockfish-nnue 13 50

sf_base =  1472653 +/-   7293 (95%)
sf_test =  1491928 +/-   7661 (95%)
diff    =    19275 +/-   7154 (95%)
speedup = 1.30886% +/- 0.486% (95%)
```

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

No functional change
2024-03-12 16:41:08 +01:00
Gahtan Nahdi f072634e24 Simplify opponentWorsening condition
Passed non-reg STC:
https://tests.stockfishchess.org/tests/view/65ea18650ec64f0526c4033a
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 226624 W: 58601 L: 58589 D: 109434
Ptnml(0-2): 1030, 27193, 56819, 27275, 995

Passed non-reg LTC:
https://tests.stockfishchess.org/tests/view/65eb7a220ec64f0526c4161a
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 243882 W: 61462 L: 61469 D: 120951
Ptnml(0-2): 197, 27559, 66419, 27586, 180

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

Bench: 1601012
2024-03-11 10:08:40 +01:00
Muzhen Gaming 10e2732978 VVLTC search tune
Result of 32k games of tuning at 60+0.6 8-thread. Link to the tuning
attempt:
https://tests.stockfishchess.org/tests/view/65def7b04b19edc854ebdec8

Passed VVLTC first SPRT:
https://tests.stockfishchess.org/tests/view/65e51b53416ecd92c162ab7f
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 37570 W: 9613 L: 9342 D: 18615
Ptnml(0-2): 2, 3454, 11601, 3727, 1

Passed VVLTC second SPRT:
https://tests.stockfishchess.org/tests/view/65e87d1c0ec64f0526c3eb39
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 123158 W: 31463 L: 31006 D: 60689
Ptnml(0-2): 5, 11589, 37935, 12044, 6

Note: The small net and psqt-only thresholds have been moved to
evaluate.h. The reasoning is that these values are used in both
`evaluate.cpp` and `evaluate_nnue.cpp`, and thus unifying their usage
avoids inconsistencies during testing, where one occurrence is changed
without the other (this happened during the search tune SPRT).

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

Bench: 1741218
2024-03-11 10:04:37 +01:00
Disservin b6dfd6bd54 Assorted cleanups
- fix naming convention for `workingDirectory`
- use type alias for `EvalFiles` everywhere
- move `ponderMode` into `LimitsType`
- move limits parsing into standalone static function

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

No functional change
2024-03-11 09:02:13 +01:00
Robert Nurnberg @ elitebook 632f1c21cd Fix wrong constant usage in go mate
Fixes an oversight in https://github.com/official-stockfish/Stockfish/pull/5094

In theory, master could stop search when run with `go mate 247` and return a TB loss (not a mate score). Also fixes the spelling of opponenWorsening.

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

No functional change
2024-03-07 21:10:33 +01:00
Muzhen Gaming 0f01a516d2 VLTC time management tune
Result of 35k games of SPSA tuning at 180+1.8. Tuning attempt can be
found here:
https://tests.stockfishchess.org/tests/view/65e40599f2ef6c733362b03b

Passed VLTC 180+1.8:
https://tests.stockfishchess.org/tests/view/65e5a6f5416ecd92c162b5d4
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 31950 W: 8225 L: 7949 D: 15776
Ptnml(0-2): 3, 3195, 9309, 3459, 9

Passed VLTC 240+2.4:
https://tests.stockfishchess.org/tests/view/65e714de0ec64f0526c3d1f1
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 65108 W: 16558 L: 16202 D: 32348
Ptnml(0-2): 7, 6366, 19449, 6728, 4

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

Bench: 1714391
2024-03-07 20:08:00 +01:00
Shahin M. Shahin 748791f80d Fix go mate x in multithreading
Fixes two issues with master for go mate x:

- when running go mate x in losing positions, master always goes to the
  maximal depth, arguably against what the UCI protocol demands

- when running go mate x in winning positions with multiple
  threads, master may return non-mate scores from the search (this issue
  is present in stockfish since at least sf16) The issues are fixed by
  (a) also checking if score is mate -x and by (b) only letting
  mainthread stop the search for go mate x commands, and by not looking
  for a best thread but using mainthread as per the default. Related:
    niklasf/python-chess#1070

More diagnostics can be found here peregrineshahin#6 (comment)

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

No functional change

Co-Authored-By: Robert Nürnberg <28635489+robertnurnberg@users.noreply.github.com>
2024-03-07 19:58:33 +01:00
Michael Chaly 6136d094c5 Introduce double extensions for PV nodes
Our double/triple extensions were allowed only for non-pv nodes. This
patch allows them to be done for PV nodes, with some stricter
conditions.

Passed STC:
https://tests.stockfishchess.org/tests/view/65d657ec1d8e83c78bfddab8
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 339424 W: 88097 L: 87318 D: 164009
Ptnml(0-2): 1573, 39935, 85729, 41090, 1385

Passed LTC:
https://tests.stockfishchess.org/tests/view/65dd63824b19edc854ebc433
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 459564 W: 115812 L: 114614 D: 229138
Ptnml(0-2): 248, 51441, 125173, 52705, 215

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

Bench: 1714391
2024-03-07 19:56:30 +01:00
rn5f107s2 1db969e620 Reduce futility_margin if opponents last move was bad
This reduces the futiltiy_margin if our opponents last move was bad by
around ~1/3 when not improving and ~1/2.7 when improving, the idea being
to retroactively futility prune moves that were played, but turned out
to be bad.  A bad move is being defined as their staticEval before their
move being lower as our staticEval now is. If the depth is 2 and we are
improving the opponent worsening flag is not set, in order to not risk
having a too low futility_margin, due to the fact that when these
conditions are met the futility_margin already drops quite low.

Passed STC:
https://tests.stockfishchess.org/tests/live_elo/65e3977bf2ef6c733362aae3
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 122432 W: 31884 L: 31436 D: 59112
Ptnml(0-2): 467, 14404, 31035, 14834, 476

Passed LTC:
https://tests.stockfishchess.org/tests/live_elo/65e47f40f2ef6c733362b6d2
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 421692 W: 106572 L: 105452 D: 209668
Ptnml(0-2): 216, 47217, 114865, 48327, 221

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

Bench: 1565939
2024-03-07 19:55:51 +01:00
Linmiao Xu bd579ab5d1 Update default main net to nn-1ceb1ade0001.nnue
Created by retraining the previous main net `nn-b1a57edbea57.nnue` with:
- some of the same options as before:
  - ranger21, more WDL skipping, 15% more loss when Q is too high
- removal of the huge 514G pre-interleaved binpack
- removal of SF-generated dfrc data (dfrc99-16tb7p-filt-v2.min.binpack)
- interleaving many binpacks at training time
- training with some bestmove capture positions where SEE < 0
- increased usage of torch.compile to speed up training by up to 40%

```yaml
experiment-name: 2560--S10-dfrc0-to-dec2023-skip-more-wdl-15p-more-loss-high-q-see-ge0-sk28
nnue-pytorch-branch: linrock/nnue-pytorch/r21-more-wdl-skip-15p-more-loss-high-q-skip-see-ge0-torch-compile-more
start-from-engine-test-net: True

early-fen-skipping: 28
training-dataset:
  # similar, not the exact same as:
  # https://github.com/official-stockfish/Stockfish/pull/4635
  - /data/S5-5af/leela96.v2.min.binpack
  - /data/S5-5af/test60-2021-11-12-novdec-12tb7p.v6-dd.min.binpack
  - /data/S5-5af/test77-2021-12-dec-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test78-2022-01-to-05-jantomay-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test78-2022-06-to-09-juntosep-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test79-2022-04-apr-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test79-2022-05-may-16tb7p.v6-dd.min.binpack

  - /data/S5-5af/test80-2022-06-jun-16tb7p.v6-dd.min.unmin.binpack
  - /data/S5-5af/test80-2022-07-jul-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test80-2022-08-aug-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test80-2022-09-sep-16tb7p.v6-dd.min.unmin.binpack
  - /data/S5-5af/test80-2022-10-oct-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test80-2022-11-nov-16tb7p.v6-dd.min.binpack

  - /data/S5-5af/test80-2023-01-jan-16tb7p.v6-sk20.min.binpack
  - /data/S5-5af/test80-2023-02-feb-16tb7p.v6-dd.min.binpack
  - /data/S5-5af/test80-2023-03-mar-2tb7p.min.unmin.binpack
  - /data/S5-5af/test80-2023-04-apr-2tb7p.binpack
  - /data/S5-5af/test80-2023-05-may-2tb7p.min.dd.binpack

  # https://github.com/official-stockfish/Stockfish/pull/4782
  - /data/S6-1ee1aba5ed/test80-2023-06-jun-2tb7p.binpack
  - /data/S6-1ee1aba5ed/test80-2023-07-jul-2tb7p.min.binpack

  # https://github.com/official-stockfish/Stockfish/pull/4972
  - /data/S8-baff1edbea57/test80-2023-08-aug-2tb7p.v6.min.binpack
  - /data/S8-baff1edbea57/test80-2023-09-sep-2tb7p.binpack
  - /data/S8-baff1edbea57/test80-2023-10-oct-2tb7p.binpack

  # https://github.com/official-stockfish/Stockfish/pull/5056
  - /data/S9-b1a57edbea57/test80-2023-11-nov-2tb7p.binpack
  - /data/S9-b1a57edbea57/test80-2023-12-dec-2tb7p.binpack

num-epochs: 800
lr: 4.375e-4
gamma: 0.995
start-lambda: 1.0
end-lambda: 0.7
```

This particular net was reached at epoch 759. Use of more torch.compile decorators
in nnue-pytorch model.py than in the previous main net training run sped up training
by up to 40% on Tesla gpus when using recent pytorch compiled with cuda 12:
https://github.com/linrock/nnue-tools/blob/7fb9831/Dockerfile

Skipping positions with bestmove captures where static exchange evaluation is >= 0
is based on the implementation from Sopel's NNUE training & experimentation log:
https://docs.google.com/document/d/1gTlrr02qSNKiXNZ_SuO4-RjK4MXBiFlLE6jvNqqMkAY
Experiment 293 - only skip captures with see>=0

Positions with bestmove captures where score == 0 are always skipped for
compatibility with minimized binpacks, since the original minimizer sets
scores to 0 for slight improvements in compression.

The trainer branch used was:
https://github.com/linrock/nnue-pytorch/tree/r21-more-wdl-skip-15p-more-loss-high-q-skip-see-ge0-torch-compile-more

Binpacks were renamed to be sorted chronologically by default when sorted by name.
The binpack data are otherwise the same as binpacks with similar names in the prior
naming convention.

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Passed STC:
https://tests.stockfishchess.org/tests/view/65e3ddd1f2ef6c733362ae5c
LLR: 2.92 (-2.94,2.94) <0.00,2.00>
Total: 149792 W: 39153 L: 38661 D: 71978
Ptnml(0-2): 675, 17586, 37905, 18032, 698

Passed LTC:
https://tests.stockfishchess.org/tests/view/65e4d91c416ecd92c162a69b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 64416 W: 16517 L: 16135 D: 31764
Ptnml(0-2): 38, 7218, 17313, 7602, 37

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

Bench: 1373183
2024-03-07 19:53:48 +01:00
FauziAkram a96b0d4609 Update elo estimates
Tests used to change the elo worth of some functions:

https://tests.stockfishchess.org/tests/view/65c3f69dc865510db0283eef
https://tests.stockfishchess.org/tests/view/65c3f935c865510db0283f2a
https://tests.stockfishchess.org/tests/view/65d1489f1d8e83c78bfd7dbf
https://tests.stockfishchess.org/tests/view/65ce9d361d8e83c78bfd4951
https://tests.stockfishchess.org/tests/view/65cfcd901d8e83c78bfd6184

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

No functional change
2024-03-07 19:53:48 +01:00
FauziAkram a615efb19f Simplify Time Management
Instead of having a formula for using extra time with larger increments.
Simply set it to 1 when the increment is lower than 0.5s and to 1.1 when
the increment is higher.

The values can later on be further improved.

Passed STC:
https://tests.stockfishchess.org/tests/view/65d25d3c1d8e83c78bfd9293
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 27488 W: 7077 L: 6848 D: 13563
Ptnml(0-2): 96, 3041, 7267, 3218, 122

Passed LTC:
https://tests.stockfishchess.org/tests/view/65d2a72c1d8e83c78bfd97fa
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 137568 W: 34612 L: 34512 D: 68444
Ptnml(0-2): 60, 14672, 39221, 14770, 61

Passed VLTC:
https://tests.stockfishchess.org/tests/view/65d7d7d39b2da0226a5a205b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 139650 W: 35229 L: 35134 D: 69287
Ptnml(0-2): 33, 14227, 41218, 14306, 41

Passed also the TCEC TC style suggested by vondele:
https://tests.stockfishchess.org/tests/view/65e4ca73416ecd92c162a57d
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 134150 W: 34278 L: 34163 D: 65709
Ptnml(0-2): 561, 15727, 34444, 15722, 621

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

Bench: 1553115
2024-03-07 19:49:01 +01:00
Gahtan Nahdi b0ac8a4e3b Simplify extension when ttMove is assumed to fail high over current beta
Simplify extension value to -3 when ttMove is assumed to fail high over current beta.

Passed non-reg STC:
https://tests.stockfishchess.org/tests/view/65d66ed81d8e83c78bfddcba
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 235136 W: 60711 L: 60708 D: 113717
Ptnml(0-2): 969, 27904, 59874, 27797, 1024

Passed non-reg LTC:
https://tests.stockfishchess.org/tests/view/65da2994944f2a78d4733107
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 662850 W: 166161 L: 166602 D: 330087
Ptnml(0-2): 394, 74895, 181274, 74482, 380

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

Bench: 1553115
2024-03-03 15:45:13 +01:00
Gahtan Nahdi 6d0d430860 Simplify IIR
Simplified depth reduction for PV nodes without a ttMove to 3.

Passed STC non-reg:
https://tests.stockfishchess.org/tests/view/65d1a90a1d8e83c78bfd855a
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 363168 W: 93648 L: 93791 D: 175729
Ptnml(0-2): 1557, 43692, 91221, 43565, 1549

Passed LTC non-reg:
https://tests.stockfishchess.org/tests/view/65d5612d1d8e83c78bfdc8e2
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 58818 W: 14946 L: 14761 D: 29111
Ptnml(0-2): 36, 6595, 15962, 6780, 36

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

Bench: 1505827
2024-03-03 15:42:17 +01:00
mstembera 7831131591 Only evaluate the PSQT part of the small net for large evals.
Thanks to Viren6 for suggesting to set complexity to 0.

STC https://tests.stockfishchess.org/tests/view/65d7d6709b2da0226a5a203f
LLR: 2.92 (-2.94,2.94) <0.00,2.00>
Total: 328384 W: 85316 L: 84554 D: 158514
Ptnml(0-2): 1414, 39076, 82486, 39766, 1450

LTC https://tests.stockfishchess.org/tests/view/65dce6d290f639b028a54d2e
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 165162 W: 41918 L: 41330 D: 81914
Ptnml(0-2): 102, 18332, 45124, 18922, 101

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

bench: 1504003
2024-03-03 15:29:58 +01:00
Disservin 0a3eb1d8fa Document TT code more
Slight refactor of the TT code with the goal to make it easier to understand / tweak.

Passed Non-Regression STC:
https://tests.stockfishchess.org/tests/view/65d51e401d8e83c78bfdc427
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 56416 W: 14750 L: 14550 D: 27116
Ptnml(0-2): 227, 6386, 14796, 6558, 241

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

No functional change
2024-03-03 15:21:57 +01:00
Gahtan Nahdi f77eddfa2f Join conditions for move sorting heuristics
closes https://github.com/official-stockfish/Stockfish/pull/5078

No functional change.
2024-03-03 15:18:13 +01:00
Disservin 0c22d5bb1a Update Actions to Node20
ensure our CI continues to run after Node16 is obsolote on github.

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

No functional change
2024-03-03 15:09:46 +01:00
Disservin c83c7f4e71 Make binaries executable again in CI
closes https://github.com/official-stockfish/Stockfish/pull/5072

No functional change
2024-03-03 15:07:32 +01:00
Disservin abcc090a62 Restore development
closes https://github.com/official-stockfish/Stockfish/pull/5073

No functional change
2024-03-03 15:01:29 +01:00
87 changed files with 9272 additions and 4079 deletions
+1
View File
@@ -7,6 +7,7 @@
{ include: [ "<__fwd/sstream.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/streambuf.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/string_view.h>", private, "<string_view>", public ] },
{ include: [ "<__system_error/errc.h>", private, "<system_error>", public ] },
# Mappings for includes between public headers
{ include: [ "<ios>", public, "<iostream>", public ] },
+4 -4
View File
@@ -1,8 +1,8 @@
{
"config": [
{
"name": "Ubuntu 20.04 GCC",
"os": "ubuntu-20.04",
"name": "Ubuntu 22.04 GCC",
"os": "ubuntu-22.04",
"simple_name": "ubuntu",
"compiler": "g++",
"comp": "gcc",
@@ -111,7 +111,7 @@
{
"binaries": "x86-64-avxvnni",
"config": {
"ubuntu-20.04": null
"ubuntu-22.04": null
}
},
{
@@ -153,7 +153,7 @@
{
"binaries": "apple-silicon",
"config": {
"os": "ubuntu-20.04"
"os": "ubuntu-22.04"
}
}
]
+7 -3
View File
@@ -10,7 +10,7 @@ jobs:
name: ${{ matrix.config.name }} ${{ matrix.binaries }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMPCXX: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
EMU: ${{ matrix.config.emu }}
EXT: ${{ matrix.config.ext }}
@@ -26,6 +26,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Download required linux packages
if: runner.os == 'Linux'
@@ -62,7 +63,7 @@ jobs:
if [ $COMP == ndk ]; then
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
fi
$COMPILER -v
$COMPCXX -v
- name: Test help target
run: make help
@@ -91,4 +92,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.config.simple_name }} ${{ matrix.binaries }}
path: .
path: |
.
!.git
!.output
+12 -6
View File
@@ -11,10 +11,14 @@ on:
paths:
- "**.cpp"
- "**.h"
permissions:
pull-requests: write
jobs:
Clang-Format:
name: Clang-Format
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
@@ -25,27 +29,29 @@ jobs:
id: clang-format
continue-on-error: true
with:
clang-format-version: "17"
clang-format-version: "18"
exclude-regex: "incbin"
- name: Comment on PR
if: steps.clang-format.outcome == 'failure'
uses: thollander/actions-comment-pull-request@1d3973dc4b8e1399c0620d3f2b1aa5e795465308 # @v2.4.3
uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # @v2.5.0
with:
message: |
clang-format 17 needs to be run on this PR.
clang-format 18 needs to be run on this PR.
If you do not have clang-format installed, the maintainer will run it when merging.
For the exact version please see https://packages.ubuntu.com/mantic/clang-format-17.
For the exact version please see https://packages.ubuntu.com/noble/clang-format-18.
_(execution **${{ github.run_id }}** / attempt **${{ github.run_attempt }}**)_
comment_tag: execution
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Comment on PR
if: steps.clang-format.outcome != 'failure'
uses: thollander/actions-comment-pull-request@1d3973dc4b8e1399c0620d3f2b1aa5e795465308 # @v2.4.3
uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # @v2.5.0
with:
message: |
_(execution **${{ github.run_id }}** / attempt **${{ github.run_attempt }}**)_
create_if_not_exists: false
comment_tag: execution
mode: delete
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+2
View File
@@ -30,6 +30,8 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+9 -4
View File
@@ -10,7 +10,7 @@ jobs:
name: ${{ matrix.config.name }} ${{ matrix.binaries }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMPCXX: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
EXT: ${{ matrix.config.ext }}
NAME: ${{ matrix.config.simple_name }}
@@ -25,6 +25,8 @@ jobs:
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install fixed GCC on Linux
if: runner.os == 'Linux'
@@ -50,7 +52,7 @@ jobs:
run: make net
- name: Check compiler
run: $COMPILER -v
run: $COMPCXX -v
- name: Test help target
run: make help
@@ -59,7 +61,7 @@ jobs:
run: git --version
- name: Check compiler
run: $COMPILER -v
run: $COMPCXX -v
- name: Show g++ cpu info
if: runner.os != 'macOS'
@@ -86,4 +88,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.config.simple_name }} ${{ matrix.binaries }}
path: .
path: |
.
!.git
!.output
+43
View File
@@ -0,0 +1,43 @@
# This workflow will play games with a debug enabled SF using the PR
name: Games
on:
workflow_call:
jobs:
Matetrack:
name: Games
runs-on: ubuntu-22.04
steps:
- name: Checkout SF repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
path: Stockfish
persist-credentials: false
- name: build debug enabled version of SF
working-directory: Stockfish/src
run: make -j build debug=yes
- name: Checkout fastchess repo
uses: actions/checkout@v4
with:
repository: Disservin/fastchess
path: fastchess
ref: 894616028492ae6114835195f14a899f6fa237d3
persist-credentials: false
- name: fastchess build
working-directory: fastchess
run: make -j
- name: Run games
working-directory: fastchess
run: |
./fastchess -rounds 4 -games 2 -repeat -concurrency 4 -openings file=app/tests/data/openings.epd format=epd order=random -srand $RANDOM\
-engine name=sf1 cmd=/home/runner/work/Stockfish/Stockfish/Stockfish/src/stockfish\
-engine name=sf2 cmd=/home/runner/work/Stockfish/Stockfish/Stockfish/src/stockfish\
-ratinginterval 1 -report penta=true -each proto=uci tc=4+0.04 -log file=fast.log | tee fast.out
cat fast.log
! grep "Assertion" fast.log > /dev/null
! grep "disconnect" fast.out > /dev/null
+2
View File
@@ -14,6 +14,7 @@ jobs:
uses: actions/checkout@v4
with:
path: Stockfish
persist-credentials: false
- name: Checkout include-what-you-use
uses: actions/checkout@v4
@@ -21,6 +22,7 @@ jobs:
repository: include-what-you-use/include-what-you-use
ref: f25caa280dc3277c4086ec345ad279a2463fea0f
path: include-what-you-use
persist-credentials: false
- name: Download required linux packages
run: |
+71
View File
@@ -0,0 +1,71 @@
# This workflow will run matetrack on the PR
name: Matetrack
on:
workflow_call:
jobs:
Matetrack:
name: Matetrack
runs-on: ubuntu-22.04
steps:
- name: Checkout SF repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
path: Stockfish
persist-credentials: false
- name: build SF
working-directory: Stockfish/src
run: make -j profile-build
- name: Checkout matetrack repo
uses: actions/checkout@v4
with:
repository: vondele/matetrack
path: matetrack
ref: 4f8a80860ed8f3607f05a9195df8b40203bdc360
persist-credentials: false
- name: matetrack install deps
working-directory: matetrack
run: pip install -r requirements.txt
- name: cache syzygy
id: cache-syzygy
uses: actions/cache@v4
with:
path: |
matetrack/3-4-5-wdl/
matetrack/3-4-5-dtz/
key: key-syzygy
- name: download syzygy 3-4-5 if needed
working-directory: matetrack
if: steps.cache-syzygy.outputs.cache-hit != 'true'
run: |
wget --no-verbose -r -nH --cut-dirs=2 --no-parent --reject="index.html*" -e robots=off https://tablebase.lichess.ovh/tables/standard/3-4-5-wdl/
wget --no-verbose -r -nH --cut-dirs=2 --no-parent --reject="index.html*" -e robots=off https://tablebase.lichess.ovh/tables/standard/3-4-5-dtz/
- name: Run matetrack
working-directory: matetrack
run: |
python matecheck.py --syzygyPath 3-4-5-wdl/:3-4-5-dtz/ --engine /home/runner/work/Stockfish/Stockfish/Stockfish/src/stockfish --epdFile mates2000.epd --nodes 100000 | tee matecheckout.out
! grep "issues were detected" matecheckout.out > /dev/null
- name: Run matetrack with --syzygy50MoveRule false
working-directory: matetrack
run: |
grep 5men cursed.epd > cursed5.epd
python matecheck.py --syzygyPath 3-4-5-wdl/:3-4-5-dtz/ --engine /home/runner/work/Stockfish/Stockfish/Stockfish/src/stockfish --epdFile cursed5.epd --nodes 100000 --syzygy50MoveRule false | tee matecheckcursed.out
! grep "issues were detected" matecheckcursed.out > /dev/null
- name: Verify mate and TB win count for matecheckcursed.out
working-directory: matetrack
run: |
mates=$(grep "Found mates:" matecheckcursed.out | awk '{print $3}')
tbwins=$(grep "Found TB wins:" matecheckcursed.out | awk '{print $4}')
if [ $(($mates + $tbwins)) -ne 32 ]; then
echo "Sum of mates and TB wins is not 32 in matecheckcursed.out" >&2
exit 1
fi
+26 -4
View File
@@ -6,7 +6,7 @@ jobs:
name: ${{ matrix.sanitizers.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMPCXX: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
CXXFLAGS: "-Werror"
strategy:
@@ -21,22 +21,36 @@ jobs:
sanitizers:
- name: Run with thread sanitizer
make_option: sanitize=thread
cxx_extra_flags: ""
instrumented_option: sanitizer-thread
- name: Run with UB sanitizer
make_option: sanitize=undefined
cxx_extra_flags: ""
instrumented_option: sanitizer-undefined
- name: Run under valgrind
make_option: ""
cxx_extra_flags: ""
instrumented_option: valgrind
- name: Run under valgrind-thread
make_option: ""
cxx_extra_flags: ""
instrumented_option: valgrind-thread
- name: Run non-instrumented
make_option: ""
cxx_extra_flags: ""
instrumented_option: none
- name: Run with glibcxx assertions
make_option: ""
cxx_extra_flags: -D_GLIBCXX_ASSERTIONS
instrumented_option: non
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Download required linux packages
run: |
@@ -47,7 +61,7 @@ jobs:
run: make net
- name: Check compiler
run: $COMPILER -v
run: $COMPCXX -v
- name: Test help target
run: make help
@@ -55,11 +69,19 @@ jobs:
- name: Check git
run: git --version
# Since Linux Kernel 6.5 we are getting false positives from the ci,
# lower the ALSR entropy to disable ALSR, which works as a temporary workaround.
# https://github.com/google/sanitizers/issues/1716
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2056762
- name: Lower ALSR entropy
run: sudo sysctl -w vm.mmap_rnd_bits=28
# Sanitizers
- name: ${{ matrix.sanitizers.name }}
run: |
export CXXFLAGS="-O1 -fno-inline"
export CXXFLAGS="-O1 -fno-inline ${{ matrix.sanitizers.cxx_extra_flags }}"
make clean
make -j4 ARCH=x86-64-sse41-popcnt ${{ matrix.sanitizers.make_option }} debug=yes optimize=no build > /dev/null
../tests/instrumented.sh --${{ matrix.sanitizers.instrumented_option }}
python3 ../tests/instrumented.py --${{ matrix.sanitizers.instrumented_option }} ./stockfish
+51 -5
View File
@@ -15,7 +15,13 @@ jobs:
Prerelease:
if: github.repository == 'official-stockfish/Stockfish' && (github.ref == 'refs/heads/master' || (startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag'))
runs-on: ubuntu-latest
permissions:
contents: write # For deleting/creating a prerelease
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
# returns null if no pre-release exists
- name: Get Commit SHA of Latest Pre-release
run: |
@@ -23,14 +29,40 @@ jobs:
sudo apt-get update
sudo apt-get install -y curl jq
echo "COMMIT_SHA=$(jq -r 'map(select(.prerelease)) | first | .tag_name' <<< $(curl -s https://api.github.com/repos/${{ github.repository_owner }}/Stockfish/releases))" >> $GITHUB_ENV
echo "COMMIT_SHA_TAG=$(jq -r 'map(select(.prerelease)) | first | .tag_name' <<< $(curl -s https://api.github.com/repos/${{ github.repository_owner }}/Stockfish/releases))" >> $GITHUB_ENV
# delete old previous pre-release and tag
- uses: actions/checkout@v4
- run: gh release delete ${{ env.COMMIT_SHA }} --cleanup-tag
if: env.COMMIT_SHA != 'null'
# delete old previous pre-release and tag
- run: gh release delete ${{ env.COMMIT_SHA_TAG }} --cleanup-tag
if: env.COMMIT_SHA_TAG != 'null'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Make sure that an old ci that still runs on master doesn't recreate a prerelease
- name: Check Pullable Commits
id: check_commits
run: |
git fetch
CHANGES=$(git rev-list HEAD..origin/master --count)
echo "CHANGES=$CHANGES" >> $GITHUB_ENV
- name: Get last commit SHA
id: last_commit
run: echo "COMMIT_SHA=$(git rev-parse HEAD | cut -c 1-8)" >> $GITHUB_ENV
- name: Get commit date
id: commit_date
run: echo "COMMIT_DATE=$(git show -s --date=format:'%Y%m%d' --format=%cd HEAD)" >> $GITHUB_ENV
# Create a new pre-release, the other upload_binaries.yml will upload the binaries
# to this pre-release.
- name: Create Prerelease
if: github.ref_name == 'master' && env.CHANGES == '0'
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with:
name: Stockfish dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
tag_name: stockfish-dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
prerelease: true
Matrix:
runs-on: ubuntu-latest
outputs:
@@ -38,6 +70,8 @@ jobs:
arm_matrix: ${{ steps.set-arm-matrix.outputs.arm_matrix }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- id: set-matrix
run: |
TASKS=$(echo $(cat .github/ci/matrix.json) )
@@ -62,15 +96,27 @@ jobs:
uses: ./.github/workflows/sanitizers.yml
Tests:
uses: ./.github/workflows/tests.yml
Matetrack:
uses: ./.github/workflows/matetrack.yml
Games:
uses: ./.github/workflows/games.yml
Binaries:
if: github.repository == 'official-stockfish/Stockfish'
needs: [Matrix, Prerelease, Compilation]
uses: ./.github/workflows/upload_binaries.yml
with:
matrix: ${{ needs.Matrix.outputs.matrix }}
permissions:
contents: write # For deleting/creating a (pre)release
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
ARM_Binaries:
if: github.repository == 'official-stockfish/Stockfish'
needs: [Matrix, Prerelease, ARMCompilation]
uses: ./.github/workflows/upload_binaries.yml
with:
matrix: ${{ needs.Matrix.outputs.arm_matrix }}
permissions:
contents: write # For deleting/creating a (pre)release
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
+16 -15
View File
@@ -6,22 +6,22 @@ jobs:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMPCXX: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
CXXFLAGS: "-Werror"
strategy:
fail-fast: false
matrix:
config:
- name: Ubuntu 20.04 GCC
os: ubuntu-20.04
- name: Ubuntu 22.04 GCC
os: ubuntu-22.04
compiler: g++
comp: gcc
run_32bit_tests: true
run_64bit_tests: true
shell: bash
- name: Ubuntu 20.04 Clang
os: ubuntu-20.04
- name: Ubuntu 22.04 Clang
os: ubuntu-22.04
compiler: clang++
comp: clang
run_32bit_tests: true
@@ -106,6 +106,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Download required linux packages
if: runner.os == 'Linux'
@@ -138,16 +139,16 @@ jobs:
- name: Build Docker container
if: matrix.config.base_image
run: |
docker buildx build --load -t sf_builder - << EOF
docker buildx build --platform ${{ matrix.config.platform }} --load -t sf_builder - << EOF
FROM ${{ matrix.config.base_image }}
WORKDIR /app
RUN apk update && apk add make g++
CMD ["sh", "script.sh"]
CMD ["sh", "src/script.sh"]
EOF
- name: Download required macOS packages
if: runner.os == 'macOS'
run: brew install coreutils
run: brew install coreutils gcc@11
- name: Setup msys and install required packages
if: runner.os == 'Windows'
@@ -172,10 +173,10 @@ jobs:
if [ $COMP == ndk ]; then
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
fi
$COMPILER -v
$COMPCXX -v
else
echo "$COMPILER -v" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}/src:/app sf_builder
echo "$COMPCXX -v" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}:/app sf_builder
fi
- name: Test help target
@@ -341,8 +342,8 @@ jobs:
- name: Test riscv64 build
if: matrix.config.run_riscv64_tests
run: |
echo "export LDFLAGS='-static' && make clean && make -j4 ARCH=riscv64 build" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}/src:/app sf_builder
echo "cd src && export LDFLAGS='-static' && make clean && make -j4 ARCH=riscv64 build" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}:/app sf_builder
../tests/signature.sh $benchref
# ppc64 tests
@@ -350,8 +351,8 @@ jobs:
- name: Test ppc64 build
if: matrix.config.run_ppc64_tests
run: |
echo "export LDFLAGS='-static' && make clean && make -j4 ARCH=ppc-64 build" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}/src:/app sf_builder
echo "cd src && export LDFLAGS='-static' && make clean && make -j4 ARCH=ppc-64 build" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}:/app sf_builder
../tests/signature.sh $benchref
# Other tests
+11 -2
View File
@@ -5,13 +5,16 @@ on:
matrix:
type: string
required: true
secrets:
token:
required: true
jobs:
Artifacts:
name: ${{ matrix.config.name }} ${{ matrix.binaries }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMPCXX: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
EXT: ${{ matrix.config.ext }}
NAME: ${{ matrix.config.simple_name }}
@@ -25,6 +28,8 @@ jobs:
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Download artifact from compilation
uses: actions/download-artifact@v4
@@ -54,6 +59,7 @@ jobs:
mv "${{ matrix.config.simple_name }} ${{ matrix.binaries }}" stockfish-workflow
cd stockfish-workflow
cp -r src ../stockfish/
cp -r scripts ../stockfish/
cp stockfish-$NAME-$BINARY$EXT ../stockfish/
cp "Top CPU Contributors.txt" ../stockfish/
cp Copying.txt ../stockfish/
@@ -65,6 +71,7 @@ jobs:
- name: Create tar
if: runner.os != 'Windows'
run: |
chmod +x ./stockfish/stockfish-$NAME-$BINARY$EXT
tar -cvf stockfish-$NAME-$BINARY.tar stockfish
- name: Create zip
@@ -77,6 +84,7 @@ jobs:
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with:
files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.${{ matrix.config.archive_ext }}
token: ${{ secrets.token }}
- name: Get last commit sha
id: last_commit
@@ -97,9 +105,10 @@ jobs:
- name: Prerelease
if: github.ref_name == 'master' && env.CHANGES == '0'
continue-on-error: true
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # @v1
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with:
name: Stockfish dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
tag_name: stockfish-dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
prerelease: true
files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.${{ matrix.config.archive_ext }}
token: ${{ secrets.token }}
+5
View File
@@ -10,3 +10,8 @@ src/-lstdc++.res
# Neural network for the NNUE evaluation
**/*.nnue
# Files generated by the instrumented tests
tsan.supp
__pycache__/
tests/syzygy
tests/bench_tmp.epd
+14
View File
@@ -20,6 +20,7 @@ Alexander Kure
Alexander Pagel (Lolligerhans)
Alfredo Menezes (lonfom169)
Ali AlZhrani (Cooffe)
Andreas Jan van der Meulen (Andyson007)
Andreas Matthies (Matthies)
Andrei Vetrov (proukornew)
Andrew Grant (AndyGrant)
@@ -44,8 +45,11 @@ Bruno de Melo Costa (BM123499)
Bruno Pellanda (pellanda)
Bryan Cross (crossbr)
candirufish
Carlos Esparza Sánchez (ces42)
Chess13234
Chris Bao (sscg13)
Chris Cain (ceebo)
Ciekce
clefrks
Clemens L. (rn5f107s2)
Cody Ho (aesrentai)
@@ -67,9 +71,11 @@ Douglas Matos Gomes (dsmsgms)
Dubslow
Eduardo Cáceres (eduherminio)
Eelco de Groot (KingDefender)
Ehsan Rashid (erashid)
Elvin Liu (solarlight2)
erbsenzaehler
Ernesto Gatti
evqsx
Fabian Beuke (madnight)
Fabian Fichter (ianfab)
Fanael Linithien (Fanael)
@@ -119,13 +125,16 @@ jundery
Justin Blanchard (UncombedCoconut)
Kelly Wilson
Ken Takusagawa
Kenneth Lee (kennethlee33)
Kian E (KJE-98)
kinderchocolate
Kiran Panditrao (Krgp)
Kojirion
Krisztián Peőcz
Krystian Kuzniarek (kuzkry)
Leonardo Ljubičić (ICCF World Champion)
Leonid Pechenik (lp--)
Li Ying (yl25946)
Liam Keegan (lkeegan)
Linmiao Xu (linrock)
Linus Arver (listx)
@@ -138,6 +147,7 @@ Maciej Żenczykowski (zenczykowski)
Malcolm Campbell (xoto10)
Mark Tenzer (31m059)
marotear
Mathias Parnaudeau (mparnaudeau)
Matt Ginsberg (mattginsberg)
Matthew Lai (matthewlai)
Matthew Sullivan (Matt14916)
@@ -166,10 +176,12 @@ Niklas Fiekas (niklasf)
Nikolay Kostov (NikolayIT)
Norman Schmidt (FireFather)
notruck
Nour Berakdar (Nonlinear)
Ofek Shochat (OfekShochat, ghostway)
Ondrej Mosnáček (WOnder93)
Ondřej Mišina (AndrovT)
Oskar Werkelin Ahlin
Ömer Faruk Tutkun (OmerFarukTutkun)
Pablo Vazquez
Panthee
Pascal Romaret
@@ -204,6 +216,7 @@ sf-x
Shahin M. Shahin (peregrine)
Shane Booth (shane31)
Shawn Varghese (xXH4CKST3RXx)
Shawn Xu (xu-shawn)
Siad Daboul (Topologist)
Stefan Geschwentner (locutus2)
Stefano Cardanobile (Stefano80)
@@ -230,6 +243,7 @@ Unai Corzo (unaiic)
Uri Blass (uriblass)
Vince Negri (cuddlestmonkey)
Viren
Wencey Wang
windfishballad
xefoci7612
Xiang Wang (KatyushaScarlet)
+2 -3
View File
@@ -49,7 +49,7 @@ further discussion._
- Provide a clear and concise description of the changes in the pull request
description.
_First time contributors should add their name to [AUTHORS](../AUTHORS)._
_First time contributors should add their name to [AUTHORS](./AUTHORS)._
_Stockfish's development is not focused on adding new features. Thus any pull
request introducing new features will potentially be closed without further
@@ -59,7 +59,7 @@ discussion._
Changes to Stockfish C++ code should respect our coding style defined by
[.clang-format](.clang-format). You can format your changes by running
`make format`. This requires clang-format version 17 to be installed on your system.
`make format`. This requires clang-format version 18 to be installed on your system.
## Navigate
@@ -86,7 +86,6 @@ more details.
Thank you for contributing to Stockfish and helping us make it even better!
[copying-link]: https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt
[discord-link]: https://discord.gg/GWDRS3kU6R
[discussions-link]: https://github.com/official-stockfish/Stockfish/discussions/new
+8 -1
View File
@@ -97,7 +97,7 @@ descriptions. An example suitable for most Intel and AMD chips:
```
cd src
make -j profile-build ARCH=x86-64-avx2
make -j profile-build
```
Detailed compilation instructions for all platforms can be found in our
@@ -120,6 +120,11 @@ where the source code can be found) to generate the exact binary you are
distributing. If you make any changes to the source code, these changes must
also be made available under GPL v3.
## Acknowledgements
Stockfish uses neural networks trained on [data provided by the Leela Chess Zero
project][lc0-data-link], which is made available under the [Open Database License][odbl-link] (ODbL).
[authors-link]: https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS
[build-link]: https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml
@@ -144,6 +149,8 @@ also be made available under GPL v3.
[wiki-uci-link]: https://github.com/official-stockfish/Stockfish/wiki/UCI-&-Commands
[wiki-usage-link]: https://github.com/official-stockfish/Stockfish/wiki/Download-and-usage
[worker-link]: https://github.com/official-stockfish/fishtest/wiki/Running-the-worker
[lc0-data-link]: https://storage.lczero.org/files/training_data
[odbl-link]: https://opendatacommons.org/licenses/odbl/odbl-10.txt
[build-badge]: https://img.shields.io/github/actions/workflow/status/official-stockfish/Stockfish/stockfish.yml?branch=master&style=for-the-badge&label=stockfish&logo=github
[commits-badge]: https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge
+104 -89
View File
@@ -1,106 +1,109 @@
Contributors to Fishtest with >10,000 CPU hours, as of 2024-02-24.
Contributors to Fishtest with >10,000 CPU hours, as of 2024-08-31.
Thank you!
Username CPU Hours Games played
------------------------------------------------------------------
noobpwnftw 39302472 3055513453
technologov 20845762 994893444
linrock 8616428 560281417
noobpwnftw 40428649 3164740143
technologov 23581394 1076895482
vdv 19425375 718302718
linrock 10034115 643194527
mlang 3026000 200065824
okrout 2332151 222639518
pemo 1800019 60274069
okrout 2572676 237511408
pemo 1836785 62226157
dew 1689162 100033738
TueRens 1474943 75121774
grandphish2 1463002 91616949
JojoM 1109702 72927902
olafm 978631 71037944
sebastronomy 939955 44920556
TueRens 1648780 77891164
sebastronomy 1468328 60859092
grandphish2 1466110 91776075
JojoM 1130625 73666098
olafm 1067009 74807270
tvijlbrief 796125 51897690
gvreuls 711320 49142318
oz 781847 53910686
rpngn 768460 49812975
gvreuls 751085 52177668
mibere 703840 46867607
oz 646268 46293638
rpngn 572571 38928563
leszek 531858 39316505
cw 518116 34894291
leszek 566598 42024615
cw 519601 34988161
fastgm 503862 30260818
CSU_Dynasty 468784 31385034
ctoks 434591 28520597
maximmasiutin 429983 27066286
maximmasiutin 439192 27893522
ctoks 435148 28541909
crunchy 427414 27371625
bcross 415724 29061187
robal 371112 24642270
mgrabiak 367963 26464704
velislav 342588 22140902
mgrabiak 338763 23999170
ncfish1 329039 20624527
Fisherman 327231 21829379
robal 299836 20213182
Dantist 296386 18031762
ncfish1 267604 17881149
tolkki963 262050 22049676
Sylvain27 255595 8864404
nordlandia 249322 16420192
Fifis 237657 13065577
marrco 234581 17714473
tolkki963 233490 19773930
Calis007 217537 14450582
glinscott 208125 13277240
drabel 204167 13930674
mhoram 202894 12601997
bking_US 198894 11876016
Calis007 188631 12795784
Thanar 179852 12365359
Fifis 176209 10638245
vdv 175544 9904472
javran 169679 13481966
armo9494 162863 10937118
spams 157128 10319326
DesolatedDodo 156659 10210328
armo9494 155355 10566898
DesolatedDodo 156683 10211206
Wencey 152308 8375444
sqrt2 147963 9724586
vdbergh 140311 9225125
jcAEie 140086 10603658
vdbergh 139746 9172061
CoffeeOne 137100 5024116
malala 136182 8002293
xoto 133759 9159372
Dubslow 129614 8519312
davar 129023 8376525
DMBK 122960 8980062
dsmith 122059 7570238
javran 121564 10144656
CypressChess 120784 8672620
sschnee 120526 7547722
maposora 119734 10749710
amicic 119661 7938029
sschnee 118107 7389266
Wolfgang 114616 8070494
Wolfgang 115713 8159062
Data 113305 8220352
BrunoBanani 112960 7436849
Wencey 111502 5991676
cuistot 108503 7006992
CypressChess 108331 7759788
markkulix 112897 9133168
cuistot 109802 7121030
skiminki 107583 7218170
sterni1971 104431 5938282
MaZePallas 102823 6633619
sterni1971 100532 5880772
sunu 100167 7040199
zeryl 99331 6221261
thirdlife 99156 2245320
ElbertoOne 99028 7023771
Dubslow 98600 6903242
markkulix 97010 7643900
bigpen0r 94809 6529203
megaman7de 98456 6675076
Goatminola 96765 8257832
bigpen0r 94825 6529241
brabos 92118 6186135
Maxim 90818 3283364
psk 89957 5984901
megaman7de 88822 6052132
racerschmacer 85805 6122790
maposora 85710 7778146
Vizvezdenec 83761 5344740
0x3C33 82614 5271253
szupaw 82495 7151686
BRAVONE 81239 5054681
nssy 76497 5259388
cody 76126 4492126
jromang 76106 5236025
MarcusTullius 76103 5061991
woutboat 76072 6022922
Spprtr 75977 5252287
teddybaer 75125 5407666
Pking_cda 73776 5293873
yurikvelo 73516 5036928
MarcusTullius 71053 4803477
yurikvelo 73611 5046822
Mineta 71130 4711422
Bobo1239 70579 4794999
solarlight 70517 5028306
dv8silencer 70287 3883992
Spprtr 69646 4806763
Mineta 66325 4537742
manap 66273 4121774
szupaw 65468 5669742
tinker 64333 4268790
qurashee 61208 3429862
woutboat 59496 4906352
AGI 58195 4329580
robnjr 57262 4053117
Freja 56938 3733019
@@ -108,39 +111,45 @@ MaxKlaxxMiner 56879 3423958
ttruscott 56010 3680085
rkl 55132 4164467
jmdana 54697 4012593
notchris 53936 4184018
renouve 53811 3501516
notchris 52433 4044590
finfish 51360 3370515
eva42 51272 3599691
eastorwest 51117 3454811
Goatminola 51004 4432492
rap 49985 3219146
pb00067 49733 3298934
GPUex 48686 3684998
OuaisBla 48626 3445134
ronaldjerum 47654 3240695
biffhero 46564 3111352
oryx 45533 3539290
oryx 45639 3546530
VoyagerOne 45476 3452465
speedycpu 43842 3003273
jbwiebe 43305 2805433
Antihistamine 41788 2761312
mhunt 41735 2691355
jibarbosa 41640 4145702
homyur 39893 2850481
gri 39871 2515779
DeepnessFulled 39020 3323102
Garf 37741 2999686
SC 37299 2731694
Sylvain27 36520 1467082
Gaster319 37118 3279678
naclosagc 36562 1279618
csnodgrass 36207 2688994
Gaster319 35655 3149442
strelock 34716 2074055
gopeto 33717 2245606
EthanOConnor 33370 2090311
slakovv 32915 2021889
gopeto 31884 2076712
jojo2357 32890 2826662
shawnxu 32019 2802552
Gelma 31771 1551204
vidar808 31560 1351810
kdave 31157 2198362
manapbk 30987 1810399
ZacHFX 30551 2238078
ZacHFX 30966 2272416
TataneSan 30713 1513402
votoanthuan 30691 2460856
Prcuvu 30377 2170122
anst 30301 2190091
jkiiski 30136 1904470
@@ -149,14 +158,15 @@ hyperbolic.tom 29840 2017394
chuckstablers 29659 2093438
Pyafue 29650 1902349
belzedar94 28846 1811530
votoanthuan 27978 2285818
shawnxu 27438 2465810
mecevdimitar 27610 1721382
chriswk 26902 1868317
xwziegtm 26897 2124586
achambord 26582 1767323
somethingintheshadows 26496 2186404
Patrick_G 26276 1801617
yorkman 26193 1992080
Ulysses 25397 1701264
srowen 25743 1490684
Ulysses 25413 1702830
Jopo12321 25227 1652482
SFTUser 25182 1675689
nabildanial 25068 1531665
@@ -164,66 +174,69 @@ Sharaf_DG 24765 1786697
rodneyc 24376 1416402
jsys14 24297 1721230
agg177 23890 1395014
srowen 23842 1342508
AndreasKrug 23754 1890115
Ente 23752 1678188
jojo2357 23479 2061238
JanErik 23408 1703875
Isidor 23388 1680691
Norabor 23371 1603244
WoodMan777 23253 2023048
Nullvalue 23155 2022752
cisco2015 22920 1763301
Zirie 22542 1472937
Nullvalue 22490 1970374
AndreasKrug 22485 1769491
team-oh 22272 1636708
Roady 22220 1465606
MazeOfGalious 21978 1629593
sg4032 21947 1643353
sg4032 21950 1643373
tsim67 21747 1330880
ianh2105 21725 1632562
Skiff84 21711 1014212
xor12 21628 1680365
dex 21612 1467203
nesoneg 21494 1463031
user213718 21454 1404128
Serpensin 21452 1790510
sphinx 21211 1384728
qoo_charly_cai 21135 1514907
qoo_charly_cai 21136 1514927
IslandLambda 21062 1220838
jjoshua2 21001 1423089
Zake9298 20938 1565848
horst.prack 20878 1465656
fishtester 20729 1348888
0xB00B1ES 20590 1208666
Serpensin 20487 1729674
Dinde 20440 1292390
ols 20477 1195945
Dinde 20459 1292774
j3corre 20405 941444
Adrian.Schmidt123 20316 1281436
wei 19973 1745989
fishtester 19617 1257388
teenychess 19819 1762006
rstoesser 19569 1293588
eudhan 19274 1283717
vulcan 18871 1729392
wizardassassin 18795 1376884
Karpovbot 18766 1053178
WoodMan777 18556 1628264
jundery 18445 1115855
mkstockfishtester 18350 1690676
ville 17883 1384026
chris 17698 1487385
purplefishies 17595 1092533
dju 17414 981289
ols 17291 1042003
iisiraider 17275 1049015
Skiff84 17111 950248
DragonLord 17014 1162790
Karby 17008 1013160
pirt 16965 1271519
redstone59 16842 1461780
Karby 16839 1010124
Alb11747 16787 1213990
pirt 16493 1237199
Naven94 16414 951718
wizardassassin 16392 1148672
scuzzi 16115 994341
IgorLeMasson 16064 1147232
scuzzi 15757 968735
ako027ako 15671 1173203
infinigon 15285 965966
Nikolay.IT 15154 1068349
Andrew Grant 15114 895539
OssumOpossum 14857 1007129
LunaticBFF57 14525 1190310
enedene 14476 905279
IslandLambda 14393 958196
Hjax 14394 1005013
bpfliegel 14233 882523
YELNAMRON 14230 1128094
mpx86 14019 759568
@@ -233,54 +246,56 @@ Nesa92 13806 1116101
crocogoat 13803 1117422
joster 13710 946160
mbeier 13650 1044928
Hjax 13535 915487
Pablohn26 13552 1088532
wxt9861 13550 1312306
Dark_wizzie 13422 1007152
Rudolphous 13244 883140
Machariel 13010 863104
infinigon 12991 943216
nalanzeyu 12996 232590
mabichito 12903 749391
Jackfish 12895 868928
thijsk 12886 722107
AdrianSA 12860 804972
Flopzee 12698 894821
whelanh 12682 266404
mschmidt 12644 863193
korposzczur 12606 838168
tsim67 12570 890180
Jackfish 12553 836958
fatmurphy 12547 853210
Oakwen 12503 853105
Oakwen 12532 855759
icewulf 12447 854878
SapphireBrand 12416 969604
deflectooor 12386 579392
modolief 12386 896470
TataneSan 12358 609332
Farseer 12249 694108
Hongildong 12201 648712
pgontarz 12151 848794
dbernier 12103 860824
FormazChar 11989 907809
szczur90 12035 942376
FormazChar 12019 910409
rensonthemove 11999 971993
stocky 11954 699440
somethingintheshadows 11940 989472
MooTheCow 11892 776126
MooTheCow 11923 779432
3cho 11842 1036786
whelanh 11557 245188
ckaz 11792 732276
infinity 11470 727027
aga 11412 695127
torbjo 11395 729145
Thomas A. Anderson 11372 732094
savage84 11358 670860
Def9Infinity 11345 696552
d64 11263 789184
ali-al-zhrani 11245 779246
ckaz 11170 680866
ImperiumAeternum 11155 952000
snicolet 11106 869170
dapper 11032 771402
Ethnikoi 10993 945906
Snuuka 10938 435504
Karmatron 10859 678058
Karmatron 10871 678306
basepi 10637 744851
jibarbosa 10628 857100
Cubox 10621 826448
mecevdimitar 10609 787318
gerbil 10519 971688
michaelrpg 10509 739239
Def9Infinity 10427 686978
OIVAS7572 10420 995586
wxt9861 10412 1013864
Garruk 10365 706465
dzjp 10343 732529
RickGroszkiewicz 10263 990798
+1
View File
@@ -0,0 +1 @@
*.sh text eol=lf
+34 -1
View File
@@ -26,6 +26,17 @@ check_znver_1_2() {
[ "$vendor_id" = "AuthenticAMD" ] && [ "$cpu_family" = "23" ] && znver_1_2=true
}
# Set the file CPU loongarch64 architecture
set_arch_loongarch64() {
if check_flags 'lasx'; then
true_arch='loongarch64-lasx'
elif check_flags 'lsx'; then
true_arch='lonngarch64-lsx'
else
true_arch='loongarch64'
fi
}
# Set the file CPU x86_64 architecture
set_arch_x86_64() {
if check_flags 'avx512vnni' 'avx512dq' 'avx512f' 'avx512bw' 'avx512vl'; then
@@ -43,6 +54,20 @@ set_arch_x86_64() {
fi
}
set_arch_ppc_64() {
if $(grep -q -w "altivec" /proc/cpuinfo); then
power=$(grep -oP -m 1 'cpu\t+: POWER\K\d+' /proc/cpuinfo)
if [ "0$power" -gt 7 ]; then
# VSX started with POWER8
true_arch='ppc-64-vsx'
else
true_arch='ppc-64-altivec'
fi
else
true_arch='ppc-64'
fi
}
# Check the system type
uname_s=$(uname -s)
uname_m=$(uname -m)
@@ -51,7 +76,7 @@ case $uname_s in
case $uname_m in
'arm64')
true_arch='apple-silicon'
file_arch='x86-64-sse41-popcnt' # Supported by Rosetta 2
file_arch='m1-apple-silicon'
;;
'x86_64')
flags=$(sysctl -n machdep.cpu.features machdep.cpu.leaf7_features | tr '\n' ' ' | tr '[:upper:]' '[:lower:]' | tr -d '_.')
@@ -76,6 +101,10 @@ case $uname_s in
file_os='ubuntu'
true_arch='x86-32'
;;
'ppc64'*)
file_os='ubuntu'
set_arch_ppc_64
;;
'aarch64')
file_os='android'
true_arch='armv8'
@@ -90,6 +119,10 @@ case $uname_s in
true_arch="$true_arch-neon"
fi
;;
'loongarch64'*)
file_os='linux'
set_arch_loongarch64
;;
*) # Unsupported machine type, exit with error
printf 'Unsupported machine type: %s\n' "$uname_m"
exit 1
Executable
+75
View File
@@ -0,0 +1,75 @@
#!/bin/sh
wget_or_curl=$( (command -v wget > /dev/null 2>&1 && echo "wget -qO-") || \
(command -v curl > /dev/null 2>&1 && echo "curl -skL"))
if [ -z "$wget_or_curl" ]; then
>&2 printf "%s\n" "Neither wget or curl is installed." \
"Install one of these tools to download NNUE files automatically."
exit 1
fi
sha256sum=$( (command -v shasum > /dev/null 2>&1 && echo "shasum -a 256") || \
(command -v sha256sum > /dev/null 2>&1 && echo "sha256sum"))
if [ -z "$sha256sum" ]; then
>&2 echo "sha256sum not found, NNUE files will be assumed valid."
fi
get_nnue_filename() {
grep "$1" evaluate.h | grep "#define" | sed "s/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/"
}
validate_network() {
# If no sha256sum command is available, assume the file is always valid.
if [ -n "$sha256sum" ] && [ -f "$1" ]; then
if [ "$1" != "nn-$($sha256sum "$1" | cut -c 1-12).nnue" ]; then
rm -f "$1"
return 1
fi
fi
}
fetch_network() {
_filename="$(get_nnue_filename "$1")"
if [ -z "$_filename" ]; then
>&2 echo "NNUE file name not found for: $1"
return 1
fi
if [ -f "$_filename" ]; then
if validate_network "$_filename"; then
echo "Existing $_filename validated, skipping download"
return
else
echo "Removing invalid NNUE file: $_filename"
fi
fi
for url in \
"https://tests.stockfishchess.org/api/nn/$_filename" \
"https://github.com/official-stockfish/networks/raw/master/$_filename"; do
echo "Downloading from $url ..."
if $wget_or_curl "$url" > "$_filename"; then
if validate_network "$_filename"; then
echo "Successfully validated $_filename"
else
echo "Downloaded $_filename is invalid"
continue
fi
else
echo "Failed to download from $url"
fi
if [ -f "$_filename" ]; then
return
fi
done
# Download was not successful in the loop, return false.
>&2 echo "Failed to download $_filename"
return 1
}
fetch_network EvalFileDefaultNameBig && \
fetch_network EvalFileDefaultNameSmall
+212 -193
View File
@@ -1,5 +1,5 @@
# Stockfish, a UCI chess playing engine derived from Glaurung 2.1
# Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
# Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
#
# Stockfish is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -55,15 +55,15 @@ PGOBENCH = $(WINE_PATH) ./$(EXE) bench
SRCS = benchmark.cpp bitboard.cpp evaluate.cpp main.cpp \
misc.cpp movegen.cpp movepick.cpp position.cpp \
search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
nnue/evaluate_nnue.cpp nnue/features/half_ka_v2_hm.cpp
nnue/nnue_misc.cpp nnue/features/half_ka_v2_hm.cpp nnue/network.cpp engine.cpp score.cpp memory.cpp
HEADERS = benchmark.h bitboard.h evaluate.h misc.h movegen.h movepick.h \
nnue/evaluate_nnue.h nnue/features/half_ka_v2_hm.h nnue/layers/affine_transform.h \
HEADERS = benchmark.h bitboard.h evaluate.h misc.h movegen.h movepick.h history.h \
nnue/nnue_misc.h nnue/features/half_ka_v2_hm.h nnue/layers/affine_transform.h \
nnue/layers/affine_transform_sparse_input.h nnue/layers/clipped_relu.h nnue/layers/simd.h \
nnue/layers/sqr_clipped_relu.h nnue/nnue_accumulator.h nnue/nnue_architecture.h \
nnue/nnue_common.h nnue/nnue_feature_transformer.h position.h \
search.h syzygy/tbprobe.h thread.h thread_win32_osx.h timeman.h \
tt.h tune.h types.h uci.h ucioption.h perft.h
tt.h tune.h types.h uci.h ucioption.h perft.h nnue/network.h engine.h score.h numa.h memory.h
OBJS = $(notdir $(SRCS:.cpp=.o))
@@ -98,8 +98,12 @@ VPATH = syzygy:nnue:nnue/features
# avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
# vnni256 = yes/no --- -mavx256vnni --- Use Intel Vector Neural Network Instructions 512 with 256bit operands
# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
# altivec = yes/no --- -maltivec --- Use PowerPC Altivec SIMD extension
# vsx = yes/no --- -mvsx --- Use POWER VSX SIMD extension
# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
# dotprod = yes/no --- -DUSE_NEON_DOTPROD --- Use ARM advanced SIMD Int8 dot product instructions
# lsx = yes/no --- -mlsx --- Use Loongson SIMD eXtension
# lasx = yes/no --- -mlasx --- use Loongson Advanced SIMD eXtension
#
# Note that Makefile is space sensitive, so when adding new architectures
# or modifying existing flags, you have to make sure there are no extra spaces
@@ -124,8 +128,9 @@ endif
ifeq ($(ARCH), $(filter $(ARCH), \
x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-avxvnni x86-64-bmi2 \
x86-64-avx2 x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 e2k \
armv7 armv7-neon armv8 armv8-dotprod apple-silicon general-64 general-32 riscv64 loongarch64))
x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-64-altivec ppc-64-vsx ppc-32 e2k \
armv7 armv7-neon armv8 armv8-dotprod apple-silicon general-64 general-32 riscv64 \
loongarch64 loongarch64-lsx loongarch64-lasx))
SUPPORTED_ARCH=true
else
SUPPORTED_ARCH=false
@@ -148,13 +153,17 @@ avxvnni = no
avx512 = no
vnni256 = no
vnni512 = no
altivec = no
vsx = no
neon = no
dotprod = no
arm_version = 0
lsx = no
lasx = no
STRIP = strip
ifneq ($(shell which clang-format-17 2> /dev/null),)
CLANG-FORMAT = clang-format-17
ifneq ($(shell which clang-format-18 2> /dev/null),)
CLANG-FORMAT = clang-format-18
else
CLANG-FORMAT = clang-format
endif
@@ -355,6 +364,20 @@ ifeq ($(ARCH),ppc-64)
prefetch = yes
endif
ifeq ($(ARCH),ppc-64-altivec)
arch = ppc64
popcnt = yes
prefetch = yes
altivec = yes
endif
ifeq ($(ARCH),ppc-64-vsx)
arch = ppc64
popcnt = yes
prefetch = yes
vsx = yes
endif
ifeq ($(findstring e2k,$(ARCH)),e2k)
arch = e2k
mmx = yes
@@ -370,8 +393,19 @@ ifeq ($(ARCH),riscv64)
arch = riscv64
endif
ifeq ($(ARCH),loongarch64)
ifeq ($(findstring loongarch64,$(ARCH)),loongarch64)
arch = loongarch64
prefetch = yes
ifeq ($(findstring -lasx,$(ARCH)),-lasx)
lsx = yes
lasx = yes
endif
ifeq ($(findstring -lsx,$(ARCH)),-lsx)
lsx = yes
endif
endif
endif
@@ -408,7 +442,7 @@ ifeq ($(COMP),gcc)
ifeq ($(ARCH),riscv64)
CXXFLAGS += -latomic
endif
else ifeq ($(ARCH),loongarch64)
else ifeq ($(arch),loongarch64)
CXXFLAGS += -latomic
else
CXXFLAGS += -m$(bits)
@@ -480,7 +514,7 @@ ifeq ($(COMP),clang)
ifeq ($(ARCH),riscv64)
CXXFLAGS += -latomic
endif
else ifeq ($(ARCH),loongarch64)
else ifeq ($(arch),loongarch64)
CXXFLAGS += -latomic
else
CXXFLAGS += -m$(bits)
@@ -489,8 +523,8 @@ ifeq ($(COMP),clang)
endif
ifeq ($(KERNEL),Darwin)
CXXFLAGS += -mmacosx-version-min=10.14
LDFLAGS += -mmacosx-version-min=10.14
CXXFLAGS += -mmacosx-version-min=10.15
LDFLAGS += -mmacosx-version-min=10.15
ifneq ($(arch),any)
CXXFLAGS += -arch $(arch)
LDFLAGS += -arch $(arch)
@@ -546,11 +580,6 @@ else
endif
endif
### Travis CI script uses COMPILER to overwrite CXX
ifdef COMPILER
COMPCXX=$(COMPILER)
endif
### Allow overwriting CXX from command line
ifdef COMPCXX
CXX=$(COMPCXX)
@@ -639,7 +668,7 @@ else
endif
ifeq ($(popcnt),yes)
ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
ifeq ($(arch),$(filter $(arch),ppc64 ppc64-altivec ppc64-vsx armv7 armv8 arm64))
CXXFLAGS += -DUSE_POPCNT
else
CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT
@@ -709,6 +738,20 @@ ifeq ($(mmx),yes)
endif
endif
ifeq ($(altivec),yes)
CXXFLAGS += -maltivec
ifeq ($(COMP),gcc)
CXXFLAGS += -mabi=altivec
endif
endif
ifeq ($(vsx),yes)
CXXFLAGS += -mvsx
ifeq ($(COMP),gcc)
CXXFLAGS += -DNO_WARN_X86_INTRINSICS -DUSE_SSE2
endif
endif
ifeq ($(neon),yes)
CXXFLAGS += -DUSE_NEON=$(arm_version)
ifeq ($(KERNEL),Linux)
@@ -724,6 +767,18 @@ ifeq ($(dotprod),yes)
CXXFLAGS += -march=armv8.2-a+dotprod -DUSE_NEON_DOTPROD
endif
ifeq ($(lasx),yes)
ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
CXXFLAGS += -mlasx
endif
endif
ifeq ($(lsx),yes)
ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
CXXFLAGS += -mlsx
endif
endif
### 3.7 pext
ifeq ($(pext),yes)
CXXFLAGS += -DUSE_PEXT
@@ -796,71 +851,75 @@ endif
### ==========================================================================
help:
@echo ""
@echo "To compile stockfish, type: "
@echo ""
@echo "make -j target [ARCH=arch] [COMP=compiler] [COMPCXX=cxx]"
@echo ""
@echo "Supported targets:"
@echo ""
@echo "help > Display architecture details"
@echo "profile-build > standard build with profile-guided optimization"
@echo "build > skip profile-guided optimization"
@echo "net > Download the default nnue nets"
@echo "strip > Strip executable"
@echo "install > Install executable"
@echo "clean > Clean up"
@echo ""
@echo "Supported archs:"
@echo ""
@echo "native > select the best architecture for the host processor (default)"
@echo "x86-64-vnni512 > x86 64-bit with vnni 512bit support"
@echo "x86-64-vnni256 > x86 64-bit with vnni 512bit support, limit operands to 256bit wide"
@echo "x86-64-avx512 > x86 64-bit with avx512 support"
@echo "x86-64-avxvnni > x86 64-bit with vnni 256bit support"
@echo "x86-64-bmi2 > x86 64-bit with bmi2 support"
@echo "x86-64-avx2 > x86 64-bit with avx2 support"
@echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support"
@echo "x86-64-modern > deprecated, currently x86-64-sse41-popcnt"
@echo "x86-64-ssse3 > x86 64-bit with ssse3 support"
@echo "x86-64-sse3-popcnt > x86 64-bit with sse3 compile and popcnt support"
@echo "x86-64 > x86 64-bit generic (with sse2 support)"
@echo "x86-32-sse41-popcnt > x86 32-bit with sse41 and popcnt support"
@echo "x86-32-sse2 > x86 32-bit with sse2 support"
@echo "x86-32 > x86 32-bit generic (with mmx compile support)"
@echo "ppc-64 > PPC 64-bit"
@echo "ppc-32 > PPC 32-bit"
@echo "armv7 > ARMv7 32-bit"
@echo "armv7-neon > ARMv7 32-bit with popcnt and neon"
@echo "armv8 > ARMv8 64-bit with popcnt and neon"
@echo "armv8-dotprod > ARMv8 64-bit with popcnt, neon and dot product support"
@echo "e2k > Elbrus 2000"
@echo "apple-silicon > Apple silicon ARM64"
@echo "general-64 > unspecified 64-bit"
@echo "general-32 > unspecified 32-bit"
@echo "riscv64 > RISC-V 64-bit"
@echo "loongarch64 > LoongArch 64-bit"
@echo ""
@echo "Supported compilers:"
@echo ""
@echo "gcc > GNU compiler (default)"
@echo "mingw > GNU compiler with MinGW under Windows"
@echo "clang > LLVM Clang compiler"
@echo "icx > Intel oneAPI DPC++/C++ Compiler"
@echo "ndk > Google NDK to cross-compile for Android"
@echo ""
@echo "Simple examples. If you don't know what to do, you likely want to run one of: "
@echo ""
@echo "make -j profile-build ARCH=x86-64-avx2 # typically a fast compile for common systems "
@echo "make -j profile-build ARCH=x86-64-sse41-popcnt # A more portable compile for 64-bit systems "
@echo "make -j profile-build ARCH=x86-64 # A portable compile for 64-bit systems "
@echo ""
@echo "Advanced examples, for experienced users: "
@echo ""
@echo "make -j profile-build ARCH=x86-64-avxvnni"
@echo "make -j profile-build ARCH=x86-64-avxvnni COMP=gcc COMPCXX=g++-12.0"
@echo "make -j build ARCH=x86-64-ssse3 COMP=clang"
@echo ""
@echo "" && \
echo "To compile stockfish, type: " && \
echo "" && \
echo "make -j target [ARCH=arch] [COMP=compiler] [COMPCXX=cxx]" && \
echo "" && \
echo "Supported targets:" && \
echo "" && \
echo "help > Display architecture details" && \
echo "profile-build > standard build with profile-guided optimization" && \
echo "build > skip profile-guided optimization" && \
echo "net > Download the default nnue nets" && \
echo "strip > Strip executable" && \
echo "install > Install executable" && \
echo "clean > Clean up" && \
echo "" && \
echo "Supported archs:" && \
echo "" && \
echo "native > select the best architecture for the host processor (default)" && \
echo "x86-64-vnni512 > x86 64-bit with vnni 512bit support" && \
echo "x86-64-vnni256 > x86 64-bit with vnni 512bit support, limit operands to 256bit wide" && \
echo "x86-64-avx512 > x86 64-bit with avx512 support" && \
echo "x86-64-avxvnni > x86 64-bit with vnni 256bit support" && \
echo "x86-64-bmi2 > x86 64-bit with bmi2 support" && \
echo "x86-64-avx2 > x86 64-bit with avx2 support" && \
echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support" && \
echo "x86-64-modern > deprecated, currently x86-64-sse41-popcnt" && \
echo "x86-64-ssse3 > x86 64-bit with ssse3 support" && \
echo "x86-64-sse3-popcnt > x86 64-bit with sse3 compile and popcnt support" && \
echo "x86-64 > x86 64-bit generic (with sse2 support)" && \
echo "x86-32-sse41-popcnt > x86 32-bit with sse41 and popcnt support" && \
echo "x86-32-sse2 > x86 32-bit with sse2 support" && \
echo "x86-32 > x86 32-bit generic (with mmx compile support)" && \
echo "ppc-64 > PPC 64-bit" && \
echo "ppc-64-altivec > PPC 64-bit with altivec support" && \
echo "ppc-64-vsx > PPC 64-bit with vsx support" && \
echo "ppc-32 > PPC 32-bit" && \
echo "armv7 > ARMv7 32-bit" && \
echo "armv7-neon > ARMv7 32-bit with popcnt and neon" && \
echo "armv8 > ARMv8 64-bit with popcnt and neon" && \
echo "armv8-dotprod > ARMv8 64-bit with popcnt, neon and dot product support" && \
echo "e2k > Elbrus 2000" && \
echo "apple-silicon > Apple silicon ARM64" && \
echo "general-64 > unspecified 64-bit" && \
echo "general-32 > unspecified 32-bit" && \
echo "riscv64 > RISC-V 64-bit" && \
echo "loongarch64 > LoongArch 64-bit" && \
echo "loongarch64-lsx > LoongArch 64-bit with SIMD eXtension" && \
echo "loongarch64-lasx > LoongArch 64-bit with Advanced SIMD eXtension" && \
echo "" && \
echo "Supported compilers:" && \
echo "" && \
echo "gcc > GNU compiler (default)" && \
echo "mingw > GNU compiler with MinGW under Windows" && \
echo "clang > LLVM Clang compiler" && \
echo "icx > Intel oneAPI DPC++/C++ Compiler" && \
echo "ndk > Google NDK to cross-compile for Android" && \
echo "" && \
echo "Simple examples. If you don't know what to do, you likely want to run one of: " && \
echo "" && \
echo "make -j profile-build ARCH=x86-64-avx2 # typically a fast compile for common systems " && \
echo "make -j profile-build ARCH=x86-64-sse41-popcnt # A more portable compile for 64-bit systems " && \
echo "make -j profile-build ARCH=x86-64 # A portable compile for 64-bit systems " && \
echo "" && \
echo "Advanced examples, for experienced users: " && \
echo "" && \
echo "make -j profile-build ARCH=x86-64-avxvnni" && \
echo "make -j profile-build ARCH=x86-64-avxvnni COMP=gcc COMPCXX=g++-12.0" && \
echo "make -j build ARCH=x86-64-ssse3 COMP=clang" && \
echo ""
ifneq ($(SUPPORTED_ARCH), true)
@echo "Specify a supported architecture with the ARCH option for more details"
@echo ""
@@ -922,59 +981,9 @@ profileclean:
@rm -f stockfish.res
@rm -f ./-lstdc++.res
define fetch_network
@echo "Default net: $(nnuenet)"
@if [ "x$(curl_or_wget)" = "x" ]; then \
echo "Neither curl nor wget is installed. Install one of these tools unless the net has been downloaded manually"; \
fi
@if [ "x$(shasum_command)" = "x" ]; then \
echo "shasum / sha256sum not found, skipping net validation"; \
elif test -f "$(nnuenet)"; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Removing invalid network"; rm -f $(nnuenet); \
fi; \
fi;
@for nnuedownloadurl in "$(nnuedownloadurl1)" "$(nnuedownloadurl2)"; do \
if test -f "$(nnuenet)"; then \
echo "$(nnuenet) available : OK"; break; \
else \
if [ "x$(curl_or_wget)" != "x" ]; then \
echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\
else \
echo "No net found and download not possible"; exit 1;\
fi; \
fi; \
if [ "x$(shasum_command)" != "x" ]; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Removing failed download"; rm -f $(nnuenet); \
fi; \
fi; \
done
@if ! test -f "$(nnuenet)"; then \
echo "Failed to download $(nnuenet)."; \
fi;
@if [ "x$(shasum_command)" != "x" ]; then \
if [ "$(nnuenet)" = "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Network validated"; break; \
fi; \
fi;
endef
# set up shell variables for the net stuff
define netvariables
$(eval nnuenet := $(shell grep $(1) evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
$(eval nnuedownloadurl1 := https://tests.stockfishchess.org/api/nn/$(nnuenet))
$(eval nnuedownloadurl2 := https://github.com/official-stockfish/networks/raw/master/$(nnuenet))
$(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
$(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi))
endef
# evaluation network (nnue)
net:
$(call netvariables, EvalFileDefaultNameBig)
$(call fetch_network)
$(call netvariables, EvalFileDefaultNameSmall)
$(call fetch_network)
@$(SHELL) ../scripts/net.sh
format:
$(CLANG-FORMAT) -i $(SRCS) $(HEADERS) -style=file
@@ -991,61 +1000,71 @@ all: $(EXE) .depend
config-sanity: net
@echo ""
@echo "Config:"
@echo "debug: '$(debug)'"
@echo "sanitize: '$(sanitize)'"
@echo "optimize: '$(optimize)'"
@echo "arch: '$(arch)'"
@echo "bits: '$(bits)'"
@echo "kernel: '$(KERNEL)'"
@echo "os: '$(OS)'"
@echo "prefetch: '$(prefetch)'"
@echo "popcnt: '$(popcnt)'"
@echo "pext: '$(pext)'"
@echo "sse: '$(sse)'"
@echo "mmx: '$(mmx)'"
@echo "sse2: '$(sse2)'"
@echo "ssse3: '$(ssse3)'"
@echo "sse41: '$(sse41)'"
@echo "avx2: '$(avx2)'"
@echo "avxvnni: '$(avxvnni)'"
@echo "avx512: '$(avx512)'"
@echo "vnni256: '$(vnni256)'"
@echo "vnni512: '$(vnni512)'"
@echo "neon: '$(neon)'"
@echo "dotprod: '$(dotprod)'"
@echo "arm_version: '$(arm_version)'"
@echo "target_windows: '$(target_windows)'"
@echo ""
@echo "Flags:"
@echo "CXX: $(CXX)"
@echo "CXXFLAGS: $(CXXFLAGS)"
@echo "LDFLAGS: $(LDFLAGS)"
@echo ""
@echo "Testing config sanity. If this fails, try 'make help' ..."
@echo ""
@test "$(debug)" = "yes" || test "$(debug)" = "no"
@test "$(optimize)" = "yes" || test "$(optimize)" = "no"
@test "$(SUPPORTED_ARCH)" = "true"
@test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
@echo "Config:" && \
echo "debug: '$(debug)'" && \
echo "sanitize: '$(sanitize)'" && \
echo "optimize: '$(optimize)'" && \
echo "arch: '$(arch)'" && \
echo "bits: '$(bits)'" && \
echo "kernel: '$(KERNEL)'" && \
echo "os: '$(OS)'" && \
echo "prefetch: '$(prefetch)'" && \
echo "popcnt: '$(popcnt)'" && \
echo "pext: '$(pext)'" && \
echo "sse: '$(sse)'" && \
echo "mmx: '$(mmx)'" && \
echo "sse2: '$(sse2)'" && \
echo "ssse3: '$(ssse3)'" && \
echo "sse41: '$(sse41)'" && \
echo "avx2: '$(avx2)'" && \
echo "avxvnni: '$(avxvnni)'" && \
echo "avx512: '$(avx512)'" && \
echo "vnni256: '$(vnni256)'" && \
echo "vnni512: '$(vnni512)'" && \
echo "altivec: '$(altivec)'" && \
echo "vsx: '$(vsx)'" && \
echo "neon: '$(neon)'" && \
echo "dotprod: '$(dotprod)'" && \
echo "arm_version: '$(arm_version)'" && \
echo "lsx: '$(lsx)'" && \
echo "lasx: '$(lasx)'" && \
echo "target_windows: '$(target_windows)'" && \
echo "" && \
echo "Flags:" && \
echo "CXX: $(CXX)" && \
echo "CXXFLAGS: $(CXXFLAGS)" && \
echo "LDFLAGS: $(LDFLAGS)" && \
echo "" && \
echo "Testing config sanity. If this fails, try 'make help' ..." && \
echo "" && \
(test "$(debug)" = "yes" || test "$(debug)" = "no") && \
(test "$(optimize)" = "yes" || test "$(optimize)" = "no") && \
(test "$(SUPPORTED_ARCH)" = "true") && \
(test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "e2k" || \
test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" || test "$(arch)" = "riscv64" || test "$(arch)" = "loongarch64"
@test "$(bits)" = "32" || test "$(bits)" = "64"
@test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
@test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
@test "$(pext)" = "yes" || test "$(pext)" = "no"
@test "$(sse)" = "yes" || test "$(sse)" = "no"
@test "$(mmx)" = "yes" || test "$(mmx)" = "no"
@test "$(sse2)" = "yes" || test "$(sse2)" = "no"
@test "$(ssse3)" = "yes" || test "$(ssse3)" = "no"
@test "$(sse41)" = "yes" || test "$(sse41)" = "no"
@test "$(avx2)" = "yes" || test "$(avx2)" = "no"
@test "$(avx512)" = "yes" || test "$(avx512)" = "no"
@test "$(vnni256)" = "yes" || test "$(vnni256)" = "no"
@test "$(vnni512)" = "yes" || test "$(vnni512)" = "no"
@test "$(neon)" = "yes" || test "$(neon)" = "no"
@test "$(comp)" = "gcc" || test "$(comp)" = "icx" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \
|| test "$(comp)" = "armv7a-linux-androideabi16-clang" || test "$(comp)" = "aarch64-linux-android21-clang"
test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" || \
test "$(arch)" = "riscv64" || test "$(arch)" = "loongarch64") && \
(test "$(bits)" = "32" || test "$(bits)" = "64") && \
(test "$(prefetch)" = "yes" || test "$(prefetch)" = "no") && \
(test "$(popcnt)" = "yes" || test "$(popcnt)" = "no") && \
(test "$(pext)" = "yes" || test "$(pext)" = "no") && \
(test "$(sse)" = "yes" || test "$(sse)" = "no") && \
(test "$(mmx)" = "yes" || test "$(mmx)" = "no") && \
(test "$(sse2)" = "yes" || test "$(sse2)" = "no") && \
(test "$(ssse3)" = "yes" || test "$(ssse3)" = "no") && \
(test "$(sse41)" = "yes" || test "$(sse41)" = "no") && \
(test "$(avx2)" = "yes" || test "$(avx2)" = "no") && \
(test "$(avx512)" = "yes" || test "$(avx512)" = "no") && \
(test "$(vnni256)" = "yes" || test "$(vnni256)" = "no") && \
(test "$(vnni512)" = "yes" || test "$(vnni512)" = "no") && \
(test "$(altivec)" = "yes" || test "$(altivec)" = "no") && \
(test "$(vsx)" = "yes" || test "$(vsx)" = "no") && \
(test "$(neon)" = "yes" || test "$(neon)" = "no") && \
(test "$(lsx)" = "yes" || test "$(lsx)" = "no") && \
(test "$(lasx)" = "yes" || test "$(lasx)" = "no") && \
(test "$(comp)" = "gcc" || test "$(comp)" = "icx" || test "$(comp)" = "mingw" || \
test "$(comp)" = "clang" || test "$(comp)" = "armv7a-linux-androideabi16-clang" || \
test "$(comp)" = "aarch64-linux-android21-clang")
$(EXE): $(OBJS)
+$(CXX) -o $@ $(OBJS) $(LDFLAGS)
@@ -1056,14 +1075,14 @@ FORCE:
clang-profile-make:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-instr-generate ' \
EXTRALDFLAGS=' -fprofile-instr-generate' \
EXTRACXXFLAGS='-fprofile-generate ' \
EXTRALDFLAGS=' -fprofile-generate' \
all
clang-profile-use:
$(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-instr-use=stockfish.profdata' \
EXTRACXXFLAGS='-fprofile-use=stockfish.profdata' \
EXTRALDFLAGS='-fprofile-use ' \
all
+353 -6
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,14 +17,13 @@
*/
#include "benchmark.h"
#include "numa.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <vector>
#include "position.h"
namespace {
// clang-format off
@@ -93,9 +92,285 @@ const std::vector<std::string> Defaults = {
};
// clang-format on
// clang-format off
// human-randomly picked 5 games with <60 moves from
// https://tests.stockfishchess.org/tests/view/665c71f9fd45fb0f907c21e0
// only moves for one side
const std::vector<std::vector<std::string>> BenchmarkPositions = {
{
"rnbq1k1r/ppp1bppp/4pn2/8/2B5/2NP1N2/PPP2PPP/R1BQR1K1 b - - 2 8",
"rnbq1k1r/pp2bppp/4pn2/2p5/2B2B2/2NP1N2/PPP2PPP/R2QR1K1 b - - 1 9",
"r1bq1k1r/pp2bppp/2n1pn2/2p5/2B1NB2/3P1N2/PPP2PPP/R2QR1K1 b - - 3 10",
"r1bq1k1r/pp2bppp/2n1p3/2p5/2B1PB2/5N2/PPP2PPP/R2QR1K1 b - - 0 11",
"r1b2k1r/pp2bppp/2n1p3/2p5/2B1PB2/5N2/PPP2PPP/3RR1K1 b - - 0 12",
"r1b1k2r/pp2bppp/2n1p3/2p5/2B1PB2/2P2N2/PP3PPP/3RR1K1 b - - 0 13",
"r1b1k2r/1p2bppp/p1n1p3/2p5/4PB2/2P2N2/PP2BPPP/3RR1K1 b - - 1 14",
"r1b1k2r/4bppp/p1n1p3/1pp5/P3PB2/2P2N2/1P2BPPP/3RR1K1 b - - 0 15",
"r1b1k2r/4bppp/p1n1p3/1P6/2p1PB2/2P2N2/1P2BPPP/3RR1K1 b - - 0 16",
"r1b1k2r/4bppp/2n1p3/1p6/2p1PB2/1PP2N2/4BPPP/3RR1K1 b - - 0 17",
"r3k2r/3bbppp/2n1p3/1p6/2P1PB2/2P2N2/4BPPP/3RR1K1 b - - 0 18",
"r3k2r/3bbppp/2n1p3/8/1pP1P3/2P2N2/3BBPPP/3RR1K1 b - - 1 19",
"1r2k2r/3bbppp/2n1p3/8/1pPNP3/2P5/3BBPPP/3RR1K1 b - - 3 20",
"1r2k2r/3bbppp/2n1p3/8/2PNP3/2B5/4BPPP/3RR1K1 b - - 0 21",
"1r2k2r/3bb1pp/2n1pp2/1N6/2P1P3/2B5/4BPPP/3RR1K1 b - - 1 22",
"1r2k2r/3b2pp/2n1pp2/1N6/1BP1P3/8/4BPPP/3RR1K1 b - - 0 23",
"1r2k2r/3b2pp/4pp2/1N6/1nP1P3/8/3RBPPP/4R1K1 b - - 1 24",
"1r5r/3bk1pp/4pp2/1N6/1nP1PP2/8/3RB1PP/4R1K1 b - - 0 25",
"1r5r/3bk1pp/2n1pp2/1N6/2P1PP2/8/3RBKPP/4R3 b - - 2 26",
"1r5r/3bk1pp/2n2p2/1N2p3/2P1PP2/6P1/3RBK1P/4R3 b - - 0 27",
"1r1r4/3bk1pp/2n2p2/1N2p3/2P1PP2/6P1/3RBK1P/R7 b - - 2 28",
"1r1r4/N3k1pp/2n1bp2/4p3/2P1PP2/6P1/3RBK1P/R7 b - - 4 29",
"1r1r4/3bk1pp/2N2p2/4p3/2P1PP2/6P1/3RBK1P/R7 b - - 0 30",
"1r1R4/4k1pp/2b2p2/4p3/2P1PP2/6P1/4BK1P/R7 b - - 0 31",
"3r4/4k1pp/2b2p2/4P3/2P1P3/6P1/4BK1P/R7 b - - 0 32",
"3r4/R3k1pp/2b5/4p3/2P1P3/6P1/4BK1P/8 b - - 1 33",
"8/3rk1pp/2b5/R3p3/2P1P3/6P1/4BK1P/8 b - - 3 34",
"8/3r2pp/2bk4/R1P1p3/4P3/6P1/4BK1P/8 b - - 0 35",
"8/2kr2pp/2b5/R1P1p3/4P3/4K1P1/4B2P/8 b - - 2 36",
"1k6/3r2pp/2b5/RBP1p3/4P3/4K1P1/7P/8 b - - 4 37",
"8/1k1r2pp/2b5/R1P1p3/4P3/3BK1P1/7P/8 b - - 6 38",
"1k6/3r2pp/2b5/2P1p3/4P3/3BK1P1/7P/R7 b - - 8 39",
"1k6/r5pp/2b5/2P1p3/4P3/3BK1P1/7P/5R2 b - - 10 40",
"1k3R2/6pp/2b5/2P1p3/4P3/r2BK1P1/7P/8 b - - 12 41",
"5R2/2k3pp/2b5/2P1p3/4P3/r2B2P1/3K3P/8 b - - 14 42",
"5R2/2k3pp/2b5/2P1p3/4P3/3BK1P1/r6P/8 b - - 16 43",
"5R2/2k3pp/2b5/2P1p3/4P3/r2B2P1/4K2P/8 b - - 18 44",
"5R2/2k3pp/2b5/2P1p3/4P3/3B1KP1/r6P/8 b - - 20 45",
"8/2k2Rpp/2b5/2P1p3/4P3/r2B1KP1/7P/8 b - - 22 46",
"3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/4K2P/8 b - - 24 47",
"3k4/5Rpp/2b5/2P1p3/4P3/3B1KP1/r6P/8 b - - 26 48",
"3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/4K2P/8 b - - 28 49",
"3k4/5Rpp/2b5/2P1p3/4P3/3BK1P1/r6P/8 b - - 30 50",
"3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/3K3P/8 b - - 32 51",
"3k4/5Rpp/2b5/2P1p3/4P3/2KB2P1/r6P/8 b - - 34 52",
"3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/2K4P/8 b - - 36 53",
"3k4/5Rpp/2b5/2P1p3/4P3/1K1B2P1/r6P/8 b - - 38 54",
"3k4/6Rp/2b5/2P1p3/4P3/1K1B2P1/7r/8 b - - 0 55",
"3k4/8/2b3Rp/2P1p3/4P3/1K1B2P1/7r/8 b - - 1 56",
"8/2k3R1/2b4p/2P1p3/4P3/1K1B2P1/7r/8 b - - 3 57",
"3k4/8/2b3Rp/2P1p3/4P3/1K1B2P1/7r/8 b - - 5 58",
"8/2k5/2b3Rp/2P1p3/1K2P3/3B2P1/7r/8 b - - 7 59",
"8/2k5/2b3Rp/2P1p3/4P3/2KB2P1/3r4/8 b - - 9 60",
"8/2k5/2b3Rp/2P1p3/1K2P3/3B2P1/6r1/8 b - - 11 61",
"8/2k5/2b3Rp/2P1p3/4P3/2KB2P1/3r4/8 b - - 13 62",
"8/2k5/2b3Rp/2P1p3/2K1P3/3B2P1/6r1/8 b - - 15 63",
"4b3/2k3R1/7p/2P1p3/2K1P3/3B2P1/6r1/8 b - - 17 64",
},
{
"r1bqkbnr/npp1pppp/p7/3P4/4pB2/2N5/PPP2PPP/R2QKBNR w KQkq - 1 6",
"r1bqkb1r/npp1pppp/p4n2/3P4/4pB2/2N5/PPP1QPPP/R3KBNR w KQkq - 3 7",
"r2qkb1r/npp1pppp/p4n2/3P1b2/4pB2/2N5/PPP1QPPP/2KR1BNR w kq - 5 8",
"r2qkb1r/1pp1pppp/p4n2/1n1P1b2/4pB2/2N4P/PPP1QPP1/2KR1BNR w kq - 1 9",
"r2qkb1r/1pp1pppp/5n2/1p1P1b2/4pB2/7P/PPP1QPP1/2KR1BNR w kq - 0 10",
"r2qkb1r/1ppbpppp/5n2/1Q1P4/4pB2/7P/PPP2PP1/2KR1BNR w kq - 1 11",
"3qkb1r/1Qpbpppp/5n2/3P4/4pB2/7P/rPP2PP1/2KR1BNR w k - 0 12",
"q3kb1r/1Qpbpppp/5n2/3P4/4pB2/7P/rPP2PP1/1K1R1BNR w k - 2 13",
"r3kb1r/2pbpppp/5n2/3P4/4pB2/7P/1PP2PP1/1K1R1BNR w k - 0 14",
"r3kb1r/2Bb1ppp/4pn2/3P4/4p3/7P/1PP2PP1/1K1R1BNR w k - 0 15",
"r3kb1r/2Bb2pp/4pn2/8/4p3/7P/1PP2PP1/1K1R1BNR w k - 0 16",
"r3k2r/2Bb2pp/4pn2/2b5/4p3/7P/1PP1NPP1/1K1R1B1R w k - 2 17",
"r6r/2Bbk1pp/4pn2/2b5/3Np3/7P/1PP2PP1/1K1R1B1R w - - 4 18",
"r6r/b2bk1pp/4pn2/4B3/3Np3/7P/1PP2PP1/1K1R1B1R w - - 6 19",
"r1r5/b2bk1pp/4pn2/4B3/2BNp3/7P/1PP2PP1/1K1R3R w - - 8 20",
"r7/b2bk1pp/4pn2/2r1B3/2BNp3/1P5P/2P2PP1/1K1R3R w - - 1 21",
"rb6/3bk1pp/4pn2/2r1B3/2BNpP2/1P5P/2P3P1/1K1R3R w - - 1 22",
"1r6/3bk1pp/4pn2/2r5/2BNpP2/1P5P/2P3P1/1K1R3R w - - 0 23",
"1r6/3bk1p1/4pn1p/2r5/2BNpP2/1P5P/2P3P1/2KR3R w - - 0 24",
"8/3bk1p1/1r2pn1p/2r5/2BNpP1P/1P6/2P3P1/2KR3R w - - 1 25",
"8/3bk3/1r2pnpp/2r5/2BNpP1P/1P6/2P3P1/2K1R2R w - - 0 26",
"2b5/4k3/1r2pnpp/2r5/2BNpP1P/1P4P1/2P5/2K1R2R w - - 1 27",
"8/1b2k3/1r2pnpp/2r5/2BNpP1P/1P4P1/2P5/2K1R1R1 w - - 3 28",
"8/1b1nk3/1r2p1pp/2r5/2BNpPPP/1P6/2P5/2K1R1R1 w - - 1 29",
"8/1b2k3/1r2p1pp/2r1nP2/2BNp1PP/1P6/2P5/2K1R1R1 w - - 1 30",
"8/1b2k3/1r2p1p1/2r1nPp1/2BNp2P/1P6/2P5/2K1R1R1 w - - 0 31",
"8/1b2k3/1r2p1n1/2r3p1/2BNp2P/1P6/2P5/2K1R1R1 w - - 0 32",
"8/1b2k3/1r2p1n1/6r1/2BNp2P/1P6/2P5/2K1R3 w - - 0 33",
"8/1b2k3/1r2p3/4n1P1/2BNp3/1P6/2P5/2K1R3 w - - 1 34",
"8/1b2k3/1r2p3/4n1P1/2BN4/1P2p3/2P5/2K4R w - - 0 35",
"8/1b2k3/1r2p2R/6P1/2nN4/1P2p3/2P5/2K5 w - - 0 36",
"8/1b2k3/3rp2R/6P1/2PN4/4p3/2P5/2K5 w - - 1 37",
"8/4k3/3rp2R/6P1/2PN4/2P1p3/6b1/2K5 w - - 1 38",
"8/4k3/r3p2R/2P3P1/3N4/2P1p3/6b1/2K5 w - - 1 39",
"8/3k4/r3p2R/2P2NP1/8/2P1p3/6b1/2K5 w - - 3 40",
"8/3k4/4p2R/2P3P1/8/2P1N3/6b1/r1K5 w - - 1 41",
"8/3k4/4p2R/2P3P1/8/2P1N3/3K2b1/6r1 w - - 3 42",
"8/3k4/4p2R/2P3P1/8/2PKNb2/8/6r1 w - - 5 43",
"8/4k3/4p1R1/2P3P1/8/2PKNb2/8/6r1 w - - 7 44",
"8/4k3/4p1R1/2P3P1/3K4/2P1N3/8/6rb w - - 9 45",
"8/3k4/4p1R1/2P1K1P1/8/2P1N3/8/6rb w - - 11 46",
"8/3k4/4p1R1/2P3P1/5K2/2P1N3/8/4r2b w - - 13 47",
"8/3k4/2b1p2R/2P3P1/5K2/2P1N3/8/4r3 w - - 15 48",
"8/3k4/2b1p3/2P3P1/5K2/2P1N2R/8/6r1 w - - 17 49",
"2k5/7R/2b1p3/2P3P1/5K2/2P1N3/8/6r1 w - - 19 50",
"2k5/7R/4p3/2P3P1/b1P2K2/4N3/8/6r1 w - - 1 51",
"2k5/3bR3/4p3/2P3P1/2P2K2/4N3/8/6r1 w - - 3 52",
"3k4/3b2R1/4p3/2P3P1/2P2K2/4N3/8/6r1 w - - 5 53",
"3kb3/6R1/4p1P1/2P5/2P2K2/4N3/8/6r1 w - - 1 54",
"3kb3/6R1/4p1P1/2P5/2P2KN1/8/8/2r5 w - - 3 55",
"3kb3/6R1/4p1P1/2P1N3/2P2K2/8/8/5r2 w - - 5 56",
"3kb3/6R1/4p1P1/2P1N3/2P5/4K3/8/4r3 w - - 7 57",
},
{
"rnbq1rk1/ppp1npb1/4p1p1/3P3p/3PP3/2N2N2/PP2BPPP/R1BQ1RK1 b - - 0 8",
"rnbq1rk1/ppp1npb1/6p1/3pP2p/3P4/2N2N2/PP2BPPP/R1BQ1RK1 b - - 0 9",
"rn1q1rk1/ppp1npb1/6p1/3pP2p/3P2b1/2N2N2/PP2BPPP/R1BQR1K1 b - - 2 10",
"r2q1rk1/ppp1npb1/2n3p1/3pP2p/3P2bN/2N5/PP2BPPP/R1BQR1K1 b - - 4 11",
"r4rk1/pppqnpb1/2n3p1/3pP2p/3P2bN/2N4P/PP2BPP1/R1BQR1K1 b - - 0 12",
"r4rk1/pppqnpb1/2n3p1/3pP2p/3P3N/7P/PP2NPP1/R1BQR1K1 b - - 0 13",
"r4rk1/pppq1pb1/2n3p1/3pPN1p/3P4/7P/PP2NPP1/R1BQR1K1 b - - 0 14",
"r4rk1/ppp2pb1/2n3p1/3pPq1p/3P1N2/7P/PP3PP1/R1BQR1K1 b - - 1 15",
"r4rk1/pppq1pb1/2n3p1/3pP2p/P2P1N2/7P/1P3PP1/R1BQR1K1 b - - 0 16",
"r2n1rk1/pppq1pb1/6p1/3pP2p/P2P1N2/R6P/1P3PP1/2BQR1K1 b - - 2 17",
"r4rk1/pppq1pb1/4N1p1/3pP2p/P2P4/R6P/1P3PP1/2BQR1K1 b - - 0 18",
"r4rk1/ppp2pb1/4q1p1/3pP1Bp/P2P4/R6P/1P3PP1/3QR1K1 b - - 1 19",
"r3r1k1/ppp2pb1/4q1p1/3pP1Bp/P2P1P2/R6P/1P4P1/3QR1K1 b - - 0 20",
"r3r1k1/ppp3b1/4qpp1/3pP2p/P2P1P1B/R6P/1P4P1/3QR1K1 b - - 1 21",
"r3r1k1/ppp3b1/4q1p1/3pP2p/P4P1B/R6P/1P4P1/3QR1K1 b - - 0 22",
"r4rk1/ppp3b1/4q1p1/3pP1Bp/P4P2/R6P/1P4P1/3QR1K1 b - - 2 23",
"r4rk1/pp4b1/4q1p1/2ppP1Bp/P4P2/3R3P/1P4P1/3QR1K1 b - - 1 24",
"r4rk1/pp4b1/4q1p1/2p1P1Bp/P2p1PP1/3R3P/1P6/3QR1K1 b - - 0 25",
"r4rk1/pp4b1/4q1p1/2p1P1B1/P2p1PP1/3R4/1P6/3QR1K1 b - - 0 26",
"r5k1/pp3rb1/4q1p1/2p1P1B1/P2p1PP1/6R1/1P6/3QR1K1 b - - 2 27",
"5rk1/pp3rb1/4q1p1/2p1P1B1/P2pRPP1/6R1/1P6/3Q2K1 b - - 4 28",
"5rk1/1p3rb1/p3q1p1/P1p1P1B1/3pRPP1/6R1/1P6/3Q2K1 b - - 0 29",
"4r1k1/1p3rb1/p3q1p1/P1p1P1B1/3pRPP1/1P4R1/8/3Q2K1 b - - 0 30",
"4r1k1/5rb1/pP2q1p1/2p1P1B1/3pRPP1/1P4R1/8/3Q2K1 b - - 0 31",
"4r1k1/5rb1/pq4p1/2p1P1B1/3pRPP1/1P4R1/4Q3/6K1 b - - 1 32",
"4r1k1/1r4b1/pq4p1/2p1P1B1/3pRPP1/1P4R1/2Q5/6K1 b - - 3 33",
"4r1k1/1r4b1/1q4p1/p1p1P1B1/3p1PP1/1P4R1/2Q5/4R1K1 b - - 1 34",
"4r1k1/3r2b1/1q4p1/p1p1P1B1/2Qp1PP1/1P4R1/8/4R1K1 b - - 3 35",
"4r1k1/3r2b1/4q1p1/p1p1P1B1/2Qp1PP1/1P4R1/5K2/4R3 b - - 5 36",
"4r1k1/3r2b1/6p1/p1p1P1B1/2Pp1PP1/6R1/5K2/4R3 b - - 0 37",
"4r1k1/3r2b1/6p1/p1p1P1B1/2P2PP1/3p2R1/5K2/3R4 b - - 1 38",
"5rk1/3r2b1/6p1/p1p1P1B1/2P2PP1/3p2R1/8/3RK3 b - - 3 39",
"5rk1/6b1/6p1/p1p1P1B1/2Pr1PP1/3R4/8/3RK3 b - - 0 40",
"5rk1/3R2b1/6p1/p1p1P1B1/2r2PP1/8/8/3RK3 b - - 1 41",
"5rk1/3R2b1/6p1/p1p1P1B1/4rPP1/8/3K4/3R4 b - - 3 42",
"1r4k1/3R2b1/6p1/p1p1P1B1/4rPP1/2K5/8/3R4 b - - 5 43",
"1r4k1/3R2b1/6p1/p1p1P1B1/2K2PP1/4r3/8/3R4 b - - 7 44",
"1r3bk1/8/3R2p1/p1p1P1B1/2K2PP1/4r3/8/3R4 b - - 9 45",
"1r3bk1/8/6R1/2p1P1B1/p1K2PP1/4r3/8/3R4 b - - 0 46",
"1r3b2/5k2/R7/2p1P1B1/p1K2PP1/4r3/8/3R4 b - - 2 47",
"5b2/1r3k2/R7/2p1P1B1/p1K2PP1/4r3/8/7R b - - 4 48",
"5b2/5k2/R7/2pKP1B1/pr3PP1/4r3/8/7R b - - 6 49",
"5b2/5k2/R1K5/2p1P1B1/p2r1PP1/4r3/8/7R b - - 8 50",
"8/R4kb1/2K5/2p1P1B1/p2r1PP1/4r3/8/7R b - - 10 51",
"8/R5b1/2K3k1/2p1PPB1/p2r2P1/4r3/8/7R b - - 0 52",
"8/6R1/2K5/2p1PPk1/p2r2P1/4r3/8/7R b - - 0 53",
"8/6R1/2K5/2p1PP2/p2r1kP1/4r3/8/5R2 b - - 2 54",
"8/6R1/2K2P2/2p1P3/p2r2P1/4r1k1/8/5R2 b - - 0 55",
"8/5PR1/2K5/2p1P3/p2r2P1/4r3/6k1/5R2 b - - 0 56",
},
{
"rn1qkb1r/p1pbpppp/5n2/8/2pP4/2N5/1PQ1PPPP/R1B1KBNR w KQkq - 0 7",
"r2qkb1r/p1pbpppp/2n2n2/8/2pP4/2N2N2/1PQ1PPPP/R1B1KB1R w KQkq - 2 8",
"r2qkb1r/p1pbpppp/5n2/8/1npPP3/2N2N2/1PQ2PPP/R1B1KB1R w KQkq - 1 9",
"r2qkb1r/p1pb1ppp/4pn2/8/1npPP3/2N2N2/1P3PPP/R1BQKB1R w KQkq - 0 10",
"r2qk2r/p1pbbppp/4pn2/8/1nBPP3/2N2N2/1P3PPP/R1BQK2R w KQkq - 1 11",
"r2q1rk1/p1pbbppp/4pn2/8/1nBPP3/2N2N2/1P3PPP/R1BQ1RK1 w - - 3 12",
"r2q1rk1/2pbbppp/p3pn2/8/1nBPPB2/2N2N2/1P3PPP/R2Q1RK1 w - - 0 13",
"r2q1rk1/2p1bppp/p3pn2/1b6/1nBPPB2/2N2N2/1P3PPP/R2QR1K1 w - - 2 14",
"r2q1rk1/4bppp/p1p1pn2/1b6/1nBPPB2/1PN2N2/5PPP/R2QR1K1 w - - 0 15",
"r4rk1/3qbppp/p1p1pn2/1b6/1nBPPB2/1PN2N2/3Q1PPP/R3R1K1 w - - 2 16",
"r4rk1/1q2bppp/p1p1pn2/1b6/1nBPPB2/1PN2N1P/3Q1PP1/R3R1K1 w - - 1 17",
"r3r1k1/1q2bppp/p1p1pn2/1b6/1nBPPB2/1PN2N1P/4QPP1/R3R1K1 w - - 3 18",
"r3r1k1/1q1nbppp/p1p1p3/1b6/1nBPPB2/1PN2N1P/4QPP1/3RR1K1 w - - 5 19",
"r3rbk1/1q1n1ppp/p1p1p3/1b6/1nBPPB2/1PN2N1P/3RQPP1/4R1K1 w - - 7 20",
"r3rbk1/1q3ppp/pnp1p3/1b6/1nBPPB2/1PN2N1P/3RQPP1/4R2K w - - 9 21",
"2r1rbk1/1q3ppp/pnp1p3/1b6/1nBPPB2/1PN2N1P/3RQPP1/1R5K w - - 11 22",
"2r1rbk1/1q4pp/pnp1pp2/1b6/1nBPPB2/1PN2N1P/4QPP1/1R1R3K w - - 0 23",
"2r1rbk1/5qpp/pnp1pp2/1b6/1nBPP3/1PN1BN1P/4QPP1/1R1R3K w - - 2 24",
"2r1rbk1/5qp1/pnp1pp1p/1b6/1nBPP3/1PN1BN1P/4QPP1/1R1R2K1 w - - 0 25",
"2r1rbk1/5qp1/pnp1pp1p/1b6/2BPP3/1P2BN1P/n3QPP1/1R1R2K1 w - - 0 26",
"r3rbk1/5qp1/pnp1pp1p/1b6/2BPP3/1P2BN1P/Q4PP1/1R1R2K1 w - - 1 27",
"rr3bk1/5qp1/pnp1pp1p/1b6/2BPP3/1P2BN1P/Q4PP1/R2R2K1 w - - 3 28",
"rr2qbk1/6p1/pnp1pp1p/1b6/2BPP3/1P2BN1P/4QPP1/R2R2K1 w - - 5 29",
"rr2qbk1/6p1/1np1pp1p/pb6/2BPP3/1P1QBN1P/5PP1/R2R2K1 w - - 0 30",
"rr2qbk1/6p1/1n2pp1p/pp6/3PP3/1P1QBN1P/5PP1/R2R2K1 w - - 0 31",
"rr2qbk1/6p1/1n2pp1p/1p1P4/p3P3/1P1QBN1P/5PP1/R2R2K1 w - - 0 32",
"rr2qbk1/3n2p1/3Ppp1p/1p6/p3P3/1P1QBN1P/5PP1/R2R2K1 w - - 1 33",
"rr3bk1/3n2p1/3Ppp1p/1p5q/pP2P3/3QBN1P/5PP1/R2R2K1 w - - 1 34",
"rr3bk1/3n2p1/3Ppp1p/1p5q/1P2P3/p2QBN1P/5PP1/2RR2K1 w - - 0 35",
"1r3bk1/3n2p1/r2Ppp1p/1p5q/1P2P3/pQ2BN1P/5PP1/2RR2K1 w - - 2 36",
"1r2qbk1/2Rn2p1/r2Ppp1p/1p6/1P2P3/pQ2BN1P/5PP1/3R2K1 w - - 4 37",
"1r2qbk1/2Rn2p1/r2Ppp1p/1pB5/1P2P3/1Q3N1P/p4PP1/3R2K1 w - - 0 38",
"1r2q1k1/2Rn2p1/r2bpp1p/1pB5/1P2P3/1Q3N1P/p4PP1/R5K1 w - - 0 39",
"1r2q1k1/2Rn2p1/3rpp1p/1p6/1P2P3/1Q3N1P/p4PP1/R5K1 w - - 0 40",
"2r1q1k1/2Rn2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 1 41",
"1r2q1k1/1R1n2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 3 42",
"2r1q1k1/2Rn2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 5 43",
"1r2q1k1/1R1n2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 7 44",
"1rq3k1/R2n2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 9 45",
"2q3k1/Rr1n2p1/3rpp1p/1p6/1P2P3/5N1P/4QPP1/R5K1 w - - 11 46",
"Rrq3k1/3n2p1/3rpp1p/1p6/1P2P3/5N1P/4QPP1/R5K1 w - - 13 47",
},
{
"rn1qkb1r/1pp2ppp/p4p2/3p1b2/5P2/1P2PN2/P1PP2PP/RN1QKB1R b KQkq - 1 6",
"r2qkb1r/1pp2ppp/p1n2p2/3p1b2/3P1P2/1P2PN2/P1P3PP/RN1QKB1R b KQkq - 0 7",
"r2qkb1r/1pp2ppp/p4p2/3p1b2/1n1P1P2/1P1BPN2/P1P3PP/RN1QK2R b KQkq - 2 8",
"r2qkb1r/1pp2ppp/p4p2/3p1b2/3P1P2/1P1PPN2/P5PP/RN1QK2R b KQkq - 0 9",
"r2qk2r/1pp2ppp/p2b1p2/3p1b2/3P1P2/1PNPPN2/P5PP/R2QK2R b KQkq - 2 10",
"r2qk2r/1p3ppp/p1pb1p2/3p1b2/3P1P2/1PNPPN2/P5PP/R2Q1RK1 b kq - 1 11",
"r2q1rk1/1p3ppp/p1pb1p2/3p1b2/3P1P2/1PNPPN2/P2Q2PP/R4RK1 b - - 3 12",
"r2qr1k1/1p3ppp/p1pb1p2/3p1b2/3P1P2/1P1PPN2/P2QN1PP/R4RK1 b - - 5 13",
"r3r1k1/1p3ppp/pqpb1p2/3p1b2/3P1P2/1P1PPNN1/P2Q2PP/R4RK1 b - - 7 14",
"r3r1k1/1p3ppp/pqp2p2/3p1b2/1b1P1P2/1P1PPNN1/P1Q3PP/R4RK1 b - - 9 15",
"r3r1k1/1p1b1ppp/pqp2p2/3p4/1b1P1P2/1P1PPNN1/P4QPP/R4RK1 b - - 11 16",
"2r1r1k1/1p1b1ppp/pqp2p2/3p4/1b1PPP2/1P1P1NN1/P4QPP/R4RK1 b - - 0 17",
"2r1r1k1/1p1b1ppp/pq3p2/2pp4/1b1PPP2/PP1P1NN1/5QPP/R4RK1 b - - 0 18",
"2r1r1k1/1p1b1ppp/pq3p2/2Pp4/4PP2/PPbP1NN1/5QPP/R4RK1 b - - 0 19",
"2r1r1k1/1p1b1ppp/p4p2/2Pp4/4PP2/PqbP1NN1/5QPP/RR4K1 b - - 1 20",
"2r1r1k1/1p1b1ppp/p4p2/2Pp4/q3PP2/P1bP1NN1/R4QPP/1R4K1 b - - 3 21",
"2r1r1k1/1p3ppp/p4p2/1bPP4/q4P2/P1bP1NN1/R4QPP/1R4K1 b - - 0 22",
"2r1r1k1/1p3ppp/p4p2/2PP4/q4P2/P1bb1NN1/R4QPP/2R3K1 b - - 1 23",
"2r1r1k1/1p3ppp/p2P1p2/2P5/2q2P2/P1bb1NN1/R4QPP/2R3K1 b - - 0 24",
"2rr2k1/1p3ppp/p2P1p2/2P5/2q2P2/P1bb1NN1/R4QPP/2R4K b - - 2 25",
"2rr2k1/1p3ppp/p2P1p2/2Q5/5P2/P1bb1NN1/R5PP/2R4K b - - 0 26",
"3r2k1/1p3ppp/p2P1p2/2r5/5P2/P1bb1N2/R3N1PP/2R4K b - - 1 27",
"3r2k1/1p3ppp/p2P1p2/2r5/5P2/P1b2N2/4R1PP/2R4K b - - 0 28",
"3r2k1/1p3ppp/p2P1p2/2r5/1b3P2/P4N2/4R1PP/3R3K b - - 2 29",
"3r2k1/1p2Rppp/p2P1p2/b1r5/5P2/P4N2/6PP/3R3K b - - 4 30",
"3r2k1/1R3ppp/p1rP1p2/b7/5P2/P4N2/6PP/3R3K b - - 0 31",
"3r2k1/1R3ppp/p2R1p2/b7/5P2/P4N2/6PP/7K b - - 0 32",
"6k1/1R3ppp/p2r1p2/b7/5P2/P4NP1/7P/7K b - - 0 33",
"6k1/1R3p1p/p2r1pp1/b7/5P1P/P4NP1/8/7K b - - 0 34",
"6k1/3R1p1p/pr3pp1/b7/5P1P/P4NP1/8/7K b - - 2 35",
"6k1/5p2/pr3pp1/b2R3p/5P1P/P4NP1/8/7K b - - 1 36",
"6k1/5p2/pr3pp1/7p/5P1P/P1bR1NP1/8/7K b - - 3 37",
"6k1/5p2/p1r2pp1/7p/5P1P/P1bR1NP1/6K1/8 b - - 5 38",
"6k1/5p2/p1r2pp1/b2R3p/5P1P/P4NP1/6K1/8 b - - 7 39",
"6k1/5p2/p4pp1/b2R3p/5P1P/P4NPK/2r5/8 b - - 9 40",
"6k1/2b2p2/p4pp1/7p/5P1P/P2R1NPK/2r5/8 b - - 11 41",
"6k1/2b2p2/5pp1/p6p/3N1P1P/P2R2PK/2r5/8 b - - 1 42",
"6k1/2b2p2/5pp1/p6p/3N1P1P/P1R3PK/r7/8 b - - 3 43",
"6k1/5p2/1b3pp1/p6p/5P1P/P1R3PK/r1N5/8 b - - 5 44",
"8/5pk1/1bR2pp1/p6p/5P1P/P5PK/r1N5/8 b - - 7 45",
"3b4/5pk1/2R2pp1/p4P1p/7P/P5PK/r1N5/8 b - - 0 46",
"8/4bpk1/2R2pp1/p4P1p/6PP/P6K/r1N5/8 b - - 0 47",
"8/5pk1/2R2pP1/p6p/6PP/b6K/r1N5/8 b - - 0 48",
"8/6k1/2R2pp1/p6P/7P/b6K/r1N5/8 b - - 0 49",
"8/6k1/2R2p2/p6p/7P/b5K1/r1N5/8 b - - 1 50",
"8/8/2R2pk1/p6p/7P/b4K2/r1N5/8 b - - 3 51",
"8/8/2R2pk1/p6p/7P/4NK2/rb6/8 b - - 5 52",
"2R5/8/5pk1/7p/p6P/4NK2/rb6/8 b - - 1 53",
"6R1/8/5pk1/7p/p6P/4NK2/1b6/r7 b - - 3 54",
"R7/5k2/5p2/7p/p6P/4NK2/1b6/r7 b - - 5 55",
"R7/5k2/5p2/7p/7P/p3N3/1b2K3/r7 b - - 1 56",
"8/R4k2/5p2/7p/7P/p3N3/1b2K3/7r b - - 3 57",
"8/8/5pk1/7p/R6P/p3N3/1b2K3/7r b - - 5 58",
"8/8/5pk1/7p/R6P/p7/4K3/2bN3r b - - 7 59",
"8/8/5pk1/7p/R6P/p7/4KN1r/2b5 b - - 9 60",
"8/8/5pk1/7p/R6P/p3K3/1b3N1r/8 b - - 11 61",
"8/8/R4pk1/7p/7P/p1b1K3/5N1r/8 b - - 13 62",
"8/8/5pk1/7p/7P/2b1K3/R4N1r/8 b - - 0 63",
"8/8/5pk1/7p/3K3P/8/R4N1r/4b3 b - - 2 64",
}
};
// clang-format on
} // namespace
namespace Stockfish {
namespace Stockfish::Benchmark {
// Builds a list of UCI commands to be run by bench. There
// are five parameters: TT size in MB, number of search threads that
@@ -108,7 +383,7 @@ namespace Stockfish {
// bench 64 1 100000 default nodes : search default positions for 100K nodes each
// bench 64 4 5000 current movetime : search current position with 4 threads for 5 sec
// bench 16 1 5 blah perft : run a perft 5 on positions in file "blah"
std::vector<std::string> setup_bench(const Position& current, std::istream& is) {
std::vector<std::string> setup_bench(const std::string& currentFen, std::istream& is) {
std::vector<std::string> fens, list;
std::string go, token;
@@ -126,7 +401,7 @@ std::vector<std::string> setup_bench(const Position& current, std::istream& is)
fens = Defaults;
else if (fenFile == "current")
fens.push_back(current.fen());
fens.push_back(currentFen);
else
{
@@ -162,4 +437,76 @@ std::vector<std::string> setup_bench(const Position& current, std::istream& is)
return list;
}
BenchmarkSetup setup_benchmark(std::istream& is) {
// TT_SIZE_PER_THREAD is chosen such that roughly half of the hash is used all positions
// for the current sequence have been searched.
static constexpr int TT_SIZE_PER_THREAD = 128;
static constexpr int DEFAULT_DURATION_S = 150;
BenchmarkSetup setup{};
// Assign default values to missing arguments
int desiredTimeS;
if (!(is >> setup.threads))
setup.threads = get_hardware_concurrency();
else
setup.originalInvocation += std::to_string(setup.threads);
if (!(is >> setup.ttSize))
setup.ttSize = TT_SIZE_PER_THREAD * setup.threads;
else
setup.originalInvocation += " " + std::to_string(setup.ttSize);
if (!(is >> desiredTimeS))
desiredTimeS = DEFAULT_DURATION_S;
else
setup.originalInvocation += " " + std::to_string(desiredTimeS);
setup.filledInvocation += std::to_string(setup.threads) + " " + std::to_string(setup.ttSize)
+ " " + std::to_string(desiredTimeS);
auto getCorrectedTime = [&](int ply) {
// time per move is fit roughly based on LTC games
// seconds = 50/{ply+15}
// ms = 50000/{ply+15}
// with this fit 10th move gets 2000ms
// adjust for desired 10th move time
return 50000.0 / (static_cast<double>(ply) + 15.0);
};
float totalTime = 0;
for (const auto& game : BenchmarkPositions)
{
setup.commands.emplace_back("ucinewgame");
int ply = 1;
for (int i = 0; i < static_cast<int>(game.size()); ++i)
{
const float correctedTime = getCorrectedTime(ply);
totalTime += correctedTime;
ply += 1;
}
}
float timeScaleFactor = static_cast<float>(desiredTimeS * 1000) / totalTime;
for (const auto& game : BenchmarkPositions)
{
setup.commands.emplace_back("ucinewgame");
int ply = 1;
for (const std::string& fen : game)
{
setup.commands.emplace_back("position fen " + fen);
const int correctedTime = static_cast<int>(getCorrectedTime(ply) * timeScaleFactor);
setup.commands.emplace_back("go movetime " + std::to_string(correctedTime));
ply += 1;
}
}
return setup;
}
} // namespace Stockfish
+12 -4
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,11 +23,19 @@
#include <string>
#include <vector>
namespace Stockfish {
namespace Stockfish::Benchmark {
class Position;
std::vector<std::string> setup_bench(const std::string&, std::istream&);
std::vector<std::string> setup_bench(const Position&, std::istream&);
struct BenchmarkSetup {
int ttSize;
int threads;
std::vector<std::string> commands;
std::string originalInvocation;
std::string filledInvocation;
};
BenchmarkSetup setup_benchmark(std::istream&);
} // namespace Stockfish
+33 -21
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -34,15 +34,14 @@ Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
Magic RookMagics[SQUARE_NB];
Magic BishopMagics[SQUARE_NB];
alignas(64) Magic Magics[SQUARE_NB][2];
namespace {
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]);
// Returns the bitboard of target square for the given step
// from the given square. If the step is off the board, returns empty bitboard.
@@ -82,8 +81,8 @@ void Bitboards::init() {
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
init_magics(ROOK, RookTable, RookMagics);
init_magics(BISHOP, BishopTable, BishopMagics);
init_magics(ROOK, RookTable, Magics);
init_magics(BISHOP, BishopTable, Magics);
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
{
@@ -124,8 +123,14 @@ Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
for (Direction d : (pt == ROOK ? RookDirections : BishopDirections))
{
Square s = sq;
while (safe_destination(s, d) && !(occupied & s))
while (safe_destination(s, d))
{
attacks |= (s += d);
if (occupied & s)
{
break;
}
}
}
return attacks;
@@ -134,41 +139,49 @@ Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
// Computes all rook and bishop attacks at startup. Magic
// bitboards are used to look up attacks of sliding pieces. As a reference see
// www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
// called "fancy" approach.
void init_magics(PieceType pt, Bitboard table[], Magic magics[]) {
// https://www.chessprogramming.org/Magic_Bitboards. In particular, here we use
// the so called "fancy" approach.
void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]) {
#ifndef USE_PEXT
// Optimal PRNG seeds to pick the correct magics in the shortest time
int seeds[][RANK_NB] = {{8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020},
{728, 10316, 55013, 32803, 12281, 15100, 16645, 255}};
Bitboard occupancy[4096], reference[4096], edges, b;
int epoch[4096] = {}, cnt = 0, size = 0;
Bitboard occupancy[4096];
int epoch[4096] = {}, cnt = 0;
#endif
Bitboard reference[4096];
int size = 0;
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
// Board edges are not considered in the relevant occupancies
edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
Bitboard edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
// Given a square 's', the mask is the bitboard of sliding attacks from
// 's' computed on an empty board. The index must be big enough to contain
// all the attacks for each possible subset of the mask and so is 2 power
// the number of 1s of the mask. Hence we deduce the size of the shift to
// apply to the 64 or 32 bits word to get the index.
Magic& m = magics[s];
Magic& m = magics[s][pt - BISHOP];
m.mask = sliding_attack(pt, s, 0) & ~edges;
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
#ifndef USE_PEXT
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
#endif
// Set the offset for the attacks table of the square. We have individual
// table sizes for each square with "Fancy Magic Bitboards".
m.attacks = s == SQ_A1 ? table : magics[s - 1].attacks + size;
m.attacks = s == SQ_A1 ? table : magics[s - 1][pt - BISHOP].attacks + size;
size = 0;
// Use Carry-Rippler trick to enumerate all subsets of masks[s] and
// store the corresponding sliding attack bitboard in reference[].
b = size = 0;
Bitboard b = 0;
do
{
#ifndef USE_PEXT
occupancy[size] = b;
#endif
reference[size] = sliding_attack(pt, s, b);
if (HasPext)
@@ -178,9 +191,7 @@ void init_magics(PieceType pt, Bitboard table[], Magic magics[]) {
b = (b - m.mask) & m.mask;
} while (b);
if (HasPext)
continue;
#ifndef USE_PEXT
PRNG rng(seeds[Is64Bit][rank_of(s)]);
// Find a magic for square 's' picking up an (almost) random number
@@ -209,6 +220,7 @@ void init_magics(PieceType pt, Bitboard table[], Magic magics[]) {
break;
}
}
#endif
}
}
}
+18 -15
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,6 +22,7 @@
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <cstdint>
#include <cstdlib>
#include <string>
@@ -67,27 +68,31 @@ extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
// Magic holds all magic bitboards relevant data for a single square
struct Magic {
Bitboard mask;
Bitboard magic;
Bitboard* attacks;
unsigned shift;
#ifndef USE_PEXT
Bitboard magic;
unsigned shift;
#endif
// Compute the attack's index using the 'magic bitboards' approach
unsigned index(Bitboard occupied) const {
if (HasPext)
return unsigned(pext(occupied, mask));
#ifdef USE_PEXT
return unsigned(pext(occupied, mask));
#else
if (Is64Bit)
return unsigned(((occupied & mask) * magic) >> shift);
unsigned lo = unsigned(occupied) & unsigned(mask);
unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
#endif
}
Bitboard attacks_bb(Bitboard occupied) const { return attacks[index(occupied)]; }
};
extern Magic RookMagics[SQUARE_NB];
extern Magic BishopMagics[SQUARE_NB];
extern Magic Magics[SQUARE_NB][2];
constexpr Bitboard square_bb(Square s) {
assert(is_ok(s));
@@ -229,9 +234,8 @@ inline Bitboard attacks_bb(Square s, Bitboard occupied) {
switch (Pt)
{
case BISHOP :
return BishopMagics[s].attacks[BishopMagics[s].index(occupied)];
case ROOK :
return RookMagics[s].attacks[RookMagics[s].index(occupied)];
return Magics[s][Pt - BISHOP].attacks_bb(occupied);
case QUEEN :
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
default :
@@ -265,11 +269,10 @@ inline int popcount(Bitboard b) {
#ifndef USE_POPCNT
union {
Bitboard bb;
uint16_t u[4];
} v = {b};
return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
std::uint16_t indices[4];
std::memcpy(indices, &b, sizeof(b));
return PopCnt16[indices[0]] + PopCnt16[indices[1]] + PopCnt16[indices[2]]
+ PopCnt16[indices[3]];
#elif defined(_MSC_VER)
+369
View File
@@ -0,0 +1,369 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "engine.h"
#include <cassert>
#include <deque>
#include <iosfwd>
#include <memory>
#include <ostream>
#include <sstream>
#include <string_view>
#include <utility>
#include <vector>
#include "evaluate.h"
#include "misc.h"
#include "nnue/network.h"
#include "nnue/nnue_common.h"
#include "perft.h"
#include "position.h"
#include "search.h"
#include "syzygy/tbprobe.h"
#include "types.h"
#include "uci.h"
#include "ucioption.h"
namespace Stockfish {
namespace NN = Eval::NNUE;
constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
Engine::Engine(std::optional<std::string> path) :
binaryDirectory(path ? CommandLine::get_binary_directory(*path) : ""),
numaContext(NumaConfig::from_system()),
states(new std::deque<StateInfo>(1)),
threads(),
networks(
numaContext,
NN::Networks(
NN::NetworkBig({EvalFileDefaultNameBig, "None", ""}, NN::EmbeddedNNUEType::BIG),
NN::NetworkSmall({EvalFileDefaultNameSmall, "None", ""}, NN::EmbeddedNNUEType::SMALL))) {
pos.set(StartFEN, false, &states->back());
options.add( //
"Debug Log File", Option("", [](const Option& o) {
start_logger(o);
return std::nullopt;
}));
options.add( //
"NumaPolicy", Option("auto", [this](const Option& o) {
set_numa_config_from_option(o);
return numa_config_information_as_string() + "\n"
+ thread_allocation_information_as_string();
}));
options.add( //
"Threads", Option(1, 1, 1024, [this](const Option&) {
resize_threads();
return thread_allocation_information_as_string();
}));
options.add( //
"Hash", Option(16, 1, MaxHashMB, [this](const Option& o) {
set_tt_size(o);
return std::nullopt;
}));
options.add( //
"Clear Hash", Option([this](const Option&) {
search_clear();
return std::nullopt;
}));
options.add( //
"Ponder", Option(false));
options.add( //
"MultiPV", Option(1, 1, MAX_MOVES));
options.add("Skill Level", Option(20, 0, 20));
options.add("Move Overhead", Option(10, 0, 5000));
options.add("nodestime", Option(0, 0, 10000));
options.add("UCI_Chess960", Option(false));
options.add("UCI_LimitStrength", Option(false));
options.add("UCI_Elo",
Option(Stockfish::Search::Skill::LowestElo, Stockfish::Search::Skill::LowestElo,
Stockfish::Search::Skill::HighestElo));
options.add("UCI_ShowWDL", Option(false));
options.add( //
"SyzygyPath", Option("", [](const Option& o) {
Tablebases::init(o);
return std::nullopt;
}));
options.add("SyzygyProbeDepth", Option(1, 1, 100));
options.add("Syzygy50MoveRule", Option(true));
options.add("SyzygyProbeLimit", Option(7, 0, 7));
options.add( //
"EvalFile", Option(EvalFileDefaultNameBig, [this](const Option& o) {
load_big_network(o);
return std::nullopt;
}));
options.add( //
"EvalFileSmall", Option(EvalFileDefaultNameSmall, [this](const Option& o) {
load_small_network(o);
return std::nullopt;
}));
load_networks();
resize_threads();
}
std::uint64_t Engine::perft(const std::string& fen, Depth depth, bool isChess960) {
verify_networks();
return Benchmark::perft(fen, depth, isChess960);
}
void Engine::go(Search::LimitsType& limits) {
assert(limits.perft == 0);
verify_networks();
threads.start_thinking(options, pos, states, limits);
}
void Engine::stop() { threads.stop = true; }
void Engine::search_clear() {
wait_for_search_finished();
tt.clear(threads);
threads.clear();
// @TODO wont work with multiple instances
Tablebases::init(options["SyzygyPath"]); // Free mapped files
}
void Engine::set_on_update_no_moves(std::function<void(const Engine::InfoShort&)>&& f) {
updateContext.onUpdateNoMoves = std::move(f);
}
void Engine::set_on_update_full(std::function<void(const Engine::InfoFull&)>&& f) {
updateContext.onUpdateFull = std::move(f);
}
void Engine::set_on_iter(std::function<void(const Engine::InfoIter&)>&& f) {
updateContext.onIter = std::move(f);
}
void Engine::set_on_bestmove(std::function<void(std::string_view, std::string_view)>&& f) {
updateContext.onBestmove = std::move(f);
}
void Engine::set_on_verify_networks(std::function<void(std::string_view)>&& f) {
onVerifyNetworks = std::move(f);
}
void Engine::wait_for_search_finished() { threads.main_thread()->wait_for_search_finished(); }
void Engine::set_position(const std::string& fen, const std::vector<std::string>& moves) {
// Drop the old state and create a new one
states = StateListPtr(new std::deque<StateInfo>(1));
pos.set(fen, options["UCI_Chess960"], &states->back());
for (const auto& move : moves)
{
auto m = UCIEngine::to_move(pos, move);
if (m == Move::none())
break;
states->emplace_back();
pos.do_move(m, states->back());
}
}
// modifiers
void Engine::set_numa_config_from_option(const std::string& o) {
if (o == "auto" || o == "system")
{
numaContext.set_numa_config(NumaConfig::from_system());
}
else if (o == "hardware")
{
// Don't respect affinity set in the system.
numaContext.set_numa_config(NumaConfig::from_system(false));
}
else if (o == "none")
{
numaContext.set_numa_config(NumaConfig{});
}
else
{
numaContext.set_numa_config(NumaConfig::from_string(o));
}
// Force reallocation of threads in case affinities need to change.
resize_threads();
threads.ensure_network_replicated();
}
void Engine::resize_threads() {
threads.wait_for_search_finished();
threads.set(numaContext.get_numa_config(), {options, threads, tt, networks}, updateContext);
// Reallocate the hash with the new threadpool size
set_tt_size(options["Hash"]);
threads.ensure_network_replicated();
}
void Engine::set_tt_size(size_t mb) {
wait_for_search_finished();
tt.resize(mb, threads);
}
void Engine::set_ponderhit(bool b) { threads.main_manager()->ponder = b; }
// network related
void Engine::verify_networks() const {
networks->big.verify(options["EvalFile"], onVerifyNetworks);
networks->small.verify(options["EvalFileSmall"], onVerifyNetworks);
}
void Engine::load_networks() {
networks.modify_and_replicate([this](NN::Networks& networks_) {
networks_.big.load(binaryDirectory, options["EvalFile"]);
networks_.small.load(binaryDirectory, options["EvalFileSmall"]);
});
threads.clear();
threads.ensure_network_replicated();
}
void Engine::load_big_network(const std::string& file) {
networks.modify_and_replicate(
[this, &file](NN::Networks& networks_) { networks_.big.load(binaryDirectory, file); });
threads.clear();
threads.ensure_network_replicated();
}
void Engine::load_small_network(const std::string& file) {
networks.modify_and_replicate(
[this, &file](NN::Networks& networks_) { networks_.small.load(binaryDirectory, file); });
threads.clear();
threads.ensure_network_replicated();
}
void Engine::save_network(const std::pair<std::optional<std::string>, std::string> files[2]) {
networks.modify_and_replicate([&files](NN::Networks& networks_) {
networks_.big.save(files[0].first);
networks_.small.save(files[1].first);
});
}
// utility functions
void Engine::trace_eval() const {
StateListPtr trace_states(new std::deque<StateInfo>(1));
Position p;
p.set(pos.fen(), options["UCI_Chess960"], &trace_states->back());
verify_networks();
sync_cout << "\n" << Eval::trace(p, *networks) << sync_endl;
}
const OptionsMap& Engine::get_options() const { return options; }
OptionsMap& Engine::get_options() { return options; }
std::string Engine::fen() const { return pos.fen(); }
void Engine::flip() { pos.flip(); }
std::string Engine::visualize() const {
std::stringstream ss;
ss << pos;
return ss.str();
}
int Engine::get_hashfull(int maxAge) const { return tt.hashfull(maxAge); }
std::vector<std::pair<size_t, size_t>> Engine::get_bound_thread_count_by_numa_node() const {
auto counts = threads.get_bound_thread_count_by_numa_node();
const NumaConfig& cfg = numaContext.get_numa_config();
std::vector<std::pair<size_t, size_t>> ratios;
NumaIndex n = 0;
for (; n < counts.size(); ++n)
ratios.emplace_back(counts[n], cfg.num_cpus_in_numa_node(n));
if (!counts.empty())
for (; n < cfg.num_numa_nodes(); ++n)
ratios.emplace_back(0, cfg.num_cpus_in_numa_node(n));
return ratios;
}
std::string Engine::get_numa_config_as_string() const {
return numaContext.get_numa_config().to_string();
}
std::string Engine::numa_config_information_as_string() const {
auto cfgStr = get_numa_config_as_string();
return "Available processors: " + cfgStr;
}
std::string Engine::thread_binding_information_as_string() const {
auto boundThreadsByNode = get_bound_thread_count_by_numa_node();
std::stringstream ss;
if (boundThreadsByNode.empty())
return ss.str();
bool isFirst = true;
for (auto&& [current, total] : boundThreadsByNode)
{
if (!isFirst)
ss << ":";
ss << current << "/" << total;
isFirst = false;
}
return ss.str();
}
std::string Engine::thread_allocation_information_as_string() const {
std::stringstream ss;
size_t threadsSize = threads.size();
ss << "Using " << threadsSize << (threadsSize > 1 ? " threads" : " thread");
auto boundThreadsByNodeStr = thread_binding_information_as_string();
if (boundThreadsByNodeStr.empty())
return ss.str();
ss << " with NUMA node thread binding: ";
ss << boundThreadsByNodeStr;
return ss.str();
}
}
+130
View File
@@ -0,0 +1,130 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENGINE_H_INCLUDED
#define ENGINE_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <functional>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "nnue/network.h"
#include "numa.h"
#include "position.h"
#include "search.h"
#include "syzygy/tbprobe.h" // for Stockfish::Depth
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
namespace Stockfish {
class Engine {
public:
using InfoShort = Search::InfoShort;
using InfoFull = Search::InfoFull;
using InfoIter = Search::InfoIteration;
Engine(std::optional<std::string> path = std::nullopt);
// Cannot be movable due to components holding backreferences to fields
Engine(const Engine&) = delete;
Engine(Engine&&) = delete;
Engine& operator=(const Engine&) = delete;
Engine& operator=(Engine&&) = delete;
~Engine() { wait_for_search_finished(); }
std::uint64_t perft(const std::string& fen, Depth depth, bool isChess960);
// non blocking call to start searching
void go(Search::LimitsType&);
// non blocking call to stop searching
void stop();
// blocking call to wait for search to finish
void wait_for_search_finished();
// set a new position, moves are in UCI format
void set_position(const std::string& fen, const std::vector<std::string>& moves);
// modifiers
void set_numa_config_from_option(const std::string& o);
void resize_threads();
void set_tt_size(size_t mb);
void set_ponderhit(bool);
void search_clear();
void set_on_update_no_moves(std::function<void(const InfoShort&)>&&);
void set_on_update_full(std::function<void(const InfoFull&)>&&);
void set_on_iter(std::function<void(const InfoIter&)>&&);
void set_on_bestmove(std::function<void(std::string_view, std::string_view)>&&);
void set_on_verify_networks(std::function<void(std::string_view)>&&);
// network related
void verify_networks() const;
void load_networks();
void load_big_network(const std::string& file);
void load_small_network(const std::string& file);
void save_network(const std::pair<std::optional<std::string>, std::string> files[2]);
// utility functions
void trace_eval() const;
const OptionsMap& get_options() const;
OptionsMap& get_options();
int get_hashfull(int maxAge = 0) const;
std::string fen() const;
void flip();
std::string visualize() const;
std::vector<std::pair<size_t, size_t>> get_bound_thread_count_by_numa_node() const;
std::string get_numa_config_as_string() const;
std::string numa_config_information_as_string() const;
std::string thread_allocation_information_as_string() const;
std::string thread_binding_information_as_string() const;
private:
const std::string binaryDirectory;
NumaReplicationContext numaContext;
Position pos;
StateListPtr states;
OptionsMap options;
ThreadPool threads;
TranspositionTable tt;
LazyNumaReplicated<Eval::NNUE::Networks> networks;
Search::SearchManager::UpdateContext updateContext;
std::function<void(std::string_view)> onVerifyNetworks;
};
} // namespace Stockfish
#endif // #ifndef ENGINE_H_INCLUDED
+42 -167
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,161 +22,21 @@
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <optional>
#include <memory>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <tuple>
#include "incbin/incbin.h"
#include "misc.h"
#include "nnue/evaluate_nnue.h"
#include "nnue/nnue_architecture.h"
#include "nnue/network.h"
#include "nnue/nnue_misc.h"
#include "position.h"
#include "types.h"
#include "uci.h"
#include "ucioption.h"
// Macro to embed the default efficiently updatable neural network (NNUE) file
// data in the engine binary (using incbin.h, by Dale Weiler).
// This macro invocation will declare the following three variables
// const unsigned char gEmbeddedNNUEData[]; // a pointer to the embedded data
// const unsigned char *const gEmbeddedNNUEEnd; // a marker to the end
// const unsigned int gEmbeddedNNUESize; // the size of the embedded file
// Note that this does not work in Microsoft Visual Studio.
#if !defined(_MSC_VER) && !defined(NNUE_EMBEDDING_OFF)
INCBIN(EmbeddedNNUEBig, EvalFileDefaultNameBig);
INCBIN(EmbeddedNNUESmall, EvalFileDefaultNameSmall);
#else
const unsigned char gEmbeddedNNUEBigData[1] = {0x0};
const unsigned char* const gEmbeddedNNUEBigEnd = &gEmbeddedNNUEBigData[1];
const unsigned int gEmbeddedNNUEBigSize = 1;
const unsigned char gEmbeddedNNUESmallData[1] = {0x0};
const unsigned char* const gEmbeddedNNUESmallEnd = &gEmbeddedNNUESmallData[1];
const unsigned int gEmbeddedNNUESmallSize = 1;
#endif
#include "nnue/nnue_accumulator.h"
namespace Stockfish {
namespace Eval {
// Tries to load a NNUE network at startup time, or when the engine
// receives a UCI command "setoption name EvalFile value nn-[a-z0-9]{12}.nnue"
// The name of the NNUE network is always retrieved from the EvalFile option.
// We search the given network in three locations: internally (the default
// network may be embedded in the binary), in the active working directory and
// in the engine directory. Distro packagers may define the DEFAULT_NNUE_DIRECTORY
// variable to have the engine search in a special directory in their distro.
NNUE::EvalFiles NNUE::load_networks(const std::string& rootDirectory,
const OptionsMap& options,
NNUE::EvalFiles evalFiles) {
for (auto& [netSize, evalFile] : evalFiles)
{
std::string user_eval_file = options[evalFile.optionName];
if (user_eval_file.empty())
user_eval_file = evalFile.defaultName;
#if defined(DEFAULT_NNUE_DIRECTORY)
std::vector<std::string> dirs = {"<internal>", "", rootDirectory,
stringify(DEFAULT_NNUE_DIRECTORY)};
#else
std::vector<std::string> dirs = {"<internal>", "", rootDirectory};
#endif
for (const std::string& directory : dirs)
{
if (evalFile.current != user_eval_file)
{
if (directory != "<internal>")
{
std::ifstream stream(directory + user_eval_file, std::ios::binary);
auto description = NNUE::load_eval(stream, netSize);
if (description.has_value())
{
evalFile.current = user_eval_file;
evalFile.netDescription = description.value();
}
}
if (directory == "<internal>" && user_eval_file == evalFile.defaultName)
{
// C++ way to prepare a buffer for a memory stream
class MemoryBuffer: public std::basic_streambuf<char> {
public:
MemoryBuffer(char* p, size_t n) {
setg(p, p, p + n);
setp(p, p + n);
}
};
MemoryBuffer buffer(
const_cast<char*>(reinterpret_cast<const char*>(
netSize == Small ? gEmbeddedNNUESmallData : gEmbeddedNNUEBigData)),
size_t(netSize == Small ? gEmbeddedNNUESmallSize : gEmbeddedNNUEBigSize));
(void) gEmbeddedNNUEBigEnd; // Silence warning on unused variable
(void) gEmbeddedNNUESmallEnd;
std::istream stream(&buffer);
auto description = NNUE::load_eval(stream, netSize);
if (description.has_value())
{
evalFile.current = user_eval_file;
evalFile.netDescription = description.value();
}
}
}
}
}
return evalFiles;
}
// Verifies that the last net used was loaded successfully
void NNUE::verify(const OptionsMap& options,
const std::unordered_map<Eval::NNUE::NetSize, EvalFile>& evalFiles) {
for (const auto& [netSize, evalFile] : evalFiles)
{
std::string user_eval_file = options[evalFile.optionName];
if (user_eval_file.empty())
user_eval_file = evalFile.defaultName;
if (evalFile.current != user_eval_file)
{
std::string msg1 =
"Network evaluation parameters compatible with the engine must be available.";
std::string msg2 =
"The network file " + user_eval_file + " was not loaded successfully.";
std::string msg3 = "The UCI option EvalFile might need to specify the full path, "
"including the directory name, to the network file.";
std::string msg4 = "The default net can be downloaded from: "
"https://tests.stockfishchess.org/api/nn/"
+ evalFile.defaultName;
std::string msg5 = "The engine will be terminated now.";
sync_cout << "info string ERROR: " << msg1 << sync_endl;
sync_cout << "info string ERROR: " << msg2 << sync_endl;
sync_cout << "info string ERROR: " << msg3 << sync_endl;
sync_cout << "info string ERROR: " << msg4 << sync_endl;
sync_cout << "info string ERROR: " << msg5 << sync_endl;
exit(EXIT_FAILURE);
}
sync_cout << "info string NNUE evaluation using " << user_eval_file << sync_endl;
}
}
}
// Returns a static, purely materialistic evaluation of the position from
// the point of view of the given color. It can be divided by PawnValue to get
// an approximation of the material advantage on the board in terms of pawns.
@@ -185,31 +45,44 @@ int Eval::simple_eval(const Position& pos, Color c) {
+ (pos.non_pawn_material(c) - pos.non_pawn_material(~c));
}
bool Eval::use_smallnet(const Position& pos) {
int simpleEval = simple_eval(pos, pos.side_to_move());
return std::abs(simpleEval) > 962;
}
// Evaluate is the evaluator for the outer world. It returns a static evaluation
// of the position from the point of view of the side to move.
Value Eval::evaluate(const Position& pos, int optimism) {
Value Eval::evaluate(const Eval::NNUE::Networks& networks,
const Position& pos,
Eval::NNUE::AccumulatorCaches& caches,
int optimism) {
assert(!pos.checkers());
int simpleEval = simple_eval(pos, pos.side_to_move());
bool smallNet = std::abs(simpleEval) > 1050;
bool smallNet = use_smallnet(pos);
auto [psqt, positional] = smallNet ? networks.small.evaluate(pos, &caches.small)
: networks.big.evaluate(pos, &caches.big);
int nnueComplexity;
Value nnue = (125 * psqt + 131 * positional) / 128;
Value nnue = smallNet ? NNUE::evaluate<NNUE::Small>(pos, true, &nnueComplexity)
: NNUE::evaluate<NNUE::Big>(pos, true, &nnueComplexity);
// Re-evaluate the position when higher eval accuracy is worth the time spent
if (smallNet && (std::abs(nnue) < 236))
{
std::tie(psqt, positional) = networks.big.evaluate(pos, &caches.big);
nnue = (125 * psqt + 131 * positional) / 128;
smallNet = false;
}
// Blend optimism and eval with nnue complexity and material imbalance
optimism += optimism * (nnueComplexity + std::abs(simpleEval - nnue)) / 512;
nnue -= nnue * (nnueComplexity + std::abs(simpleEval - nnue)) / 32768;
// Blend optimism and eval with nnue complexity
int nnueComplexity = std::abs(psqt - positional);
optimism += optimism * nnueComplexity / 468;
nnue -= nnue * nnueComplexity / (smallNet ? 20233 : 17879);
int npm = pos.non_pawn_material() / 64;
int v = (nnue * (915 + npm + 9 * pos.count<PAWN>()) + optimism * (154 + npm)) / 1024;
int material = 535 * pos.count<PAWN>() + pos.non_pawn_material();
int v = (nnue * (77777 + material) + optimism * (7777 + material)) / 77777;
// Damp down the evaluation linearly when shuffling
int shuffling = pos.rule50_count();
v = v * (200 - shuffling) / 214;
v -= v * pos.rule50_count() / 212;
// Guarantee evaluation does not hit the tablebase range
v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
@@ -221,25 +94,27 @@ Value Eval::evaluate(const Position& pos, int optimism) {
// a string (suitable for outputting to stdout) that contains the detailed
// descriptions and values of each evaluation term. Useful for debugging.
// Trace scores are from white's point of view
std::string Eval::trace(Position& pos) {
std::string Eval::trace(Position& pos, const Eval::NNUE::Networks& networks) {
if (pos.checkers())
return "Final evaluation: none (in check)";
auto caches = std::make_unique<Eval::NNUE::AccumulatorCaches>(networks);
std::stringstream ss;
ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2);
ss << '\n' << NNUE::trace(pos) << '\n';
ss << '\n' << NNUE::trace(pos, networks, *caches) << '\n';
ss << std::showpoint << std::showpos << std::fixed << std::setprecision(2) << std::setw(15);
Value v;
v = NNUE::evaluate<NNUE::Big>(pos, false);
v = pos.side_to_move() == WHITE ? v : -v;
ss << "NNUE evaluation " << 0.01 * UCI::to_cp(v) << " (white side)\n";
auto [psqt, positional] = networks.big.evaluate(pos, &caches->big);
Value v = psqt + positional;
v = pos.side_to_move() == WHITE ? v : -v;
ss << "NNUE evaluation " << 0.01 * UCIEngine::to_cp(v, pos) << " (white side)\n";
v = evaluate(pos, VALUE_ZERO);
v = evaluate(networks, pos, *caches, VALUE_ZERO);
v = pos.side_to_move() == WHITE ? v : -v;
ss << "Final evaluation " << 0.01 * UCI::to_cp(v) << " (white side)";
ss << "Final evaluation " << 0.01 * UCIEngine::to_cp(v, pos) << " (white side)";
ss << " [with scaled NNUE, ...]";
ss << "\n";
+15 -30
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,50 +20,35 @@
#define EVALUATE_H_INCLUDED
#include <string>
#include <unordered_map>
#include "types.h"
namespace Stockfish {
class Position;
class OptionsMap;
namespace Eval {
std::string trace(Position& pos);
int simple_eval(const Position& pos, Color c);
Value evaluate(const Position& pos, int optimism);
// The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue
// for the build process (profile-build and fishtest) to work. Do not change the
// name of the macro, as it is used in the Makefile.
#define EvalFileDefaultNameBig "nn-b1a57edbea57.nnue"
#define EvalFileDefaultNameSmall "nn-baff1ede1f90.nnue"
struct EvalFile {
// UCI option name
std::string optionName;
// Default net name, will use one of the macros above
std::string defaultName;
// Selected net name, either via uci option or default
std::string current;
// Net description extracted from the net file
std::string netDescription;
};
// name of the macro or the location where this macro is defined, as it is used
// in the Makefile/Fishtest.
#define EvalFileDefaultNameBig "nn-287197aae49d.nnue"
#define EvalFileDefaultNameSmall "nn-287197aae49d.nnue"
namespace NNUE {
struct Networks;
struct AccumulatorCaches;
}
enum NetSize : int;
using EvalFiles = std::unordered_map<Eval::NNUE::NetSize, EvalFile>;
EvalFiles load_networks(const std::string&, const OptionsMap&, EvalFiles);
void verify(const OptionsMap&, const EvalFiles&);
} // namespace NNUE
std::string trace(Position& pos, const Eval::NNUE::Networks& networks);
int simple_eval(const Position& pos, Color c);
bool use_smallnet(const Position& pos);
Value evaluate(const NNUE::Networks& networks,
const Position& pos,
Eval::NNUE::AccumulatorCaches& caches,
int optimism);
} // namespace Eval
} // namespace Stockfish
+165
View File
@@ -0,0 +1,165 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HISTORY_H_INCLUDED
#define HISTORY_H_INCLUDED
#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <type_traits> // IWYU pragma: keep
#include "misc.h"
#include "position.h"
namespace Stockfish {
constexpr int PAWN_HISTORY_SIZE = 512; // has to be a power of 2
constexpr int CORRECTION_HISTORY_SIZE = 32768; // has to be a power of 2
constexpr int CORRECTION_HISTORY_LIMIT = 1024;
constexpr int LOW_PLY_HISTORY_SIZE = 4;
static_assert((PAWN_HISTORY_SIZE & (PAWN_HISTORY_SIZE - 1)) == 0,
"PAWN_HISTORY_SIZE has to be a power of 2");
static_assert((CORRECTION_HISTORY_SIZE & (CORRECTION_HISTORY_SIZE - 1)) == 0,
"CORRECTION_HISTORY_SIZE has to be a power of 2");
enum PawnHistoryType {
Normal,
Correction
};
template<PawnHistoryType T = Normal>
inline int pawn_structure_index(const Position& pos) {
return pos.pawn_key() & ((T == Normal ? PAWN_HISTORY_SIZE : CORRECTION_HISTORY_SIZE) - 1);
}
inline int minor_piece_index(const Position& pos) {
return pos.minor_piece_key() & (CORRECTION_HISTORY_SIZE - 1);
}
template<Color c>
inline int non_pawn_index(const Position& pos) {
return pos.non_pawn_key(c) & (CORRECTION_HISTORY_SIZE - 1);
}
// StatsEntry is the container of various numerical statistics. We use a class
// instead of a naked value to directly call history update operator<<() on
// the entry. The first template parameter T is the base type of the array,
// and the second template parameter D limits the range of updates in [-D, D]
// when we update values with the << operator
template<typename T, int D>
class StatsEntry {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
T entry;
public:
StatsEntry& operator=(const T& v) {
entry = v;
return *this;
}
operator const T&() const { return entry; }
void operator<<(int bonus) {
// Make sure that bonus is in range [-D, D]
int clampedBonus = std::clamp(bonus, -D, D);
entry += clampedBonus - entry * std::abs(clampedBonus) / D;
assert(std::abs(entry) <= D);
}
};
enum StatsType {
NoCaptures,
Captures
};
template<typename T, int D, std::size_t... Sizes>
using Stats = MultiArray<StatsEntry<T, D>, Sizes...>;
// ButterflyHistory records how often quiet moves have been successful or unsuccessful
// during the current search, and is used for reduction and move ordering decisions.
// It uses 2 tables (one for each color) indexed by the move's from and to squares,
// see https://www.chessprogramming.org/Butterfly_Boards (~11 elo)
using ButterflyHistory = Stats<std::int16_t, 7183, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)>;
// LowPlyHistory is adressed by play and move's from and to squares, used
// to improve move ordering near the root
using LowPlyHistory =
Stats<std::int16_t, 7183, LOW_PLY_HISTORY_SIZE, int(SQUARE_NB) * int(SQUARE_NB)>;
// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
using CapturePieceToHistory = Stats<std::int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;
// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
using PieceToHistory = Stats<std::int16_t, 30000, PIECE_NB, SQUARE_NB>;
// ContinuationHistory is the combined history of a given pair of moves, usually
// the current one given a previous one. The nested history table is based on
// PieceToHistory instead of ButterflyBoards.
// (~63 elo)
using ContinuationHistory = MultiArray<PieceToHistory, PIECE_NB, SQUARE_NB>;
// PawnHistory is addressed by the pawn structure and a move's [piece][to]
using PawnHistory = Stats<std::int16_t, 8192, PAWN_HISTORY_SIZE, PIECE_NB, SQUARE_NB>;
// Correction histories record differences between the static evaluation of
// positions and their search score. It is used to improve the static evaluation
// used by some search heuristics.
// see https://www.chessprogramming.org/Static_Evaluation_Correction_History
enum CorrHistType {
Pawn, // By color and pawn structure
Minor, // By color and positions of minor pieces (Knight, Bishop)
NonPawn, // By non-pawn material positions and color
PieceTo, // By [piece][to] move
Continuation, // Combined history of move pairs
};
namespace Detail {
template<CorrHistType>
struct CorrHistTypedef {
using type = Stats<std::int16_t, CORRECTION_HISTORY_LIMIT, CORRECTION_HISTORY_SIZE, COLOR_NB>;
};
template<>
struct CorrHistTypedef<PieceTo> {
using type = Stats<std::int16_t, CORRECTION_HISTORY_LIMIT, PIECE_NB, SQUARE_NB>;
};
template<>
struct CorrHistTypedef<Continuation> {
using type = MultiArray<CorrHistTypedef<PieceTo>::type, PIECE_NB, SQUARE_NB>;
};
}
template<CorrHistType T>
using CorrectionHistory = typename Detail::CorrHistTypedef<T>::type;
} // namespace Stockfish
#endif // #ifndef HISTORY_H_INCLUDED
+167 -59
View File
@@ -3,8 +3,8 @@
* @author Dale Weiler
* @brief Utility for including binary files
*
* Facilities for including binary files into the current translation unit
* and making use of them externally in other translation units.
* Facilities for including binary files into the current translation unit and
* making use from them externally in other translation units.
*/
#ifndef INCBIN_HDR
#define INCBIN_HDR
@@ -26,7 +26,9 @@
defined(__SSSE3__) || \
defined(__SSE4_1__) || \
defined(__SSE4_2__) || \
defined(__neon__)
defined(__neon__) || \
defined(__ARM_NEON) || \
defined(__ALTIVEC__)
# define INCBIN_ALIGNMENT_INDEX 4
#elif ULONG_MAX != 0xffffffffu
# define INCBIN_ALIGNMENT_INDEX 3
@@ -64,6 +66,9 @@
X
#define INCBIN_INVOKE(N, ...) \
INCBIN_EVAL(N(__VA_ARGS__))
/* Variable argument count for overloading by arity */
#define INCBIN_VA_ARG_COUNTER(_1, _2, _3, N, ...) N
#define INCBIN_VA_ARGC(...) INCBIN_VA_ARG_COUNTER(__VA_ARGS__, 3, 2, 1, 0)
/* Green Hills uses a different directive for including binary data */
#if defined(__ghs__)
@@ -117,29 +122,50 @@
#endif
/**
* @brief Optionally override the linker section into which data is emitted.
*
* @warning If you use this facility, you'll have to deal with platform-specific linker output
* section naming on your own
*
* Overriding the default linker output section, e.g for esp8266/Arduino:
* @code
* #define INCBIN_OUTPUT_SECTION ".irom.text"
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
* // Data is emitted into program memory that never gets copied to RAM
* @endcode
* @brief Optionally override the linker section into which size and data is
* emitted.
*
* @warning If you use this facility, you might have to deal with
* platform-specific linker output section naming on your own.
*/
#if !defined(INCBIN_OUTPUT_SECTION)
# if defined(__APPLE__)
# define INCBIN_OUTPUT_SECTION ".const_data"
# define INCBIN_OUTPUT_SECTION ".const_data"
# else
# define INCBIN_OUTPUT_SECTION ".rodata"
# define INCBIN_OUTPUT_SECTION ".rodata"
# endif
#endif
/**
* @brief Optionally override the linker section into which data is emitted.
*
* @warning If you use this facility, you might have to deal with
* platform-specific linker output section naming on your own.
*/
#if !defined(INCBIN_OUTPUT_DATA_SECTION)
# define INCBIN_OUTPUT_DATA_SECTION INCBIN_OUTPUT_SECTION
#endif
/**
* @brief Optionally override the linker section into which size is emitted.
*
* @warning If you use this facility, you might have to deal with
* platform-specific linker output section naming on your own.
*
* @note This is useful for Harvard architectures where program memory cannot
* be directly read from the program without special instructions. With this you
* can chose to put the size variable in RAM rather than ROM.
*/
#if !defined(INCBIN_OUTPUT_SIZE_SECTION)
# define INCBIN_OUTPUT_SIZE_SECTION INCBIN_OUTPUT_SECTION
#endif
#if defined(__APPLE__)
/* The directives are different for Apple-branded compilers */
# include "TargetConditionals.h"
# if defined(TARGET_OS_IPHONE) && !defined(INCBIN_SILENCE_BITCODE_WARNING)
# warning "incbin is incompatible with bitcode. Using the library will break upload to App Store if you have bitcode enabled. Add `#define INCBIN_SILENCE_BITCODE_WARNING` before including this header to silence this warning."
# endif
/* The directives are different for Apple branded compilers */
# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
# define INCBIN_INT ".long "
@@ -179,27 +205,17 @@
/**
* @brief Specify the prefix to use for symbol names.
*
* By default this is `g', producing symbols of the form:
* @code
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
* @note By default this is "g".
*
* // Now you have the following symbols:
* // const unsigned char gFooData[];
* // const unsigned char *const gFooEnd;
* // const unsigned int gFooSize;
* @endcode
*
* If however you specify a prefix before including: e.g:
* @code
* #define INCBIN_PREFIX incbin
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols instead:
* // const unsigned char incbinFooData[];
* // const unsigned char *const incbinFooEnd;
* // const unsigned int incbinFooSize;
* // const unsigned char incbinFoo<data>[];
* // const unsigned char *const incbinFoo<end>;
* // const unsigned int incbinFoo<size>;
* @endcode
*/
#if !defined(INCBIN_PREFIX)
@@ -213,18 +229,8 @@
* - INCBIN_STYLE_CAMEL "CamelCase"
* - INCBIN_STYLE_SNAKE "snake_case"
*
* Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
* @code
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
* @note By default this is INCBIN_STYLE_CAMEL
*
* // Now you have the following symbols:
* // const unsigned char <prefix>FooData[];
* // const unsigned char *const <prefix>FooEnd;
* // const unsigned int <prefix>FooSize;
* @endcode
*
* If however you specify a style before including: e.g:
* @code
* #define INCBIN_STYLE INCBIN_STYLE_SNAKE
* #include "incbin.h"
@@ -261,8 +267,8 @@
INCBIN_STRINGIZE( \
INCBIN_STYLE_IDENT(TYPE)) \
/* Generate the global labels by indirectly invoking the macro
* with our style type and concatenate the name against them. */
/* Generate the global labels by indirectly invoking the macro with our style
* type and concatenating the name against them. */
#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
INCBIN_INVOKE( \
INCBIN_GLOBAL, \
@@ -288,23 +294,38 @@
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
* @param NAME The name given for the binary data
*
* @code
* INCBIN_EXTERN(Foo);
*
* // Now you have the following symbols:
* // extern const unsigned char <prefix>FooData[];
* // extern const unsigned char *const <prefix>FooEnd;
* // extern const unsigned int <prefix>FooSize;
* // extern const unsigned char <prefix>Foo<data>[];
* // extern const unsigned char *const <prefix>Foo<end>;
* // extern const unsigned int <prefix>Foo<size>;
* @endcode
*
* You may specify a custom optional data type as well as the first argument.
* @code
* INCBIN_EXTERN(custom_type, Foo);
*
* // Now you have the following symbols:
* // extern const custom_type <prefix>Foo<data>[];
* // extern const custom_type *const <prefix>Foo<end>;
* // extern const unsigned int <prefix>Foo<size>;
* @endcode
*/
#define INCBIN_EXTERN(NAME) \
INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
#define INCBIN_EXTERN(...) \
INCBIN_CONCATENATE(INCBIN_EXTERN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
#define INCBIN_EXTERN_1(NAME, ...) \
INCBIN_EXTERN_2(unsigned char, NAME)
#define INCBIN_EXTERN_2(TYPE, NAME) \
INCBIN_EXTERNAL const INCBIN_ALIGN TYPE \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(DATA))[]; \
INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
INCBIN_EXTERNAL const INCBIN_ALIGN TYPE *const \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(END)); \
@@ -313,6 +334,29 @@
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(SIZE))
/**
* @brief Externally reference textual data included in another translation unit.
*
* Produces three external symbols that reference the textual data included in
* another translation unit.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name given for the textual data
*
* @code
* INCBIN_EXTERN(Foo);
*
* // Now you have the following symbols:
* // extern const char <prefix>Foo<data>[];
* // extern const char *const <prefix>Foo<end>;
* // extern const unsigned int <prefix>Foo<size>;
* @endcode
*/
#define INCTXT_EXTERN(NAME) \
INCBIN_EXTERN_2(char, NAME)
/**
* @brief Include a binary file into the current translation unit.
*
@@ -322,6 +366,7 @@
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
* @param NAME The name to associate with this binary data (as an identifier.)
* @param FILENAME The file to include (as a string literal.)
*
@@ -329,9 +374,20 @@
* INCBIN(Icon, "icon.png");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>IconData[];
* // const unsigned char *const <prefix>IconEnd;
* // const unsigned int <prefix>IconSize;
* // const unsigned char <prefix>Icon<data>[];
* // const unsigned char *const <prefix>Icon<end>;
* // const unsigned int <prefix>Icon<size>;
* @endcode
*
* You may specify a custom optional data type as well as the first argument.
* These macros are specialized by arity.
* @code
* INCBIN(custom_type, Icon, "icon.png");
*
* // Now you have the following symbols:
* // const custom_type <prefix>Icon<data>[];
* // const custom_type *const <prefix>Icon<end>;
* // const unsigned int <prefix>Icon<size>;
* @endcode
*
* @warning This must be used in global scope
@@ -341,15 +397,28 @@
* please @see INCBIN_EXTERN.
*/
#ifdef _MSC_VER
#define INCBIN(NAME, FILENAME) \
INCBIN_EXTERN(NAME)
# define INCBIN(NAME, FILENAME) \
INCBIN_EXTERN(NAME)
#else
#define INCBIN(NAME, FILENAME) \
# define INCBIN(...) \
INCBIN_CONCATENATE(INCBIN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
# if defined(__GNUC__)
# define INCBIN_1(...) _Pragma("GCC error \"Single argument INCBIN not allowed\"")
# elif defined(__clang__)
# define INCBIN_1(...) _Pragma("clang error \"Single argument INCBIN not allowed\"")
# else
# define INCBIN_1(...) /* Cannot do anything here */
# endif
# define INCBIN_2(NAME, FILENAME) \
INCBIN_3(unsigned char, NAME, FILENAME)
# define INCBIN_3(TYPE, NAME, FILENAME) INCBIN_COMMON(TYPE, NAME, FILENAME, /* No terminator for binary data */)
# define INCBIN_COMMON(TYPE, NAME, FILENAME, TERMINATOR) \
__asm__(INCBIN_SECTION \
INCBIN_GLOBAL_LABELS(NAME, DATA) \
INCBIN_ALIGN_HOST \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
INCBIN_MACRO " \"" FILENAME "\"\n" \
TERMINATOR \
INCBIN_GLOBAL_LABELS(NAME, END) \
INCBIN_ALIGN_BYTE \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
@@ -362,7 +431,46 @@
INCBIN_ALIGN_HOST \
".text\n" \
); \
INCBIN_EXTERN(NAME)
INCBIN_EXTERN(TYPE, NAME)
#endif
/**
* @brief Include a textual file into the current translation unit.
*
* This behaves the same as INCBIN except it produces char compatible arrays
* and implicitly adds a null-terminator byte, thus the size of data included
* by this is one byte larger than that of INCBIN.
*
* Includes a textual file into the current translation unit, producing three
* symbols for objects that encode the data and size respectively.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name to associate with this binary data (as an identifier.)
* @param FILENAME The file to include (as a string literal.)
*
* @code
* INCTXT(Readme, "readme.txt");
*
* // Now you have the following symbols:
* // const char <prefix>Readme<data>[];
* // const char *const <prefix>Readme<end>;
* // const unsigned int <prefix>Readme<size>;
* @endcode
*
* @warning This must be used in global scope
* @warning The identifiers may be different if INCBIN_STYLE is not default
*
* To externally reference the data included by this in another translation unit
* please @see INCBIN_EXTERN.
*/
#if defined(_MSC_VER)
# define INCTXT(NAME, FILENAME) \
INCBIN_EXTERN(NAME)
#else
# define INCTXT(NAME, FILENAME) \
INCBIN_COMMON(char, NAME, FILENAME, INCBIN_BYTE "0\n")
#endif
#endif
#endif
+4 -8
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,15 +17,13 @@
*/
#include <iostream>
#include <unordered_map>
#include "bitboard.h"
#include "evaluate.h"
#include "misc.h"
#include "position.h"
#include "tune.h"
#include "types.h"
#include "uci.h"
#include "tune.h"
using namespace Stockfish;
@@ -36,11 +34,9 @@ int main(int argc, char* argv[]) {
Bitboards::init();
Position::init();
UCI uci(argc, argv);
UCIEngine uci(argc, argv);
Tune::init(uci.options);
uci.evalFiles = Eval::NNUE::load_networks(uci.workingDirectory(), uci.options, uci.evalFiles);
Tune::init(uci.engine_options());
uci.loop();
+268
View File
@@ -0,0 +1,268 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "memory.h"
#include <cstdlib>
#if __has_include("features.h")
#include <features.h>
#endif
#if defined(__linux__) && !defined(__ANDROID__)
#include <sys/mman.h>
#endif
#if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) \
|| (defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) && !defined(_WIN32)) \
|| defined(__e2k__)
#define POSIXALIGNEDALLOC
#include <stdlib.h>
#endif
#ifdef _WIN32
#if _WIN32_WINNT < 0x0601
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601 // Force to include needed API prototypes
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <ios> // std::hex, std::dec
#include <iostream> // std::cerr
#include <ostream> // std::endl
#include <windows.h>
// The needed Windows API for processor groups could be missed from old Windows
// versions, so instead of calling them directly (forcing the linker to resolve
// the calls at compile time), try to load them at runtime. To do this we need
// first to define the corresponding function pointers.
extern "C" {
using OpenProcessToken_t = bool (*)(HANDLE, DWORD, PHANDLE);
using LookupPrivilegeValueA_t = bool (*)(LPCSTR, LPCSTR, PLUID);
using AdjustTokenPrivileges_t =
bool (*)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
}
#endif
namespace Stockfish {
// Wrappers for systems where the c++17 implementation does not guarantee the
// availability of aligned_alloc(). Memory allocated with std_aligned_alloc()
// must be freed with std_aligned_free().
void* std_aligned_alloc(size_t alignment, size_t size) {
#if defined(_ISOC11_SOURCE)
return aligned_alloc(alignment, size);
#elif defined(POSIXALIGNEDALLOC)
void* mem = nullptr;
posix_memalign(&mem, alignment, size);
return mem;
#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64)
return _mm_malloc(size, alignment);
#elif defined(_WIN32)
return _aligned_malloc(size, alignment);
#else
return std::aligned_alloc(alignment, size);
#endif
}
void std_aligned_free(void* ptr) {
#if defined(POSIXALIGNEDALLOC)
free(ptr);
#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64)
_mm_free(ptr);
#elif defined(_WIN32)
_aligned_free(ptr);
#else
free(ptr);
#endif
}
// aligned_large_pages_alloc() will return suitably aligned memory,
// if possible using large pages.
#if defined(_WIN32)
static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize) {
#if !defined(_WIN64)
return nullptr;
#else
HANDLE hProcessToken{};
LUID luid{};
void* mem = nullptr;
const size_t largePageSize = GetLargePageMinimum();
if (!largePageSize)
return nullptr;
// Dynamically link OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges
HMODULE hAdvapi32 = GetModuleHandle(TEXT("advapi32.dll"));
if (!hAdvapi32)
hAdvapi32 = LoadLibrary(TEXT("advapi32.dll"));
auto OpenProcessToken_f =
OpenProcessToken_t((void (*)()) GetProcAddress(hAdvapi32, "OpenProcessToken"));
if (!OpenProcessToken_f)
return nullptr;
auto LookupPrivilegeValueA_f =
LookupPrivilegeValueA_t((void (*)()) GetProcAddress(hAdvapi32, "LookupPrivilegeValueA"));
if (!LookupPrivilegeValueA_f)
return nullptr;
auto AdjustTokenPrivileges_f =
AdjustTokenPrivileges_t((void (*)()) GetProcAddress(hAdvapi32, "AdjustTokenPrivileges"));
if (!AdjustTokenPrivileges_f)
return nullptr;
// We need SeLockMemoryPrivilege, so try to enable it for the process
if (!OpenProcessToken_f( // OpenProcessToken()
GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken))
return nullptr;
if (LookupPrivilegeValueA_f(nullptr, "SeLockMemoryPrivilege", &luid))
{
TOKEN_PRIVILEGES tp{};
TOKEN_PRIVILEGES prevTp{};
DWORD prevTpLen = 0;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges()
// succeeds, we still need to query GetLastError() to ensure that the privileges
// were actually obtained.
if (AdjustTokenPrivileges_f(hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp,
&prevTpLen)
&& GetLastError() == ERROR_SUCCESS)
{
// Round up size to full pages and allocate
allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
mem = VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
PAGE_READWRITE);
// Privilege no longer needed, restore previous state
AdjustTokenPrivileges_f(hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr);
}
}
CloseHandle(hProcessToken);
return mem;
#endif
}
void* aligned_large_pages_alloc(size_t allocSize) {
// Try to allocate large pages
void* mem = aligned_large_pages_alloc_windows(allocSize);
// Fall back to regular, page-aligned, allocation if necessary
if (!mem)
mem = VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
return mem;
}
#else
void* aligned_large_pages_alloc(size_t allocSize) {
#if defined(__linux__)
constexpr size_t alignment = 2 * 1024 * 1024; // 2MB page size assumed
#else
constexpr size_t alignment = 4096; // small page size assumed
#endif
// Round up to multiples of alignment
size_t size = ((allocSize + alignment - 1) / alignment) * alignment;
void* mem = std_aligned_alloc(alignment, size);
#if defined(MADV_HUGEPAGE)
madvise(mem, size, MADV_HUGEPAGE);
#endif
return mem;
}
#endif
bool has_large_pages() {
#if defined(_WIN32)
constexpr size_t page_size = 2 * 1024 * 1024; // 2MB page size assumed
void* mem = aligned_large_pages_alloc_windows(page_size);
if (mem == nullptr)
{
return false;
}
else
{
aligned_large_pages_free(mem);
return true;
}
#elif defined(__linux__)
#if defined(MADV_HUGEPAGE)
return true;
#else
return false;
#endif
#else
return false;
#endif
}
// aligned_large_pages_free() will free the previously memory allocated
// by aligned_large_pages_alloc(). The effect is a nop if mem == nullptr.
#if defined(_WIN32)
void aligned_large_pages_free(void* mem) {
if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
{
DWORD err = GetLastError();
std::cerr << "Failed to free large page memory. Error code: 0x" << std::hex << err
<< std::dec << std::endl;
exit(EXIT_FAILURE);
}
}
#else
void aligned_large_pages_free(void* mem) { std_aligned_free(mem); }
#endif
} // namespace Stockfish
+218
View File
@@ -0,0 +1,218 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MEMORY_H_INCLUDED
#define MEMORY_H_INCLUDED
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "types.h"
namespace Stockfish {
void* std_aligned_alloc(size_t alignment, size_t size);
void std_aligned_free(void* ptr);
// Memory aligned by page size, min alignment: 4096 bytes
void* aligned_large_pages_alloc(size_t size);
void aligned_large_pages_free(void* mem);
bool has_large_pages();
// Frees memory which was placed there with placement new.
// Works for both single objects and arrays of unknown bound.
template<typename T, typename FREE_FUNC>
void memory_deleter(T* ptr, FREE_FUNC free_func) {
if (!ptr)
return;
// Explicitly needed to call the destructor
if constexpr (!std::is_trivially_destructible_v<T>)
ptr->~T();
free_func(ptr);
return;
}
// Frees memory which was placed there with placement new.
// Works for both single objects and arrays of unknown bound.
template<typename T, typename FREE_FUNC>
void memory_deleter_array(T* ptr, FREE_FUNC free_func) {
if (!ptr)
return;
// Move back on the pointer to where the size is allocated
const size_t array_offset = std::max(sizeof(size_t), alignof(T));
char* raw_memory = reinterpret_cast<char*>(ptr) - array_offset;
if constexpr (!std::is_trivially_destructible_v<T>)
{
const size_t size = *reinterpret_cast<size_t*>(raw_memory);
// Explicitly call the destructor for each element in reverse order
for (size_t i = size; i-- > 0;)
ptr[i].~T();
}
free_func(raw_memory);
}
// Allocates memory for a single object and places it there with placement new
template<typename T, typename ALLOC_FUNC, typename... Args>
inline std::enable_if_t<!std::is_array_v<T>, T*> memory_allocator(ALLOC_FUNC alloc_func,
Args&&... args) {
void* raw_memory = alloc_func(sizeof(T));
ASSERT_ALIGNED(raw_memory, alignof(T));
return new (raw_memory) T(std::forward<Args>(args)...);
}
// Allocates memory for an array of unknown bound and places it there with placement new
template<typename T, typename ALLOC_FUNC>
inline std::enable_if_t<std::is_array_v<T>, std::remove_extent_t<T>*>
memory_allocator(ALLOC_FUNC alloc_func, size_t num) {
using ElementType = std::remove_extent_t<T>;
const size_t array_offset = std::max(sizeof(size_t), alignof(ElementType));
// Save the array size in the memory location
char* raw_memory =
reinterpret_cast<char*>(alloc_func(array_offset + num * sizeof(ElementType)));
ASSERT_ALIGNED(raw_memory, alignof(T));
new (raw_memory) size_t(num);
for (size_t i = 0; i < num; ++i)
new (raw_memory + array_offset + i * sizeof(ElementType)) ElementType();
// Need to return the pointer at the start of the array so that
// the indexing in unique_ptr<T[]> works.
return reinterpret_cast<ElementType*>(raw_memory + array_offset);
}
//
//
// aligned large page unique ptr
//
//
template<typename T>
struct LargePageDeleter {
void operator()(T* ptr) const { return memory_deleter<T>(ptr, aligned_large_pages_free); }
};
template<typename T>
struct LargePageArrayDeleter {
void operator()(T* ptr) const { return memory_deleter_array<T>(ptr, aligned_large_pages_free); }
};
template<typename T>
using LargePagePtr =
std::conditional_t<std::is_array_v<T>,
std::unique_ptr<T, LargePageArrayDeleter<std::remove_extent_t<T>>>,
std::unique_ptr<T, LargePageDeleter<T>>>;
// make_unique_large_page for single objects
template<typename T, typename... Args>
std::enable_if_t<!std::is_array_v<T>, LargePagePtr<T>> make_unique_large_page(Args&&... args) {
static_assert(alignof(T) <= 4096,
"aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
T* obj = memory_allocator<T>(aligned_large_pages_alloc, std::forward<Args>(args)...);
return LargePagePtr<T>(obj);
}
// make_unique_large_page for arrays of unknown bound
template<typename T>
std::enable_if_t<std::is_array_v<T>, LargePagePtr<T>> make_unique_large_page(size_t num) {
using ElementType = std::remove_extent_t<T>;
static_assert(alignof(ElementType) <= 4096,
"aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
ElementType* memory = memory_allocator<T>(aligned_large_pages_alloc, num);
return LargePagePtr<T>(memory);
}
//
//
// aligned unique ptr
//
//
template<typename T>
struct AlignedDeleter {
void operator()(T* ptr) const { return memory_deleter<T>(ptr, std_aligned_free); }
};
template<typename T>
struct AlignedArrayDeleter {
void operator()(T* ptr) const { return memory_deleter_array<T>(ptr, std_aligned_free); }
};
template<typename T>
using AlignedPtr =
std::conditional_t<std::is_array_v<T>,
std::unique_ptr<T, AlignedArrayDeleter<std::remove_extent_t<T>>>,
std::unique_ptr<T, AlignedDeleter<T>>>;
// make_unique_aligned for single objects
template<typename T, typename... Args>
std::enable_if_t<!std::is_array_v<T>, AlignedPtr<T>> make_unique_aligned(Args&&... args) {
const auto func = [](size_t size) { return std_aligned_alloc(alignof(T), size); };
T* obj = memory_allocator<T>(func, std::forward<Args>(args)...);
return AlignedPtr<T>(obj);
}
// make_unique_aligned for arrays of unknown bound
template<typename T>
std::enable_if_t<std::is_array_v<T>, AlignedPtr<T>> make_unique_aligned(size_t num) {
using ElementType = std::remove_extent_t<T>;
const auto func = [](size_t size) { return std_aligned_alloc(alignof(ElementType), size); };
ElementType* memory = memory_allocator<T>(func, num);
return AlignedPtr<T>(memory);
}
// Get the first aligned element of an array.
// ptr must point to an array of size at least `sizeof(T) * N + alignment` bytes,
// where N is the number of elements in the array.
template<uintptr_t Alignment, typename T>
T* align_ptr_up(T* ptr) {
static_assert(alignof(T) < Alignment);
const uintptr_t ptrint = reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(ptr));
return reinterpret_cast<T*>(
reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
}
} // namespace Stockfish
#endif // #ifndef MEMORY_H_INCLUDED
+116 -370
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,64 +18,29 @@
#include "misc.h"
#ifdef _WIN32
#if _WIN32_WINNT < 0x0601
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601 // Force to include needed API prototypes
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
// The needed Windows API for processor groups could be missed from old Windows
// versions, so instead of calling them directly (forcing the linker to resolve
// the calls at compile time), try to load them at runtime. To do this we need
// first to define the corresponding function pointers.
extern "C" {
using fun1_t = bool (*)(LOGICAL_PROCESSOR_RELATIONSHIP,
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX,
PDWORD);
using fun2_t = bool (*)(USHORT, PGROUP_AFFINITY);
using fun3_t = bool (*)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
using fun4_t = bool (*)(USHORT, PGROUP_AFFINITY, USHORT, PUSHORT);
using fun5_t = WORD (*)();
using fun6_t = bool (*)(HANDLE, DWORD, PHANDLE);
using fun7_t = bool (*)(LPCSTR, LPCSTR, PLUID);
using fun8_t = bool (*)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
}
#endif
#include <array>
#include <atomic>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <mutex>
#include <sstream>
#include <string_view>
#include "types.h"
#if defined(__linux__) && !defined(__ANDROID__)
#include <sys/mman.h>
#endif
#if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) \
|| (defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) && !defined(_WIN32)) \
|| defined(__e2k__)
#define POSIXALIGNEDALLOC
#include <stdlib.h>
#endif
namespace Stockfish {
namespace {
// Version number or dev.
constexpr std::string_view version = "16.1";
constexpr std::string_view version = "dev";
// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
@@ -149,15 +114,17 @@ class Logger {
// Returns the full name of the current Stockfish version.
// For local dev compiles we try to append the commit sha and commit date
// from git if that fails only the local compilation date is set and "nogit" is specified:
// Stockfish dev-YYYYMMDD-SHA
// or
// Stockfish dev-YYYYMMDD-nogit
//
// For local dev compiles we try to append the commit SHA and
// commit date from git. If that fails only the local compilation
// date is set and "nogit" is specified:
// Stockfish dev-YYYYMMDD-SHA
// or
// Stockfish dev-YYYYMMDD-nogit
//
// For releases (non-dev builds) we only include the version number:
// Stockfish version
std::string engine_info(bool to_uci) {
// Stockfish version
std::string engine_version_info() {
std::stringstream ss;
ss << "Stockfish " << version << std::setfill('0');
@@ -168,8 +135,9 @@ std::string engine_info(bool to_uci) {
ss << stringify(GIT_DATE);
#else
constexpr std::string_view months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
std::string month, day, year;
std::stringstream date(__DATE__); // From compiler, format is "Sep 21 2008"
std::string month, day, year;
std::stringstream date(__DATE__); // From compiler, format is "Sep 21 2008"
date >> month >> day >> year;
ss << year << std::setw(2) << std::setfill('0') << (1 + months.find(month) / 4)
@@ -185,11 +153,14 @@ std::string engine_info(bool to_uci) {
#endif
}
ss << (to_uci ? "\nid author " : " by ") << "the Stockfish developers (see AUTHORS file)";
return ss.str();
}
std::string engine_info(bool to_uci) {
return engine_version_info() + (to_uci ? "\nid author " : " by ")
+ "the Stockfish developers (see AUTHORS file)";
}
// Returns a string trying to describe the compiler we use
std::string compiler_info() {
@@ -318,44 +289,67 @@ template<size_t N>
struct DebugInfo {
std::atomic<int64_t> data[N] = {0};
constexpr inline std::atomic<int64_t>& operator[](int index) { return data[index]; }
[[nodiscard]] constexpr std::atomic<int64_t>& operator[](size_t index) {
assert(index < N);
return data[index];
}
};
DebugInfo<2> hit[MaxDebugSlots];
DebugInfo<2> mean[MaxDebugSlots];
DebugInfo<3> stdev[MaxDebugSlots];
DebugInfo<6> correl[MaxDebugSlots];
struct DebugExtremes: public DebugInfo<3> {
DebugExtremes() {
data[1] = std::numeric_limits<int64_t>::min();
data[2] = std::numeric_limits<int64_t>::max();
}
};
std::array<DebugInfo<2>, MaxDebugSlots> hit;
std::array<DebugInfo<2>, MaxDebugSlots> mean;
std::array<DebugInfo<3>, MaxDebugSlots> stdev;
std::array<DebugInfo<6>, MaxDebugSlots> correl;
std::array<DebugExtremes, MaxDebugSlots> extremes;
} // namespace
void dbg_hit_on(bool cond, int slot) {
++hit[slot][0];
++hit.at(slot)[0];
if (cond)
++hit[slot][1];
++hit.at(slot)[1];
}
void dbg_mean_of(int64_t value, int slot) {
++mean[slot][0];
mean[slot][1] += value;
++mean.at(slot)[0];
mean.at(slot)[1] += value;
}
void dbg_stdev_of(int64_t value, int slot) {
++stdev[slot][0];
stdev[slot][1] += value;
stdev[slot][2] += value * value;
++stdev.at(slot)[0];
stdev.at(slot)[1] += value;
stdev.at(slot)[2] += value * value;
}
void dbg_extremes_of(int64_t value, int slot) {
++extremes.at(slot)[0];
int64_t current_max = extremes.at(slot)[1].load();
while (current_max < value && !extremes.at(slot)[1].compare_exchange_weak(current_max, value))
{}
int64_t current_min = extremes.at(slot)[2].load();
while (current_min > value && !extremes.at(slot)[2].compare_exchange_weak(current_min, value))
{}
}
void dbg_correl_of(int64_t value1, int64_t value2, int slot) {
++correl[slot][0];
correl[slot][1] += value1;
correl[slot][2] += value1 * value1;
correl[slot][3] += value2;
correl[slot][4] += value2 * value2;
correl[slot][5] += value1 * value2;
++correl.at(slot)[0];
correl.at(slot)[1] += value1;
correl.at(slot)[2] += value1 * value1;
correl.at(slot)[3] += value2;
correl.at(slot)[4] += value2 * value2;
correl.at(slot)[5] += value1 * value2;
}
void dbg_print() {
@@ -382,6 +376,13 @@ void dbg_print() {
std::cerr << "Stdev #" << i << ": Total " << n << " Stdev " << r << std::endl;
}
for (int i = 0; i < MaxDebugSlots; ++i)
if ((n = extremes[i][0]))
{
std::cerr << "Extremity #" << i << ": Total " << n << " Min " << extremes[i][2]
<< " Max " << extremes[i][1] << std::endl;
}
for (int i = 0; i < MaxDebugSlots; ++i)
if ((n = correl[i][0]))
{
@@ -408,6 +409,8 @@ std::ostream& operator<<(std::ostream& os, SyncCout sc) {
return os;
}
void sync_cout_start() { std::cout << IO_LOCK; }
void sync_cout_end() { std::cout << IO_UNLOCK; }
// Trampoline helper to avoid moving Logger to misc.h
void start_logger(const std::string& fname) { Logger::start(fname); }
@@ -415,14 +418,14 @@ void start_logger(const std::string& fname) { Logger::start(fname); }
#ifdef NO_PREFETCH
void prefetch(void*) {}
void prefetch(const void*) {}
#else
void prefetch(void* addr) {
void prefetch(const void* addr) {
#if defined(_MSC_VER)
_mm_prefetch((char*) addr, _MM_HINT_T0);
_mm_prefetch((char const*) addr, _MM_HINT_T0);
#else
__builtin_prefetch(addr);
#endif
@@ -430,289 +433,6 @@ void prefetch(void* addr) {
#endif
// Wrapper for systems where the c++17 implementation
// does not guarantee the availability of aligned_alloc(). Memory allocated with
// std_aligned_alloc() must be freed with std_aligned_free().
void* std_aligned_alloc(size_t alignment, size_t size) {
#if defined(POSIXALIGNEDALLOC)
void* mem;
return posix_memalign(&mem, alignment, size) ? nullptr : mem;
#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64)
return _mm_malloc(size, alignment);
#elif defined(_WIN32)
return _aligned_malloc(size, alignment);
#else
return std::aligned_alloc(alignment, size);
#endif
}
void std_aligned_free(void* ptr) {
#if defined(POSIXALIGNEDALLOC)
free(ptr);
#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64)
_mm_free(ptr);
#elif defined(_WIN32)
_aligned_free(ptr);
#else
free(ptr);
#endif
}
// aligned_large_pages_alloc() will return suitably aligned memory, if possible using large pages.
#if defined(_WIN32)
static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize) {
#if !defined(_WIN64)
return nullptr;
#else
HANDLE hProcessToken{};
LUID luid{};
void* mem = nullptr;
const size_t largePageSize = GetLargePageMinimum();
if (!largePageSize)
return nullptr;
// Dynamically link OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges
HMODULE hAdvapi32 = GetModuleHandle(TEXT("advapi32.dll"));
if (!hAdvapi32)
hAdvapi32 = LoadLibrary(TEXT("advapi32.dll"));
auto fun6 = fun6_t((void (*)()) GetProcAddress(hAdvapi32, "OpenProcessToken"));
if (!fun6)
return nullptr;
auto fun7 = fun7_t((void (*)()) GetProcAddress(hAdvapi32, "LookupPrivilegeValueA"));
if (!fun7)
return nullptr;
auto fun8 = fun8_t((void (*)()) GetProcAddress(hAdvapi32, "AdjustTokenPrivileges"));
if (!fun8)
return nullptr;
// We need SeLockMemoryPrivilege, so try to enable it for the process
if (!fun6( // OpenProcessToken()
GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken))
return nullptr;
if (fun7( // LookupPrivilegeValue(nullptr, SE_LOCK_MEMORY_NAME, &luid)
nullptr, "SeLockMemoryPrivilege", &luid))
{
TOKEN_PRIVILEGES tp{};
TOKEN_PRIVILEGES prevTp{};
DWORD prevTpLen = 0;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds,
// we still need to query GetLastError() to ensure that the privileges were actually obtained.
if (fun8( // AdjustTokenPrivileges()
hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen)
&& GetLastError() == ERROR_SUCCESS)
{
// Round up size to full pages and allocate
allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
mem = VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
PAGE_READWRITE);
// Privilege no longer needed, restore previous state
fun8( // AdjustTokenPrivileges ()
hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr);
}
}
CloseHandle(hProcessToken);
return mem;
#endif
}
void* aligned_large_pages_alloc(size_t allocSize) {
// Try to allocate large pages
void* mem = aligned_large_pages_alloc_windows(allocSize);
// Fall back to regular, page-aligned, allocation if necessary
if (!mem)
mem = VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
return mem;
}
#else
void* aligned_large_pages_alloc(size_t allocSize) {
#if defined(__linux__)
constexpr size_t alignment = 2 * 1024 * 1024; // assumed 2MB page size
#else
constexpr size_t alignment = 4096; // assumed small page size
#endif
// Round up to multiples of alignment
size_t size = ((allocSize + alignment - 1) / alignment) * alignment;
void* mem = std_aligned_alloc(alignment, size);
#if defined(MADV_HUGEPAGE)
madvise(mem, size, MADV_HUGEPAGE);
#endif
return mem;
}
#endif
// aligned_large_pages_free() will free the previously allocated ttmem
#if defined(_WIN32)
void aligned_large_pages_free(void* mem) {
if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
{
DWORD err = GetLastError();
std::cerr << "Failed to free large page memory. Error code: 0x" << std::hex << err
<< std::dec << std::endl;
exit(EXIT_FAILURE);
}
}
#else
void aligned_large_pages_free(void* mem) { std_aligned_free(mem); }
#endif
namespace WinProcGroup {
#ifndef _WIN32
void bindThisThread(size_t) {}
#else
// Retrieves logical processor information using Windows-specific
// API and returns the best node id for the thread with index idx. Original
// code from Texel by Peter Österlund.
static int best_node(size_t idx) {
int threads = 0;
int nodes = 0;
int cores = 0;
DWORD returnLength = 0;
DWORD byteOffset = 0;
// Early exit if the needed API is not available at runtime
HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll"));
auto fun1 = (fun1_t) (void (*)()) GetProcAddress(k32, "GetLogicalProcessorInformationEx");
if (!fun1)
return -1;
// First call to GetLogicalProcessorInformationEx() to get returnLength.
// We expect the call to fail due to null buffer.
if (fun1(RelationAll, nullptr, &returnLength))
return -1;
// Once we know returnLength, allocate the buffer
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, *ptr;
ptr = buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) malloc(returnLength);
// Second call to GetLogicalProcessorInformationEx(), now we expect to succeed
if (!fun1(RelationAll, buffer, &returnLength))
{
free(buffer);
return -1;
}
while (byteOffset < returnLength)
{
if (ptr->Relationship == RelationNumaNode)
nodes++;
else if (ptr->Relationship == RelationProcessorCore)
{
cores++;
threads += (ptr->Processor.Flags == LTP_PC_SMT) ? 2 : 1;
}
assert(ptr->Size);
byteOffset += ptr->Size;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) (((char*) ptr) + ptr->Size);
}
free(buffer);
std::vector<int> groups;
// Run as many threads as possible on the same node until the core limit is
// reached, then move on to filling the next node.
for (int n = 0; n < nodes; n++)
for (int i = 0; i < cores / nodes; i++)
groups.push_back(n);
// In case a core has more than one logical processor (we assume 2) and we
// still have threads to allocate, spread them evenly across available nodes.
for (int t = 0; t < threads - cores; t++)
groups.push_back(t % nodes);
// If we still have more threads than the total number of logical processors
// then return -1 and let the OS to decide what to do.
return idx < groups.size() ? groups[idx] : -1;
}
// Sets the group affinity of the current thread
void bindThisThread(size_t idx) {
// Use only local variables to be thread-safe
int node = best_node(idx);
if (node == -1)
return;
// Early exit if the needed API are not available at runtime
HMODULE k32 = GetModuleHandle(TEXT("Kernel32.dll"));
auto fun2 = fun2_t((void (*)()) GetProcAddress(k32, "GetNumaNodeProcessorMaskEx"));
auto fun3 = fun3_t((void (*)()) GetProcAddress(k32, "SetThreadGroupAffinity"));
auto fun4 = fun4_t((void (*)()) GetProcAddress(k32, "GetNumaNodeProcessorMask2"));
auto fun5 = fun5_t((void (*)()) GetProcAddress(k32, "GetMaximumProcessorGroupCount"));
if (!fun2 || !fun3)
return;
if (!fun4 || !fun5)
{
GROUP_AFFINITY affinity;
if (fun2(node, &affinity)) // GetNumaNodeProcessorMaskEx
fun3(GetCurrentThread(), &affinity, nullptr); // SetThreadGroupAffinity
}
else
{
// If a numa node has more than one processor group, we assume they are
// sized equal and we spread threads evenly across the groups.
USHORT elements, returnedElements;
elements = fun5(); // GetMaximumProcessorGroupCount
GROUP_AFFINITY* affinity = (GROUP_AFFINITY*) malloc(elements * sizeof(GROUP_AFFINITY));
if (fun4(node, affinity, elements, &returnedElements)) // GetNumaNodeProcessorMask2
fun3(GetCurrentThread(), &affinity[idx % returnedElements],
nullptr); // SetThreadGroupAffinity
free(affinity);
}
}
#endif
} // namespace WinProcGroup
#ifdef _WIN32
#include <direct.h>
#define GETCWD _getcwd
@@ -721,13 +441,30 @@ void bindThisThread(size_t idx) {
#define GETCWD getcwd
#endif
CommandLine::CommandLine(int _argc, char** _argv) :
argc(_argc),
argv(_argv) {
std::string pathSeparator;
size_t str_to_size_t(const std::string& s) {
unsigned long long value = std::stoull(s);
if (value > std::numeric_limits<size_t>::max())
std::exit(EXIT_FAILURE);
return static_cast<size_t>(value);
}
// Extract the path+name of the executable binary
std::string argv0 = argv[0];
std::optional<std::string> read_file_to_string(const std::string& path) {
std::ifstream f(path, std::ios_base::binary);
if (!f)
return std::nullopt;
return std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>());
}
void remove_whitespace(std::string& s) {
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return std::isspace(c); }), s.end());
}
bool is_whitespace(std::string_view s) {
return std::all_of(s.begin(), s.end(), [](char c) { return std::isspace(c); });
}
std::string CommandLine::get_binary_directory(std::string argv0) {
std::string pathSeparator;
#ifdef _WIN32
pathSeparator = "\\";
@@ -743,15 +480,11 @@ CommandLine::CommandLine(int _argc, char** _argv) :
#endif
// Extract the working directory
workingDirectory = "";
char buff[40000];
char* cwd = GETCWD(buff, 40000);
if (cwd)
workingDirectory = cwd;
auto workingDirectory = CommandLine::get_working_directory();
// Extract the binary directory path from argv0
binaryDirectory = argv0;
size_t pos = binaryDirectory.find_last_of("\\/");
auto binaryDirectory = argv0;
size_t pos = binaryDirectory.find_last_of("\\/");
if (pos == std::string::npos)
binaryDirectory = "." + pathSeparator;
else
@@ -760,6 +493,19 @@ CommandLine::CommandLine(int _argc, char** _argv) :
// Pattern replacement: "./" at the start of path is replaced by the working directory
if (binaryDirectory.find("." + pathSeparator) == 0)
binaryDirectory.replace(0, 1, workingDirectory);
return binaryDirectory;
}
std::string CommandLine::get_working_directory() {
std::string workingDirectory = "";
char buff[40000];
char* cwd = GETCWD(buff, 40000);
if (cwd)
workingDirectory = cwd;
return workingDirectory;
}
} // namespace Stockfish
+148 -40
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,12 +20,16 @@
#define MISC_H_INCLUDED
#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <iosfwd>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#define stringify2(x) #x
@@ -33,25 +37,40 @@
namespace Stockfish {
std::string engine_version_info();
std::string engine_info(bool to_uci = false);
std::string compiler_info();
// Preloads the given address in L1/L2 cache. This is a non-blocking
// function that doesn't stall the CPU waiting for data to be loaded from memory,
// which can be quite slow.
void prefetch(void* addr);
void prefetch(const void* addr);
void start_logger(const std::string& fname);
void* std_aligned_alloc(size_t alignment, size_t size);
void std_aligned_free(void* ptr);
// memory aligned by page size, min alignment: 4096 bytes
void* aligned_large_pages_alloc(size_t size);
// nop if mem == nullptr
void aligned_large_pages_free(void* mem);
void start_logger(const std::string& fname);
size_t str_to_size_t(const std::string& s);
#if defined(__linux__)
struct PipeDeleter {
void operator()(FILE* file) const {
if (file != nullptr)
{
pclose(file);
}
}
};
#endif
// Reads the file as bytes.
// Returns std::nullopt if the file does not exist.
std::optional<std::string> read_file_to_string(const std::string& path);
void dbg_hit_on(bool cond, int slot = 0);
void dbg_mean_of(int64_t value, int slot = 0);
void dbg_stdev_of(int64_t value, int slot = 0);
void dbg_extremes_of(int64_t value, int slot = 0);
void dbg_correl_of(int64_t value1, int64_t value2, int slot = 0);
void dbg_print();
@@ -63,6 +82,30 @@ inline TimePoint now() {
.count();
}
inline std::vector<std::string_view> split(std::string_view s, std::string_view delimiter) {
std::vector<std::string_view> res;
if (s.empty())
return res;
size_t begin = 0;
for (;;)
{
const size_t end = s.find(delimiter, begin);
if (end == std::string::npos)
break;
res.emplace_back(s.substr(begin, end - begin));
begin = end + delimiter.size();
}
res.emplace_back(s.substr(begin));
return res;
}
void remove_whitespace(std::string& s);
bool is_whitespace(std::string_view s);
enum SyncCout {
IO_LOCK,
@@ -73,26 +116,12 @@ std::ostream& operator<<(std::ostream&, SyncCout);
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
// Get the first aligned element of an array.
// ptr must point to an array of size at least `sizeof(T) * N + alignment` bytes,
// where N is the number of elements in the array.
template<uintptr_t Alignment, typename T>
T* align_ptr_up(T* ptr) {
static_assert(alignof(T) < Alignment);
const uintptr_t ptrint = reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(ptr));
return reinterpret_cast<T*>(
reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
}
void sync_cout_start();
void sync_cout_end();
// True if and only if the binary is compiled on a little-endian machine
static inline const union {
uint32_t i;
char c[4];
} Le = {0x01020304};
static inline const bool IsLittleEndian = (Le.c[0] == 4);
static inline const std::uint16_t Le = 1;
static inline const bool IsLittleEndian = *reinterpret_cast<const char*>(&Le) == 1;
template<typename T, std::size_t MaxSize>
@@ -111,6 +140,92 @@ class ValueList {
};
template<typename T, std::size_t Size, std::size_t... Sizes>
class MultiArray;
namespace Detail {
template<typename T, std::size_t Size, std::size_t... Sizes>
struct MultiArrayHelper {
using ChildType = MultiArray<T, Sizes...>;
};
template<typename T, std::size_t Size>
struct MultiArrayHelper<T, Size> {
using ChildType = T;
};
}
// MultiArray is a generic N-dimensional array.
// The template parameters (Size and Sizes) encode the dimensions of the array.
template<typename T, std::size_t Size, std::size_t... Sizes>
class MultiArray {
using ChildType = typename Detail::MultiArrayHelper<T, Size, Sizes...>::ChildType;
using ArrayType = std::array<ChildType, Size>;
ArrayType data_;
public:
using value_type = typename ArrayType::value_type;
using size_type = typename ArrayType::size_type;
using difference_type = typename ArrayType::difference_type;
using reference = typename ArrayType::reference;
using const_reference = typename ArrayType::const_reference;
using pointer = typename ArrayType::pointer;
using const_pointer = typename ArrayType::const_pointer;
using iterator = typename ArrayType::iterator;
using const_iterator = typename ArrayType::const_iterator;
using reverse_iterator = typename ArrayType::reverse_iterator;
using const_reverse_iterator = typename ArrayType::const_reverse_iterator;
constexpr auto& at(size_type index) noexcept { return data_.at(index); }
constexpr const auto& at(size_type index) const noexcept { return data_.at(index); }
constexpr auto& operator[](size_type index) noexcept { return data_[index]; }
constexpr const auto& operator[](size_type index) const noexcept { return data_[index]; }
constexpr auto& front() noexcept { return data_.front(); }
constexpr const auto& front() const noexcept { return data_.front(); }
constexpr auto& back() noexcept { return data_.back(); }
constexpr const auto& back() const noexcept { return data_.back(); }
auto* data() { return data_.data(); }
const auto* data() const { return data_.data(); }
constexpr auto begin() noexcept { return data_.begin(); }
constexpr auto end() noexcept { return data_.end(); }
constexpr auto begin() const noexcept { return data_.begin(); }
constexpr auto end() const noexcept { return data_.end(); }
constexpr auto cbegin() const noexcept { return data_.cbegin(); }
constexpr auto cend() const noexcept { return data_.cend(); }
constexpr auto rbegin() noexcept { return data_.rbegin(); }
constexpr auto rend() noexcept { return data_.rend(); }
constexpr auto rbegin() const noexcept { return data_.rbegin(); }
constexpr auto rend() const noexcept { return data_.rend(); }
constexpr auto crbegin() const noexcept { return data_.crbegin(); }
constexpr auto crend() const noexcept { return data_.crend(); }
constexpr bool empty() const noexcept { return data_.empty(); }
constexpr size_type size() const noexcept { return data_.size(); }
constexpr size_type max_size() const noexcept { return data_.max_size(); }
template<typename U>
void fill(const U& v) {
static_assert(std::is_assignable_v<T, U>, "Cannot assign fill value to entry type");
for (auto& ele : data_)
{
if constexpr (sizeof...(Sizes) == 0)
ele = v;
else
ele.fill(v);
}
}
constexpr void swap(MultiArray<T, Size, Sizes...>& other) noexcept { data_.swap(other.data_); }
};
// xorshift64star Pseudo-Random Number Generator
// This class is based on original code written and dedicated
// to the public domain by Sebastiano Vigna (2014).
@@ -169,25 +284,18 @@ inline uint64_t mul_hi64(uint64_t a, uint64_t b) {
#endif
}
// Under Windows it is not possible for a process to run on more than one
// logical processor group. This usually means being limited to using max 64
// cores. To overcome this, some special platform-specific API should be
// called to set group affinity for each thread. Original code from Texel by
// Peter Österlund.
namespace WinProcGroup {
void bindThisThread(size_t idx);
}
struct CommandLine {
public:
CommandLine(int, char**);
CommandLine(int _argc, char** _argv) :
argc(_argc),
argv(_argv) {}
static std::string get_binary_directory(std::string argv0);
static std::string get_working_directory();
int argc;
char** argv;
std::string binaryDirectory; // path of the executable directory
std::string workingDirectory; // path of the working directory
};
namespace Utility {
+16 -40
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -75,17 +75,6 @@ ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard ta
b2 &= target;
}
if constexpr (Type == QUIET_CHECKS)
{
// To make a quiet check, you either make a direct check by pushing a pawn
// or push a blocker pawn that is not on the same file as the enemy king.
// Discovered check promotion has been already generated amongst the captures.
Square ksq = pos.square<KING>(Them);
Bitboard dcCandidatePawns = pos.blockers_for_king(Them) & ~file_bb(ksq);
b1 &= pawn_attacks_bb(Them, ksq) | shift<Up>(dcCandidatePawns);
b2 &= pawn_attacks_bb(Them, ksq) | shift<Up + Up>(dcCandidatePawns);
}
while (b1)
{
Square to = pop_lsb(b1);
@@ -158,7 +147,7 @@ ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard ta
}
template<Color Us, PieceType Pt, bool Checks>
template<Color Us, PieceType Pt>
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");
@@ -170,10 +159,6 @@ ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target)
Square from = pop_lsb(bb);
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
// To check, you either move freely a blocker or make a direct check.
if (Checks && (Pt == QUEEN || !(pos.blockers_for_king(~Us) & from)))
b &= pos.check_squares(Pt);
while (b)
*moveList++ = Move(from, pop_lsb(b));
}
@@ -187,9 +172,8 @@ ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
static_assert(Type != LEGAL, "Unsupported type in generate_all()");
constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
const Square ksq = pos.square<KING>(Us);
Bitboard target;
const Square ksq = pos.square<KING>(Us);
Bitboard target;
// Skip generating non-king moves when in double check
if (Type != EVASIONS || !more_than_one(pos.checkers()))
@@ -197,29 +181,24 @@ ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
target = Type == EVASIONS ? between_bb(ksq, lsb(pos.checkers()))
: Type == NON_EVASIONS ? ~pos.pieces(Us)
: Type == CAPTURES ? pos.pieces(~Us)
: ~pos.pieces(); // QUIETS || QUIET_CHECKS
: ~pos.pieces(); // QUIETS
moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
moveList = generate_moves<Us, KNIGHT, Checks>(pos, moveList, target);
moveList = generate_moves<Us, BISHOP, Checks>(pos, moveList, target);
moveList = generate_moves<Us, ROOK, Checks>(pos, moveList, target);
moveList = generate_moves<Us, QUEEN, Checks>(pos, moveList, target);
moveList = generate_moves<Us, KNIGHT>(pos, moveList, target);
moveList = generate_moves<Us, BISHOP>(pos, moveList, target);
moveList = generate_moves<Us, ROOK>(pos, moveList, target);
moveList = generate_moves<Us, QUEEN>(pos, moveList, target);
}
if (!Checks || pos.blockers_for_king(~Us) & ksq)
{
Bitboard b = attacks_bb<KING>(ksq) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
if (Checks)
b &= ~attacks_bb<QUEEN>(pos.square<KING>(~Us));
Bitboard b = attacks_bb<KING>(ksq) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
while (b)
*moveList++ = Move(ksq, pop_lsb(b));
while (b)
*moveList++ = Move(ksq, pop_lsb(b));
if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
for (CastlingRights cr : {Us & KING_SIDE, Us & QUEEN_SIDE})
if (!pos.castling_impeded(cr) && pos.can_castle(cr))
*moveList++ = Move::make<CASTLING>(ksq, pos.castling_rook_square(cr));
}
if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
for (CastlingRights cr : {Us & KING_SIDE, Us & QUEEN_SIDE})
if (!pos.castling_impeded(cr) && pos.can_castle(cr))
*moveList++ = Move::make<CASTLING>(ksq, pos.castling_rook_square(cr));
return moveList;
}
@@ -231,8 +210,6 @@ ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
// <QUIETS> Generates all pseudo-legal non-captures and underpromotions
// <EVASIONS> Generates all pseudo-legal check evasions
// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
// <QUIET_CHECKS> Generates all pseudo-legal non-captures giving check,
// except castling and promotions
//
// Returns a pointer to the end of the move list.
template<GenType Type>
@@ -251,7 +228,6 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) {
template ExtMove* generate<CAPTURES>(const Position&, ExtMove*);
template ExtMove* generate<QUIETS>(const Position&, ExtMove*);
template ExtMove* generate<EVASIONS>(const Position&, ExtMove*);
template ExtMove* generate<QUIET_CHECKS>(const Position&, ExtMove*);
template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
+1 -2
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,7 +31,6 @@ class Position;
enum GenType {
CAPTURES,
QUIETS,
QUIET_CHECKS,
EVASIONS,
NON_EVASIONS,
LEGAL
+56 -122
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,12 +18,11 @@
#include "movepick.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <utility>
#include <limits>
#include "bitboard.h"
#include "misc.h"
#include "position.h"
namespace Stockfish {
@@ -35,7 +34,6 @@ enum Stages {
MAIN_TT,
CAPTURE_INIT,
GOOD_CAPTURE,
REFUTATION,
QUIET_INIT,
GOOD_QUIET,
BAD_CAPTURE,
@@ -54,13 +52,11 @@ enum Stages {
// generate qsearch moves
QSEARCH_TT,
QCAPTURE_INIT,
QCAPTURE,
QCHECK_INIT,
QCHECK
QCAPTURE
};
// Sort moves in descending order up to and including
// a given limit. The order of moves smaller than the limit is left unspecified.
// Sort moves in descending order up to and including a given limit.
// The order of moves smaller than the limit is left unspecified.
void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) {
for (ExtMove *sortedEnd = begin, *p = begin + 1; p < end; ++p)
@@ -78,56 +74,38 @@ void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) {
// Constructors of the MovePicker class. As arguments, we pass information
// to help it return the (presumably) good moves first, to decide which
// moves to return (in the quiescence search, for instance, we only want to
// search captures, promotions, and some checks) and how important a good
// move ordering is at the current node.
// to decide which class of moves to emit, to help sorting the (presumably)
// good moves first, and how important move ordering is at the current node.
// MovePicker constructor for the main search
// MovePicker constructor for the main search and for the quiescence search
MovePicker::MovePicker(const Position& p,
Move ttm,
Depth d,
const ButterflyHistory* mh,
const LowPlyHistory* lph,
const CapturePieceToHistory* cph,
const PieceToHistory** ch,
const PawnHistory* ph,
Move cm,
const Move* killers) :
int pl) :
pos(p),
mainHistory(mh),
lowPlyHistory(lph),
captureHistory(cph),
continuationHistory(ch),
pawnHistory(ph),
ttMove(ttm),
refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}},
depth(d) {
assert(d > 0);
depth(d),
ply(pl) {
stage = (pos.checkers() ? EVASION_TT : MAIN_TT) + !(ttm && pos.pseudo_legal(ttm));
if (pos.checkers())
stage = EVASION_TT + !(ttm && pos.pseudo_legal(ttm));
else
stage = (depth > 0 ? MAIN_TT : QSEARCH_TT) + !(ttm && pos.pseudo_legal(ttm));
}
// Constructor for quiescence search
MovePicker::MovePicker(const Position& p,
Move ttm,
Depth d,
const ButterflyHistory* mh,
const CapturePieceToHistory* cph,
const PieceToHistory** ch,
const PawnHistory* ph) :
pos(p),
mainHistory(mh),
captureHistory(cph),
continuationHistory(ch),
pawnHistory(ph),
ttMove(ttm),
depth(d) {
assert(d <= 0);
stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) + !(ttm && pos.pseudo_legal(ttm));
}
// Constructor for ProbCut: we generate captures with SEE greater
// than or equal to the given threshold.
// MovePicker constructor for ProbCut: we generate captures with Static Exchange
// Evaluation (SEE) greater than or equal to the given threshold.
MovePicker::MovePicker(const Position& p, Move ttm, int th, const CapturePieceToHistory* cph) :
pos(p),
captureHistory(cph),
@@ -139,9 +117,9 @@ MovePicker::MovePicker(const Position& p, Move ttm, int th, const CapturePieceTo
+ !(ttm && pos.capture_stage(ttm) && pos.pseudo_legal(ttm) && pos.see_ge(ttm, threshold));
}
// Assigns a numerical value to each move in a list, used
// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring
// captures with a good history. Quiets moves are ordered using the history tables.
// Assigns a numerical value to each move in a list, used for sorting.
// Captures are ordered by Most Valuable Victim (MVV), preferring captures
// with a good history. Quiets moves are ordered using the history tables.
template<GenType Type>
void MovePicker::score() {
@@ -180,37 +158,36 @@ void MovePicker::score() {
// histories
m.value = 2 * (*mainHistory)[pos.side_to_move()][m.from_to()];
m.value += 2 * (*pawnHistory)[pawn_structure_index(pos)][pc][to];
m.value += 2 * (*continuationHistory[0])[pc][to];
m.value += (*continuationHistory[0])[pc][to];
m.value += (*continuationHistory[1])[pc][to];
m.value += (*continuationHistory[2])[pc][to] / 4;
m.value += (*continuationHistory[2])[pc][to];
m.value += (*continuationHistory[3])[pc][to];
m.value += (*continuationHistory[4])[pc][to] / 3;
m.value += (*continuationHistory[5])[pc][to];
// bonus for checks
m.value += bool(pos.check_squares(pt) & to) * 16384;
// bonus for escaping from capture
m.value += threatenedPieces & from ? (pt == QUEEN && !(to & threatenedByRook) ? 50000
: pt == ROOK && !(to & threatenedByMinor) ? 25000
: !(to & threatenedByPawn) ? 15000
m.value += threatenedPieces & from ? (pt == QUEEN && !(to & threatenedByRook) ? 51700
: pt == ROOK && !(to & threatenedByMinor) ? 25600
: !(to & threatenedByPawn) ? 14450
: 0)
: 0;
// malus for putting piece en prise
m.value -= !(threatenedPieces & from)
? (pt == QUEEN ? bool(to & threatenedByRook) * 50000
+ bool(to & threatenedByMinor) * 10000
: pt == ROOK ? bool(to & threatenedByMinor) * 25000
: pt != PAWN ? bool(to & threatenedByPawn) * 15000
: 0)
: 0;
m.value -= (pt == QUEEN ? bool(to & threatenedByRook) * 49000
: pt == ROOK && bool(to & threatenedByMinor) ? 24335
: 0);
if (ply < LOW_PLY_HISTORY_SIZE)
m.value += 8 * (*lowPlyHistory)[ply][m.from_to()] / (1 + 2 * ply);
}
else // Type == EVASIONS
{
if (pos.capture_stage(m))
m.value =
PieceValue[pos.piece_on(m.to_sq())] - type_of(pos.moved_piece(m)) + (1 << 28);
m.value = PieceValue[pos.piece_on(m.to_sq())] + (1 << 28);
else
m.value = (*mainHistory)[pos.side_to_move()][m.from_to()]
+ (*continuationHistory[0])[pos.moved_piece(m)][m.to_sq()]
@@ -219,29 +196,23 @@ void MovePicker::score() {
}
// Returns the next move satisfying a predicate function.
// It never returns the TT move.
template<MovePicker::PickType T, typename Pred>
// This never returns the TT move, as it was emitted before.
template<typename Pred>
Move MovePicker::select(Pred filter) {
while (cur < endMoves)
{
if constexpr (T == Best)
std::swap(*cur, *std::max_element(cur, endMoves));
for (; cur < endMoves; ++cur)
if (*cur != ttMove && filter())
return *cur++;
cur++;
}
return Move::none();
}
// Most important method of the MovePicker class. It
// returns a new pseudo-legal move every time it is called until there are no more
// moves left, picking the move with the highest score from a list of generated moves.
Move MovePicker::next_move(bool skipQuiets) {
// This is the most important method of the MovePicker class. We emit one
// new pseudo-legal move on every call until there are no more moves left,
// picking the move with the highest score from a list of generated moves.
Move MovePicker::next_move() {
auto quiet_threshold = [](Depth d) { return -3330 * d; };
auto quiet_threshold = [](Depth d) { return -3560 * d; };
top:
switch (stage)
@@ -266,29 +237,13 @@ top:
goto top;
case GOOD_CAPTURE :
if (select<Next>([&]() {
if (select([&]() {
// Move losing capture to endBadCaptures to be tried later
return pos.see_ge(*cur, -cur->value / 18) ? true
: (*endBadCaptures++ = *cur, false);
}))
return *(cur - 1);
// Prepare the pointers to loop over the refutations array
cur = std::begin(refutations);
endMoves = std::end(refutations);
// If the countermove is the same as a killer, skip it
if (refutations[0] == refutations[2] || refutations[1] == refutations[2])
--endMoves;
++stage;
[[fallthrough]];
case REFUTATION :
if (select<Next>([&]() {
return *cur != Move::none() && !pos.capture_stage(*cur) && pos.pseudo_legal(*cur);
}))
return *(cur - 1);
++stage;
[[fallthrough]];
@@ -306,11 +261,9 @@ top:
[[fallthrough]];
case GOOD_QUIET :
if (!skipQuiets && select<Next>([&]() {
return *cur != refutations[0] && *cur != refutations[1] && *cur != refutations[2];
}))
if (!skipQuiets && select([]() { return true; }))
{
if ((cur - 1)->value > -8000 || (cur - 1)->value <= quiet_threshold(depth))
if ((cur - 1)->value > -7998 || (cur - 1)->value <= quiet_threshold(depth))
return *(cur - 1);
// Remaining quiets are bad
@@ -325,7 +278,7 @@ top:
[[fallthrough]];
case BAD_CAPTURE :
if (select<Next>([]() { return true; }))
if (select([]() { return true; }))
return *(cur - 1);
// Prepare the pointers to loop over the bad quiets
@@ -337,9 +290,7 @@ top:
case BAD_QUIET :
if (!skipQuiets)
return select<Next>([&]() {
return *cur != refutations[0] && *cur != refutations[1] && *cur != refutations[2];
});
return select([]() { return true; });
return Move::none();
@@ -348,39 +299,22 @@ top:
endMoves = generate<EVASIONS>(pos, cur);
score<EVASIONS>();
partial_insertion_sort(cur, endMoves, std::numeric_limits<int>::min());
++stage;
[[fallthrough]];
case EVASION :
return select<Best>([]() { return true; });
case QCAPTURE :
return select([]() { return true; });
case PROBCUT :
return select<Next>([&]() { return pos.see_ge(*cur, threshold); });
case QCAPTURE :
if (select<Next>([]() { return true; }))
return *(cur - 1);
// If we did not find any move and we do not try checks, we have finished
if (depth != DEPTH_QS_CHECKS)
return Move::none();
++stage;
[[fallthrough]];
case QCHECK_INIT :
cur = moves;
endMoves = generate<QUIET_CHECKS>(pos, cur);
++stage;
[[fallthrough]];
case QCHECK :
return select<Next>([]() { return true; });
return select([&]() { return pos.see_ge(*cur, threshold); });
}
assert(false);
return Move::none(); // Silence warning
}
void MovePicker::skip_quiet_moves() { skipQuiets = true; }
} // namespace Stockfish
+22 -142
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,139 +19,22 @@
#ifndef MOVEPICK_H_INCLUDED
#define MOVEPICK_H_INCLUDED
#include <array>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <type_traits> // IWYU pragma: keep
#include "history.h"
#include "movegen.h"
#include "types.h"
#include "position.h"
namespace Stockfish {
constexpr int PAWN_HISTORY_SIZE = 512; // has to be a power of 2
constexpr int CORRECTION_HISTORY_SIZE = 16384; // has to be a power of 2
constexpr int CORRECTION_HISTORY_LIMIT = 1024;
class Position;
static_assert((PAWN_HISTORY_SIZE & (PAWN_HISTORY_SIZE - 1)) == 0,
"PAWN_HISTORY_SIZE has to be a power of 2");
static_assert((CORRECTION_HISTORY_SIZE & (CORRECTION_HISTORY_SIZE - 1)) == 0,
"CORRECTION_HISTORY_SIZE has to be a power of 2");
enum PawnHistoryType {
Normal,
Correction
};
template<PawnHistoryType T = Normal>
inline int pawn_structure_index(const Position& pos) {
return pos.pawn_key() & ((T == Normal ? PAWN_HISTORY_SIZE : CORRECTION_HISTORY_SIZE) - 1);
}
// StatsEntry stores the stat table value. It is usually a number but could
// be a move or even a nested history. We use a class instead of a naked value
// to directly call history update operator<<() on the entry so to use stats
// tables at caller sites as simple multi-dim arrays.
template<typename T, int D>
class StatsEntry {
T entry;
public:
void operator=(const T& v) { entry = v; }
T* operator&() { return &entry; }
T* operator->() { return &entry; }
operator const T&() const { return entry; }
void operator<<(int bonus) {
assert(std::abs(bonus) <= D); // Ensure range is [-D, D]
static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
entry += bonus - entry * std::abs(bonus) / D;
assert(std::abs(entry) <= D);
}
};
// Stats is a generic N-dimensional array used to store various statistics.
// The first template parameter T is the base type of the array, and the second
// template parameter D limits the range of updates in [-D, D] when we update
// values with the << operator, while the last parameters (Size and Sizes)
// encode the dimensions of the array.
template<typename T, int D, int Size, int... Sizes>
struct Stats: public std::array<Stats<T, D, Sizes...>, Size> {
using stats = Stats<T, D, Size, Sizes...>;
void fill(const T& v) {
// For standard-layout 'this' points to the first struct member
assert(std::is_standard_layout_v<stats>);
using entry = StatsEntry<T, D>;
entry* p = reinterpret_cast<entry*>(this);
std::fill(p, p + sizeof(*this) / sizeof(entry), v);
}
};
template<typename T, int D, int Size>
struct Stats<T, D, Size>: public std::array<StatsEntry<T, D>, Size> {};
// In stats table, D=0 means that the template parameter is not used
enum StatsParams {
NOT_USED = 0
};
enum StatsType {
NoCaptures,
Captures
};
// ButterflyHistory records how often quiet moves have been successful or unsuccessful
// during the current search, and is used for reduction and move ordering decisions.
// It uses 2 tables (one for each color) indexed by the move's from and to squares,
// see www.chessprogramming.org/Butterfly_Boards (~11 elo)
using ButterflyHistory = Stats<int16_t, 7183, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)>;
// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
// move, see www.chessprogramming.org/Countermove_Heuristic
using CounterMoveHistory = Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB>;
// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
using CapturePieceToHistory = Stats<int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;
// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
using PieceToHistory = Stats<int16_t, 29952, PIECE_NB, SQUARE_NB>;
// ContinuationHistory is the combined history of a given pair of moves, usually
// the current one given a previous one. The nested history table is based on
// PieceToHistory instead of ButterflyBoards.
// (~63 elo)
using ContinuationHistory = Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB>;
// PawnHistory is addressed by the pawn structure and a move's [piece][to]
using PawnHistory = Stats<int16_t, 8192, PAWN_HISTORY_SIZE, PIECE_NB, SQUARE_NB>;
// CorrectionHistory is addressed by color and pawn structure
using CorrectionHistory =
Stats<int16_t, CORRECTION_HISTORY_LIMIT, COLOR_NB, CORRECTION_HISTORY_SIZE>;
// MovePicker class is used to pick one pseudo-legal move at a time from the
// current position. The most important method is next_move(), which returns a
// new pseudo-legal move each time it is called, until there are no moves left,
// when Move::none() is returned. In order to improve the efficiency of the
// alpha-beta algorithm, MovePicker attempts to return the moves which are most
// likely to get a cut-off first.
// The MovePicker class is used to pick one pseudo-legal move at a time from the
// current position. The most important method is next_move(), which emits one
// new pseudo-legal move on every call, until there are no moves left, when
// Move::none() is returned. In order to improve the efficiency of the alpha-beta
// algorithm, MovePicker attempts to return the moves which are most likely to get
// a cut-off first.
class MovePicker {
enum PickType {
Next,
Best
};
public:
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
@@ -159,23 +42,17 @@ class MovePicker {
Move,
Depth,
const ButterflyHistory*,
const LowPlyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
const PawnHistory*,
Move,
const Move*);
MovePicker(const Position&,
Move,
Depth,
const ButterflyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
const PawnHistory*);
int);
MovePicker(const Position&, Move, int, const CapturePieceToHistory*);
Move next_move(bool skipQuiets = false);
Move next_move();
void skip_quiet_moves();
private:
template<PickType T, typename Pred>
template<typename Pred>
Move select(Pred);
template<GenType>
void score();
@@ -184,15 +61,18 @@ class MovePicker {
const Position& pos;
const ButterflyHistory* mainHistory;
const LowPlyHistory* lowPlyHistory;
const CapturePieceToHistory* captureHistory;
const PieceToHistory** continuationHistory;
const PawnHistory* pawnHistory;
Move ttMove;
ExtMove refutations[3], *cur, *endMoves, *endBadCaptures, *beginBadQuiets, *endBadQuiets;
int stage;
int threshold;
Depth depth;
ExtMove moves[MAX_MOVES];
ExtMove * cur, *endMoves, *endBadCaptures, *beginBadQuiets, *endBadQuiets;
int stage;
int threshold;
Depth depth;
int ply;
bool skipQuiets = false;
ExtMove moves[MAX_MOVES];
};
} // namespace Stockfish
-482
View File
@@ -1,482 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Code for calculating NNUE evaluation function
#include "evaluate_nnue.h"
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <optional>
#include <sstream>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include "../evaluate.h"
#include "../misc.h"
#include "../position.h"
#include "../types.h"
#include "../uci.h"
#include "nnue_accumulator.h"
#include "nnue_common.h"
namespace Stockfish::Eval::NNUE {
// Input feature converter
LargePagePtr<FeatureTransformer<TransformedFeatureDimensionsBig, &StateInfo::accumulatorBig>>
featureTransformerBig;
LargePagePtr<FeatureTransformer<TransformedFeatureDimensionsSmall, &StateInfo::accumulatorSmall>>
featureTransformerSmall;
// Evaluation function
AlignedPtr<Network<TransformedFeatureDimensionsBig, L2Big, L3Big>> networkBig[LayerStacks];
AlignedPtr<Network<TransformedFeatureDimensionsSmall, L2Small, L3Small>> networkSmall[LayerStacks];
// Evaluation function file names
namespace Detail {
// Initialize the evaluation function parameters
template<typename T>
void initialize(AlignedPtr<T>& pointer) {
pointer.reset(reinterpret_cast<T*>(std_aligned_alloc(alignof(T), sizeof(T))));
std::memset(pointer.get(), 0, sizeof(T));
}
template<typename T>
void initialize(LargePagePtr<T>& pointer) {
static_assert(alignof(T) <= 4096,
"aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
pointer.reset(reinterpret_cast<T*>(aligned_large_pages_alloc(sizeof(T))));
std::memset(pointer.get(), 0, sizeof(T));
}
// Read evaluation function parameters
template<typename T>
bool read_parameters(std::istream& stream, T& reference) {
std::uint32_t header;
header = read_little_endian<std::uint32_t>(stream);
if (!stream || header != T::get_hash_value())
return false;
return reference.read_parameters(stream);
}
// Write evaluation function parameters
template<typename T>
bool write_parameters(std::ostream& stream, const T& reference) {
write_little_endian<std::uint32_t>(stream, T::get_hash_value());
return reference.write_parameters(stream);
}
} // namespace Detail
// Initialize the evaluation function parameters
static void initialize(NetSize netSize) {
if (netSize == Small)
{
Detail::initialize(featureTransformerSmall);
for (std::size_t i = 0; i < LayerStacks; ++i)
Detail::initialize(networkSmall[i]);
}
else
{
Detail::initialize(featureTransformerBig);
for (std::size_t i = 0; i < LayerStacks; ++i)
Detail::initialize(networkBig[i]);
}
}
// Read network header
static bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc) {
std::uint32_t version, size;
version = read_little_endian<std::uint32_t>(stream);
*hashValue = read_little_endian<std::uint32_t>(stream);
size = read_little_endian<std::uint32_t>(stream);
if (!stream || version != Version)
return false;
desc->resize(size);
stream.read(&(*desc)[0], size);
return !stream.fail();
}
// Write network header
static bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc) {
write_little_endian<std::uint32_t>(stream, Version);
write_little_endian<std::uint32_t>(stream, hashValue);
write_little_endian<std::uint32_t>(stream, std::uint32_t(desc.size()));
stream.write(&desc[0], desc.size());
return !stream.fail();
}
// Read network parameters
static bool read_parameters(std::istream& stream, NetSize netSize, std::string& netDescription) {
std::uint32_t hashValue;
if (!read_header(stream, &hashValue, &netDescription))
return false;
if (hashValue != HashValue[netSize])
return false;
if (netSize == Big && !Detail::read_parameters(stream, *featureTransformerBig))
return false;
if (netSize == Small && !Detail::read_parameters(stream, *featureTransformerSmall))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
{
if (netSize == Big && !Detail::read_parameters(stream, *(networkBig[i])))
return false;
if (netSize == Small && !Detail::read_parameters(stream, *(networkSmall[i])))
return false;
}
return stream && stream.peek() == std::ios::traits_type::eof();
}
// Write network parameters
static bool
write_parameters(std::ostream& stream, NetSize netSize, const std::string& netDescription) {
if (!write_header(stream, HashValue[netSize], netDescription))
return false;
if (netSize == Big && !Detail::write_parameters(stream, *featureTransformerBig))
return false;
if (netSize == Small && !Detail::write_parameters(stream, *featureTransformerSmall))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
{
if (netSize == Big && !Detail::write_parameters(stream, *(networkBig[i])))
return false;
if (netSize == Small && !Detail::write_parameters(stream, *(networkSmall[i])))
return false;
}
return bool(stream);
}
void hint_common_parent_position(const Position& pos) {
int simpleEval = simple_eval(pos, pos.side_to_move());
if (std::abs(simpleEval) > 1050)
featureTransformerSmall->hint_common_access(pos);
else
featureTransformerBig->hint_common_access(pos);
}
// Evaluation function. Perform differential calculation.
template<NetSize Net_Size>
Value evaluate(const Position& pos, bool adjusted, int* complexity) {
// We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize;
constexpr int delta = 24;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformedFeaturesUnaligned
[FeatureTransformer < Net_Size == Small ? TransformedFeatureDimensionsSmall
: TransformedFeatureDimensionsBig,
nullptr > ::BufferSize + alignment / sizeof(TransformedFeatureType)];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
#else
alignas(alignment) TransformedFeatureType
transformedFeatures[FeatureTransformer < Net_Size == Small ? TransformedFeatureDimensionsSmall
: TransformedFeatureDimensionsBig,
nullptr > ::BufferSize];
#endif
ASSERT_ALIGNED(transformedFeatures, alignment);
const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
const auto psqt = Net_Size == Small
? featureTransformerSmall->transform(pos, transformedFeatures, bucket)
: featureTransformerBig->transform(pos, transformedFeatures, bucket);
const auto positional = Net_Size == Small ? networkSmall[bucket]->propagate(transformedFeatures)
: networkBig[bucket]->propagate(transformedFeatures);
if (complexity)
*complexity = std::abs(psqt - positional) / OutputScale;
// Give more value to positional evaluation when adjusted flag is set
if (adjusted)
return static_cast<Value>(((1024 - delta) * psqt + (1024 + delta) * positional)
/ (1024 * OutputScale));
else
return static_cast<Value>((psqt + positional) / OutputScale);
}
template Value evaluate<Big>(const Position& pos, bool adjusted, int* complexity);
template Value evaluate<Small>(const Position& pos, bool adjusted, int* complexity);
struct NnueEvalTrace {
static_assert(LayerStacks == PSQTBuckets);
Value psqt[LayerStacks];
Value positional[LayerStacks];
std::size_t correctBucket;
};
static NnueEvalTrace trace_evaluate(const Position& pos) {
// We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformedFeaturesUnaligned
[FeatureTransformer<TransformedFeatureDimensionsBig, nullptr>::BufferSize
+ alignment / sizeof(TransformedFeatureType)];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
#else
alignas(alignment) TransformedFeatureType
transformedFeatures[FeatureTransformer<TransformedFeatureDimensionsBig, nullptr>::BufferSize];
#endif
ASSERT_ALIGNED(transformedFeatures, alignment);
NnueEvalTrace t{};
t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
for (IndexType bucket = 0; bucket < LayerStacks; ++bucket)
{
const auto materialist = featureTransformerBig->transform(pos, transformedFeatures, bucket);
const auto positional = networkBig[bucket]->propagate(transformedFeatures);
t.psqt[bucket] = static_cast<Value>(materialist / OutputScale);
t.positional[bucket] = static_cast<Value>(positional / OutputScale);
}
return t;
}
constexpr std::string_view PieceToChar(" PNBRQK pnbrqk");
// Converts a Value into (centi)pawns and writes it in a buffer.
// The buffer must have capacity for at least 5 chars.
static void format_cp_compact(Value v, char* buffer) {
buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
int cp = std::abs(UCI::to_cp(v));
if (cp >= 10000)
{
buffer[1] = '0' + cp / 10000;
cp %= 10000;
buffer[2] = '0' + cp / 1000;
cp %= 1000;
buffer[3] = '0' + cp / 100;
buffer[4] = ' ';
}
else if (cp >= 1000)
{
buffer[1] = '0' + cp / 1000;
cp %= 1000;
buffer[2] = '0' + cp / 100;
cp %= 100;
buffer[3] = '.';
buffer[4] = '0' + cp / 10;
}
else
{
buffer[1] = '0' + cp / 100;
cp %= 100;
buffer[2] = '.';
buffer[3] = '0' + cp / 10;
cp %= 10;
buffer[4] = '0' + cp / 1;
}
}
// Converts a Value into pawns, always keeping two decimals
static void format_cp_aligned_dot(Value v, std::stringstream& stream) {
const double pawns = std::abs(0.01 * UCI::to_cp(v));
stream << (v < 0 ? '-'
: v > 0 ? '+'
: ' ')
<< std::setiosflags(std::ios::fixed) << std::setw(6) << std::setprecision(2) << pawns;
}
// Returns a string with the value of each piece on a board,
// and a table for (PSQT, Layers) values bucket by bucket.
std::string trace(Position& pos) {
std::stringstream ss;
char board[3 * 8 + 1][8 * 8 + 2];
std::memset(board, ' ', sizeof(board));
for (int row = 0; row < 3 * 8 + 1; ++row)
board[row][8 * 8 + 1] = '\0';
// A lambda to output one box of the board
auto writeSquare = [&board](File file, Rank rank, Piece pc, Value value) {
const int x = int(file) * 8;
const int y = (7 - int(rank)) * 3;
for (int i = 1; i < 8; ++i)
board[y][x + i] = board[y + 3][x + i] = '-';
for (int i = 1; i < 3; ++i)
board[y + i][x] = board[y + i][x + 8] = '|';
board[y][x] = board[y][x + 8] = board[y + 3][x + 8] = board[y + 3][x] = '+';
if (pc != NO_PIECE)
board[y + 1][x + 4] = PieceToChar[pc];
if (value != VALUE_NONE)
format_cp_compact(value, &board[y + 2][x + 2]);
};
// We estimate the value of each piece by doing a differential evaluation from
// the current base eval, simulating the removal of the piece from its square.
Value base = evaluate<NNUE::Big>(pos);
base = pos.side_to_move() == WHITE ? base : -base;
for (File f = FILE_A; f <= FILE_H; ++f)
for (Rank r = RANK_1; r <= RANK_8; ++r)
{
Square sq = make_square(f, r);
Piece pc = pos.piece_on(sq);
Value v = VALUE_NONE;
if (pc != NO_PIECE && type_of(pc) != KING)
{
auto st = pos.state();
pos.remove_piece(sq);
st->accumulatorBig.computed[WHITE] = false;
st->accumulatorBig.computed[BLACK] = false;
Value eval = evaluate<NNUE::Big>(pos);
eval = pos.side_to_move() == WHITE ? eval : -eval;
v = base - eval;
pos.put_piece(pc, sq);
st->accumulatorBig.computed[WHITE] = false;
st->accumulatorBig.computed[BLACK] = false;
}
writeSquare(f, r, pc, v);
}
ss << " NNUE derived piece values:\n";
for (int row = 0; row < 3 * 8 + 1; ++row)
ss << board[row] << '\n';
ss << '\n';
auto t = trace_evaluate(pos);
ss << " NNUE network contributions "
<< (pos.side_to_move() == WHITE ? "(White to move)" : "(Black to move)") << std::endl
<< "+------------+------------+------------+------------+\n"
<< "| Bucket | Material | Positional | Total |\n"
<< "| | (PSQT) | (Layers) | |\n"
<< "+------------+------------+------------+------------+\n";
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket)
{
ss << "| " << bucket << " ";
ss << " | ";
format_cp_aligned_dot(t.psqt[bucket], ss);
ss << " "
<< " | ";
format_cp_aligned_dot(t.positional[bucket], ss);
ss << " "
<< " | ";
format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], ss);
ss << " "
<< " |";
if (bucket == t.correctBucket)
ss << " <-- this bucket is used";
ss << '\n';
}
ss << "+------------+------------+------------+------------+\n";
return ss.str();
}
// Load eval, from a file stream or a memory stream
std::optional<std::string> load_eval(std::istream& stream, NetSize netSize) {
initialize(netSize);
std::string netDescription;
return read_parameters(stream, netSize, netDescription) ? std::make_optional(netDescription)
: std::nullopt;
}
// Save eval, to a file stream or a memory stream
bool save_eval(std::ostream& stream,
NetSize netSize,
const std::string& name,
const std::string& netDescription) {
if (name.empty() || name == "None")
return false;
return write_parameters(stream, netSize, netDescription);
}
// Save eval, to a file given by its name
bool save_eval(const std::optional<std::string>& filename,
NetSize netSize,
const std::unordered_map<Eval::NNUE::NetSize, Eval::EvalFile>& evalFiles) {
std::string actualFilename;
std::string msg;
if (filename.has_value())
actualFilename = filename.value();
else
{
if (evalFiles.at(netSize).current
!= (netSize == Small ? EvalFileDefaultNameSmall : EvalFileDefaultNameBig))
{
msg = "Failed to export a net. "
"A non-embedded net can only be saved if the filename is specified";
sync_cout << msg << sync_endl;
return false;
}
actualFilename = (netSize == Small ? EvalFileDefaultNameSmall : EvalFileDefaultNameBig);
}
std::ofstream stream(actualFilename, std::ios_base::binary);
bool saved = save_eval(stream, netSize, evalFiles.at(netSize).current,
evalFiles.at(netSize).netDescription);
msg = saved ? "Network saved successfully to " + actualFilename : "Failed to export a net";
sync_cout << msg << sync_endl;
return saved;
}
} // namespace Stockfish::Eval::NNUE
-93
View File
@@ -1,93 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// header used in NNUE evaluation function
#ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
#define NNUE_EVALUATE_NNUE_H_INCLUDED
#include <cstdint>
#include <iosfwd>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include "../misc.h"
#include "../types.h"
#include "nnue_architecture.h"
#include "nnue_feature_transformer.h"
namespace Stockfish {
class Position;
namespace Eval {
struct EvalFile;
}
}
namespace Stockfish::Eval::NNUE {
// Hash value of evaluation function structure
constexpr std::uint32_t HashValue[2] = {
FeatureTransformer<TransformedFeatureDimensionsBig, nullptr>::get_hash_value()
^ Network<TransformedFeatureDimensionsBig, L2Big, L3Big>::get_hash_value(),
FeatureTransformer<TransformedFeatureDimensionsSmall, nullptr>::get_hash_value()
^ Network<TransformedFeatureDimensionsSmall, L2Small, L3Small>::get_hash_value()};
// Deleter for automating release of memory area
template<typename T>
struct AlignedDeleter {
void operator()(T* ptr) const {
ptr->~T();
std_aligned_free(ptr);
}
};
template<typename T>
struct LargePageDeleter {
void operator()(T* ptr) const {
ptr->~T();
aligned_large_pages_free(ptr);
}
};
template<typename T>
using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>;
template<typename T>
using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
std::string trace(Position& pos);
template<NetSize Net_Size>
Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr);
void hint_common_parent_position(const Position& pos);
std::optional<std::string> load_eval(std::istream& stream, NetSize netSize);
bool save_eval(std::ostream& stream,
NetSize netSize,
const std::string& name,
const std::string& netDescription);
bool save_eval(const std::optional<std::string>& filename,
NetSize netSize,
const std::unordered_map<Eval::NNUE::NetSize, Eval::EvalFile>&);
} // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
+4 -2
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
#include "../../bitboard.h"
#include "../../position.h"
#include "../../types.h"
#include "../nnue_common.h"
#include "../nnue_accumulator.h"
namespace Stockfish::Eval::NNUE::Features {
@@ -49,6 +49,8 @@ void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active)
// Explicit template instantiations
template void HalfKAv2_hm::append_active_indices<WHITE>(const Position& pos, IndexList& active);
template void HalfKAv2_hm::append_active_indices<BLACK>(const Position& pos, IndexList& active);
template IndexType HalfKAv2_hm::make_index<WHITE>(Square s, Piece pc, Square ksq);
template IndexType HalfKAv2_hm::make_index<BLACK>(Square s, Piece pc, Square ksq);
// Get a list of indices for recently changed features
template<Color Perspective>
+5 -5
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -63,10 +63,6 @@ class HalfKAv2_hm {
{PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE}};
// Index of a feature for a given king position and another piece on some square
template<Color Perspective>
static IndexType make_index(Square s, Piece pc, Square ksq);
public:
// Feature name
static constexpr const char* Name = "HalfKAv2_hm(Friend)";
@@ -126,6 +122,10 @@ class HalfKAv2_hm {
static constexpr IndexType MaxActiveDimensions = 32;
using IndexList = ValueList<IndexType, MaxActiveDimensions>;
// Index of a feature for a given king position and another piece on some square
template<Color Perspective>
static IndexType make_index(Square s, Piece pc, Square ksq);
// Get a list of indices for active features
template<Color Perspective>
static void append_active_indices(const Position& pos, IndexList& active);
+29 -31
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -39,25 +39,26 @@
namespace Stockfish::Eval::NNUE::Layers {
#if defined(USE_SSSE3) || defined(USE_NEON_DOTPROD)
#define ENABLE_SEQ_OPT
#endif
// Fallback implementation for older/other architectures.
// Requires the input to be padded to at least 16 values.
#if !defined(USE_SSSE3)
#ifndef ENABLE_SEQ_OPT
template<IndexType InputDimensions, IndexType PaddedInputDimensions, IndexType OutputDimensions>
static void affine_transform_non_ssse3(std::int32_t* output,
const std::int8_t* weights,
const std::int32_t* biases,
const std::uint8_t* input) {
#if defined(USE_SSE2) || defined(USE_NEON_DOTPROD) || defined(USE_NEON)
#if defined(USE_SSE2) || defined(USE_NEON)
#if defined(USE_SSE2)
// At least a multiple of 16, with SSE2.
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const __m128i Zeros = _mm_setzero_si128();
const auto inputVector = reinterpret_cast<const __m128i*>(input);
#elif defined(USE_NEON_DOTPROD)
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const auto inputVector = reinterpret_cast<const int8x16_t*>(input);
#elif defined(USE_NEON)
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const auto inputVector = reinterpret_cast<const int8x8_t*>(input);
@@ -91,16 +92,8 @@ static void affine_transform_non_ssse3(std::int32_t* output,
sum = _mm_add_epi32(sum, sum_second_32);
output[i] = _mm_cvtsi128_si32(sum);
#elif defined(USE_NEON_DOTPROD)
int32x4_t sum = {biases[i]};
const auto row = reinterpret_cast<const int8x16_t*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
sum = vdotq_s32(sum, inputVector[j], row[j]);
}
output[i] = vaddvq_s32(sum);
#elif defined(USE_NEON)
int32x4_t sum = {biases[i]};
const auto row = reinterpret_cast<const int8x8_t*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
@@ -127,7 +120,8 @@ static void affine_transform_non_ssse3(std::int32_t* output,
}
#endif
}
#endif
#endif // !ENABLE_SEQ_OPT
template<IndexType InDims, IndexType OutDims>
class AffineTransform {
@@ -162,7 +156,7 @@ class AffineTransform {
}
static constexpr IndexType get_weight_index(IndexType i) {
#if defined(USE_SSSE3)
#ifdef ENABLE_SEQ_OPT
return get_weight_index_scrambled(i);
#else
return i;
@@ -190,29 +184,28 @@ class AffineTransform {
// Forward propagation
void propagate(const InputType* input, OutputType* output) const {
#if defined(USE_SSSE3)
#ifdef ENABLE_SEQ_OPT
if constexpr (OutputDimensions > 1)
{
#if defined(USE_AVX512)
using vec_t = __m512i;
#define vec_setzero _mm512_setzero_si512
#define vec_set_32 _mm512_set1_epi32
#define vec_add_dpbusd_32 Simd::m512_add_dpbusd_epi32
#define vec_hadd Simd::m512_hadd
#elif defined(USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#define vec_hadd Simd::m256_hadd
#elif defined(USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#define vec_hadd Simd::m128_hadd
#elif defined(USE_NEON_DOTPROD)
using vec_t = int32x4_t;
#define vec_set_32 vdupq_n_s32
#define vec_add_dpbusd_32(acc, a, b) \
Simd::dotprod_m128_add_dpbusd_epi32(acc, vreinterpretq_s8_s32(a), \
vreinterpretq_s8_s32(b))
#endif
static constexpr IndexType OutputSimdWidth = sizeof(vec_t) / sizeof(OutputType);
@@ -242,28 +235,33 @@ class AffineTransform {
for (IndexType k = 0; k < NumRegs; ++k)
outptr[k] = acc[k];
#undef vec_setzero
#undef vec_set_32
#undef vec_add_dpbusd_32
#undef vec_hadd
}
else if constexpr (OutputDimensions == 1)
{
// We cannot use AVX512 for the last layer because there are only 32 inputs
// and the buffer is not padded to 64 elements.
#if defined(USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_setzero() _mm256_setzero_si256()
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#define vec_hadd Simd::m256_hadd
#elif defined(USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_setzero() _mm_setzero_si128()
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#define vec_hadd Simd::m128_hadd
#elif defined(USE_NEON_DOTPROD)
using vec_t = int32x4_t;
#define vec_setzero() vdupq_n_s32(0)
#define vec_set_32 vdupq_n_s32
#define vec_add_dpbusd_32(acc, a, b) \
Simd::dotprod_m128_add_dpbusd_epi32(acc, vreinterpretq_s8_s32(a), \
vreinterpretq_s8_s32(b))
#define vec_hadd Simd::neon_m128_hadd
#endif
const auto inputVector = reinterpret_cast<const vec_t*>(input);
+44 -16
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,17 +38,41 @@
namespace Stockfish::Eval::NNUE::Layers {
#if (USE_SSSE3 | (USE_NEON >= 8))
alignas(CacheLineSize) static inline const
std::array<std::array<std::uint16_t, 8>, 256> lookup_indices = []() {
std::array<std::array<std::uint16_t, 8>, 256> v{};
for (unsigned i = 0; i < 256; ++i)
{
std::uint64_t j = i, k = 0;
while (j)
v[i][k++] = pop_lsb(j);
}
return v;
}();
static constexpr int lsb_index64[64] = {
0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, 54, 58, 35, 52, 50, 42,
21, 44, 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43,
31, 22, 10, 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63};
constexpr int constexpr_lsb(uint64_t bb) {
assert(bb != 0);
constexpr uint64_t debruijn64 = 0x03F79D71B4CB0A89ULL;
return lsb_index64[((bb ^ (bb - 1)) * debruijn64) >> 58];
}
alignas(CacheLineSize) static constexpr struct OffsetIndices {
#if (USE_SSE41)
std::uint8_t offset_indices[256][8];
#else
std::uint16_t offset_indices[256][8];
#endif
constexpr OffsetIndices() :
offset_indices() {
for (int i = 0; i < 256; ++i)
{
std::uint64_t j = i, k = 0;
while (j)
{
offset_indices[i][k++] = constexpr_lsb(j);
j &= j - 1;
}
while (k < 8)
offset_indices[i][k++] = 0;
}
}
} Lookup;
// Find indices of nonzero numbers in an int32_t array
template<const IndexType InputDimensions>
@@ -74,7 +98,11 @@ void find_nnz(const std::int32_t* input, std::uint16_t* out, IndexType& count_ou
using vec128_t = __m128i;
#define vec128_zero _mm_setzero_si128()
#define vec128_set_16(a) _mm_set1_epi16(a)
#define vec128_load(a) _mm_load_si128(a)
#if (USE_SSE41)
#define vec128_load(a) _mm_cvtepu8_epi16(_mm_loadl_epi64(a))
#else
#define vec128_load(a) _mm_load_si128(a)
#endif
#define vec128_storeu(a, b) _mm_storeu_si128(a, b)
#define vec128_add(a, b) _mm_add_epi16(a, b)
#elif defined(USE_NEON)
@@ -110,9 +138,9 @@ void find_nnz(const std::int32_t* input, std::uint16_t* out, IndexType& count_ou
}
for (IndexType j = 0; j < OutputsPerChunk; ++j)
{
const auto lookup = (nnz >> (j * 8)) & 0xFF;
const auto offsets =
vec128_load(reinterpret_cast<const vec128_t*>(&lookup_indices[lookup]));
const unsigned lookup = (nnz >> (j * 8)) & 0xFF;
const vec128_t offsets =
vec128_load(reinterpret_cast<const vec128_t*>(&Lookup.offset_indices[lookup]));
vec128_storeu(reinterpret_cast<vec128_t*>(out + count), vec128_add(base, offsets));
count += popcount(lookup);
base = vec128_add(base, increment);
+23 -27
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -65,41 +65,37 @@ class ClippedReLU {
if constexpr (InputDimensions % SimdWidth == 0)
{
constexpr IndexType NumChunks = InputDimensions / SimdWidth;
const __m256i Zero = _mm256_setzero_si256();
const __m256i Offsets = _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
const auto in = reinterpret_cast<const __m256i*>(input);
const auto out = reinterpret_cast<__m256i*>(output);
for (IndexType i = 0; i < NumChunks; ++i)
{
const __m256i words0 =
_mm256_srai_epi16(_mm256_packs_epi32(_mm256_load_si256(&in[i * 4 + 0]),
_mm256_load_si256(&in[i * 4 + 1])),
_mm256_srli_epi16(_mm256_packus_epi32(_mm256_load_si256(&in[i * 4 + 0]),
_mm256_load_si256(&in[i * 4 + 1])),
WeightScaleBits);
const __m256i words1 =
_mm256_srai_epi16(_mm256_packs_epi32(_mm256_load_si256(&in[i * 4 + 2]),
_mm256_load_si256(&in[i * 4 + 3])),
_mm256_srli_epi16(_mm256_packus_epi32(_mm256_load_si256(&in[i * 4 + 2]),
_mm256_load_si256(&in[i * 4 + 3])),
WeightScaleBits);
_mm256_store_si256(
&out[i], _mm256_permutevar8x32_epi32(
_mm256_max_epi8(_mm256_packs_epi16(words0, words1), Zero), Offsets));
_mm256_store_si256(&out[i], _mm256_permutevar8x32_epi32(
_mm256_packs_epi16(words0, words1), Offsets));
}
}
else
{
constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
const __m128i Zero = _mm_setzero_si128();
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i)
{
const __m128i words0 = _mm_srai_epi16(
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 1])),
const __m128i words0 = _mm_srli_epi16(
_mm_packus_epi32(_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 1])),
WeightScaleBits);
const __m128i words1 = _mm_srai_epi16(
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 3])),
const __m128i words1 = _mm_srli_epi16(
_mm_packus_epi32(_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 3])),
WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i], _mm_max_epi8(packedbytes, Zero));
_mm_store_si128(&out[i], _mm_packs_epi16(words0, words1));
}
}
constexpr IndexType Start = InputDimensions % SimdWidth == 0
@@ -109,9 +105,7 @@ class ClippedReLU {
#elif defined(USE_SSE2)
constexpr IndexType NumChunks = InputDimensions / SimdWidth;
#ifdef USE_SSE41
const __m128i Zero = _mm_setzero_si128();
#else
#ifndef USE_SSE41
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
@@ -119,6 +113,15 @@ class ClippedReLU {
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i)
{
#if defined(USE_SSE41)
const __m128i words0 = _mm_srli_epi16(
_mm_packus_epi32(_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 1])),
WeightScaleBits);
const __m128i words1 = _mm_srli_epi16(
_mm_packus_epi32(_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 3])),
WeightScaleBits);
_mm_store_si128(&out[i], _mm_packs_epi16(words0, words1));
#else
const __m128i words0 = _mm_srai_epi16(
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 1])),
WeightScaleBits);
@@ -126,15 +129,8 @@ class ClippedReLU {
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 3])),
WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i],
#ifdef USE_SSE41
_mm_max_epi8(packedbytes, Zero)
#else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
_mm_store_si128(&out[i], _mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s));
#endif
);
}
constexpr IndexType Start = NumChunks * SimdWidth;
+1 -34
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -43,39 +43,6 @@ namespace Stockfish::Simd {
return _mm512_reduce_add_epi32(sum) + bias;
}
/*
Parameters:
sum0 = [zmm0.i128[0], zmm0.i128[1], zmm0.i128[2], zmm0.i128[3]]
sum1 = [zmm1.i128[0], zmm1.i128[1], zmm1.i128[2], zmm1.i128[3]]
sum2 = [zmm2.i128[0], zmm2.i128[1], zmm2.i128[2], zmm2.i128[3]]
sum3 = [zmm3.i128[0], zmm3.i128[1], zmm3.i128[2], zmm3.i128[3]]
Returns:
ret = [
reduce_add_epi32(zmm0.i128[0]), reduce_add_epi32(zmm1.i128[0]), reduce_add_epi32(zmm2.i128[0]), reduce_add_epi32(zmm3.i128[0]),
reduce_add_epi32(zmm0.i128[1]), reduce_add_epi32(zmm1.i128[1]), reduce_add_epi32(zmm2.i128[1]), reduce_add_epi32(zmm3.i128[1]),
reduce_add_epi32(zmm0.i128[2]), reduce_add_epi32(zmm1.i128[2]), reduce_add_epi32(zmm2.i128[2]), reduce_add_epi32(zmm3.i128[2]),
reduce_add_epi32(zmm0.i128[3]), reduce_add_epi32(zmm1.i128[3]), reduce_add_epi32(zmm2.i128[3]), reduce_add_epi32(zmm3.i128[3])
]
*/
[[maybe_unused]] static __m512i
m512_hadd128x16_interleave(__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3) {
__m512i sum01a = _mm512_unpacklo_epi32(sum0, sum1);
__m512i sum01b = _mm512_unpackhi_epi32(sum0, sum1);
__m512i sum23a = _mm512_unpacklo_epi32(sum2, sum3);
__m512i sum23b = _mm512_unpackhi_epi32(sum2, sum3);
__m512i sum01 = _mm512_add_epi32(sum01a, sum01b);
__m512i sum23 = _mm512_add_epi32(sum23a, sum23b);
__m512i sum0123a = _mm512_unpacklo_epi64(sum01, sum23);
__m512i sum0123b = _mm512_unpackhi_epi64(sum01, sum23);
return _mm512_add_epi32(sum0123a, sum0123b);
}
[[maybe_unused]] static void m512_add_dpbusd_epi32(__m512i& acc, __m512i a, __m512i b) {
#if defined(USE_VNNI)
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
+467
View File
@@ -0,0 +1,467 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "network.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <memory>
#include <optional>
#include <type_traits>
#include <vector>
#define INCBIN_SILENCE_BITCODE_WARNING
#include "../incbin/incbin.h"
#include "../evaluate.h"
#include "../memory.h"
#include "../misc.h"
#include "../position.h"
#include "../types.h"
#include "nnue_architecture.h"
#include "nnue_common.h"
#include "nnue_misc.h"
// Macro to embed the default efficiently updatable neural network (NNUE) file
// data in the engine binary (using incbin.h, by Dale Weiler).
// This macro invocation will declare the following three variables
// const unsigned char gEmbeddedNNUEData[]; // a pointer to the embedded data
// const unsigned char *const gEmbeddedNNUEEnd; // a marker to the end
// const unsigned int gEmbeddedNNUESize; // the size of the embedded file
// Note that this does not work in Microsoft Visual Studio.
#if !defined(_MSC_VER) && !defined(NNUE_EMBEDDING_OFF)
INCBIN(EmbeddedNNUEBig, EvalFileDefaultNameBig);
INCBIN(EmbeddedNNUESmall, EvalFileDefaultNameSmall);
#else
const unsigned char gEmbeddedNNUEBigData[1] = {0x0};
const unsigned char* const gEmbeddedNNUEBigEnd = &gEmbeddedNNUEBigData[1];
const unsigned int gEmbeddedNNUEBigSize = 1;
const unsigned char gEmbeddedNNUESmallData[1] = {0x0};
const unsigned char* const gEmbeddedNNUESmallEnd = &gEmbeddedNNUESmallData[1];
const unsigned int gEmbeddedNNUESmallSize = 1;
#endif
namespace {
struct EmbeddedNNUE {
EmbeddedNNUE(const unsigned char* embeddedData,
const unsigned char* embeddedEnd,
const unsigned int embeddedSize) :
data(embeddedData),
end(embeddedEnd),
size(embeddedSize) {}
const unsigned char* data;
const unsigned char* end;
const unsigned int size;
};
using namespace Stockfish::Eval::NNUE;
EmbeddedNNUE get_embedded(EmbeddedNNUEType type) {
if (type == EmbeddedNNUEType::BIG)
return EmbeddedNNUE(gEmbeddedNNUEBigData, gEmbeddedNNUEBigEnd, gEmbeddedNNUEBigSize);
else
return EmbeddedNNUE(gEmbeddedNNUESmallData, gEmbeddedNNUESmallEnd, gEmbeddedNNUESmallSize);
}
}
namespace Stockfish::Eval::NNUE {
namespace Detail {
// Read evaluation function parameters
template<typename T>
bool read_parameters(std::istream& stream, T& reference) {
std::uint32_t header;
header = read_little_endian<std::uint32_t>(stream);
if (!stream || header != T::get_hash_value())
return false;
return reference.read_parameters(stream);
}
// Write evaluation function parameters
template<typename T>
bool write_parameters(std::ostream& stream, T& reference) {
write_little_endian<std::uint32_t>(stream, T::get_hash_value());
return reference.write_parameters(stream);
}
} // namespace Detail
template<typename Arch, typename Transformer>
Network<Arch, Transformer>::Network(const Network<Arch, Transformer>& other) :
evalFile(other.evalFile),
embeddedType(other.embeddedType) {
if (other.featureTransformer)
featureTransformer = make_unique_large_page<Transformer>(*other.featureTransformer);
network = make_unique_aligned<Arch[]>(LayerStacks);
if (!other.network)
return;
for (std::size_t i = 0; i < LayerStacks; ++i)
network[i] = other.network[i];
}
template<typename Arch, typename Transformer>
Network<Arch, Transformer>&
Network<Arch, Transformer>::operator=(const Network<Arch, Transformer>& other) {
evalFile = other.evalFile;
embeddedType = other.embeddedType;
if (other.featureTransformer)
featureTransformer = make_unique_large_page<Transformer>(*other.featureTransformer);
network = make_unique_aligned<Arch[]>(LayerStacks);
if (!other.network)
return *this;
for (std::size_t i = 0; i < LayerStacks; ++i)
network[i] = other.network[i];
return *this;
}
template<typename Arch, typename Transformer>
void Network<Arch, Transformer>::load(const std::string& rootDirectory, std::string evalfilePath) {
#if defined(DEFAULT_NNUE_DIRECTORY)
std::vector<std::string> dirs = {"<internal>", "", rootDirectory,
stringify(DEFAULT_NNUE_DIRECTORY)};
#else
std::vector<std::string> dirs = {"<internal>", "", rootDirectory};
#endif
if (evalfilePath.empty())
evalfilePath = evalFile.defaultName;
for (const auto& directory : dirs)
{
if (evalFile.current != evalfilePath)
{
if (directory != "<internal>")
{
load_user_net(directory, evalfilePath);
}
if (directory == "<internal>" && evalfilePath == evalFile.defaultName)
{
load_internal();
}
}
}
}
template<typename Arch, typename Transformer>
bool Network<Arch, Transformer>::save(const std::optional<std::string>& filename) const {
std::string actualFilename;
std::string msg;
if (filename.has_value())
actualFilename = filename.value();
else
{
if (evalFile.current != evalFile.defaultName)
{
msg = "Failed to export a net. "
"A non-embedded net can only be saved if the filename is specified";
sync_cout << msg << sync_endl;
return false;
}
actualFilename = evalFile.defaultName;
}
std::ofstream stream(actualFilename, std::ios_base::binary);
bool saved = save(stream, evalFile.current, evalFile.netDescription);
msg = saved ? "Network saved successfully to " + actualFilename : "Failed to export a net";
sync_cout << msg << sync_endl;
return saved;
}
template<typename Arch, typename Transformer>
NetworkOutput
Network<Arch, Transformer>::evaluate(const Position& pos,
AccumulatorCaches::Cache<FTDimensions>* cache) const {
// We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType
transformedFeaturesUnaligned[FeatureTransformer<FTDimensions, nullptr>::BufferSize
+ alignment / sizeof(TransformedFeatureType)];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
#else
alignas(alignment) TransformedFeatureType
transformedFeatures[FeatureTransformer<FTDimensions, nullptr>::BufferSize];
#endif
ASSERT_ALIGNED(transformedFeatures, alignment);
const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
const auto psqt = featureTransformer->transform(pos, cache, transformedFeatures, bucket);
const auto positional = network[bucket].propagate(transformedFeatures);
return {static_cast<Value>(psqt / OutputScale), static_cast<Value>(positional / OutputScale)};
}
template<typename Arch, typename Transformer>
void Network<Arch, Transformer>::verify(std::string evalfilePath,
const std::function<void(std::string_view)>& f) const {
if (evalfilePath.empty())
evalfilePath = evalFile.defaultName;
if (evalFile.current != evalfilePath)
{
if (f)
{
std::string msg1 =
"Network evaluation parameters compatible with the engine must be available.";
std::string msg2 = "The network file " + evalfilePath + " was not loaded successfully.";
std::string msg3 = "The UCI option EvalFile might need to specify the full path, "
"including the directory name, to the network file.";
std::string msg4 = "The default net can be downloaded from: "
"https://tests.stockfishchess.org/api/nn/"
+ evalFile.defaultName;
std::string msg5 = "The engine will be terminated now.";
std::string msg = "ERROR: " + msg1 + '\n' + "ERROR: " + msg2 + '\n' + "ERROR: " + msg3
+ '\n' + "ERROR: " + msg4 + '\n' + "ERROR: " + msg5 + '\n';
f(msg);
}
exit(EXIT_FAILURE);
}
if (f)
{
size_t size = sizeof(*featureTransformer) + sizeof(Arch) * LayerStacks;
f("info string NNUE evaluation using " + evalfilePath + " ("
+ std::to_string(size / (1024 * 1024)) + "MiB, ("
+ std::to_string(featureTransformer->InputDimensions) + ", "
+ std::to_string(network[0].TransformedFeatureDimensions) + ", "
+ std::to_string(network[0].FC_0_OUTPUTS) + ", " + std::to_string(network[0].FC_1_OUTPUTS)
+ ", 1))");
}
}
template<typename Arch, typename Transformer>
void Network<Arch, Transformer>::hint_common_access(
const Position& pos, AccumulatorCaches::Cache<FTDimensions>* cache) const {
featureTransformer->hint_common_access(pos, cache);
}
template<typename Arch, typename Transformer>
NnueEvalTrace
Network<Arch, Transformer>::trace_evaluate(const Position& pos,
AccumulatorCaches::Cache<FTDimensions>* cache) const {
// We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType
transformedFeaturesUnaligned[FeatureTransformer<FTDimensions, nullptr>::BufferSize
+ alignment / sizeof(TransformedFeatureType)];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
#else
alignas(alignment) TransformedFeatureType
transformedFeatures[FeatureTransformer<FTDimensions, nullptr>::BufferSize];
#endif
ASSERT_ALIGNED(transformedFeatures, alignment);
NnueEvalTrace t{};
t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
for (IndexType bucket = 0; bucket < LayerStacks; ++bucket)
{
const auto materialist =
featureTransformer->transform(pos, cache, transformedFeatures, bucket);
const auto positional = network[bucket].propagate(transformedFeatures);
t.psqt[bucket] = static_cast<Value>(materialist / OutputScale);
t.positional[bucket] = static_cast<Value>(positional / OutputScale);
}
return t;
}
template<typename Arch, typename Transformer>
void Network<Arch, Transformer>::load_user_net(const std::string& dir,
const std::string& evalfilePath) {
std::ifstream stream(dir + evalfilePath, std::ios::binary);
auto description = load(stream);
if (description.has_value())
{
evalFile.current = evalfilePath;
evalFile.netDescription = description.value();
}
}
template<typename Arch, typename Transformer>
void Network<Arch, Transformer>::load_internal() {
// C++ way to prepare a buffer for a memory stream
class MemoryBuffer: public std::basic_streambuf<char> {
public:
MemoryBuffer(char* p, size_t n) {
setg(p, p, p + n);
setp(p, p + n);
}
};
const auto embedded = get_embedded(embeddedType);
MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(embedded.data)),
size_t(embedded.size));
std::istream stream(&buffer);
auto description = load(stream);
if (description.has_value())
{
evalFile.current = evalFile.defaultName;
evalFile.netDescription = description.value();
}
}
template<typename Arch, typename Transformer>
void Network<Arch, Transformer>::initialize() {
featureTransformer = make_unique_large_page<Transformer>();
network = make_unique_aligned<Arch[]>(LayerStacks);
}
template<typename Arch, typename Transformer>
bool Network<Arch, Transformer>::save(std::ostream& stream,
const std::string& name,
const std::string& netDescription) const {
if (name.empty() || name == "None")
return false;
return write_parameters(stream, netDescription);
}
template<typename Arch, typename Transformer>
std::optional<std::string> Network<Arch, Transformer>::load(std::istream& stream) {
initialize();
std::string description;
return read_parameters(stream, description) ? std::make_optional(description) : std::nullopt;
}
// Read network header
template<typename Arch, typename Transformer>
bool Network<Arch, Transformer>::read_header(std::istream& stream,
std::uint32_t* hashValue,
std::string* desc) const {
std::uint32_t version, size;
version = read_little_endian<std::uint32_t>(stream);
*hashValue = read_little_endian<std::uint32_t>(stream);
size = read_little_endian<std::uint32_t>(stream);
if (!stream || version != Version)
return false;
desc->resize(size);
stream.read(&(*desc)[0], size);
return !stream.fail();
}
// Write network header
template<typename Arch, typename Transformer>
bool Network<Arch, Transformer>::write_header(std::ostream& stream,
std::uint32_t hashValue,
const std::string& desc) const {
write_little_endian<std::uint32_t>(stream, Version);
write_little_endian<std::uint32_t>(stream, hashValue);
write_little_endian<std::uint32_t>(stream, std::uint32_t(desc.size()));
stream.write(&desc[0], desc.size());
return !stream.fail();
}
template<typename Arch, typename Transformer>
bool Network<Arch, Transformer>::read_parameters(std::istream& stream,
std::string& netDescription) const {
std::uint32_t hashValue;
if (!read_header(stream, &hashValue, &netDescription))
return false;
if (hashValue != Network::hash)
return false;
if (!Detail::read_parameters(stream, *featureTransformer))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
{
if (!Detail::read_parameters(stream, network[i]))
return false;
}
return stream && stream.peek() == std::ios::traits_type::eof();
}
template<typename Arch, typename Transformer>
bool Network<Arch, Transformer>::write_parameters(std::ostream& stream,
const std::string& netDescription) const {
if (!write_header(stream, Network::hash, netDescription))
return false;
if (!Detail::write_parameters(stream, *featureTransformer))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
{
if (!Detail::write_parameters(stream, network[i]))
return false;
}
return bool(stream);
}
// Explicit template instantiation
template class Network<
NetworkArchitecture<TransformedFeatureDimensionsBig, L2Big, L3Big>,
FeatureTransformer<TransformedFeatureDimensionsBig, &StateInfo::accumulatorBig>>;
template class Network<
NetworkArchitecture<TransformedFeatureDimensionsSmall, L2Small, L3Small>,
FeatureTransformer<TransformedFeatureDimensionsSmall, &StateInfo::accumulatorSmall>>;
} // namespace Stockfish::Eval::NNUE
+134
View File
@@ -0,0 +1,134 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETWORK_H_INCLUDED
#define NETWORK_H_INCLUDED
#include <cstdint>
#include <functional>
#include <iostream>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include "../memory.h"
#include "../position.h"
#include "../types.h"
#include "nnue_accumulator.h"
#include "nnue_architecture.h"
#include "nnue_feature_transformer.h"
#include "nnue_misc.h"
namespace Stockfish::Eval::NNUE {
enum class EmbeddedNNUEType {
BIG,
SMALL,
};
using NetworkOutput = std::tuple<Value, Value>;
template<typename Arch, typename Transformer>
class Network {
static constexpr IndexType FTDimensions = Arch::TransformedFeatureDimensions;
public:
Network(EvalFile file, EmbeddedNNUEType type) :
evalFile(file),
embeddedType(type) {}
Network(const Network& other);
Network(Network&& other) = default;
Network& operator=(const Network& other);
Network& operator=(Network&& other) = default;
void load(const std::string& rootDirectory, std::string evalfilePath);
bool save(const std::optional<std::string>& filename) const;
NetworkOutput evaluate(const Position& pos,
AccumulatorCaches::Cache<FTDimensions>* cache) const;
void hint_common_access(const Position& pos,
AccumulatorCaches::Cache<FTDimensions>* cache) const;
void verify(std::string evalfilePath, const std::function<void(std::string_view)>&) const;
NnueEvalTrace trace_evaluate(const Position& pos,
AccumulatorCaches::Cache<FTDimensions>* cache) const;
private:
void load_user_net(const std::string&, const std::string&);
void load_internal();
void initialize();
bool save(std::ostream&, const std::string&, const std::string&) const;
std::optional<std::string> load(std::istream&);
bool read_header(std::istream&, std::uint32_t*, std::string*) const;
bool write_header(std::ostream&, std::uint32_t, const std::string&) const;
bool read_parameters(std::istream&, std::string&) const;
bool write_parameters(std::ostream&, const std::string&) const;
// Input feature converter
LargePagePtr<Transformer> featureTransformer;
// Evaluation function
AlignedPtr<Arch[]> network;
EvalFile evalFile;
EmbeddedNNUEType embeddedType;
// Hash value of evaluation function structure
static constexpr std::uint32_t hash = Transformer::get_hash_value() ^ Arch::get_hash_value();
template<IndexType Size>
friend struct AccumulatorCaches::Cache;
};
// Definitions of the network types
using SmallFeatureTransformer =
FeatureTransformer<TransformedFeatureDimensionsSmall, &StateInfo::accumulatorSmall>;
using SmallNetworkArchitecture =
NetworkArchitecture<TransformedFeatureDimensionsSmall, L2Small, L3Small>;
using BigFeatureTransformer =
FeatureTransformer<TransformedFeatureDimensionsBig, &StateInfo::accumulatorBig>;
using BigNetworkArchitecture = NetworkArchitecture<TransformedFeatureDimensionsBig, L2Big, L3Big>;
using NetworkBig = Network<BigNetworkArchitecture, BigFeatureTransformer>;
using NetworkSmall = Network<SmallNetworkArchitecture, SmallFeatureTransformer>;
struct Networks {
Networks(NetworkBig&& nB, NetworkSmall&& nS) :
big(std::move(nB)),
small(std::move(nS)) {}
NetworkBig big;
NetworkSmall small;
};
} // namespace Stockfish
#endif
+63 -4
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,12 +28,71 @@
namespace Stockfish::Eval::NNUE {
using BiasType = std::int16_t;
using PSQTWeightType = std::int32_t;
using IndexType = std::uint32_t;
// Class that holds the result of affine transformation of input features
template<IndexType Size>
struct alignas(CacheLineSize) Accumulator {
std::int16_t accumulation[2][Size];
std::int32_t psqtAccumulation[2][PSQTBuckets];
bool computed[2];
std::int16_t accumulation[COLOR_NB][Size];
std::int32_t psqtAccumulation[COLOR_NB][PSQTBuckets];
bool computed[COLOR_NB];
};
// AccumulatorCaches struct provides per-thread accumulator caches, where each
// cache contains multiple entries for each of the possible king squares.
// When the accumulator needs to be refreshed, the cached entry is used to more
// efficiently update the accumulator, instead of rebuilding it from scratch.
// This idea, was first described by Luecx (author of Koivisto) and
// is commonly referred to as "Finny Tables".
struct AccumulatorCaches {
template<typename Networks>
AccumulatorCaches(const Networks& networks) {
clear(networks);
}
template<IndexType Size>
struct alignas(CacheLineSize) Cache {
struct alignas(CacheLineSize) Entry {
BiasType accumulation[Size];
PSQTWeightType psqtAccumulation[PSQTBuckets];
Bitboard byColorBB[COLOR_NB];
Bitboard byTypeBB[PIECE_TYPE_NB];
// To initialize a refresh entry, we set all its bitboards empty,
// so we put the biases in the accumulation, without any weights on top
void clear(const BiasType* biases) {
std::memcpy(accumulation, biases, sizeof(accumulation));
std::memset((uint8_t*) this + offsetof(Entry, psqtAccumulation), 0,
sizeof(Entry) - offsetof(Entry, psqtAccumulation));
}
};
template<typename Network>
void clear(const Network& network) {
for (auto& entries1D : entries)
for (auto& entry : entries1D)
entry.clear(network.featureTransformer->biases);
}
std::array<Entry, COLOR_NB>& operator[](Square sq) { return entries[sq]; }
std::array<std::array<Entry, COLOR_NB>, SQUARE_NB> entries;
};
template<typename Networks>
void clear(const Networks& networks) {
big.clear(networks.big);
small.clear(networks.small);
}
Cache<TransformedFeatureDimensionsBig> big;
Cache<TransformedFeatureDimensionsSmall> small;
};
} // namespace Stockfish::Eval::NNUE
+3 -8
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,13 +37,8 @@ namespace Stockfish::Eval::NNUE {
// Input features used in evaluation function
using FeatureSet = Features::HalfKAv2_hm;
enum NetSize : int {
Big,
Small
};
// Number of input feature dimensions after conversion
constexpr IndexType TransformedFeatureDimensionsBig = 2560;
constexpr IndexType TransformedFeatureDimensionsBig = 3072;
constexpr int L2Big = 15;
constexpr int L3Big = 32;
@@ -55,7 +50,7 @@ constexpr IndexType PSQTBuckets = 8;
constexpr IndexType LayerStacks = 8;
template<IndexType L1, int L2, int L3>
struct Network {
struct NetworkArchitecture {
static constexpr IndexType TransformedFeatureDimensions = L1;
static constexpr int FC_0_OUTPUTS = L2;
static constexpr int FC_1_OUTPUTS = L3;
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
File diff suppressed because it is too large Load Diff
+203
View File
@@ -0,0 +1,203 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Code for calculating NNUE evaluation function
#include "nnue_misc.h"
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iosfwd>
#include <iostream>
#include <sstream>
#include <string_view>
#include <tuple>
#include "../evaluate.h"
#include "../position.h"
#include "../types.h"
#include "../uci.h"
#include "network.h"
#include "nnue_accumulator.h"
namespace Stockfish::Eval::NNUE {
constexpr std::string_view PieceToChar(" PNBRQK pnbrqk");
void hint_common_parent_position(const Position& pos,
const Networks& networks,
AccumulatorCaches& caches) {
if (Eval::use_smallnet(pos))
networks.small.hint_common_access(pos, &caches.small);
else
networks.big.hint_common_access(pos, &caches.big);
}
namespace {
// Converts a Value into (centi)pawns and writes it in a buffer.
// The buffer must have capacity for at least 5 chars.
void format_cp_compact(Value v, char* buffer, const Position& pos) {
buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
int cp = std::abs(UCIEngine::to_cp(v, pos));
if (cp >= 10000)
{
buffer[1] = '0' + cp / 10000;
cp %= 10000;
buffer[2] = '0' + cp / 1000;
cp %= 1000;
buffer[3] = '0' + cp / 100;
buffer[4] = ' ';
}
else if (cp >= 1000)
{
buffer[1] = '0' + cp / 1000;
cp %= 1000;
buffer[2] = '0' + cp / 100;
cp %= 100;
buffer[3] = '.';
buffer[4] = '0' + cp / 10;
}
else
{
buffer[1] = '0' + cp / 100;
cp %= 100;
buffer[2] = '.';
buffer[3] = '0' + cp / 10;
cp %= 10;
buffer[4] = '0' + cp / 1;
}
}
// Converts a Value into pawns, always keeping two decimals
void format_cp_aligned_dot(Value v, std::stringstream& stream, const Position& pos) {
const double pawns = std::abs(0.01 * UCIEngine::to_cp(v, pos));
stream << (v < 0 ? '-'
: v > 0 ? '+'
: ' ')
<< std::setiosflags(std::ios::fixed) << std::setw(6) << std::setprecision(2) << pawns;
}
}
// Returns a string with the value of each piece on a board,
// and a table for (PSQT, Layers) values bucket by bucket.
std::string
trace(Position& pos, const Eval::NNUE::Networks& networks, Eval::NNUE::AccumulatorCaches& caches) {
std::stringstream ss;
char board[3 * 8 + 1][8 * 8 + 2];
std::memset(board, ' ', sizeof(board));
for (int row = 0; row < 3 * 8 + 1; ++row)
board[row][8 * 8 + 1] = '\0';
// A lambda to output one box of the board
auto writeSquare = [&board, &pos](File file, Rank rank, Piece pc, Value value) {
const int x = int(file) * 8;
const int y = (7 - int(rank)) * 3;
for (int i = 1; i < 8; ++i)
board[y][x + i] = board[y + 3][x + i] = '-';
for (int i = 1; i < 3; ++i)
board[y + i][x] = board[y + i][x + 8] = '|';
board[y][x] = board[y][x + 8] = board[y + 3][x + 8] = board[y + 3][x] = '+';
if (pc != NO_PIECE)
board[y + 1][x + 4] = PieceToChar[pc];
if (is_valid(value))
format_cp_compact(value, &board[y + 2][x + 2], pos);
};
// We estimate the value of each piece by doing a differential evaluation from
// the current base eval, simulating the removal of the piece from its square.
auto [psqt, positional] = networks.big.evaluate(pos, &caches.big);
Value base = psqt + positional;
base = pos.side_to_move() == WHITE ? base : -base;
for (File f = FILE_A; f <= FILE_H; ++f)
for (Rank r = RANK_1; r <= RANK_8; ++r)
{
Square sq = make_square(f, r);
Piece pc = pos.piece_on(sq);
Value v = VALUE_NONE;
if (pc != NO_PIECE && type_of(pc) != KING)
{
auto st = pos.state();
pos.remove_piece(sq);
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] = false;
std::tie(psqt, positional) = networks.big.evaluate(pos, &caches.big);
Value eval = psqt + positional;
eval = pos.side_to_move() == WHITE ? eval : -eval;
v = base - eval;
pos.put_piece(pc, sq);
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] = false;
}
writeSquare(f, r, pc, v);
}
ss << " NNUE derived piece values:\n";
for (int row = 0; row < 3 * 8 + 1; ++row)
ss << board[row] << '\n';
ss << '\n';
auto t = networks.big.trace_evaluate(pos, &caches.big);
ss << " NNUE network contributions "
<< (pos.side_to_move() == WHITE ? "(White to move)" : "(Black to move)") << std::endl
<< "+------------+------------+------------+------------+\n"
<< "| Bucket | Material | Positional | Total |\n"
<< "| | (PSQT) | (Layers) | |\n"
<< "+------------+------------+------------+------------+\n";
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket)
{
ss << "| " << bucket << " " //
<< " | ";
format_cp_aligned_dot(t.psqt[bucket], ss, pos);
ss << " " //
<< " | ";
format_cp_aligned_dot(t.positional[bucket], ss, pos);
ss << " " //
<< " | ";
format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], ss, pos);
ss << " " //
<< " |";
if (bucket == t.correctBucket)
ss << " <-- this bucket is used";
ss << '\n';
}
ss << "+------------+------------+------------+------------+\n";
return ss.str();
}
} // namespace Stockfish::Eval::NNUE
+64
View File
@@ -0,0 +1,64 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NNUE_MISC_H_INCLUDED
#define NNUE_MISC_H_INCLUDED
#include <cstddef>
#include <string>
#include "../types.h"
#include "nnue_architecture.h"
namespace Stockfish {
class Position;
namespace Eval::NNUE {
struct EvalFile {
// Default net name, will use one of the EvalFileDefaultName* macros defined
// in evaluate.h
std::string defaultName;
// Selected net name, either via uci option or default
std::string current;
// Net description extracted from the net file
std::string netDescription;
};
struct NnueEvalTrace {
static_assert(LayerStacks == PSQTBuckets);
Value psqt[LayerStacks];
Value positional[LayerStacks];
std::size_t correctBucket;
};
struct Networks;
struct AccumulatorCaches;
std::string trace(Position& pos, const Networks& networks, AccumulatorCaches& caches);
void hint_common_parent_position(const Position& pos,
const Networks& networks,
AccumulatorCaches& caches);
} // namespace Stockfish::Eval::NNUE
} // namespace Stockfish
#endif // #ifndef NNUE_MISC_H_INCLUDED
+1346
View File
File diff suppressed because it is too large Load Diff
+5 -6
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@
#include "types.h"
#include "uci.h"
namespace Stockfish {
namespace Stockfish::Benchmark {
// Utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned.
@@ -51,18 +51,17 @@ uint64_t perft(Position& pos, Depth depth) {
pos.undo_move(m);
}
if (Root)
sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
sync_cout << UCIEngine::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
}
return nodes;
}
inline void perft(const std::string& fen, Depth depth, bool isChess960) {
inline uint64_t perft(const std::string& fen, Depth depth, bool isChess960) {
StateListPtr states(new std::deque<StateInfo>(1));
Position p;
p.set(fen, isChess960, &states->back());
uint64_t nodes = perft<true>(p, depth);
sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
return perft<true>(p, depth);
}
}
+105 -72
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -78,7 +78,7 @@ std::ostream& operator<<(std::ostream& os, const Position& pos) {
<< std::setw(16) << pos.key() << std::setfill(' ') << std::dec << "\nCheckers: ";
for (Bitboard b = pos.checkers(); b;)
os << UCI::square(pop_lsb(b)) << " ";
os << UCIEngine::square(pop_lsb(b)) << " ";
if (int(Tablebases::MaxCardinality) >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING))
{
@@ -119,6 +119,9 @@ void Position::init() {
for (Piece pc : Pieces)
for (Square s = SQ_A1; s <= SQ_H8; ++s)
Zobrist::psq[pc][s] = rng.rand<Key>();
// pawns on these squares will promote
std::fill_n(Zobrist::psq[W_PAWN] + SQ_A8, 8, 0);
std::fill_n(Zobrist::psq[B_PAWN], 8, 0);
for (File f = FILE_A; f <= FILE_H; ++f)
Zobrist::enpassant[f] = rng.rand<Key>();
@@ -334,8 +337,10 @@ void Position::set_check_info() const {
// The function is only used when a new position is set up
void Position::set_state() const {
st->key = st->materialKey = 0;
st->pawnKey = Zobrist::noPawns;
st->key = st->materialKey = 0;
st->minorPieceKey = 0;
st->nonPawnKey[WHITE] = st->nonPawnKey[BLACK] = 0;
st->pawnKey = Zobrist::noPawns;
st->nonPawnMaterial[WHITE] = st->nonPawnMaterial[BLACK] = VALUE_ZERO;
st->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
@@ -350,8 +355,18 @@ void Position::set_state() const {
if (type_of(pc) == PAWN)
st->pawnKey ^= Zobrist::psq[pc][s];
else if (type_of(pc) != KING)
st->nonPawnMaterial[color_of(pc)] += PieceValue[pc];
else
{
st->nonPawnKey[color_of(pc)] ^= Zobrist::psq[pc][s];
if (type_of(pc) != KING)
{
st->nonPawnMaterial[color_of(pc)] += PieceValue[pc];
if (type_of(pc) <= BISHOP)
st->minorPieceKey ^= Zobrist::psq[pc][s];
}
}
}
if (st->epSquare != SQ_NONE)
@@ -364,7 +379,7 @@ void Position::set_state() const {
for (Piece pc : Pieces)
for (int cnt = 0; cnt < pieceCount[pc]; ++cnt)
st->materialKey ^= Zobrist::psq[pc][cnt];
st->materialKey ^= Zobrist::psq[pc][8 + cnt];
}
@@ -431,8 +446,8 @@ string Position::fen() const {
if (!can_castle(ANY_CASTLING))
ss << '-';
ss << (ep_square() == SQ_NONE ? " - " : " " + UCI::square(ep_square()) + " ") << st->rule50
<< " " << 1 + (gamePly - (sideToMove == BLACK)) / 2;
ss << (ep_square() == SQ_NONE ? " - " : " " + UCIEngine::square(ep_square()) + " ")
<< st->rule50 << " " << 1 + (gamePly - (sideToMove == BLACK)) / 2;
return ss.str();
}
@@ -472,14 +487,23 @@ void Position::update_slider_blockers(Color c) const {
// Slider attacks use the occupied bitboard to indicate occupancy.
Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
return (pawn_attacks_bb(BLACK, s) & pieces(WHITE, PAWN))
| (pawn_attacks_bb(WHITE, s) & pieces(BLACK, PAWN))
| (attacks_bb<KNIGHT>(s) & pieces(KNIGHT))
| (attacks_bb<ROOK>(s, occupied) & pieces(ROOK, QUEEN))
return (attacks_bb<ROOK>(s, occupied) & pieces(ROOK, QUEEN))
| (attacks_bb<BISHOP>(s, occupied) & pieces(BISHOP, QUEEN))
| (attacks_bb<KING>(s) & pieces(KING));
| (pawn_attacks_bb(BLACK, s) & pieces(WHITE, PAWN))
| (pawn_attacks_bb(WHITE, s) & pieces(BLACK, PAWN))
| (attacks_bb<KNIGHT>(s) & pieces(KNIGHT)) | (attacks_bb<KING>(s) & pieces(KING));
}
bool Position::attackers_to_exist(Square s, Bitboard occupied, Color c) const {
return ((attacks_bb<ROOK>(s) & pieces(c, ROOK, QUEEN))
&& (attacks_bb<ROOK>(s, occupied) & pieces(c, ROOK, QUEEN)))
|| ((attacks_bb<BISHOP>(s) & pieces(c, BISHOP, QUEEN))
&& (attacks_bb<BISHOP>(s, occupied) & pieces(c, BISHOP, QUEEN)))
|| (((pawn_attacks_bb(~c, s) & pieces(PAWN)) | (attacks_bb<KNIGHT>(s) & pieces(KNIGHT))
| (attacks_bb<KING>(s) & pieces(KING)))
& pieces(c));
}
// Tests whether a pseudo-legal move is legal
bool Position::legal(Move m) const {
@@ -521,7 +545,7 @@ bool Position::legal(Move m) const {
Direction step = to > from ? WEST : EAST;
for (Square s = to; s != from; s += step)
if (attackers_to(s) & pieces(~us))
if (attackers_to_exist(s, pieces(), ~us))
return false;
// In case of Chess960, verify if the Rook blocks some checks.
@@ -532,7 +556,7 @@ bool Position::legal(Move m) const {
// If the moving piece is a king, check whether the destination square is
// attacked by the opponent.
if (type_of(piece_on(from)) == KING)
return !(attackers_to(to, pieces() ^ from) & pieces(~us));
return !(attackers_to_exist(to, pieces() ^ from, ~us));
// A non-king move is legal if and only if it is not pinned or it
// is moving along the ray towards or away from the king.
@@ -601,7 +625,7 @@ bool Position::pseudo_legal(const Move m) const {
}
// In case of king moves under check we have to remove the king so as to catch
// invalid moves like b1a1 when opposite queen is on c1.
else if (attackers_to(to, pieces() ^ from) & pieces(~us))
else if (attackers_to_exist(to, pieces() ^ from, ~us))
return false;
}
@@ -659,7 +683,12 @@ bool Position::gives_check(Move m) const {
// Makes a move, and saves all information necessary
// to a StateInfo object. The move is assumed to be legal. Pseudo-legal
// moves should be filtered out before this function is called.
void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// If a pointer to the TT table is passed, the entry for the new position
// will be prefetched
void Position::do_move(Move m,
StateInfo& newSt,
bool givesCheck,
const TranspositionTable* tt = nullptr) {
assert(m.is_ok());
assert(&newSt != st);
@@ -671,6 +700,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// our state pointer to point to the new (ready to be updated) state.
std::memcpy(&newSt, st, offsetof(StateInfo, key));
newSt.previous = st;
st->next = &newSt;
st = &newSt;
// Increment ply counters. In particular, rule50 will be reset to zero later on
@@ -682,8 +712,9 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// Used by NNUE
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] = false;
auto& dp = st->dirtyPiece;
dp.dirty_num = 1;
auto& dp = st->dirtyPiece;
dp.dirty_num = 1;
Color us = sideToMove;
Color them = ~us;
@@ -705,6 +736,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
do_castling<true>(us, from, to, rfrom, rto);
k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto];
st->nonPawnKey[us] ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto];
captured = NO_PIECE;
}
@@ -730,7 +762,13 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
st->pawnKey ^= Zobrist::psq[captured][capsq];
}
else
{
st->nonPawnMaterial[them] -= PieceValue[captured];
st->nonPawnKey[them] ^= Zobrist::psq[captured][capsq];
if (type_of(captured) <= BISHOP)
st->minorPieceKey ^= Zobrist::psq[captured][capsq];
}
dp.dirty_num = 2; // 1 piece moved, 1 piece captured
dp.piece[1] = captured;
@@ -740,9 +778,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// Update board and piece lists
remove_piece(capsq);
// Update material hash key and prefetch access to materialTable
k ^= Zobrist::psq[captured][capsq];
st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
st->materialKey ^= Zobrist::psq[captured][8 + pieceCount[captured]];
// Reset rule 50 counter
st->rule50 = 0;
@@ -789,7 +826,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
else if (m.type_of() == PROMOTION)
{
Piece promotion = make_piece(us, m.promotion_type());
Piece promotion = make_piece(us, m.promotion_type());
PieceType promotionType = type_of(promotion);
assert(relative_rank(us, to) == RANK_8);
assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN);
@@ -805,10 +843,13 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
dp.dirty_num++;
// Update hash keys
k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
st->pawnKey ^= Zobrist::psq[pc][to];
st->materialKey ^=
Zobrist::psq[promotion][pieceCount[promotion] - 1] ^ Zobrist::psq[pc][pieceCount[pc]];
// Zobrist::psq[pc][to] is zero, so we don't need to clear it
k ^= Zobrist::psq[promotion][to];
st->materialKey ^= Zobrist::psq[promotion][8 + pieceCount[promotion] - 1]
^ Zobrist::psq[pc][8 + pieceCount[pc]];
if (promotionType <= BISHOP)
st->minorPieceKey ^= Zobrist::psq[promotion][to];
// Update material
st->nonPawnMaterial[us] += PieceValue[promotion];
@@ -821,11 +862,21 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
st->rule50 = 0;
}
// Set capture piece
st->capturedPiece = captured;
else
{
st->nonPawnKey[us] ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
if (type_of(pc) <= BISHOP)
st->minorPieceKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
}
// Update the key with the final value
st->key = k;
if (tt)
prefetch(tt->first_entry(key()));
// Set capture piece
st->capturedPiece = captured;
// Calculate checkers bitboard (if move gives check)
st->checkersBB = givesCheck ? attackers_to(square<KING>(them)) & pieces(us) : 0;
@@ -955,7 +1006,7 @@ void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Squ
// Used to do a "null move": it flips
// the side to move without executing any move on the board.
void Position::do_null_move(StateInfo& newSt, TranspositionTable& tt) {
void Position::do_null_move(StateInfo& newSt, const TranspositionTable& tt) {
assert(!checkers());
assert(&newSt != st);
@@ -963,13 +1014,9 @@ void Position::do_null_move(StateInfo& newSt, TranspositionTable& tt) {
std::memcpy(&newSt, st, offsetof(StateInfo, accumulatorBig));
newSt.previous = st;
st->next = &newSt;
st = &newSt;
st->dirtyPiece.dirty_num = 0;
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] = false;
if (st->epSquare != SQ_NONE)
{
st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
@@ -977,9 +1024,13 @@ void Position::do_null_move(StateInfo& newSt, TranspositionTable& tt) {
}
st->key ^= Zobrist::side;
++st->rule50;
prefetch(tt.first_entry(key()));
st->dirtyPiece.dirty_num = 0;
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] = false;
st->pliesFromNull = 0;
sideToMove = ~sideToMove;
@@ -1002,26 +1053,6 @@ void Position::undo_null_move() {
}
// Computes the new hash key after the given move. Needed
// for speculative prefetch. It doesn't recognize special moves like castling,
// en passant and promotions.
Key Position::key_after(Move m) const {
Square from = m.from_sq();
Square to = m.to_sq();
Piece pc = piece_on(from);
Piece captured = piece_on(to);
Key k = st->key ^ Zobrist::side;
if (captured)
k ^= Zobrist::psq[captured][to];
k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from];
return (captured || type_of(pc) == PAWN) ? k : adjust_key50<true>(k);
}
// Tests if the SEE (Static Exchange Evaluation)
// value of move is greater or equal to the given threshold. We'll use an
// algorithm similar to alpha-beta pruning with a null window.
@@ -1109,8 +1140,9 @@ bool Position::see_ge(Move m, int threshold) const {
else if ((bb = stmAttackers & pieces(QUEEN)))
{
if ((swap = QueenValue - swap) < res)
break;
swap = QueenValue - swap;
// implies that the previous recapture was done by a higher rated piece than a Queen (King is excluded)
assert(swap >= res);
occupied ^= least_significant_square_bb(bb);
attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
@@ -1133,11 +1165,12 @@ bool Position::is_draw(int ply) const {
if (st->rule50 > 99 && (!checkers() || MoveList<LEGAL>(*this).size()))
return true;
// Return a draw score if a position repeats once earlier but strictly
// after the root, or repeats twice before or at the root.
return st->repetition && st->repetition < ply;
return is_repetition(ply);
}
// Return a draw score if a position repeats once earlier but strictly
// after the root, or repeats twice before or at the root.
bool Position::is_repetition(int ply) const { return st->repetition && st->repetition < ply; }
// Tests whether there has been at least one repetition
// of positions since the last capture or pawn move.
@@ -1156,9 +1189,9 @@ bool Position::has_repeated() const {
}
// Tests if the position has a move which draws by repetition,
// or an earlier position has a move that directly reaches the current position.
bool Position::has_game_cycle(int ply) const {
// Tests if the position has a move which draws by repetition.
// This function accurately matches the outcome of is_draw() over all legal moves.
bool Position::upcoming_repetition(int ply) const {
int j;
@@ -1169,10 +1202,16 @@ bool Position::has_game_cycle(int ply) const {
Key originalKey = st->key;
StateInfo* stp = st->previous;
Key other = originalKey ^ stp->key ^ Zobrist::side;
for (int i = 3; i <= end; i += 2)
{
stp = stp->previous->previous;
stp = stp->previous;
other ^= stp->key ^ stp->previous->key ^ Zobrist::side;
stp = stp->previous;
if (other != 0)
continue;
Key moveKey = originalKey ^ stp->key;
if ((j = H1(moveKey), cuckoo[j] == moveKey) || (j = H2(moveKey), cuckoo[j] == moveKey))
@@ -1188,12 +1227,6 @@ bool Position::has_game_cycle(int ply) const {
// For nodes before or at the root, check that the move is a
// repetition rather than a move to the current position.
// In the cuckoo table, both moves Rc1c5 and Rc5c1 are stored in
// the same location, so we have to select which square to check.
if (color_of(piece_on(empty(s1) ? s2 : s1)) != side_to_move())
continue;
// For repetitions before or at the root, require one more
if (stp->repetition)
return true;
}
@@ -1253,7 +1286,7 @@ bool Position::pos_is_ok() const {
return true;
if (pieceCount[W_KING] != 1 || pieceCount[B_KING] != 1
|| attackers_to(square<KING>(~sideToMove)) & pieces(sideToMove))
|| attackers_to_exist(square<KING>(~sideToMove), pieces(), sideToMove))
assert(0 && "pos_is_ok: Kings");
if ((pieces(PAWN) & (Rank1BB | Rank8BB)) || pieceCount[W_PAWN] > 8 || pieceCount[B_PAWN] > 8)
+21 -9
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -43,6 +43,8 @@ struct StateInfo {
// Copied when making a move
Key materialKey;
Key pawnKey;
Key minorPieceKey;
Key nonPawnKey[COLOR_NB];
Value nonPawnMaterial[COLOR_NB];
int castlingRights;
int rule50;
@@ -53,6 +55,7 @@ struct StateInfo {
Key key;
Bitboard checkersBB;
StateInfo* previous;
StateInfo* next;
Bitboard blockersForKing[COLOR_NB];
Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB];
@@ -122,6 +125,7 @@ class Position {
// Attacks to/from a given square
Bitboard attackers_to(Square s) const;
Bitboard attackers_to(Square s, Bitboard occupied) const;
bool attackers_to_exist(Square s, Bitboard occupied, Color c) const;
void update_slider_blockers(Color c) const;
template<PieceType Pt>
Bitboard attacks_by(Color c) const;
@@ -136,10 +140,10 @@ class Position {
Piece captured_piece() const;
// Doing and undoing moves
void do_move(Move m, StateInfo& newSt);
void do_move(Move m, StateInfo& newSt, bool givesCheck);
void do_move(Move m, StateInfo& newSt, const TranspositionTable* tt);
void do_move(Move m, StateInfo& newSt, bool givesCheck, const TranspositionTable* tt);
void undo_move(Move m);
void do_null_move(StateInfo& newSt, TranspositionTable& tt);
void do_null_move(StateInfo& newSt, const TranspositionTable& tt);
void undo_null_move();
// Static Exchange Evaluation
@@ -147,16 +151,18 @@ class Position {
// Accessing hash keys
Key key() const;
Key key_after(Move m) const;
Key material_key() const;
Key pawn_key() const;
Key minor_piece_key() const;
Key non_pawn_key(Color c) const;
// Other properties of the position
Color side_to_move() const;
int game_ply() const;
bool is_chess960() const;
bool is_draw(int ply) const;
bool has_game_cycle(int ply) const;
bool is_repetition(int ply) const;
bool upcoming_repetition(int ply) const;
bool has_repeated() const;
int rule50_count() const;
Value non_pawn_material(Color c) const;
@@ -297,6 +303,10 @@ inline Key Position::pawn_key() const { return st->pawnKey; }
inline Key Position::material_key() const { return st->materialKey; }
inline Key Position::minor_piece_key() const { return st->minorPieceKey; }
inline Key Position::non_pawn_key(Color c) const { return st->nonPawnKey[c]; }
inline Value Position::non_pawn_material(Color c) const { return st->nonPawnMaterial[c]; }
inline Value Position::non_pawn_material() const {
@@ -315,8 +325,8 @@ inline bool Position::capture(Move m) const {
}
// Returns true if a move is generated from the capture stage, having also
// queen promotions covered, i.e. consistency with the capture stage move generation
// is needed to avoid the generation of duplicate moves.
// queen promotions covered, i.e. consistency with the capture stage move
// generation is needed to avoid the generation of duplicate moves.
inline bool Position::capture_stage(Move m) const {
assert(m.is_ok());
return capture(m) || m.promotion_type() == QUEEN;
@@ -355,7 +365,9 @@ inline void Position::move_piece(Square from, Square to) {
board[to] = pc;
}
inline void Position::do_move(Move m, StateInfo& newSt) { do_move(m, newSt, gives_check(m)); }
inline void Position::do_move(Move m, StateInfo& newSt, const TranspositionTable* tt = nullptr) {
do_move(m, newSt, gives_check(m), tt);
}
inline StateInfo* Position::state() const { return st; }
+48
View File
@@ -0,0 +1,48 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "score.h"
#include <cassert>
#include <cmath>
#include <cstdlib>
#include "uci.h"
namespace Stockfish {
Score::Score(Value v, const Position& pos) {
assert(-VALUE_INFINITE < v && v < VALUE_INFINITE);
if (!is_decisive(v))
{
score = InternalUnits{UCIEngine::to_cp(v, pos)};
}
else if (std::abs(v) <= VALUE_TB)
{
auto distance = VALUE_TB - std::abs(v);
score = (v > 0) ? Tablebase{distance, true} : Tablebase{-distance, false};
}
else
{
auto distance = VALUE_MATE - std::abs(v);
score = (v > 0) ? Mate{distance} : Mate{-distance};
}
}
}
+70
View File
@@ -0,0 +1,70 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCORE_H_INCLUDED
#define SCORE_H_INCLUDED
#include <variant>
#include <utility>
#include "types.h"
namespace Stockfish {
class Position;
class Score {
public:
struct Mate {
int plies;
};
struct Tablebase {
int plies;
bool win;
};
struct InternalUnits {
int value;
};
Score() = default;
Score(Value v, const Position& pos);
template<typename T>
bool is() const {
return std::holds_alternative<T>(score);
}
template<typename T>
T get() const {
return std::get<T>(score);
}
template<typename F>
decltype(auto) visit(F&& f) const {
return std::visit(std::forward<F>(f), score);
}
private:
std::variant<Mate, Tablebase, InternalUnits> score;
};
}
#endif // #ifndef SCORE_H_INCLUDED
+946 -716
View File
File diff suppressed because it is too large Load Diff
+165 -60
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,18 +19,25 @@
#ifndef SEARCH_H_INCLUDED
#define SEARCH_H_INCLUDED
#include <algorithm>
#include <array>
#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <vector>
#include <string>
#include <string_view>
#include <vector>
#include "history.h"
#include "misc.h"
#include "movepick.h"
#include "nnue/network.h"
#include "nnue/nnue_accumulator.h"
#include "numa.h"
#include "position.h"
#include "score.h"
#include "syzygy/tbprobe.h"
#include "timeman.h"
#include "types.h"
@@ -54,20 +61,21 @@ namespace Search {
// shallower and deeper in the tree during the search. Each search thread has
// its own array of Stack objects, indexed by the current ply.
struct Stack {
Move* pv;
PieceToHistory* continuationHistory;
int ply;
Move currentMove;
Move excludedMove;
Move killers[2];
Value staticEval;
int statScore;
int moveCount;
bool inCheck;
bool ttPv;
bool ttHit;
int multipleExtensions;
int cutoffCnt;
Move* pv;
PieceToHistory* continuationHistory;
CorrectionHistory<PieceTo>* continuationCorrectionHistory;
int ply;
Move currentMove;
Move excludedMove;
Value staticEval;
int statScore;
int moveCount;
bool inCheck;
bool ttPv;
bool ttHit;
int cutoffCnt;
int reduction;
bool isTTMove;
};
@@ -85,14 +93,16 @@ struct RootMove {
return m.score != score ? m.score < score : m.previousScore < previousScore;
}
Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE;
Value averageScore = -VALUE_INFINITE;
Value uciScore = -VALUE_INFINITE;
bool scoreLowerbound = false;
bool scoreUpperbound = false;
int selDepth = 0;
int tbRank = 0;
uint64_t effort = 0;
Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE;
Value averageScore = -VALUE_INFINITE;
Value meanSquaredScore = -VALUE_INFINITE * VALUE_INFINITE;
Value uciScore = -VALUE_INFINITE;
bool scoreLowerbound = false;
bool scoreUpperbound = false;
int selDepth = 0;
int tbRank = 0;
Value tbScore;
std::vector<Move> pv;
};
@@ -100,8 +110,7 @@ struct RootMove {
using RootMoves = std::vector<RootMove>;
// LimitsType struct stores information sent by GUI about available time to
// search the current move, maximum depth/time, or if we are in analysis mode.
// LimitsType struct stores information sent by the caller about the analysis required.
struct LimitsType {
// Init explicitly due to broken value-initialization of non POD in MSVC
@@ -109,30 +118,35 @@ struct LimitsType {
time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movetime = TimePoint(0);
movestogo = depth = mate = perft = infinite = 0;
nodes = 0;
ponderMode = false;
}
bool use_time_management() const { return time[WHITE] || time[BLACK]; }
std::vector<Move> searchmoves;
TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime;
int movestogo, depth, mate, perft, infinite;
uint64_t nodes;
std::vector<std::string> searchmoves;
TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime;
int movestogo, depth, mate, perft, infinite;
uint64_t nodes;
bool ponderMode;
};
// The UCI stores the uci options, thread pool, and transposition table.
// This struct is used to easily forward data to the Search::Worker class.
struct SharedState {
SharedState(const OptionsMap& optionsMap,
ThreadPool& threadPool,
TranspositionTable& transpositionTable) :
SharedState(const OptionsMap& optionsMap,
ThreadPool& threadPool,
TranspositionTable& transpositionTable,
const LazyNumaReplicated<Eval::NNUE::Networks>& nets) :
options(optionsMap),
threads(threadPool),
tt(transpositionTable) {}
tt(transpositionTable),
networks(nets) {}
const OptionsMap& options;
ThreadPool& threads;
TranspositionTable& tt;
const OptionsMap& options;
ThreadPool& threads;
TranspositionTable& tt;
const LazyNumaReplicated<Eval::NNUE::Networks>& networks;
};
class Worker;
@@ -145,18 +159,87 @@ class ISearchManager {
virtual void check_time(Search::Worker&) = 0;
};
struct InfoShort {
int depth;
Score score;
};
struct InfoFull: InfoShort {
int selDepth;
size_t multiPV;
std::string_view wdl;
std::string_view bound;
size_t timeMs;
size_t nodes;
size_t nps;
size_t tbHits;
std::string_view pv;
int hashfull;
};
struct InfoIteration {
int depth;
std::string_view currmove;
size_t currmovenumber;
};
// Skill structure is used to implement strength limit. If we have a UCI_Elo,
// we convert it to an appropriate skill level, anchored to the Stash engine.
// This method is based on a fit of the Elo results for games played between
// Stockfish at various skill levels and various versions of the Stash engine.
// Skill 0 .. 19 now covers CCRL Blitz Elo from 1320 to 3190, approximately
// Reference: https://github.com/vondele/Stockfish/commit/a08b8d4e9711c2
struct Skill {
// Lowest and highest Elo ratings used in the skill level calculation
constexpr static int LowestElo = 1320;
constexpr static int HighestElo = 3190;
Skill(int skill_level, int uci_elo) {
if (uci_elo)
{
double e = double(uci_elo - LowestElo) / (HighestElo - LowestElo);
level = std::clamp((((37.2473 * e - 40.8525) * e + 22.2943) * e - 0.311438), 0.0, 19.0);
}
else
level = double(skill_level);
}
bool enabled() const { return level < 20.0; }
bool time_to_pick(Depth depth) const { return depth == 1 + int(level); }
Move pick_best(const RootMoves&, size_t multiPV);
double level;
Move best = Move::none();
};
// SearchManager manages the search from the main thread. It is responsible for
// keeping track of the time, and storing data strictly related to the main thread.
class SearchManager: public ISearchManager {
public:
using UpdateShort = std::function<void(const InfoShort&)>;
using UpdateFull = std::function<void(const InfoFull&)>;
using UpdateIter = std::function<void(const InfoIteration&)>;
using UpdateBestmove = std::function<void(std::string_view, std::string_view)>;
struct UpdateContext {
UpdateShort onUpdateNoMoves;
UpdateFull onUpdateFull;
UpdateIter onIter;
UpdateBestmove onBestmove;
};
SearchManager(const UpdateContext& updateContext) :
updates(updateContext) {}
void check_time(Search::Worker& worker) override;
std::string pv(const Search::Worker& worker,
const ThreadPool& threads,
const TranspositionTable& tt,
Depth depth) const;
void pv(Search::Worker& worker,
const ThreadPool& threads,
const TranspositionTable& tt,
Depth depth);
Stockfish::TimeManagement tm;
double originalTimeAdjust;
int callsCnt;
std::atomic_bool ponder;
@@ -167,6 +250,8 @@ class SearchManager: public ISearchManager {
bool stopOnPonderhit;
size_t id;
const UpdateContext& updates;
};
class NullSearchManager: public ISearchManager {
@@ -174,52 +259,62 @@ class NullSearchManager: public ISearchManager {
void check_time(Search::Worker&) override {}
};
// Search::Worker is the class that does the actual search.
// It is instantiated once per thread, and it is responsible for keeping track
// of the search history, and storing data required for the search.
class Worker {
public:
Worker(SharedState&, std::unique_ptr<ISearchManager>, size_t);
Worker(SharedState&, std::unique_ptr<ISearchManager>, size_t, NumaReplicatedAccessToken);
// Called at instantiation to initialize Reductions tables
// Reset histories, usually before a new game
// Called at instantiation to initialize reductions tables.
// Reset histories, usually before a new game.
void clear();
// Called when the program receives the UCI 'go' command.
// It searches from the root position and outputs the "bestmove".
void start_searching();
bool is_mainthread() const { return thread_idx == 0; }
bool is_mainthread() const { return threadIdx == 0; }
void ensure_network_replicated();
// Public because they need to be updatable by the stats
CounterMoveHistory counterMoves;
ButterflyHistory mainHistory;
ButterflyHistory mainHistory;
LowPlyHistory lowPlyHistory;
CapturePieceToHistory captureHistory;
ContinuationHistory continuationHistory[2][2];
PawnHistory pawnHistory;
CorrectionHistory correctionHistory;
CorrectionHistory<Pawn> pawnCorrectionHistory;
CorrectionHistory<Minor> minorPieceCorrectionHistory;
CorrectionHistory<NonPawn> nonPawnCorrectionHistory[COLOR_NB];
CorrectionHistory<Continuation> continuationCorrectionHistory;
private:
void iterative_deepening();
// Main search function for both PV and non-PV nodes
// This is the main search function, for both PV and non-PV nodes
template<NodeType nodeType>
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode);
// Quiescence search function, which is called by the main search
template<NodeType nodeType>
Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth = 0);
Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta);
Depth reduction(bool i, Depth d, int mn, int delta);
Depth reduction(bool i, Depth d, int mn, int delta) const;
// Get a pointer to the search manager, only allowed to be called by the
// main thread.
// Pointer to the search manager, only allowed to be called by the main thread
SearchManager* main_manager() const {
assert(thread_idx == 0);
assert(threadIdx == 0);
return static_cast<SearchManager*>(manager.get());
}
std::array<std::array<uint64_t, SQUARE_NB>, SQUARE_NB> effort;
TimePoint elapsed() const;
TimePoint elapsed_time() const;
Value evaluate(const Position&);
LimitsType limits;
@@ -235,7 +330,8 @@ class Worker {
Depth rootDepth, completedDepth;
Value rootDelta;
size_t thread_idx;
size_t threadIdx;
NumaReplicatedAccessToken numaAccessToken;
// Reductions lookup table initialized at startup
std::array<int, MAX_MOVES> reductions; // [depth or moveNumber]
@@ -245,14 +341,23 @@ class Worker {
Tablebases::Config tbConfig;
const OptionsMap& options;
ThreadPool& threads;
TranspositionTable& tt;
const OptionsMap& options;
ThreadPool& threads;
TranspositionTable& tt;
const LazyNumaReplicated<Eval::NNUE::Networks>& networks;
// Used by NNUE
Eval::NNUE::AccumulatorCaches refreshTable;
friend class Stockfish::ThreadPool;
friend class SearchManager;
};
struct ConthistBonus {
int index;
int weight;
};
} // namespace Search
+43 -18
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -66,7 +66,7 @@ namespace {
constexpr int TBPIECES = 7; // Max number of supported pieces
constexpr int MAX_DTZ =
1 << 18; // Max DTZ supported, large enough to deal with the syzygy TB limit.
1 << 18; // Max DTZ supported times 2, large enough to deal with the syzygy TB limit.
enum {
BigEndian,
@@ -443,6 +443,8 @@ class TBTables {
std::deque<TBTable<WDL>> wdlTable;
std::deque<TBTable<DTZ>> dtzTable;
size_t foundDTZFiles = 0;
size_t foundWDLFiles = 0;
void insert(Key key, TBTable<WDL>* wdl, TBTable<DTZ>* dtz) {
uint32_t homeBucket = uint32_t(key) & (Size - 1);
@@ -486,9 +488,16 @@ class TBTables {
memset(hashTable, 0, sizeof(hashTable));
wdlTable.clear();
dtzTable.clear();
foundDTZFiles = 0;
foundWDLFiles = 0;
}
size_t size() const { return wdlTable.size(); }
void add(const std::vector<PieceType>& pieces);
void info() const {
sync_cout << "info string Found " << foundWDLFiles << " WDL and " << foundDTZFiles
<< " DTZ tablebase files (up to " << MaxCardinality << "-man)." << sync_endl;
}
void add(const std::vector<PieceType>& pieces);
};
TBTables TBTables;
@@ -501,13 +510,22 @@ void TBTables::add(const std::vector<PieceType>& pieces) {
for (PieceType pt : pieces)
code += PieceToChar[pt];
code.insert(code.find('K', 1), "v");
TBFile file(code.insert(code.find('K', 1), "v") + ".rtbw"); // KRK -> KRvK
TBFile file_dtz(code + ".rtbz"); // KRK -> KRvK
if (file_dtz.is_open())
{
file_dtz.close();
foundDTZFiles++;
}
TBFile file(code + ".rtbw"); // KRK -> KRvK
if (!file.is_open()) // Only WDL file is checked
return;
file.close();
foundWDLFiles++;
MaxCardinality = std::max(int(pieces.size()), MaxCardinality);
@@ -1326,7 +1344,7 @@ void Tablebases::init(const std::string& paths) {
MaxCardinality = 0;
TBFile::Paths = paths;
if (paths.empty() || paths == "<empty>")
if (paths.empty())
return;
// MapB1H1H7[] encodes a square below a1-h8 diagonal to 0..27
@@ -1466,7 +1484,7 @@ void Tablebases::init(const std::string& paths) {
}
}
sync_cout << "info string Found " << TBTables.size() << " tablebases" << sync_endl;
TBTables.info();
}
// Probe the WDL table for a particular position.
@@ -1574,7 +1592,10 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) {
// Use the DTZ tables to rank root moves.
//
// A return value false indicates that not all probes were successful.
bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50) {
bool Tablebases::root_probe(Position& pos,
Search::RootMoves& rootMoves,
bool rule50,
bool rankDTZ) {
ProbeState result = OK;
StateInfo st;
@@ -1585,7 +1606,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, bool ru
// Check whether a position was repeated since the last zeroing move.
bool rep = pos.has_repeated();
int dtz, bound = rule50 ? (MAX_DTZ - 100) : 1;
int dtz, bound = rule50 ? (MAX_DTZ / 2 - 100) : 1;
// Probe and rank each move
for (auto& m : rootMoves)
@@ -1599,7 +1620,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, bool ru
WDLScore wdl = -probe_wdl(pos, &result);
dtz = dtz_before_zeroing(wdl);
}
else if (pos.is_draw(1))
else if ((rule50 && pos.is_draw(1)) || pos.is_repetition(1))
{
// In case a root move leads to a draw by repetition or 50-move rule,
// we set dtz to zero. Note: since we are only 1 ply from the root,
@@ -1624,8 +1645,10 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, bool ru
// Better moves are ranked higher. Certain wins are ranked equally.
// Losing moves are ranked equally unless a 50-move draw is in sight.
int r = dtz > 0 ? (dtz + cnt50 <= 99 && !rep ? MAX_DTZ : MAX_DTZ - (dtz + cnt50))
: dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -MAX_DTZ : -MAX_DTZ + (-dtz + cnt50))
int r = dtz > 0 ? (dtz + cnt50 <= 99 && !rep ? MAX_DTZ - (rankDTZ ? dtz : 0)
: MAX_DTZ / 2 - (dtz + cnt50))
: dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -MAX_DTZ - (rankDTZ ? dtz : 0)
: -MAX_DTZ / 2 + (-dtz + cnt50))
: 0;
m.tbRank = r;
@@ -1633,10 +1656,11 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, bool ru
// 1 cp to cursed wins and let it grow to 49 cp as the positions gets
// closer to a real win.
m.tbScore = r >= bound ? VALUE_MATE - MAX_PLY - 1
: r > 0 ? Value((std::max(3, r - (MAX_DTZ - 200)) * int(PawnValue)) / 200)
: r == 0 ? VALUE_DRAW
: r > -bound ? Value((std::min(-3, r + (MAX_DTZ - 200)) * int(PawnValue)) / 200)
: -VALUE_MATE + MAX_PLY + 1;
: r > 0 ? Value((std::max(3, r - (MAX_DTZ / 2 - 200)) * int(PawnValue)) / 200)
: r == 0 ? VALUE_DRAW
: r > -bound
? Value((std::min(-3, r + (MAX_DTZ / 2 - 200)) * int(PawnValue)) / 200)
: -VALUE_MATE + MAX_PLY + 1;
}
return true;
@@ -1683,7 +1707,8 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, boo
Config Tablebases::rank_root_moves(const OptionsMap& options,
Position& pos,
Search::RootMoves& rootMoves) {
Search::RootMoves& rootMoves,
bool rankDTZ) {
Config config;
if (rootMoves.empty())
@@ -1707,7 +1732,7 @@ Config Tablebases::rank_root_moves(const OptionsMap& options,
if (config.cardinality >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING))
{
// Rank moves using DTZ tables
config.rootInTB = root_probe(pos, rootMoves, options["Syzygy50MoveRule"]);
config.rootInTB = root_probe(pos, rootMoves, options["Syzygy50MoveRule"], rankDTZ);
if (!config.rootInTB)
{
+6 -3
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -66,9 +66,12 @@ extern int MaxCardinality;
void init(const std::string& paths);
WDLScore probe_wdl(Position& pos, ProbeState* result);
int probe_dtz(Position& pos, ProbeState* result);
bool root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50);
bool root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50, bool rankDTZ);
bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, bool rule50);
Config rank_root_moves(const OptionsMap& options, Position& pos, Search::RootMoves& rootMoves);
Config rank_root_moves(const OptionsMap& options,
Position& pos,
Search::RootMoves& rootMoves,
bool rankDTZ = false);
} // namespace Stockfish::Tablebases
+191 -80
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,17 +22,16 @@
#include <cassert>
#include <deque>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <array>
#include "misc.h"
#include "movegen.h"
#include "search.h"
#include "syzygy/tbprobe.h"
#include "timeman.h"
#include "tt.h"
#include "types.h"
#include "uci.h"
#include "ucioption.h"
namespace Stockfish {
@@ -41,13 +40,24 @@ namespace Stockfish {
// in idle_loop(). Note that 'searching' and 'exit' should be already set.
Thread::Thread(Search::SharedState& sharedState,
std::unique_ptr<Search::ISearchManager> sm,
size_t n) :
worker(std::make_unique<Search::Worker>(sharedState, std::move(sm), n)),
size_t n,
OptionalThreadToNumaNodeBinder binder) :
idx(n),
nthreads(sharedState.options["Threads"]),
stdThread(&Thread::idle_loop, this) {
wait_for_search_finished();
run_custom_job([this, &binder, &sharedState, &sm, n]() {
// Use the binder to [maybe] bind the threads to a NUMA node before doing
// the Worker allocation. Ideally we would also allocate the SearchManager
// here, but that's minor.
this->numaAccessToken = binder();
this->worker =
std::make_unique<Search::Worker>(sharedState, std::move(sm), n, this->numaAccessToken);
});
wait_for_search_finished();
}
@@ -64,35 +74,40 @@ Thread::~Thread() {
// Wakes up the thread that will start the search
void Thread::start_searching() {
mutex.lock();
searching = true;
mutex.unlock(); // Unlock before notifying saves a few CPU-cycles
cv.notify_one(); // Wake up the thread in idle_loop()
assert(worker != nullptr);
run_custom_job([this]() { worker->start_searching(); });
}
// Clears the histories for the thread worker (usually before a new game)
void Thread::clear_worker() {
assert(worker != nullptr);
run_custom_job([this]() { worker->clear(); });
}
// Blocks on the condition variable
// until the thread has finished searching.
// Blocks on the condition variable until the thread has finished searching
void Thread::wait_for_search_finished() {
std::unique_lock<std::mutex> lk(mutex);
cv.wait(lk, [&] { return !searching; });
}
// Launching a function in the thread
void Thread::run_custom_job(std::function<void()> f) {
{
std::unique_lock<std::mutex> lk(mutex);
cv.wait(lk, [&] { return !searching; });
jobFunc = std::move(f);
searching = true;
}
cv.notify_one();
}
// Thread gets parked here, blocked on the
// condition variable, when it has no work to do.
void Thread::ensure_network_replicated() { worker->ensure_network_replicated(); }
// Thread gets parked here, blocked on the condition variable
// when the thread has no work to do.
void Thread::idle_loop() {
// If OS already scheduled us on a different group than 0 then don't overwrite
// the choice, eventually we are one of many one-threaded processes running on
// some Windows NUMA hardware, for instance in fishtest. To make it simple,
// just check if running threads are below a threshold, in this case, all this
// NUMA machinery is not needed.
if (nthreads > 8)
WinProcGroup::bindThisThread(idx);
while (true)
{
std::unique_lock<std::mutex> lk(mutex);
@@ -103,81 +118,150 @@ void Thread::idle_loop() {
if (exit)
return;
std::function<void()> job = std::move(jobFunc);
jobFunc = nullptr;
lk.unlock();
worker->start_searching();
if (job)
job();
}
}
Search::SearchManager* ThreadPool::main_manager() { return main_thread()->worker->main_manager(); }
uint64_t ThreadPool::nodes_searched() const { return accumulate(&Search::Worker::nodes); }
uint64_t ThreadPool::tb_hits() const { return accumulate(&Search::Worker::tbHits); }
// Creates/destroys threads to match the requested number.
// Created and launched threads will immediately go to sleep in idle_loop.
// Upon resizing, threads are recreated to allow for binding if necessary.
void ThreadPool::set(Search::SharedState sharedState) {
void ThreadPool::set(const NumaConfig& numaConfig,
Search::SharedState sharedState,
const Search::SearchManager::UpdateContext& updateContext) {
if (threads.size() > 0) // destroy any existing thread(s)
{
main_thread()->wait_for_search_finished();
while (threads.size() > 0)
delete threads.back(), threads.pop_back();
threads.clear();
boundThreadToNumaNode.clear();
}
const size_t requested = sharedState.options["Threads"];
if (requested > 0) // create new thread(s)
{
threads.push_back(new Thread(
sharedState, std::unique_ptr<Search::ISearchManager>(new Search::SearchManager()), 0));
// Binding threads may be problematic when there's multiple NUMA nodes and
// multiple Stockfish instances running. In particular, if each instance
// runs a single thread then they would all be mapped to the first NUMA node.
// This is undesirable, and so the default behaviour (i.e. when the user does not
// change the NumaConfig UCI setting) is to not bind the threads to processors
// unless we know for sure that we span NUMA nodes and replication is required.
const std::string numaPolicy(sharedState.options["NumaPolicy"]);
const bool doBindThreads = [&]() {
if (numaPolicy == "none")
return false;
if (numaPolicy == "auto")
return numaConfig.suggests_binding_threads(requested);
// numaPolicy == "system", or explicitly set by the user
return true;
}();
boundThreadToNumaNode = doBindThreads
? numaConfig.distribute_threads_among_numa_nodes(requested)
: std::vector<NumaIndex>{};
while (threads.size() < requested)
threads.push_back(new Thread(
sharedState, std::unique_ptr<Search::ISearchManager>(new Search::NullSearchManager()),
threads.size()));
{
const size_t threadId = threads.size();
const NumaIndex numaId = doBindThreads ? boundThreadToNumaNode[threadId] : 0;
auto manager = threadId == 0 ? std::unique_ptr<Search::ISearchManager>(
std::make_unique<Search::SearchManager>(updateContext))
: std::make_unique<Search::NullSearchManager>();
// When not binding threads we want to force all access to happen
// from the same NUMA node, because in case of NUMA replicated memory
// accesses we don't want to trash cache in case the threads get scheduled
// on the same NUMA node.
auto binder = doBindThreads ? OptionalThreadToNumaNodeBinder(numaConfig, numaId)
: OptionalThreadToNumaNodeBinder(numaId);
threads.emplace_back(
std::make_unique<Thread>(sharedState, std::move(manager), threadId, binder));
}
clear();
main_thread()->wait_for_search_finished();
// Reallocate the hash with the new threadpool size
sharedState.tt.resize(sharedState.options["Hash"], requested);
}
}
// Sets threadPool data to initial values
void ThreadPool::clear() {
if (threads.size() == 0)
return;
for (Thread* th : threads)
th->worker->clear();
for (auto&& th : threads)
th->clear_worker();
main_manager()->callsCnt = 0;
main_manager()->bestPreviousScore = VALUE_INFINITE;
for (auto&& th : threads)
th->wait_for_search_finished();
// These two affect the time taken on the first move of a game:
main_manager()->bestPreviousAverageScore = VALUE_INFINITE;
main_manager()->previousTimeReduction = 1.0;
main_manager()->previousTimeReduction = 0.85;
main_manager()->callsCnt = 0;
main_manager()->bestPreviousScore = VALUE_INFINITE;
main_manager()->originalTimeAdjust = -1;
main_manager()->tm.clear();
}
void ThreadPool::run_on_thread(size_t threadId, std::function<void()> f) {
assert(threads.size() > threadId);
threads[threadId]->run_custom_job(std::move(f));
}
// Wakes up main thread waiting in idle_loop() and
// returns immediately. Main thread will wake up other threads and start the search.
void ThreadPool::wait_on_thread(size_t threadId) {
assert(threads.size() > threadId);
threads[threadId]->wait_for_search_finished();
}
size_t ThreadPool::num_threads() const { return threads.size(); }
// Wakes up main thread waiting in idle_loop() and returns immediately.
// Main thread will wake up other threads and start the search.
void ThreadPool::start_thinking(const OptionsMap& options,
Position& pos,
StateListPtr& states,
Search::LimitsType limits,
bool ponderMode) {
Search::LimitsType limits) {
main_thread()->wait_for_search_finished();
main_manager()->stopOnPonderhit = stop = abortedSearch = false;
main_manager()->ponder = ponderMode;
main_manager()->ponder = limits.ponderMode;
increaseDepth = true;
Search::RootMoves rootMoves;
const auto legalmoves = MoveList<LEGAL>(pos);
for (const auto& m : MoveList<LEGAL>(pos))
if (limits.searchmoves.empty()
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
for (const auto& uciMove : limits.searchmoves)
{
auto move = UCIEngine::to_move(pos, uciMove);
if (std::find(legalmoves.begin(), legalmoves.end(), move) != legalmoves.end())
rootMoves.emplace_back(move);
}
if (rootMoves.empty())
for (const auto& m : legalmoves)
rootMoves.emplace_back(m);
Tablebases::Config tbConfig = Tablebases::rank_root_moves(options, pos, rootMoves);
@@ -192,34 +276,38 @@ void ThreadPool::start_thinking(const OptionsMap& options,
// We use Position::set() to set root position across threads. But there are
// some StateInfo fields (previous, pliesFromNull, capturedPiece) that cannot
// be deduced from a fen string, so set() clears them and they are set from
// setupStates->back() later. The rootState is per thread, earlier states are shared
// since they are read-only.
for (Thread* th : threads)
// setupStates->back() later. The rootState is per thread, earlier states are
// shared since they are read-only.
for (auto&& th : threads)
{
th->worker->limits = limits;
th->worker->nodes = th->worker->tbHits = th->worker->nmpMinPly =
th->worker->bestMoveChanges = 0;
th->worker->rootDepth = th->worker->completedDepth = 0;
th->worker->rootMoves = rootMoves;
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
th->worker->rootState = setupStates->back();
th->worker->tbConfig = tbConfig;
th->worker->effort = {};
th->run_custom_job([&]() {
th->worker->limits = limits;
th->worker->nodes = th->worker->tbHits = th->worker->nmpMinPly =
th->worker->bestMoveChanges = 0;
th->worker->rootDepth = th->worker->completedDepth = 0;
th->worker->rootMoves = rootMoves;
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
th->worker->rootState = setupStates->back();
th->worker->tbConfig = tbConfig;
});
}
for (auto&& th : threads)
th->wait_for_search_finished();
main_thread()->start_searching();
}
Thread* ThreadPool::get_best_thread() const {
Thread* bestThread = threads.front();
Thread* bestThread = threads.front().get();
Value minScore = VALUE_NONE;
std::unordered_map<Move, int64_t, Move::MoveHash> votes(
2 * std::min(size(), bestThread->worker->rootMoves.size()));
// Find the minimum score of all threads
for (Thread* th : threads)
for (auto&& th : threads)
minScore = std::min(minScore, th->worker->rootMoves[0].score);
// Vote according to score and depth, and select the best thread
@@ -227,10 +315,10 @@ Thread* ThreadPool::get_best_thread() const {
return (th->worker->rootMoves[0].score - minScore + 14) * int(th->worker->completedDepth);
};
for (Thread* th : threads)
votes[th->worker->rootMoves[0].pv[0]] += thread_voting_value(th);
for (auto&& th : threads)
votes[th->worker->rootMoves[0].pv[0]] += thread_voting_value(th.get());
for (Thread* th : threads)
for (auto&& th : threads)
{
const auto bestThreadScore = bestThread->worker->rootMoves[0].score;
const auto newThreadScore = th->worker->rootMoves[0].score;
@@ -241,59 +329,82 @@ Thread* ThreadPool::get_best_thread() const {
const auto bestThreadMoveVote = votes[bestThreadPV[0]];
const auto newThreadMoveVote = votes[newThreadPV[0]];
const bool bestThreadInProvenWin = bestThreadScore >= VALUE_TB_WIN_IN_MAX_PLY;
const bool newThreadInProvenWin = newThreadScore >= VALUE_TB_WIN_IN_MAX_PLY;
const bool bestThreadInProvenWin = is_win(bestThreadScore);
const bool newThreadInProvenWin = is_win(newThreadScore);
const bool bestThreadInProvenLoss =
bestThreadScore != -VALUE_INFINITE && bestThreadScore <= VALUE_TB_LOSS_IN_MAX_PLY;
bestThreadScore != -VALUE_INFINITE && is_loss(bestThreadScore);
const bool newThreadInProvenLoss =
newThreadScore != -VALUE_INFINITE && newThreadScore <= VALUE_TB_LOSS_IN_MAX_PLY;
newThreadScore != -VALUE_INFINITE && is_loss(newThreadScore);
// Note that we make sure not to pick a thread with truncated-PV for better viewer experience.
// We make sure not to pick a thread with truncated principal variation
const bool betterVotingValue =
thread_voting_value(th) * int(newThreadPV.size() > 2)
thread_voting_value(th.get()) * int(newThreadPV.size() > 2)
> thread_voting_value(bestThread) * int(bestThreadPV.size() > 2);
if (bestThreadInProvenWin)
{
// Make sure we pick the shortest mate / TB conversion
if (newThreadScore > bestThreadScore)
bestThread = th;
bestThread = th.get();
}
else if (bestThreadInProvenLoss)
{
// Make sure we pick the shortest mated / TB conversion
if (newThreadInProvenLoss && newThreadScore < bestThreadScore)
bestThread = th;
bestThread = th.get();
}
else if (newThreadInProvenWin || newThreadInProvenLoss
|| (newThreadScore > VALUE_TB_LOSS_IN_MAX_PLY
|| (!is_loss(newThreadScore)
&& (newThreadMoveVote > bestThreadMoveVote
|| (newThreadMoveVote == bestThreadMoveVote && betterVotingValue))))
bestThread = th;
bestThread = th.get();
}
return bestThread;
}
// Start non-main threads
// Will be invoked by main thread after it has started searching
// Start non-main threads.
// Will be invoked by main thread after it has started searching.
void ThreadPool::start_searching() {
for (Thread* th : threads)
for (auto&& th : threads)
if (th != threads.front())
th->start_searching();
}
// Wait for non-main threads
void ThreadPool::wait_for_search_finished() const {
for (Thread* th : threads)
for (auto&& th : threads)
if (th != threads.front())
th->wait_for_search_finished();
}
std::vector<size_t> ThreadPool::get_bound_thread_count_by_numa_node() const {
std::vector<size_t> counts;
if (!boundThreadToNumaNode.empty())
{
NumaIndex highestNumaNode = 0;
for (NumaIndex n : boundThreadToNumaNode)
if (n > highestNumaNode)
highestNumaNode = n;
counts.resize(highestNumaNode + 1, 0);
for (NumaIndex n : boundThreadToNumaNode)
counts[n] += 1;
}
return counts;
}
void ThreadPool::ensure_network_replicated() {
for (auto&& th : threads)
th->ensure_network_replicated();
}
} // namespace Stockfish
+85 -28
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,19 +23,48 @@
#include <condition_variable>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <vector>
#include "numa.h"
#include "position.h"
#include "search.h"
#include "thread_win32_osx.h"
namespace Stockfish {
class OptionsMap;
using Value = int;
// Sometimes we don't want to actually bind the threads, but the recipient still
// needs to think it runs on *some* NUMA node, such that it can access structures
// that rely on NUMA node knowledge. This class encapsulates this optional process
// such that the recipient does not need to know whether the binding happened or not.
class OptionalThreadToNumaNodeBinder {
public:
OptionalThreadToNumaNodeBinder(NumaIndex n) :
numaConfig(nullptr),
numaId(n) {}
OptionalThreadToNumaNodeBinder(const NumaConfig& cfg, NumaIndex n) :
numaConfig(&cfg),
numaId(n) {}
NumaReplicatedAccessToken operator()() const {
if (numaConfig != nullptr)
return numaConfig->bind_current_thread_to_numa_node(numaId);
else
return NumaReplicatedAccessToken(numaId);
}
private:
const NumaConfig* numaConfig;
NumaIndex numaId;
};
// Abstraction of a thread. It contains a pointer to the worker and a native thread.
// After construction, the native thread is started with idle_loop()
// waiting for a signal to start searching.
@@ -43,22 +72,37 @@ using Value = int;
// the search is finished, it goes back to idle_loop() waiting for a new signal.
class Thread {
public:
Thread(Search::SharedState&, std::unique_ptr<Search::ISearchManager>, size_t);
Thread(Search::SharedState&,
std::unique_ptr<Search::ISearchManager>,
size_t,
OptionalThreadToNumaNodeBinder);
virtual ~Thread();
void idle_loop();
void start_searching();
void idle_loop();
void start_searching();
void clear_worker();
void run_custom_job(std::function<void()> f);
void ensure_network_replicated();
// Thread has been slightly altered to allow running custom jobs, so
// this name is no longer correct. However, this class (and ThreadPool)
// require further work to make them properly generic while maintaining
// appropriate specificity regarding search, from the point of view of an
// outside user, so renaming of this function is left for whenever that happens.
void wait_for_search_finished();
size_t id() const { return idx; }
std::unique_ptr<Search::Worker> worker;
std::function<void()> jobFunc;
private:
std::mutex mutex;
std::condition_variable cv;
size_t idx, nthreads;
bool exit = false, searching = true; // Set before starting std::thread
NativeThread stdThread;
std::mutex mutex;
std::condition_variable cv;
size_t idx, nthreads;
bool exit = false, searching = true; // Set before starting std::thread
NativeThread stdThread;
NumaReplicatedAccessToken numaAccessToken;
};
@@ -66,33 +110,45 @@ class Thread {
// parking and, most importantly, launching a thread. All the access to threads
// is done through this class.
class ThreadPool {
public:
ThreadPool() {}
~ThreadPool() {
// destroy any existing thread(s)
if (threads.size() > 0)
{
main_thread()->wait_for_search_finished();
while (threads.size() > 0)
delete threads.back(), threads.pop_back();
threads.clear();
}
}
void
start_thinking(const OptionsMap&, Position&, StateListPtr&, Search::LimitsType, bool = false);
void clear();
void set(Search::SharedState);
ThreadPool(const ThreadPool&) = delete;
ThreadPool(ThreadPool&&) = delete;
Search::SearchManager* main_manager() const {
return static_cast<Search::SearchManager*>(main_thread()->worker.get()->manager.get());
};
Thread* main_thread() const { return threads.front(); }
uint64_t nodes_searched() const { return accumulate(&Search::Worker::nodes); }
uint64_t tb_hits() const { return accumulate(&Search::Worker::tbHits); }
Thread* get_best_thread() const;
void start_searching();
void wait_for_search_finished() const;
ThreadPool& operator=(const ThreadPool&) = delete;
ThreadPool& operator=(ThreadPool&&) = delete;
void start_thinking(const OptionsMap&, Position&, StateListPtr&, Search::LimitsType);
void run_on_thread(size_t threadId, std::function<void()> f);
void wait_on_thread(size_t threadId);
size_t num_threads() const;
void clear();
void set(const NumaConfig& numaConfig,
Search::SharedState,
const Search::SearchManager::UpdateContext&);
Search::SearchManager* main_manager();
Thread* main_thread() const { return threads.front().get(); }
uint64_t nodes_searched() const;
uint64_t tb_hits() const;
Thread* get_best_thread() const;
void start_searching();
void wait_for_search_finished() const;
std::vector<size_t> get_bound_thread_count_by_numa_node() const;
void ensure_network_replicated();
std::atomic_bool stop, abortedSearch, increaseDepth;
@@ -104,13 +160,14 @@ class ThreadPool {
auto empty() const noexcept { return threads.empty(); }
private:
StateListPtr setupStates;
std::vector<Thread*> threads;
StateListPtr setupStates;
std::vector<std::unique_ptr<Thread>> threads;
std::vector<NumaIndex> boundThreadToNumaNode;
uint64_t accumulate(std::atomic<uint64_t> Search::Worker::*member) const {
uint64_t sum = 0;
for (Thread* th : threads)
for (auto&& th : threads)
sum += (th->worker.get()->*member).load(std::memory_order_relaxed);
return sum;
}
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
+50 -33
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,17 +30,14 @@ namespace Stockfish {
TimePoint TimeManagement::optimum() const { return optimumTime; }
TimePoint TimeManagement::maximum() const { return maximumTime; }
TimePoint TimeManagement::elapsed(size_t nodes) const {
return useNodesTime ? TimePoint(nodes) : now() - startTime;
}
void TimeManagement::clear() {
availableNodes = 0; // When in 'nodes as time' mode
availableNodes = -1; // When in 'nodes as time' mode
}
void TimeManagement::advance_nodes_time(std::int64_t nodes) {
assert(useNodesTime);
availableNodes += nodes;
availableNodes = std::max(int64_t(0), availableNodes - nodes);
}
// Called at the beginning of the search and calculates
@@ -50,15 +47,19 @@ void TimeManagement::advance_nodes_time(std::int64_t nodes) {
void TimeManagement::init(Search::LimitsType& limits,
Color us,
int ply,
const OptionsMap& options) {
// If we have no time, no need to initialize TM, except for the start time,
// which is used by movetime.
startTime = limits.startTime;
const OptionsMap& options,
double& originalTimeAdjust) {
TimePoint npmsec = TimePoint(options["nodestime"]);
// If we have no time, we don't need to fully initialize TM.
// startTime is used by movetime and useNodesTime is used in elapsed calls.
startTime = limits.startTime;
useNodesTime = npmsec != 0;
if (limits.time[us] == 0)
return;
TimePoint moveOverhead = TimePoint(options["Move Overhead"]);
TimePoint npmsec = TimePoint(options["nodestime"]);
// optScale is a percentage of available time to use for the current move.
// maxScale is a multiplier applied to optimumTime.
@@ -68,56 +69,72 @@ void TimeManagement::init(Search::LimitsType& limits,
// to nodes, and use resulting values in time management formulas.
// WARNING: to avoid time losses, the given npmsec (nodes per millisecond)
// must be much lower than the real engine speed.
if (npmsec)
if (useNodesTime)
{
useNodesTime = true;
if (!availableNodes) // Only once at game start
if (availableNodes == -1) // Only once at game start
availableNodes = npmsec * limits.time[us]; // Time is in msec
// Convert from milliseconds to nodes
limits.time[us] = TimePoint(availableNodes);
limits.inc[us] *= npmsec;
limits.npmsec = npmsec;
moveOverhead *= npmsec;
}
// Maximum move horizon of 50 moves
int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50;
// These numbers are used where multiplications, divisions or comparisons
// with constants are involved.
const int64_t scaleFactor = useNodesTime ? npmsec : 1;
const TimePoint scaledTime = limits.time[us] / scaleFactor;
const TimePoint scaledInc = limits.inc[us] / scaleFactor;
// Maximum move horizon
int centiMTG = limits.movestogo ? std::min(limits.movestogo * 100, 5000) : 5051;
// If less than one second, gradually reduce mtg
if (scaledTime < 1000 && double(centiMTG) / scaledInc > 5.051)
{
centiMTG = scaledTime * 5.051;
}
// Make sure timeLeft is > 0 since we may use it as a divisor
TimePoint timeLeft = std::max(TimePoint(1), limits.time[us] + limits.inc[us] * (mtg - 1)
- moveOverhead * (2 + mtg));
TimePoint timeLeft =
std::max(TimePoint(1),
limits.time[us]
+ (limits.inc[us] * (centiMTG - 100) - moveOverhead * (200 + centiMTG)) / 100);
// x basetime (+ z increment)
// If there is a healthy increment, timeLeft can exceed actual available
// game time for the current move, so also cap to 20% of available game time.
// If there is a healthy increment, timeLeft can exceed the actual available
// game time for the current move, so also cap to a percentage of available game time.
if (limits.movestogo == 0)
{
// Use extra time with larger increments
double optExtra = std::clamp(1.0 + 12.5 * limits.inc[us] / limits.time[us], 1.0, 1.11);
// Extra time according to timeLeft
if (originalTimeAdjust < 0)
originalTimeAdjust = 0.3128 * std::log10(timeLeft) - 0.4354;
// Calculate time constants based on current time left.
double optConstant =
std::min(0.00334 + 0.0003 * std::log10(limits.time[us] / 1000.0), 0.0049);
double maxConstant = std::max(3.4 + 3.0 * std::log10(limits.time[us] / 1000.0), 2.76);
double logTimeInSec = std::log10(scaledTime / 1000.0);
double optConstant = std::min(0.0032116 + 0.000321123 * logTimeInSec, 0.00508017);
double maxConstant = std::max(3.3977 + 3.03950 * logTimeInSec, 2.94761);
optScale = std::min(0.0120 + std::pow(ply + 3.1, 0.44) * optConstant,
0.21 * limits.time[us] / double(timeLeft))
* optExtra;
maxScale = std::min(6.9, maxConstant + ply / 12.2);
optScale = std::min(0.0121431 + std::pow(ply + 2.94693, 0.461073) * optConstant,
0.213035 * limits.time[us] / timeLeft)
* originalTimeAdjust;
maxScale = std::min(6.67704, maxConstant + ply / 11.9847);
}
// x moves in y seconds (+ z increment)
else
{
optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / double(timeLeft));
maxScale = std::min(6.3, 1.5 + 0.11 * mtg);
optScale =
std::min((0.88 + ply / 116.4) / (centiMTG / 100.0), 0.88 * limits.time[us] / timeLeft);
maxScale = 1.3 + 0.11 * (centiMTG / 100.0);
}
// Limit the maximum possible time for this move
optimumTime = TimePoint(optScale * timeLeft);
maximumTime =
TimePoint(std::min(0.84 * limits.time[us] - moveOverhead, maxScale * optimumTime)) - 10;
TimePoint(std::min(0.825179 * limits.time[us] - moveOverhead, maxScale * optimumTime)) - 10;
if (options["Ponder"])
optimumTime += optimumTime / 4;
+12 -5
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
#ifndef TIMEMAN_H_INCLUDED
#define TIMEMAN_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include "misc.h"
@@ -37,11 +36,19 @@ struct LimitsType;
// the maximum available time, the game move number, and other parameters.
class TimeManagement {
public:
void init(Search::LimitsType& limits, Color us, int ply, const OptionsMap& options);
void init(Search::LimitsType& limits,
Color us,
int ply,
const OptionsMap& options,
double& originalTimeAdjust);
TimePoint optimum() const;
TimePoint maximum() const;
TimePoint elapsed(std::size_t nodes) const;
template<typename FUNC>
TimePoint elapsed(FUNC nodes) const {
return useNodesTime ? TimePoint(nodes()) : elapsed_time();
}
TimePoint elapsed_time() const { return now() - startTime; };
void clear();
void advance_nodes_time(std::int64_t nodes);
@@ -51,7 +58,7 @@ class TimeManagement {
TimePoint optimumTime;
TimePoint maximumTime;
std::int64_t availableNodes = 0; // When in 'nodes as time' mode
std::int64_t availableNodes = -1; // When in 'nodes as time' mode
bool useNodesTime = false; // True if we are in 'nodes as time' mode
};
+166 -67
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,33 +19,93 @@
#include "tt.h"
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <thread>
#include <vector>
#include "memory.h"
#include "misc.h"
#include "syzygy/tbprobe.h"
#include "thread.h"
namespace Stockfish {
// TTEntry struct is the 10 bytes transposition table entry, defined as below:
//
// key 16 bit
// depth 8 bit
// generation 5 bit
// pv node 1 bit
// bound type 2 bit
// move 16 bit
// value 16 bit
// evaluation 16 bit
//
// These fields are in the same order as accessed by TT::probe(), since memory is fastest sequentially.
// Equally, the store order in save() matches this order.
struct TTEntry {
// Convert internal bitfields to external types
TTData read() const {
return TTData{Move(move16), Value(value16),
Value(eval16), Depth(depth8 + DEPTH_ENTRY_OFFSET),
Bound(genBound8 & 0x3), bool(genBound8 & 0x4)};
}
bool is_occupied() const;
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8);
// The returned age is a multiple of TranspositionTable::GENERATION_DELTA
uint8_t relative_age(const uint8_t generation8) const;
private:
friend class TranspositionTable;
uint16_t key16;
uint8_t depth8;
uint8_t genBound8;
Move move16;
int16_t value16;
int16_t eval16;
};
// `genBound8` is where most of the details are. We use the following constants to manipulate 5 leading generation bits
// and 3 trailing miscellaneous bits.
// These bits are reserved for other things.
static constexpr unsigned GENERATION_BITS = 3;
// increment for generation field
static constexpr int GENERATION_DELTA = (1 << GENERATION_BITS);
// cycle length
static constexpr int GENERATION_CYCLE = 255 + GENERATION_DELTA;
// mask to pull out generation number
static constexpr int GENERATION_MASK = (0xFF << GENERATION_BITS) & 0xFF;
// DEPTH_ENTRY_OFFSET exists because 1) we use `bool(depth8)` as the occupancy check, but
// 2) we need to store negative depths for QS. (`depth8` is the only field with "spare bits":
// we sacrifice the ability to store depths greater than 1<<8 less the offset, as asserted in `save`.)
bool TTEntry::is_occupied() const { return bool(depth8); }
// Populates the TTEntry with a new node's data, possibly
// overwriting an old position. The update is not atomic and can be racy.
void TTEntry::save(
Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8) {
// Preserve any existing move for the same position
// Preserve the old ttmove if we don't have a new one
if (m || uint16_t(k) != key16)
move16 = m;
// Overwrite less valuable entries (cheapest checks first)
if (b == BOUND_EXACT || uint16_t(k) != key16 || d - DEPTH_OFFSET + 2 * pv > depth8 - 4)
if (b == BOUND_EXACT || uint16_t(k) != key16 || d - DEPTH_ENTRY_OFFSET + 2 * pv > depth8 - 4
|| relative_age(generation8))
{
assert(d > DEPTH_OFFSET);
assert(d < 256 + DEPTH_OFFSET);
assert(d > DEPTH_ENTRY_OFFSET);
assert(d < 256 + DEPTH_ENTRY_OFFSET);
key16 = uint16_t(k);
depth8 = uint8_t(d - DEPTH_OFFSET);
depth8 = uint8_t(d - DEPTH_ENTRY_OFFSET);
genBound8 = uint8_t(generation8 | uint8_t(pv) << 2 | b);
value16 = int16_t(v);
eval16 = int16_t(ev);
@@ -53,100 +113,139 @@ void TTEntry::save(
}
uint8_t TTEntry::relative_age(const uint8_t generation8) const {
// Due to our packed storage format for generation and its cyclic
// nature we add GENERATION_CYCLE (256 is the modulus, plus what
// is needed to keep the unrelated lowest n bits from affecting
// the result) to calculate the entry age correctly even after
// generation8 overflows into the next cycle.
return (GENERATION_CYCLE + generation8 - genBound8) & GENERATION_MASK;
}
// TTWriter is but a very thin wrapper around the pointer
TTWriter::TTWriter(TTEntry* tte) :
entry(tte) {}
void TTWriter::write(
Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8) {
entry->save(k, v, pv, b, d, m, ev, generation8);
}
// A TranspositionTable is an array of Cluster, of size clusterCount. Each cluster consists of ClusterSize number
// of TTEntry. Each non-empty TTEntry contains information on exactly one position. The size of a Cluster should
// divide the size of a cache line for best performance, as the cacheline is prefetched when possible.
static constexpr int ClusterSize = 3;
struct Cluster {
TTEntry entry[ClusterSize];
char padding[2]; // Pad to 32 bytes
};
static_assert(sizeof(Cluster) == 32, "Suboptimal Cluster size");
// Sets the size of the transposition table,
// measured in megabytes. Transposition table consists of a power of 2 number
// measured in megabytes. Transposition table consists
// of clusters and each cluster consists of ClusterSize number of TTEntry.
void TranspositionTable::resize(size_t mbSize, int threadCount) {
void TranspositionTable::resize(size_t mbSize, ThreadPool& threads) {
aligned_large_pages_free(table);
clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
table = static_cast<Cluster*>(aligned_large_pages_alloc(clusterCount * sizeof(Cluster)));
if (!table)
{
std::cerr << "Failed to allocate " << mbSize << "MB for transposition table." << std::endl;
exit(EXIT_FAILURE);
}
clear(threadCount);
clear(threads);
}
// Initializes the entire transposition table to zero,
// in a multi-threaded way.
void TranspositionTable::clear(size_t threadCount) {
std::vector<std::thread> threads;
void TranspositionTable::clear(ThreadPool& threads) {
generation8 = 0;
const size_t threadCount = threads.num_threads();
for (size_t idx = 0; idx < size_t(threadCount); ++idx)
for (size_t i = 0; i < threadCount; ++i)
{
threads.emplace_back([this, idx, threadCount]() {
// Thread binding gives faster search on systems with a first-touch policy
if (threadCount > 8)
WinProcGroup::bindThisThread(idx);
threads.run_on_thread(i, [this, i, threadCount]() {
// Each thread will zero its part of the hash table
const size_t stride = size_t(clusterCount / threadCount), start = size_t(stride * idx),
len = idx != size_t(threadCount) - 1 ? stride : clusterCount - start;
const size_t stride = clusterCount / threadCount;
const size_t start = stride * i;
const size_t len = i + 1 != threadCount ? stride : clusterCount - start;
std::memset(&table[start], 0, len * sizeof(Cluster));
});
}
for (std::thread& th : threads)
th.join();
}
// Looks up the current position in the transposition
// table. It returns true and a pointer to the TTEntry if the position is found.
// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry
// to be replaced later. The replace value of an entry is calculated as its depth
// minus 8 times its relative age. TTEntry t1 is considered more valuable than
// TTEntry t2 if its replace value is greater than that of t2.
TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
TTEntry* const tte = first_entry(key);
const uint16_t key16 = uint16_t(key); // Use the low 16 bits as key inside the cluster
for (int i = 0; i < ClusterSize; ++i)
if (tte[i].key16 == key16 || !tte[i].depth8)
{
tte[i].genBound8 =
uint8_t(generation8 | (tte[i].genBound8 & (GENERATION_DELTA - 1))); // Refresh
return found = bool(tte[i].depth8), &tte[i];
}
// Find an entry to be replaced according to the replacement strategy
TTEntry* replace = tte;
for (int i = 1; i < ClusterSize; ++i)
// Due to our packed storage format for generation and its cyclic
// nature we add GENERATION_CYCLE (256 is the modulus, plus what
// is needed to keep the unrelated lowest n bits from affecting
// the result) to calculate the entry age correctly even after
// generation8 overflows into the next cycle.
if (replace->depth8
- ((GENERATION_CYCLE + generation8 - replace->genBound8) & GENERATION_MASK)
> tte[i].depth8
- ((GENERATION_CYCLE + generation8 - tte[i].genBound8) & GENERATION_MASK))
replace = &tte[i];
return found = false, replace;
for (size_t i = 0; i < threadCount; ++i)
threads.wait_on_thread(i);
}
// Returns an approximation of the hashtable
// occupation during a search. The hash is x permill full, as per UCI protocol.
int TranspositionTable::hashfull() const {
int cnt = 0;
// Only counts entries which match the current generation.
int TranspositionTable::hashfull(int maxAge) const {
int maxAgeInternal = maxAge << GENERATION_BITS;
int cnt = 0;
for (int i = 0; i < 1000; ++i)
for (int j = 0; j < ClusterSize; ++j)
cnt += table[i].entry[j].depth8
&& (table[i].entry[j].genBound8 & GENERATION_MASK) == generation8;
cnt += table[i].entry[j].is_occupied()
&& table[i].entry[j].relative_age(generation8) <= maxAgeInternal;
return cnt / ClusterSize;
}
void TranspositionTable::new_search() {
// increment by delta to keep lower bits as is
generation8 += GENERATION_DELTA;
}
uint8_t TranspositionTable::generation() const { return generation8; }
// Looks up the current position in the transposition
// table. It returns true if the position is found.
// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry
// to be replaced later. The replace value of an entry is calculated as its depth
// minus 8 times its relative age. TTEntry t1 is considered more valuable than
// TTEntry t2 if its replace value is greater than that of t2.
std::tuple<bool, TTData, TTWriter> TranspositionTable::probe(const Key key) const {
TTEntry* const tte = first_entry(key);
const uint16_t key16 = uint16_t(key); // Use the low 16 bits as key inside the cluster
for (int i = 0; i < ClusterSize; ++i)
if (tte[i].key16 == key16)
// This gap is the main place for read races.
// After `read()` completes that copy is final, but may be self-inconsistent.
return {tte[i].is_occupied(), tte[i].read(), TTWriter(&tte[i])};
// Find an entry to be replaced according to the replacement strategy
TTEntry* replace = tte;
for (int i = 1; i < ClusterSize; ++i)
if (replace->depth8 - replace->relative_age(generation8) * 2
> tte[i].depth8 - tte[i].relative_age(generation8) * 2)
replace = &tte[i];
return {false,
TTData{Move::none(), VALUE_NONE, VALUE_NONE, DEPTH_ENTRY_OFFSET, BOUND_NONE, false},
TTWriter(replace)};
}
TTEntry* TranspositionTable::first_entry(const Key key) const {
return &table[mul_hi64(key, clusterCount)].entry[0];
}
} // namespace Stockfish
+60 -60
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,88 +21,88 @@
#include <cstddef>
#include <cstdint>
#include <tuple>
#include "misc.h"
#include "memory.h"
#include "types.h"
namespace Stockfish {
// TTEntry struct is the 10 bytes transposition table entry, defined as below:
class ThreadPool;
struct TTEntry;
struct Cluster;
// There is only one global hash table for the engine and all its threads. For chess in particular, we even allow racy
// updates between threads to and from the TT, as taking the time to synchronize access would cost thinking time and
// thus elo. As a hash table, collisions are possible and may cause chess playing issues (bizarre blunders, faulty mate
// reports, etc). Fixing these also loses elo; however such risk decreases quickly with larger TT size.
//
// key 16 bit
// depth 8 bit
// generation 5 bit
// pv node 1 bit
// bound type 2 bit
// move 16 bit
// value 16 bit
// eval value 16 bit
struct TTEntry {
// `probe` is the primary method: given a board position, we lookup its entry in the table, and return a tuple of:
// 1) whether the entry already has this position
// 2) a copy of the prior data (if any) (may be inconsistent due to read races)
// 3) a writer object to this entry
// The copied data and the writer are separated to maintain clear boundaries between local vs global objects.
Move move() const { return Move(move16); }
Value value() const { return Value(value16); }
Value eval() const { return Value(eval16); }
Depth depth() const { return Depth(depth8 + DEPTH_OFFSET); }
bool is_pv() const { return bool(genBound8 & 0x4); }
Bound bound() const { return Bound(genBound8 & 0x3); }
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8);
private:
friend class TranspositionTable;
// A copy of the data already in the entry (possibly collided). `probe` may be racy, resulting in inconsistent data.
struct TTData {
Move move;
Value value, eval;
Depth depth;
Bound bound;
bool is_pv;
uint16_t key16;
uint8_t depth8;
uint8_t genBound8;
Move move16;
int16_t value16;
int16_t eval16;
TTData() = delete;
// clang-format off
TTData(Move m, Value v, Value ev, Depth d, Bound b, bool pv) :
move(m),
value(v),
eval(ev),
depth(d),
bound(b),
is_pv(pv) {};
// clang-format on
};
// This is used to make racy writes to the global TT.
struct TTWriter {
public:
void write(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8);
private:
friend class TranspositionTable;
TTEntry* entry;
TTWriter(TTEntry* tte);
};
// A TranspositionTable is an array of Cluster, of size clusterCount. Each
// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry
// contains information on exactly one position. The size of a Cluster should
// divide the size of a cache line for best performance, as the cacheline is
// prefetched when possible.
class TranspositionTable {
static constexpr int ClusterSize = 3;
struct Cluster {
TTEntry entry[ClusterSize];
char padding[2]; // Pad to 32 bytes
};
static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size");
// Constants used to refresh the hash table periodically
static constexpr unsigned GENERATION_BITS = 3; // nb of bits reserved for other things
static constexpr int GENERATION_DELTA =
(1 << GENERATION_BITS); // increment for generation field
static constexpr int GENERATION_CYCLE = 255 + (1 << GENERATION_BITS); // cycle length
static constexpr int GENERATION_MASK =
(0xFF << GENERATION_BITS) & 0xFF; // mask to pull out generation number
public:
~TranspositionTable() { aligned_large_pages_free(table); }
void new_search() { generation8 += GENERATION_DELTA; } // Lower bits are used for other things
TTEntry* probe(const Key key, bool& found) const;
int hashfull() const;
void resize(size_t mbSize, int threadCount);
void clear(size_t threadCount);
TTEntry* first_entry(const Key key) const {
return &table[mul_hi64(key, clusterCount)].entry[0];
}
void resize(size_t mbSize, ThreadPool& threads); // Set TT size
void clear(ThreadPool& threads); // Re-initialize memory, multithreaded
int hashfull(int maxAge = 0)
const; // Approximate what fraction of entries (permille) have been written to during this root search
uint8_t generation() const { return generation8; }
void
new_search(); // This must be called at the beginning of each root search to track entry aging
uint8_t generation() const; // The current age, used when writing new data to the TT
std::tuple<bool, TTData, TTWriter>
probe(const Key key) const; // The main method, whose retvals separate local vs global objects
TTEntry* first_entry(const Key key)
const; // This is the hash function; its only external use is memory prefetching.
private:
friend struct TTEntry;
size_t clusterCount;
Cluster* table = nullptr;
uint8_t generation8 = 0; // Size must be not bigger than TTEntry::genBound8
Cluster* table = nullptr;
uint8_t generation8 = 0; // Size must be not bigger than TTEntry::genBound8
};
} // namespace Stockfish
+38 -30
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <algorithm>
#include <iostream>
#include <map>
#include <optional>
#include <sstream>
#include <string>
@@ -30,10 +31,41 @@ using std::string;
namespace Stockfish {
bool Tune::update_on_last;
const Option* LastOption = nullptr;
OptionsMap* Tune::options;
static std::map<std::string, int> TuneResults;
bool Tune::update_on_last;
const Option* LastOption = nullptr;
OptionsMap* Tune::options;
namespace {
std::map<std::string, int> TuneResults;
std::optional<std::string> on_tune(const Option& o) {
if (!Tune::update_on_last || LastOption == &o)
Tune::read_options();
return std::nullopt;
}
}
void Tune::make_option(OptionsMap* opts, const string& n, int v, const SetRange& r) {
// Do not generate option when there is nothing to tune (ie. min = max)
if (r(v).first == r(v).second)
return;
if (TuneResults.count(n))
v = TuneResults[n];
opts->add(n, Option(v, r(v).first, r(v).second, on_tune));
LastOption = &((*opts)[n]);
// Print formatted parameters, ready to be copy-pasted in Fishtest
std::cout << n << "," //
<< v << "," //
<< r(v).first << "," //
<< r(v).second << "," //
<< (r(v).second - r(v).first) / 20.0 << "," //
<< "0.0020" << std::endl;
}
string Tune::next(string& names, bool pop) {
@@ -54,29 +86,6 @@ string Tune::next(string& names, bool pop) {
return name;
}
static void on_tune(const Option& o) {
if (!Tune::update_on_last || LastOption == &o)
Tune::read_options();
}
static void make_option(OptionsMap* options, const string& n, int v, const SetRange& r) {
// Do not generate option when there is nothing to tune (ie. min = max)
if (r(v).first == r(v).second)
return;
if (TuneResults.count(n))
v = TuneResults[n];
(*options)[n] << Option(v, r(v).first, r(v).second, on_tune);
LastOption = &((*options)[n]);
// Print formatted parameters, ready to be copy-pasted in Fishtest
std::cout << n << "," << v << "," << r(v).first << "," << r(v).second << ","
<< (r(v).second - r(v).first) / 20.0 << ","
<< "0.0020" << std::endl;
}
template<>
void Tune::Entry<int>::init_option() {
@@ -112,7 +121,6 @@ void Tune::Entry<Tune::PostUpdate>::read_option() {
namespace Stockfish {
void Tune::read_results() { /* ...insert your values here... */
}
void Tune::read_results() { /* ...insert your values here... */ }
} // namespace Stockfish
+4 -2
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -145,6 +145,8 @@ class Tune {
return add(value, (next(names), std::move(names)), args...);
}
static void make_option(OptionsMap* options, const std::string& n, int v, const SetRange& r);
std::vector<std::unique_ptr<EntryBase>> list;
public:
@@ -158,7 +160,7 @@ class Tune {
for (auto& e : instance().list)
e->init_option();
read_options();
} // Deferred, due to UCI::Options access
} // Deferred, due to UCIEngine::Options access
static void read_options() {
for (auto& e : instance().list)
e->read_option();
+38 -13
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -137,9 +137,9 @@ enum Bound {
BOUND_EXACT = BOUND_UPPER | BOUND_LOWER
};
// Value is used as an alias for int16_t, this is done to differentiate between
// a search value and any other integer value. The values used in search are always
// supposed to be in the range (-VALUE_NONE, VALUE_NONE] and should not exceed this range.
// Value is used as an alias for int, this is done to differentiate between a search
// value and any other integer value. The values used in search are always supposed
// to be in the range (-VALUE_NONE, VALUE_NONE] and should not exceed this range.
using Value = int;
constexpr Value VALUE_ZERO = 0;
@@ -155,6 +155,21 @@ constexpr Value VALUE_TB = VALUE_MATE_IN_MAX_PLY - 1;
constexpr Value VALUE_TB_WIN_IN_MAX_PLY = VALUE_TB - MAX_PLY;
constexpr Value VALUE_TB_LOSS_IN_MAX_PLY = -VALUE_TB_WIN_IN_MAX_PLY;
constexpr bool is_valid(Value value) { return value != VALUE_NONE; }
constexpr bool is_win(Value value) {
assert(is_valid(value));
return value >= VALUE_TB_WIN_IN_MAX_PLY;
}
constexpr bool is_loss(Value value) {
assert(is_valid(value));
return value <= VALUE_TB_LOSS_IN_MAX_PLY;
}
constexpr bool is_decisive(Value value) { return is_win(value) || is_loss(value); }
// In the code, we make the assumption that these values
// are such that non_pawn_material() can be used to uniquely
// identify the material on the board.
@@ -187,12 +202,21 @@ constexpr Value PieceValue[PIECE_NB] = {
using Depth = int;
enum : int {
DEPTH_QS_CHECKS = 0,
DEPTH_QS_NO_CHECKS = -1,
DEPTH_NONE = -6,
DEPTH_OFFSET = -7 // value used only for TT entry occupancy check
// The following DEPTH_ constants are used for transposition table entries
// and quiescence search move generation stages. In regular search, the
// depth stored in the transposition table is literal: the search depth
// (effort) used to make the corresponding transposition table value. In
// quiescence search, however, the transposition table entries only store
// the current quiescence move generation stage (which should thus compare
// lower than any regular search depth).
DEPTH_QS = 0,
// For transposition table entries where no searching at all was done
// (whether regular or qsearch) we use DEPTH_UNSEARCHED, which should thus
// compare lower than any quiescence or regular depth. DEPTH_ENTRY_OFFSET
// is used only for the transposition table entry occupancy check (see tt.cpp),
// and should thus be lower than DEPTH_UNSEARCHED.
DEPTH_UNSEARCHED = -2,
DEPTH_ENTRY_OFFSET = -3
};
// clang-format off
@@ -351,9 +375,10 @@ enum MoveType {
// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
// NOTE: en passant bit is set only when a pawn can be captured
//
// Special cases are Move::none() and Move::null(). We can sneak these in because in
// any normal move destination square is always different from origin square
// while Move::none() and Move::null() have the same origin and destination square.
// Special cases are Move::none() and Move::null(). We can sneak these in because
// in any normal move the destination square and origin square are always different,
// but Move::none() and Move::null() have the same origin and destination square.
class Move {
public:
Move() = default;
+419 -171
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,86 +19,74 @@
#include "uci.h"
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <deque>
#include <memory>
#include <cstdint>
#include <iterator>
#include <optional>
#include <sstream>
#include <string_view>
#include <utility>
#include <vector>
#include <cstdint>
#include "benchmark.h"
#include "evaluate.h"
#include "engine.h"
#include "memory.h"
#include "movegen.h"
#include "nnue/evaluate_nnue.h"
#include "nnue/nnue_architecture.h"
#include "position.h"
#include "score.h"
#include "search.h"
#include "syzygy/tbprobe.h"
#include "types.h"
#include "ucioption.h"
#include "perft.h"
namespace Stockfish {
constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
constexpr int NormalizeToPawnValue = 356;
constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
constexpr auto BenchmarkCommand = "speedtest";
UCI::UCI(int argc, char** argv) :
cli(argc, argv) {
constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
template<typename... Ts>
struct overload: Ts... {
using Ts::operator()...;
};
evalFiles = {{Eval::NNUE::Big, {"EvalFile", EvalFileDefaultNameBig, "None", ""}},
{Eval::NNUE::Small, {"EvalFileSmall", EvalFileDefaultNameSmall, "None", ""}}};
template<typename... Ts>
overload(Ts...) -> overload<Ts...>;
options["Debug Log File"] << Option("", [](const Option& o) { start_logger(o); });
options["Threads"] << Option(1, 1, 1024, [this](const Option&) {
threads.set({options, threads, tt});
});
options["Hash"] << Option(16, 1, MaxHashMB, [this](const Option& o) {
threads.main_thread()->wait_for_search_finished();
tt.resize(o, options["Threads"]);
});
options["Clear Hash"] << Option([this](const Option&) { search_clear(); });
options["Ponder"] << Option(false);
options["MultiPV"] << Option(1, 1, MAX_MOVES);
options["Skill Level"] << Option(20, 0, 20);
options["Move Overhead"] << Option(10, 0, 5000);
options["nodestime"] << Option(0, 0, 10000);
options["UCI_Chess960"] << Option(false);
options["UCI_LimitStrength"] << Option(false);
options["UCI_Elo"] << Option(1320, 1320, 3190);
options["UCI_ShowWDL"] << Option(false);
options["SyzygyPath"] << Option("<empty>", [](const Option& o) { Tablebases::init(o); });
options["SyzygyProbeDepth"] << Option(1, 1, 100);
options["Syzygy50MoveRule"] << Option(true);
options["SyzygyProbeLimit"] << Option(7, 0, 7);
options["EvalFile"] << Option(EvalFileDefaultNameBig, [this](const Option&) {
evalFiles = Eval::NNUE::load_networks(cli.binaryDirectory, options, evalFiles);
});
options["EvalFileSmall"] << Option(EvalFileDefaultNameSmall, [this](const Option&) {
evalFiles = Eval::NNUE::load_networks(cli.binaryDirectory, options, evalFiles);
});
threads.set({options, threads, tt});
search_clear(); // After threads are up
void UCIEngine::print_info_string(std::string_view str) {
sync_cout_start();
for (auto& line : split(str, "\n"))
{
if (!is_whitespace(line))
{
std::cout << "info string " << line << '\n';
}
}
sync_cout_end();
}
void UCI::loop() {
UCIEngine::UCIEngine(int argc, char** argv) :
engine(argv[0]),
cli(argc, argv) {
Position pos;
std::string token, cmd;
StateListPtr states(new std::deque<StateInfo>(1));
engine.get_options().add_info_listener([](const std::optional<std::string>& str) {
if (str.has_value())
print_info_string(*str);
});
pos.set(StartFEN, false, &states->back());
init_search_update_listeners();
}
void UCIEngine::init_search_update_listeners() {
engine.set_on_iter([](const auto& i) { on_iter(i); });
engine.set_on_update_no_moves([](const auto& i) { on_update_no_moves(i); });
engine.set_on_update_full(
[this](const auto& i) { on_update_full(i, engine.get_options()["UCI_ShowWDL"]); });
engine.set_on_bestmove([](const auto& bm, const auto& p) { on_bestmove(bm, p); });
engine.set_on_verify_networks([](const auto& s) { print_info_string(s); });
}
void UCIEngine::loop() {
std::string token, cmd;
for (int i = 1; i < cli.argc; ++i)
cmd += std::string(cli.argv[i]) + " ";
@@ -115,49 +103,64 @@ void UCI::loop() {
is >> std::skipws >> token;
if (token == "quit" || token == "stop")
threads.stop = true;
engine.stop();
// The GUI sends 'ponderhit' to tell that the user has played the expected move.
// So, 'ponderhit' is sent if pondering was done on the same move that the user
// has played. The search should continue, but should also switch from pondering
// to the normal search.
else if (token == "ponderhit")
threads.main_manager()->ponder = false; // Switch to the normal search
engine.set_ponderhit(false);
else if (token == "uci")
{
sync_cout << "id name " << engine_info(true) << "\n"
<< options << "\nuciok" << sync_endl;
<< engine.get_options() << sync_endl;
sync_cout << "uciok" << sync_endl;
}
else if (token == "setoption")
setoption(is);
else if (token == "go")
go(pos, is, states);
{
// send info strings after the go command is sent for old GUIs and python-chess
print_info_string(engine.numa_config_information_as_string());
print_info_string(engine.thread_allocation_information_as_string());
go(is);
}
else if (token == "position")
position(pos, is, states);
position(is);
else if (token == "ucinewgame")
search_clear();
engine.search_clear();
else if (token == "isready")
sync_cout << "readyok" << sync_endl;
// Add custom non-UCI commands, mainly for debugging purposes.
// These commands must not be used during a search!
else if (token == "flip")
pos.flip();
engine.flip();
else if (token == "bench")
bench(pos, is, states);
bench(is);
else if (token == BenchmarkCommand)
benchmark(is);
else if (token == "d")
sync_cout << pos << sync_endl;
sync_cout << engine.visualize() << sync_endl;
else if (token == "eval")
trace_eval(pos);
engine.trace_eval();
else if (token == "compiler")
sync_cout << compiler_info() << sync_endl;
else if (token == "export_net")
{
std::optional<std::string> filename;
std::string f;
if (is >> std::skipws >> f)
filename = f;
Eval::NNUE::save_eval(filename, Eval::NNUE::Big, evalFiles);
std::pair<std::optional<std::string>, std::string> files[2];
if (is >> std::skipws >> files[0].second)
files[0].first = files[0].second;
if (is >> std::skipws >> files[1].second)
files[1].first = files[1].second;
engine.save_network(files);
}
else if (token == "--help" || token == "help" || token == "--license" || token == "license")
sync_cout
@@ -175,18 +178,16 @@ void UCI::loop() {
} while (token != "quit" && cli.argc == 1); // The command-line arguments are one-shot
}
void UCI::go(Position& pos, std::istringstream& is, StateListPtr& states) {
Search::LimitsType UCIEngine::parse_limits(std::istream& is) {
Search::LimitsType limits;
std::string token;
bool ponderMode = false;
limits.startTime = now(); // The search starts as early as possible
while (is >> token)
if (token == "searchmoves") // Needs to be the last command on the line
while (is >> token)
limits.searchmoves.push_back(to_move(pos, token));
limits.searchmoves.push_back(to_lower(token));
else if (token == "wtime")
is >> limits.time[WHITE];
@@ -211,24 +212,33 @@ void UCI::go(Position& pos, std::istringstream& is, StateListPtr& states) {
else if (token == "infinite")
limits.infinite = 1;
else if (token == "ponder")
ponderMode = true;
limits.ponderMode = true;
Eval::NNUE::verify(options, evalFiles);
if (limits.perft)
{
perft(pos.fen(), limits.perft, options["UCI_Chess960"]);
return;
}
threads.start_thinking(options, pos, states, limits, ponderMode);
return limits;
}
void UCI::bench(Position& pos, std::istream& args, StateListPtr& states) {
void UCIEngine::go(std::istringstream& is) {
Search::LimitsType limits = parse_limits(is);
if (limits.perft)
perft(limits);
else
engine.go(limits);
}
void UCIEngine::bench(std::istream& args) {
std::string token;
uint64_t num, nodes = 0, cnt = 1;
uint64_t nodesSearched = 0;
const auto& options = engine.get_options();
std::vector<std::string> list = setup_bench(pos, args);
engine.set_on_update_full([&](const auto& i) {
nodesSearched = i.nodes;
on_update_full(i, options["UCI_ShowWDL"]);
});
std::vector<std::string> list = Benchmark::setup_bench(engine.fen(), args);
num = count_if(list.begin(), list.end(),
[](const std::string& s) { return s.find("go ") == 0 || s.find("eval") == 0; });
@@ -242,24 +252,33 @@ void UCI::bench(Position& pos, std::istream& args, StateListPtr& states) {
if (token == "go" || token == "eval")
{
std::cerr << "\nPosition: " << cnt++ << '/' << num << " (" << pos.fen() << ")"
std::cerr << "\nPosition: " << cnt++ << '/' << num << " (" << engine.fen() << ")"
<< std::endl;
if (token == "go")
{
go(pos, is, states);
threads.main_thread()->wait_for_search_finished();
nodes += threads.nodes_searched();
Search::LimitsType limits = parse_limits(is);
if (limits.perft)
nodesSearched = perft(limits);
else
{
engine.go(limits);
engine.wait_for_search_finished();
}
nodes += nodesSearched;
nodesSearched = 0;
}
else
trace_eval(pos);
engine.trace_eval();
}
else if (token == "setoption")
setoption(is);
else if (token == "position")
position(pos, is, states);
position(is);
else if (token == "ucinewgame")
{
search_clear(); // Search::clear() may take a while
engine.search_clear(); // search_clear may take a while
elapsed = now();
}
}
@@ -268,36 +287,191 @@ void UCI::bench(Position& pos, std::istream& args, StateListPtr& states) {
dbg_print();
std::cerr << "\n==========================="
<< "\nTotal time (ms) : " << elapsed << "\nNodes searched : " << nodes
std::cerr << "\n===========================" //
<< "\nTotal time (ms) : " << elapsed //
<< "\nNodes searched : " << nodes //
<< "\nNodes/second : " << 1000 * nodes / elapsed << std::endl;
// reset callback, to not capture a dangling reference to nodesSearched
engine.set_on_update_full([&](const auto& i) { on_update_full(i, options["UCI_ShowWDL"]); });
}
void UCI::trace_eval(Position& pos) {
StateListPtr states(new std::deque<StateInfo>(1));
Position p;
p.set(pos.fen(), options["UCI_Chess960"], &states->back());
void UCIEngine::benchmark(std::istream& args) {
// Probably not very important for a test this long, but include for completeness and sanity.
static constexpr int NUM_WARMUP_POSITIONS = 3;
Eval::NNUE::verify(options, evalFiles);
std::string token;
uint64_t nodes = 0, cnt = 1;
uint64_t nodesSearched = 0;
sync_cout << "\n" << Eval::trace(p) << sync_endl;
engine.set_on_update_full([&](const Engine::InfoFull& i) { nodesSearched = i.nodes; });
engine.set_on_iter([](const auto&) {});
engine.set_on_update_no_moves([](const auto&) {});
engine.set_on_bestmove([](const auto&, const auto&) {});
engine.set_on_verify_networks([](const auto&) {});
Benchmark::BenchmarkSetup setup = Benchmark::setup_benchmark(args);
const int numGoCommands = count_if(setup.commands.begin(), setup.commands.end(),
[](const std::string& s) { return s.find("go ") == 0; });
TimePoint totalTime = 0;
// Set options once at the start.
auto ss = std::istringstream("name Threads value " + std::to_string(setup.threads));
setoption(ss);
ss = std::istringstream("name Hash value " + std::to_string(setup.ttSize));
setoption(ss);
ss = std::istringstream("name UCI_Chess960 value false");
setoption(ss);
// Warmup
for (const auto& cmd : setup.commands)
{
std::istringstream is(cmd);
is >> std::skipws >> token;
if (token == "go")
{
// One new line is produced by the search, so omit it here
std::cerr << "\rWarmup position " << cnt++ << '/' << NUM_WARMUP_POSITIONS;
Search::LimitsType limits = parse_limits(is);
TimePoint elapsed = now();
// Run with silenced network verification
engine.go(limits);
engine.wait_for_search_finished();
totalTime += now() - elapsed;
nodes += nodesSearched;
nodesSearched = 0;
}
else if (token == "position")
position(is);
else if (token == "ucinewgame")
{
engine.search_clear(); // search_clear may take a while
}
if (cnt > NUM_WARMUP_POSITIONS)
break;
}
std::cerr << "\n";
cnt = 1;
nodes = 0;
int numHashfullReadings = 0;
constexpr int hashfullAges[] = {0, 999}; // Only normal hashfull and touched hash.
int totalHashfull[std::size(hashfullAges)] = {0};
int maxHashfull[std::size(hashfullAges)] = {0};
auto updateHashfullReadings = [&]() {
numHashfullReadings += 1;
for (int i = 0; i < static_cast<int>(std::size(hashfullAges)); ++i)
{
const int hashfull = engine.get_hashfull(hashfullAges[i]);
maxHashfull[i] = std::max(maxHashfull[i], hashfull);
totalHashfull[i] += hashfull;
}
};
engine.search_clear(); // search_clear may take a while
for (const auto& cmd : setup.commands)
{
std::istringstream is(cmd);
is >> std::skipws >> token;
if (token == "go")
{
// One new line is produced by the search, so omit it here
std::cerr << "\rPosition " << cnt++ << '/' << numGoCommands;
Search::LimitsType limits = parse_limits(is);
TimePoint elapsed = now();
// Run with silenced network verification
engine.go(limits);
engine.wait_for_search_finished();
totalTime += now() - elapsed;
updateHashfullReadings();
nodes += nodesSearched;
nodesSearched = 0;
}
else if (token == "position")
position(is);
else if (token == "ucinewgame")
{
engine.search_clear(); // search_clear may take a while
}
}
totalTime = std::max<TimePoint>(totalTime, 1); // Ensure positivity to avoid a 'divide by zero'
dbg_print();
std::cerr << "\n";
static_assert(
std::size(hashfullAges) == 2 && hashfullAges[0] == 0 && hashfullAges[1] == 999,
"Hardcoded for display. Would complicate the code needlessly in the current state.");
std::string threadBinding = engine.thread_binding_information_as_string();
if (threadBinding.empty())
threadBinding = "none";
// clang-format off
std::cerr << "==========================="
<< "\nVersion : "
<< engine_version_info()
// "\nCompiled by : "
<< compiler_info()
<< "Large pages : " << (has_large_pages() ? "yes" : "no")
<< "\nUser invocation : " << BenchmarkCommand << " "
<< setup.originalInvocation << "\nFilled invocation : " << BenchmarkCommand
<< " " << setup.filledInvocation
<< "\nAvailable processors : " << engine.get_numa_config_as_string()
<< "\nThread count : " << setup.threads
<< "\nThread binding : " << threadBinding
<< "\nTT size [MiB] : " << setup.ttSize
<< "\nHash max, avg [per mille] : "
<< "\n single search : " << maxHashfull[0] << ", "
<< totalHashfull[0] / numHashfullReadings
<< "\n single game : " << maxHashfull[1] << ", "
<< totalHashfull[1] / numHashfullReadings
<< "\nTotal nodes searched : " << nodes
<< "\nTotal search time [s] : " << totalTime / 1000.0
<< "\nNodes/second : " << 1000 * nodes / totalTime << std::endl;
// clang-format on
init_search_update_listeners();
}
void UCI::search_clear() {
threads.main_thread()->wait_for_search_finished();
tt.clear(options["Threads"]);
threads.clear();
Tablebases::init(options["SyzygyPath"]); // Free mapped files
void UCIEngine::setoption(std::istringstream& is) {
engine.wait_for_search_finished();
engine.get_options().setoption(is);
}
void UCI::setoption(std::istringstream& is) {
threads.main_thread()->wait_for_search_finished();
options.setoption(is);
std::uint64_t UCIEngine::perft(const Search::LimitsType& limits) {
auto nodes = engine.perft(engine.fen(), limits.perft, engine.get_options()["UCI_Chess960"]);
sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
return nodes;
}
void UCI::position(Position& pos, std::istringstream& is, StateListPtr& states) {
Move m;
void UCIEngine::position(std::istringstream& is) {
std::string token, fen;
is >> token;
@@ -313,42 +487,99 @@ void UCI::position(Position& pos, std::istringstream& is, StateListPtr& states)
else
return;
states = StateListPtr(new std::deque<StateInfo>(1)); // Drop the old state and create a new one
pos.set(fen, options["UCI_Chess960"], &states->back());
std::vector<std::string> moves;
// Parse the move list, if any
while (is >> token && (m = to_move(pos, token)) != Move::none())
while (is >> token)
{
states->emplace_back();
pos.do_move(m, states->back());
moves.push_back(token);
}
engine.set_position(fen, moves);
}
int UCI::to_cp(Value v) { return 100 * v / NormalizeToPawnValue; }
namespace {
std::string UCI::value(Value v) {
assert(-VALUE_INFINITE < v && v < VALUE_INFINITE);
struct WinRateParams {
double a;
double b;
};
WinRateParams win_rate_params(const Position& pos) {
int material = pos.count<PAWN>() + 3 * pos.count<KNIGHT>() + 3 * pos.count<BISHOP>()
+ 5 * pos.count<ROOK>() + 9 * pos.count<QUEEN>();
// The fitted model only uses data for material counts in [17, 78], and is anchored at count 58.
double m = std::clamp(material, 17, 78) / 58.0;
// Return a = p_a(material) and b = p_b(material), see github.com/official-stockfish/WDL_model
constexpr double as[] = {-37.45051876, 121.19101539, -132.78783573, 420.70576692};
constexpr double bs[] = {90.26261072, -137.26549898, 71.10130540, 51.35259597};
double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3];
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
return {a, b};
}
// The win rate model is 1 / (1 + exp((a - eval) / b)), where a = p_a(material) and b = p_b(material).
// It fits the LTC fishtest statistics rather accurately.
int win_rate_model(Value v, const Position& pos) {
auto [a, b] = win_rate_params(pos);
// Return the win rate in per mille units, rounded to the nearest integer.
return int(0.5 + 1000 / (1 + std::exp((a - double(v)) / b)));
}
}
std::string UCIEngine::format_score(const Score& s) {
constexpr int TB_CP = 20000;
const auto format =
overload{[](Score::Mate mate) -> std::string {
auto m = (mate.plies > 0 ? (mate.plies + 1) : mate.plies) / 2;
return std::string("mate ") + std::to_string(m);
},
[](Score::Tablebase tb) -> std::string {
return std::string("cp ")
+ std::to_string((tb.win ? TB_CP - tb.plies : -TB_CP - tb.plies));
},
[](Score::InternalUnits units) -> std::string {
return std::string("cp ") + std::to_string(units.value);
}};
return s.visit(format);
}
// Turns a Value to an integer centipawn number,
// without treatment of mate and similar special scores.
int UCIEngine::to_cp(Value v, const Position& pos) {
// In general, the score can be defined via the WDL as
// (log(1/L - 1) - log(1/W - 1)) / (log(1/L - 1) + log(1/W - 1)).
// Based on our win_rate_model, this simply yields v / a.
auto [a, b] = win_rate_params(pos);
return std::round(100 * int(v) / a);
}
std::string UCIEngine::wdl(Value v, const Position& pos) {
std::stringstream ss;
if (std::abs(v) < VALUE_TB_WIN_IN_MAX_PLY)
ss << "cp " << to_cp(v);
else if (std::abs(v) <= VALUE_TB)
{
const int ply = VALUE_TB - std::abs(v); // recompute ss->ply
ss << "cp " << (v > 0 ? 20000 - ply : -20000 + ply);
}
else
ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
int wdl_w = win_rate_model(v, pos);
int wdl_l = win_rate_model(-v, pos);
int wdl_d = 1000 - wdl_w - wdl_l;
ss << wdl_w << " " << wdl_d << " " << wdl_l;
return ss.str();
}
std::string UCI::square(Square s) {
std::string UCIEngine::square(Square s) {
return std::string{char('a' + file_of(s)), char('1' + rank_of(s))};
}
std::string UCI::move(Move m, bool chess960) {
std::string UCIEngine::move(Move m, bool chess960) {
if (m == Move::none())
return "(none)";
@@ -369,45 +600,15 @@ std::string UCI::move(Move m, bool chess960) {
return move;
}
namespace {
// The win rate model returns the probability of winning (in per mille units) given an
// eval and a game ply. It fits the LTC fishtest statistics rather accurately.
int win_rate_model(Value v, int ply) {
// The fitted model only uses data for moves in [8, 120], and is anchored at move 32.
double m = std::clamp(ply / 2 + 1, 8, 120) / 32.0;
std::string UCIEngine::to_lower(std::string str) {
std::transform(str.begin(), str.end(), str.begin(), [](auto c) { return std::tolower(c); });
// The coefficients of a third-order polynomial fit is based on the fishtest data
// for two parameters that need to transform eval to the argument of a logistic
// function.
constexpr double as[] = {-1.06249702, 7.42016937, 0.89425629, 348.60356174};
constexpr double bs[] = {-5.33122190, 39.57831533, -90.84473771, 123.40620748};
// Enforce that NormalizeToPawnValue corresponds to a 50% win rate at move 32.
static_assert(NormalizeToPawnValue == int(0.5 + as[0] + as[1] + as[2] + as[3]));
double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3];
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
// Return the win rate in per mille units, rounded to the nearest integer.
return int(0.5 + 1000 / (1 + std::exp((a - double(v)) / b)));
}
return str;
}
std::string UCI::wdl(Value v, int ply) {
std::stringstream ss;
int wdl_w = win_rate_model(v, ply);
int wdl_l = win_rate_model(-v, ply);
int wdl_d = 1000 - wdl_w - wdl_l;
ss << " wdl " << wdl_w << " " << wdl_d << " " << wdl_l;
return ss.str();
}
Move UCI::to_move(const Position& pos, std::string& str) {
if (str.length() == 5)
str[4] = char(tolower(str[4])); // The promotion piece character must be lowercased
Move UCIEngine::to_move(const Position& pos, std::string str) {
str = to_lower(str);
for (const auto& m : MoveList<LEGAL>(pos))
if (str == move(m, pos.is_chess960()))
@@ -416,4 +617,51 @@ Move UCI::to_move(const Position& pos, std::string& str) {
return Move::none();
}
void UCIEngine::on_update_no_moves(const Engine::InfoShort& info) {
sync_cout << "info depth " << info.depth << " score " << format_score(info.score) << sync_endl;
}
void UCIEngine::on_update_full(const Engine::InfoFull& info, bool showWDL) {
std::stringstream ss;
ss << "info";
ss << " depth " << info.depth //
<< " seldepth " << info.selDepth //
<< " multipv " << info.multiPV //
<< " score " << format_score(info.score); //
if (showWDL)
ss << " wdl " << info.wdl;
if (!info.bound.empty())
ss << " " << info.bound;
ss << " nodes " << info.nodes //
<< " nps " << info.nps //
<< " hashfull " << info.hashfull //
<< " tbhits " << info.tbHits //
<< " time " << info.timeMs //
<< " pv " << info.pv; //
sync_cout << ss.str() << sync_endl;
}
void UCIEngine::on_iter(const Engine::InfoIter& info) {
std::stringstream ss;
ss << "info";
ss << " depth " << info.depth //
<< " currmove " << info.currmove //
<< " currmovenumber " << info.currmovenumber; //
sync_cout << ss.str() << sync_endl;
}
void UCIEngine::on_bestmove(std::string_view bestmove, std::string_view ponder) {
sync_cout << "bestmove " << bestmove;
if (!ponder.empty())
std::cout << " ponder " << ponder;
std::cout << sync_endl;
}
} // namespace Stockfish
+33 -30
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,57 +19,60 @@
#ifndef UCI_H_INCLUDED
#define UCI_H_INCLUDED
#include <cstdint>
#include <iostream>
#include <string>
#include <unordered_map>
#include <string_view>
#include "evaluate.h"
#include "engine.h"
#include "misc.h"
#include "position.h"
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
#include "search.h"
namespace Stockfish {
namespace Eval::NNUE {
enum NetSize : int;
}
class Position;
class Move;
class Score;
enum Square : int;
using Value = int;
class UCI {
class UCIEngine {
public:
UCI(int argc, char** argv);
UCIEngine(int argc, char** argv);
void loop();
static int to_cp(Value v);
static std::string value(Value v);
static int to_cp(Value v, const Position& pos);
static std::string format_score(const Score& s);
static std::string square(Square s);
static std::string move(Move m, bool chess960);
static std::string wdl(Value v, int ply);
static Move to_move(const Position& pos, std::string& str);
static std::string wdl(Value v, const Position& pos);
static std::string to_lower(std::string str);
static Move to_move(const Position& pos, std::string str);
const std::string& workingDirectory() const { return cli.workingDirectory; }
static Search::LimitsType parse_limits(std::istream& is);
OptionsMap options;
std::unordered_map<Eval::NNUE::NetSize, Eval::EvalFile> evalFiles;
auto& engine_options() { return engine.get_options(); }
private:
TranspositionTable tt;
ThreadPool threads;
CommandLine cli;
Engine engine;
CommandLine cli;
void go(Position& pos, std::istringstream& is, StateListPtr& states);
void bench(Position& pos, std::istream& args, StateListPtr& states);
void position(Position& pos, std::istringstream& is, StateListPtr& states);
void trace_eval(Position& pos);
void search_clear();
void setoption(std::istringstream& is);
static void print_info_string(std::string_view str);
void go(std::istringstream& is);
void bench(std::istream& args);
void benchmark(std::istream& args);
void position(std::istringstream& is);
void setoption(std::istringstream& is);
std::uint64_t perft(const Search::LimitsType&);
static void on_update_no_moves(const Engine::InfoShort& info);
static void on_update_full(const Engine::InfoFull& info, bool showWDL);
static void on_iter(const Engine::InfoIter& info);
static void on_bestmove(std::string_view bestmove, std::string_view ponder);
void init_search_update_listeners();
};
} // namespace Stockfish
+47 -19
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <utility>
@@ -36,6 +37,8 @@ bool CaseInsensitiveLess::operator()(const std::string& s1, const std::string& s
[](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); });
}
void OptionsMap::add_info_listener(InfoListener&& message_func) { info = std::move(message_func); }
void OptionsMap::setoption(std::istringstream& is) {
std::string token, name, value;
@@ -55,15 +58,36 @@ void OptionsMap::setoption(std::istringstream& is) {
sync_cout << "No such option: " << name << sync_endl;
}
Option OptionsMap::operator[](const std::string& name) const {
const Option& OptionsMap::operator[](const std::string& name) const {
auto it = options_map.find(name);
return it != options_map.end() ? it->second : Option();
assert(it != options_map.end());
return it->second;
}
// Inits options and assigns idx in the correct printing order
void OptionsMap::add(const std::string& name, const Option& option) {
if (!options_map.count(name))
{
static size_t insert_order = 0;
options_map[name] = option;
options_map[name].parent = this;
options_map[name].idx = insert_order++;
}
else
{
std::cerr << "Option \"" << name << "\" was already added!" << std::endl;
std::exit(EXIT_FAILURE);
}
}
Option& OptionsMap::operator[](const std::string& name) { return options_map[name]; }
std::size_t OptionsMap::count(const std::string& name) const { return options_map.count(name); }
Option::Option(const OptionsMap* map) :
parent(map) {}
Option::Option(const char* v, OnChange f) :
type("string"),
min(0),
@@ -118,16 +142,7 @@ bool Option::operator==(const char* s) const {
return !CaseInsensitiveLess()(currentValue, s) && !CaseInsensitiveLess()(s, currentValue);
}
// Inits options and assigns idx in the correct printing order
void Option::operator<<(const Option& o) {
static size_t insert_order = 0;
*this = o;
idx = insert_order++;
}
bool Option::operator!=(const char* s) const { return !(*this == s); }
// Updates currentValue and triggers on_change() action. It's up to
@@ -148,16 +163,23 @@ Option& Option::operator=(const std::string& v) {
std::string token;
std::istringstream ss(defaultValue);
while (ss >> token)
comboMap[token] << Option();
comboMap.add(token, Option());
if (!comboMap.count(v) || v == "var")
return *this;
}
if (type != "button")
if (type == "string")
currentValue = v == "<empty>" ? "" : v;
else if (type != "button")
currentValue = v;
if (on_change)
on_change(*this);
{
const auto ret = on_change(*this);
if (ret && parent != nullptr && parent->info != nullptr)
parent->info(ret);
}
return *this;
}
@@ -170,10 +192,16 @@ std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
const Option& o = it.second;
os << "\noption name " << it.first << " type " << o.type;
if (o.type == "string" || o.type == "check" || o.type == "combo")
if (o.type == "check" || o.type == "combo")
os << " default " << o.defaultValue;
if (o.type == "spin")
else if (o.type == "string")
{
std::string defaultValue = o.defaultValue.empty() ? "<empty>" : o.defaultValue;
os << " default " << defaultValue;
}
else if (o.type == "spin")
os << " default " << int(stof(o.defaultValue)) << " min " << o.min << " max "
<< o.max;
+51 -26
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
#include <functional>
#include <iosfwd>
#include <map>
#include <optional>
#include <string>
namespace Stockfish {
@@ -31,31 +32,14 @@ struct CaseInsensitiveLess {
bool operator()(const std::string&, const std::string&) const;
};
class Option;
class OptionsMap {
public:
void setoption(std::istringstream&);
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
Option operator[](const std::string&) const;
Option& operator[](const std::string&);
std::size_t count(const std::string&) const;
private:
// The options container is defined as a std::map
using OptionsStore = std::map<std::string, Option, CaseInsensitiveLess>;
OptionsStore options_map;
};
class OptionsMap;
// The Option class implements each option as specified by the UCI protocol
class Option {
public:
using OnChange = std::function<void(const Option&)>;
using OnChange = std::function<std::optional<std::string>(const Option&)>;
Option(const OptionsMap*);
Option(OnChange = nullptr);
Option(bool v, OnChange = nullptr);
Option(const char* v, OnChange = nullptr);
@@ -63,18 +47,59 @@ class Option {
Option(const char* v, const char* cur, OnChange = nullptr);
Option& operator=(const std::string&);
void operator<<(const Option&);
operator int() const;
operator std::string() const;
bool operator==(const char*) const;
bool operator!=(const char*) const;
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
int operator<<(const Option&) = delete;
private:
std::string defaultValue, currentValue, type;
int min, max;
size_t idx;
OnChange on_change;
friend class OptionsMap;
friend class Engine;
friend class Tune;
std::string defaultValue, currentValue, type;
int min, max;
size_t idx;
OnChange on_change;
const OptionsMap* parent = nullptr;
};
class OptionsMap {
public:
using InfoListener = std::function<void(std::optional<std::string>)>;
OptionsMap() = default;
OptionsMap(const OptionsMap&) = delete;
OptionsMap(OptionsMap&&) = delete;
OptionsMap& operator=(const OptionsMap&) = delete;
OptionsMap& operator=(OptionsMap&&) = delete;
void add_info_listener(InfoListener&&);
void setoption(std::istringstream&);
const Option& operator[](const std::string&) const;
void add(const std::string&, const Option& option);
std::size_t count(const std::string&) const;
private:
friend class Engine;
friend class Option;
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
// The options container is defined as a std::map
using OptionsStore = std::map<std::string, Option, CaseInsensitiveLess>;
OptionsStore options_map;
InfoListener info;
};
}
+1
View File
@@ -0,0 +1 @@
*.sh text eol=lf
+520
View File
@@ -0,0 +1,520 @@
import argparse
import re
import sys
import subprocess
import pathlib
import os
from testing import (
EPD,
TSAN,
Stockfish as Engine,
MiniTestFramework,
OrderedClassMembers,
Valgrind,
Syzygy,
)
PATH = pathlib.Path(__file__).parent.resolve()
CWD = os.getcwd()
def get_prefix():
if args.valgrind:
return Valgrind.get_valgrind_command()
if args.valgrind_thread:
return Valgrind.get_valgrind_thread_command()
return []
def get_threads():
if args.valgrind_thread or args.sanitizer_thread:
return 2
return 1
def get_path():
return os.path.abspath(os.path.join(CWD, args.stockfish_path))
def postfix_check(output):
if args.sanitizer_undefined:
for idx, line in enumerate(output):
if "runtime error:" in line:
# print next possible 50 lines
for i in range(50):
debug_idx = idx + i
if debug_idx < len(output):
print(output[debug_idx])
return False
if args.sanitizer_thread:
for idx, line in enumerate(output):
if "WARNING: ThreadSanitizer:" in line:
# print next possible 50 lines
for i in range(50):
debug_idx = idx + i
if debug_idx < len(output):
print(output[debug_idx])
return False
return True
def Stockfish(*args, **kwargs):
return Engine(get_prefix(), get_path(), *args, **kwargs)
class TestCLI(metaclass=OrderedClassMembers):
def beforeAll(self):
pass
def afterAll(self):
pass
def beforeEach(self):
self.stockfish = None
def afterEach(self):
assert postfix_check(self.stockfish.get_output()) == True
self.stockfish.clear_output()
def test_eval(self):
self.stockfish = Stockfish("eval".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_go_nodes_1000(self):
self.stockfish = Stockfish("go nodes 1000".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_go_depth_10(self):
self.stockfish = Stockfish("go depth 10".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_go_perft_4(self):
self.stockfish = Stockfish("go perft 4".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_go_movetime_1000(self):
self.stockfish = Stockfish("go movetime 1000".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_go_wtime_8000_btime_8000_winc_500_binc_500(self):
self.stockfish = Stockfish(
"go wtime 8000 btime 8000 winc 500 binc 500".split(" "),
True,
)
assert self.stockfish.process.returncode == 0
def test_go_wtime_1000_btime_1000_winc_0_binc_0(self):
self.stockfish = Stockfish(
"go wtime 1000 btime 1000 winc 0 binc 0".split(" "),
True,
)
assert self.stockfish.process.returncode == 0
def test_go_wtime_1000_btime_1000_winc_0_binc_0_movestogo_5(self):
self.stockfish = Stockfish(
"go wtime 1000 btime 1000 winc 0 binc 0 movestogo 5".split(" "),
True,
)
assert self.stockfish.process.returncode == 0
def test_go_movetime_200(self):
self.stockfish = Stockfish("go movetime 200".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_go_nodes_20000_searchmoves_e2e4_d2d4(self):
self.stockfish = Stockfish(
"go nodes 20000 searchmoves e2e4 d2d4".split(" "), True
)
assert self.stockfish.process.returncode == 0
def test_bench_128_threads_8_default_depth(self):
self.stockfish = Stockfish(
f"bench 128 {get_threads()} 8 default depth".split(" "),
True,
)
assert self.stockfish.process.returncode == 0
def test_bench_128_threads_3_bench_tmp_epd_depth(self):
self.stockfish = Stockfish(
f"bench 128 {get_threads()} 3 {os.path.join(PATH,'bench_tmp.epd')} depth".split(
" "
),
True,
)
assert self.stockfish.process.returncode == 0
def test_d(self):
self.stockfish = Stockfish("d".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_compiler(self):
self.stockfish = Stockfish("compiler".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_license(self):
self.stockfish = Stockfish("license".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_uci(self):
self.stockfish = Stockfish("uci".split(" "), True)
assert self.stockfish.process.returncode == 0
def test_export_net_verify_nnue(self):
current_path = os.path.abspath(os.getcwd())
self.stockfish = Stockfish(
f"export_net {os.path.join(current_path , 'verify.nnue')}".split(" "), True
)
assert self.stockfish.process.returncode == 0
# verify the generated net equals the base net
def test_network_equals_base(self):
self.stockfish = Stockfish(
["uci"],
True,
)
output = self.stockfish.process.stdout
# find line
for line in output.split("\n"):
if "option name EvalFile type string default" in line:
network = line.split(" ")[-1]
break
# find network file in src dir
network = os.path.join(PATH.parent.resolve(), "src", network)
if not os.path.exists(network):
print(
f"Network file {network} not found, please download the network file over the make command."
)
assert False
diff = subprocess.run(["diff", network, f"verify.nnue"])
assert diff.returncode == 0
class TestInteractive(metaclass=OrderedClassMembers):
def beforeAll(self):
self.stockfish = Stockfish()
def afterAll(self):
self.stockfish.quit()
assert self.stockfish.close() == 0
def afterEach(self):
assert postfix_check(self.stockfish.get_output()) == True
self.stockfish.clear_output()
def test_startup_output(self):
self.stockfish.starts_with("Stockfish")
def test_uci_command(self):
self.stockfish.send_command("uci")
self.stockfish.equals("uciok")
def test_set_threads_option(self):
self.stockfish.send_command(f"setoption name Threads value {get_threads()}")
def test_ucinewgame_and_startpos_nodes_1000(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position startpos")
self.stockfish.send_command("go nodes 1000")
self.stockfish.starts_with("bestmove")
def test_ucinewgame_and_startpos_moves(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position startpos moves e2e4 e7e6")
self.stockfish.send_command("go nodes 1000")
self.stockfish.starts_with("bestmove")
def test_fen_position_1(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position fen 5rk1/1K4p1/8/8/3B4/8/8/8 b - - 0 1")
self.stockfish.send_command("go nodes 1000")
self.stockfish.starts_with("bestmove")
def test_fen_position_2_flip(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position fen 5rk1/1K4p1/8/8/3B4/8/8/8 b - - 0 1")
self.stockfish.send_command("flip")
self.stockfish.send_command("go nodes 1000")
self.stockfish.starts_with("bestmove")
def test_depth_5_with_callback(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position startpos")
self.stockfish.send_command("go depth 5")
def callback(output):
regex = r"info depth \d+ seldepth \d+ multipv \d+ score cp \d+ nodes \d+ nps \d+ hashfull \d+ tbhits \d+ time \d+ pv"
if output.startswith("info depth") and not re.match(regex, output):
assert False
if output.startswith("bestmove"):
return True
return False
self.stockfish.check_output(callback)
def test_ucinewgame_and_go_depth_9(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("setoption name UCI_ShowWDL value true")
self.stockfish.send_command("position startpos")
self.stockfish.send_command("go depth 9")
depth = 1
def callback(output):
nonlocal depth
regex = rf"info depth {depth} seldepth \d+ multipv \d+ score cp \d+ wdl \d+ \d+ \d+ nodes \d+ nps \d+ hashfull \d+ tbhits \d+ time \d+ pv"
if output.startswith("info depth"):
if not re.match(regex, output):
assert False
depth += 1
if output.startswith("bestmove"):
assert depth == 10
return True
return False
self.stockfish.check_output(callback)
def test_clear_hash(self):
self.stockfish.send_command("setoption name Clear Hash")
def test_fen_position_mate_1(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 5K2/8/2qk4/2nPp3/3r4/6B1/B7/3R4 w - e6"
)
self.stockfish.send_command("go depth 18")
self.stockfish.expect("* score mate 1 * pv d5e6")
self.stockfish.equals("bestmove d5e6")
def test_fen_position_mate_minus_1(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 2brrb2/8/p7/Q7/1p1kpPp1/1P1pN1K1/3P4/8 b - -"
)
self.stockfish.send_command("go depth 18")
self.stockfish.expect("* score mate -1 *")
self.stockfish.starts_with("bestmove")
def test_fen_position_fixed_node(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 5K2/8/2P1P1Pk/6pP/3p2P1/1P6/3P4/8 w - - 0 1"
)
self.stockfish.send_command("go nodes 500000")
self.stockfish.starts_with("bestmove")
def test_fen_position_with_mate_go_depth(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 8/5R2/2K1P3/4k3/8/b1PPpp1B/5p2/8 w - -"
)
self.stockfish.send_command("go depth 18 searchmoves c6d7")
self.stockfish.expect("* score mate 2 * pv c6d7 * f7f5")
self.stockfish.starts_with("bestmove")
def test_fen_position_with_mate_go_mate(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 8/5R2/2K1P3/4k3/8/b1PPpp1B/5p2/8 w - -"
)
self.stockfish.send_command("go mate 2 searchmoves c6d7")
self.stockfish.expect("* score mate 2 * pv c6d7 *")
self.stockfish.starts_with("bestmove")
def test_fen_position_with_mate_go_nodes(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 8/5R2/2K1P3/4k3/8/b1PPpp1B/5p2/8 w - -"
)
self.stockfish.send_command("go nodes 500000 searchmoves c6d7")
self.stockfish.expect("* score mate 2 * pv c6d7 * f7f5")
self.stockfish.starts_with("bestmove")
def test_fen_position_depth_27(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen r1b2r1k/pp1p2pp/2p5/2B1q3/8/8/P1PN2PP/R4RK1 w - - 0 18"
)
self.stockfish.send_command("go")
self.stockfish.contains("score mate 1")
self.stockfish.starts_with("bestmove")
def test_fen_position_with_mate_go_depth_and_promotion(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 8/5R2/2K1P3/4k3/8/b1PPpp1B/5p2/8 w - - moves c6d7 f2f1q"
)
self.stockfish.send_command("go depth 18")
self.stockfish.expect("* score mate 1 * pv f7f5")
self.stockfish.starts_with("bestmove f7f5")
def test_fen_position_with_mate_go_depth_and_searchmoves(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 8/5R2/2K1P3/4k3/8/b1PPpp1B/5p2/8 w - -"
)
self.stockfish.send_command("go depth 18 searchmoves c6d7")
self.stockfish.expect("* score mate 2 * pv c6d7 * f7f5")
self.stockfish.starts_with("bestmove c6d7")
def test_fen_position_with_moves_with_mate_go_depth_and_searchmoves(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command(
"position fen 8/5R2/2K1P3/4k3/8/b1PPpp1B/5p2/8 w - - moves c6d7"
)
self.stockfish.send_command("go depth 18 searchmoves e3e2")
self.stockfish.expect("* score mate -1 * pv e3e2 f7f5")
self.stockfish.starts_with("bestmove e3e2")
def test_verify_nnue_network(self):
current_path = os.path.abspath(os.getcwd())
Stockfish(
f"export_net {os.path.join(current_path , 'verify.nnue')}".split(" "), True
)
self.stockfish.send_command("setoption name EvalFile value verify.nnue")
self.stockfish.send_command("position startpos")
self.stockfish.send_command("go depth 5")
self.stockfish.starts_with("bestmove")
def test_multipv_setting(self):
self.stockfish.send_command("setoption name MultiPV value 4")
self.stockfish.send_command("position startpos")
self.stockfish.send_command("go depth 5")
self.stockfish.starts_with("bestmove")
def test_fen_position_with_skill_level(self):
self.stockfish.send_command("setoption name Skill Level value 10")
self.stockfish.send_command("position startpos")
self.stockfish.send_command("go depth 5")
self.stockfish.starts_with("bestmove")
self.stockfish.send_command("setoption name Skill Level value 20")
class TestSyzygy(metaclass=OrderedClassMembers):
def beforeAll(self):
self.stockfish = Stockfish()
def afterAll(self):
self.stockfish.quit()
assert self.stockfish.close() == 0
def afterEach(self):
assert postfix_check(self.stockfish.get_output()) == True
self.stockfish.clear_output()
def test_syzygy_setup(self):
self.stockfish.starts_with("Stockfish")
self.stockfish.send_command("uci")
self.stockfish.send_command(
f"setoption name SyzygyPath value {os.path.join(PATH, 'syzygy')}"
)
self.stockfish.expect(
"info string Found 35 WDL and 35 DTZ tablebase files (up to 4-man)."
)
def test_syzygy_bench(self):
self.stockfish.send_command("bench 128 1 8 default depth")
self.stockfish.expect("Nodes searched :*")
def test_syzygy_position(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position fen 4k3/PP6/8/8/8/8/8/4K3 w - - 0 1")
self.stockfish.send_command("go depth 5")
def check_output(output):
if "score cp 20000" in output or "score mate" in output:
return True
self.stockfish.check_output(check_output)
self.stockfish.expect("bestmove *")
def test_syzygy_position_2(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position fen 8/1P6/2B5/8/4K3/8/6k1/8 w - - 0 1")
self.stockfish.send_command("go depth 5")
def check_output(output):
if "score cp 20000" in output or "score mate" in output:
return True
self.stockfish.check_output(check_output)
self.stockfish.expect("bestmove *")
def test_syzygy_position_3(self):
self.stockfish.send_command("ucinewgame")
self.stockfish.send_command("position fen 8/1P6/2B5/8/4K3/8/6k1/8 b - - 0 1")
self.stockfish.send_command("go depth 5")
def check_output(output):
if "score cp -20000" in output or "score mate" in output:
return True
self.stockfish.check_output(check_output)
self.stockfish.expect("bestmove *")
def parse_args():
parser = argparse.ArgumentParser(description="Run Stockfish with testing options")
parser.add_argument("--valgrind", action="store_true", help="Run valgrind testing")
parser.add_argument(
"--valgrind-thread", action="store_true", help="Run valgrind-thread testing"
)
parser.add_argument(
"--sanitizer-undefined",
action="store_true",
help="Run sanitizer-undefined testing",
)
parser.add_argument(
"--sanitizer-thread", action="store_true", help="Run sanitizer-thread testing"
)
parser.add_argument(
"--none", action="store_true", help="Run without any testing options"
)
parser.add_argument("stockfish_path", type=str, help="Path to Stockfish binary")
return parser.parse_args()
if __name__ == "__main__":
args = parse_args()
EPD.create_bench_epd()
TSAN.set_tsan_option()
Syzygy.download_syzygy()
framework = MiniTestFramework()
# Each test suite will be ran inside a temporary directory
framework.run([TestCLI, TestInteractive, TestSyzygy])
EPD.delete_bench_epd()
TSAN.unset_tsan_option()
if framework.has_failed():
sys.exit(1)
sys.exit(0)
-199
View File
@@ -1,199 +0,0 @@
#!/bin/bash
# check for errors under Valgrind or sanitizers.
error()
{
echo "instrumented testing failed on line $1"
exit 1
}
trap 'error ${LINENO}' ERR
# define suitable post and prefixes for testing options
case $1 in
--valgrind)
echo "valgrind testing started"
prefix=''
exeprefix='valgrind --error-exitcode=42 --errors-for-leak-kinds=all --leak-check=full'
postfix='1>/dev/null'
threads="1"
;;
--valgrind-thread)
echo "valgrind-thread testing started"
prefix=''
exeprefix='valgrind --fair-sched=try --error-exitcode=42'
postfix='1>/dev/null'
threads="2"
;;
--sanitizer-undefined)
echo "sanitizer-undefined testing started"
prefix='!'
exeprefix=''
postfix='2>&1 | grep -A50 "runtime error:"'
threads="1"
;;
--sanitizer-thread)
echo "sanitizer-thread testing started"
prefix='!'
exeprefix=''
postfix='2>&1 | grep -A50 "WARNING: ThreadSanitizer:"'
threads="2"
cat << EOF > tsan.supp
race:Stockfish::TTEntry::move
race:Stockfish::TTEntry::depth
race:Stockfish::TTEntry::bound
race:Stockfish::TTEntry::save
race:Stockfish::TTEntry::value
race:Stockfish::TTEntry::eval
race:Stockfish::TTEntry::is_pv
race:Stockfish::TranspositionTable::probe
race:Stockfish::TranspositionTable::hashfull
EOF
export TSAN_OPTIONS="suppressions=./tsan.supp"
;;
*)
echo "unknown testing started"
prefix=''
exeprefix=''
postfix=''
threads="1"
;;
esac
cat << EOF > bench_tmp.epd
Rn6/1rbq1bk1/2p2n1p/2Bp1p2/3Pp1pP/1N2P1P1/2Q1NPB1/6K1 w - - 2 26
rnbqkb1r/ppp1pp2/5n1p/3p2p1/P2PP3/5P2/1PP3PP/RNBQKBNR w KQkq - 0 3
3qnrk1/4bp1p/1p2p1pP/p2bN3/1P1P1B2/P2BQ3/5PP1/4R1K1 w - - 9 28
r4rk1/1b2ppbp/pq4pn/2pp1PB1/1p2P3/1P1P1NN1/1PP3PP/R2Q1RK1 w - - 0 13
EOF
# simple command line testing
for args in "eval" \
"go nodes 1000" \
"go depth 10" \
"go perft 4" \
"go movetime 1000" \
"go wtime 8000 btime 8000 winc 500 binc 500" \
"go wtime 1000 btime 1000 winc 0 binc 0" \
"go wtime 1000 btime 1000 winc 0 binc 0" \
"go wtime 1000 btime 1000 winc 0 binc 0 movestogo 5" \
"go movetime 200" \
"go nodes 20000 searchmoves e2e4 d2d4" \
"bench 128 $threads 8 default depth" \
"bench 128 $threads 3 bench_tmp.epd depth" \
"export_net verify.nnue" \
"d" \
"compiler" \
"license" \
"uci"
do
echo "$prefix $exeprefix ./stockfish $args $postfix"
eval "$prefix $exeprefix ./stockfish $args $postfix"
done
# verify the generated net equals the base net
network=`./stockfish uci | grep 'option name EvalFile type string default' | awk '{print $NF}'`
echo "Comparing $network to the written verify.nnue"
diff $network verify.nnue
# more general testing, following an uci protocol exchange
cat << EOF > game.exp
set timeout 240
spawn $exeprefix ./stockfish
send "uci\n"
expect "uciok"
# send "setoption name Debug Log File value debug.log\n"
send "setoption name Threads value $threads\n"
send "ucinewgame\n"
send "position startpos\n"
send "go nodes 1000\n"
expect "bestmove"
send "position startpos moves e2e4 e7e6\n"
send "go nodes 1000\n"
expect "bestmove"
send "position fen 5rk1/1K4p1/8/8/3B4/8/8/8 b - - 0 1\n"
send "go depth 10\n"
expect "bestmove"
send "setoption name UCI_ShowWDL value true\n"
send "position startpos\n"
send "flip\n"
send "go depth 5\n"
expect "bestmove"
send "setoption name Skill Level value 10\n"
send "position startpos\n"
send "go depth 5\n"
expect "bestmove"
send "setoption name Clear Hash\n"
send "setoption name EvalFile value verify.nnue\n"
send "position startpos\n"
send "go depth 5\n"
expect "bestmove"
send "setoption name MultiPV value 4\n"
send "position startpos\n"
send "go depth 5\n"
send "quit\n"
expect eof
# return error code of the spawned program, useful for Valgrind
lassign [wait] pid spawnid os_error_flag value
exit \$value
EOF
#download TB as needed
if [ ! -d ../tests/syzygy ]; then
curl -sL https://api.github.com/repos/niklasf/python-chess/tarball/9b9aa13f9f36d08aadfabff872882f4ab1494e95 | tar -xzf -
mv niklasf-python-chess-9b9aa13 ../tests/syzygy
fi
cat << EOF > syzygy.exp
set timeout 240
spawn $exeprefix ./stockfish
send "uci\n"
send "setoption name SyzygyPath value ../tests/syzygy/\n"
expect "info string Found 35 tablebases" {} timeout {exit 1}
send "bench 128 1 8 default depth\n"
send "ucinewgame\n"
send "position fen 4k3/PP6/8/8/8/8/8/4K3 w - - 0 1\n"
send "go depth 5\n"
expect "bestmove"
send "position fen 8/1P6/2B5/8/4K3/8/6k1/8 w - - 0 1\n"
send "go depth 5\n"
expect "bestmove"
send "quit\n"
expect eof
# return error code of the spawned program, useful for Valgrind
lassign [wait] pid spawnid os_error_flag value
exit \$value
EOF
for exp in game.exp syzygy.exp
do
echo "$prefix expect $exp $postfix"
eval "$prefix expect $exp $postfix"
rm $exp
done
rm -f tsan.supp bench_tmp.epd
echo "instrumented testing OK"
+1 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash
# verify perft numbers (positions from www.chessprogramming.org/Perft_Results)
# verify perft numbers (positions from https://www.chessprogramming.org/Perft_Results)
error()
{
+400
View File
@@ -0,0 +1,400 @@
import subprocess
from typing import List
import os
import collections
import time
import sys
import traceback
import fnmatch
from functools import wraps
from contextlib import redirect_stdout
import io
import tarfile
import pathlib
import concurrent.futures
import tempfile
import shutil
import requests
CYAN_COLOR = "\033[36m"
GRAY_COLOR = "\033[2m"
RED_COLOR = "\033[31m"
GREEN_COLOR = "\033[32m"
RESET_COLOR = "\033[0m"
WHITE_BOLD = "\033[1m"
MAX_TIMEOUT = 60 * 5
PATH = pathlib.Path(__file__).parent.resolve()
class Valgrind:
@staticmethod
def get_valgrind_command():
return [
"valgrind",
"--error-exitcode=42",
"--errors-for-leak-kinds=all",
"--leak-check=full",
]
@staticmethod
def get_valgrind_thread_command():
return ["valgrind", "--error-exitcode=42", "--fair-sched=try"]
class TSAN:
@staticmethod
def set_tsan_option():
with open(f"tsan.supp", "w") as f:
f.write(
"""
race:Stockfish::TTEntry::read
race:Stockfish::TTEntry::save
race:Stockfish::TranspositionTable::probe
race:Stockfish::TranspositionTable::hashfull
"""
)
os.environ["TSAN_OPTIONS"] = "suppressions=./tsan.supp"
@staticmethod
def unset_tsan_option():
os.environ.pop("TSAN_OPTIONS", None)
os.remove(f"tsan.supp")
class EPD:
@staticmethod
def create_bench_epd():
with open(f"{os.path.join(PATH,'bench_tmp.epd')}", "w") as f:
f.write(
"""
Rn6/1rbq1bk1/2p2n1p/2Bp1p2/3Pp1pP/1N2P1P1/2Q1NPB1/6K1 w - - 2 26
rnbqkb1r/ppp1pp2/5n1p/3p2p1/P2PP3/5P2/1PP3PP/RNBQKBNR w KQkq - 0 3
3qnrk1/4bp1p/1p2p1pP/p2bN3/1P1P1B2/P2BQ3/5PP1/4R1K1 w - - 9 28
r4rk1/1b2ppbp/pq4pn/2pp1PB1/1p2P3/1P1P1NN1/1PP3PP/R2Q1RK1 w - - 0 13
"""
)
@staticmethod
def delete_bench_epd():
os.remove(f"{os.path.join(PATH,'bench_tmp.epd')}")
class Syzygy:
@staticmethod
def get_syzygy_path():
return os.path.abspath("syzygy")
@staticmethod
def download_syzygy():
if not os.path.isdir(os.path.join(PATH, "syzygy")):
url = "https://api.github.com/repos/niklasf/python-chess/tarball/9b9aa13f9f36d08aadfabff872882f4ab1494e95"
file = "niklasf-python-chess-9b9aa13"
with tempfile.TemporaryDirectory() as tmpdirname:
tarball_path = os.path.join(tmpdirname, f"{file}.tar.gz")
response = requests.get(url, stream=True)
with open(tarball_path, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
with tarfile.open(tarball_path, "r:gz") as tar:
tar.extractall(tmpdirname)
shutil.move(
os.path.join(tmpdirname, file), os.path.join(PATH, "syzygy")
)
class OrderedClassMembers(type):
@classmethod
def __prepare__(self, name, bases):
return collections.OrderedDict()
def __new__(self, name, bases, classdict):
classdict["__ordered__"] = [
key for key in classdict.keys() if key not in ("__module__", "__qualname__")
]
return type.__new__(self, name, bases, classdict)
class TimeoutException(Exception):
def __init__(self, message: str, timeout: int):
self.message = message
self.timeout = timeout
def timeout_decorator(timeout: float):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(func, *args, **kwargs)
try:
result = future.result(timeout=timeout)
except concurrent.futures.TimeoutError:
raise TimeoutException(
f"Function {func.__name__} timed out after {timeout} seconds",
timeout,
)
return result
return wrapper
return decorator
class MiniTestFramework:
def __init__(self):
self.passed_test_suites = 0
self.failed_test_suites = 0
self.passed_tests = 0
self.failed_tests = 0
self.stop_on_failure = True
def has_failed(self) -> bool:
return self.failed_test_suites > 0
def run(self, classes: List[type]) -> bool:
self.start_time = time.time()
for test_class in classes:
with tempfile.TemporaryDirectory() as tmpdirname:
original_cwd = os.getcwd()
os.chdir(tmpdirname)
try:
if self.__run(test_class):
self.failed_test_suites += 1
else:
self.passed_test_suites += 1
except Exception as e:
self.failed_test_suites += 1
print(f"\n{RED_COLOR}Error: {e}{RESET_COLOR}")
finally:
os.chdir(original_cwd)
self.__print_summary(round(time.time() - self.start_time, 2))
return self.has_failed()
def __run(self, test_class) -> bool:
test_instance = test_class()
test_name = test_instance.__class__.__name__
test_methods = [m for m in test_instance.__ordered__ if m.startswith("test_")]
print(f"\nTest Suite: {test_name}")
if hasattr(test_instance, "beforeAll"):
test_instance.beforeAll()
fails = 0
for method in test_methods:
fails += self.__run_test_method(test_instance, method)
if hasattr(test_instance, "afterAll"):
test_instance.afterAll()
self.failed_tests += fails
return fails > 0
def __run_test_method(self, test_instance, method: str) -> int:
print(f" Running {method}... \r", end="", flush=True)
buffer = io.StringIO()
fails = 0
try:
t0 = time.time()
with redirect_stdout(buffer):
if hasattr(test_instance, "beforeEach"):
test_instance.beforeEach()
getattr(test_instance, method)()
if hasattr(test_instance, "afterEach"):
test_instance.afterEach()
duration = time.time() - t0
self.print_success(f" {method} ({duration * 1000:.2f}ms)")
self.passed_tests += 1
except Exception as e:
if isinstance(e, TimeoutException):
self.print_failure(
f" {method} (hit execution limit of {e.timeout} seconds)"
)
if isinstance(e, AssertionError):
self.__handle_assertion_error(t0, method)
if self.stop_on_failure:
self.__print_buffer_output(buffer)
raise e
fails += 1
finally:
self.__print_buffer_output(buffer)
return fails
def __handle_assertion_error(self, start_time, method: str):
duration = time.time() - start_time
self.print_failure(f" {method} ({duration * 1000:.2f}ms)")
traceback_output = "".join(traceback.format_tb(sys.exc_info()[2]))
colored_traceback = "\n".join(
f" {CYAN_COLOR}{line}{RESET_COLOR}"
for line in traceback_output.splitlines()
)
print(colored_traceback)
def __print_buffer_output(self, buffer: io.StringIO):
output = buffer.getvalue()
if output:
indented_output = "\n".join(f" {line}" for line in output.splitlines())
print(f" {RED_COLOR}⎯⎯⎯⎯⎯OUTPUT⎯⎯⎯⎯⎯{RESET_COLOR}")
print(f"{GRAY_COLOR}{indented_output}{RESET_COLOR}")
print(f" {RED_COLOR}⎯⎯⎯⎯⎯OUTPUT⎯⎯⎯⎯⎯{RESET_COLOR}")
def __print_summary(self, duration: float):
print(f"\n{WHITE_BOLD}Test Summary{RESET_COLOR}\n")
print(
f" Test Suites: {GREEN_COLOR}{self.passed_test_suites} passed{RESET_COLOR}, {RED_COLOR}{self.failed_test_suites} failed{RESET_COLOR}, {self.passed_test_suites + self.failed_test_suites} total"
)
print(
f" Tests: {GREEN_COLOR}{self.passed_tests} passed{RESET_COLOR}, {RED_COLOR}{self.failed_tests} failed{RESET_COLOR}, {self.passed_tests + self.failed_tests} total"
)
print(f" Time: {duration}s\n")
def print_failure(self, add: str):
print(f" {RED_COLOR}{RESET_COLOR}{add}", flush=True)
def print_success(self, add: str):
print(f" {GREEN_COLOR}{RESET_COLOR}{add}", flush=True)
class Stockfish:
def __init__(
self,
prefix: List[str],
path: str,
args: List[str] = [],
cli: bool = False,
):
self.path = path
self.process = None
self.args = args
self.cli = cli
self.prefix = prefix
self.output = []
self.start()
def _check_process_alive(self):
if not self.process or self.process.poll() is not None:
print("\n".join(self.output))
raise RuntimeError("Stockfish process has terminated")
def start(self):
if self.cli:
self.process = subprocess.run(
self.prefix + [self.path] + self.args,
capture_output=True,
text=True,
)
if self.process.returncode != 0:
print(self.process.stdout)
print(self.process.stderr)
print(f"Process failed with return code {self.process.returncode}")
return
self.process = subprocess.Popen(
self.prefix + [self.path] + self.args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
bufsize=1,
)
def setoption(self, name: str, value: str):
self.send_command(f"setoption name {name} value {value}")
def send_command(self, command: str):
if not self.process:
raise RuntimeError("Stockfish process is not started")
self._check_process_alive()
self.process.stdin.write(command + "\n")
self.process.stdin.flush()
@timeout_decorator(MAX_TIMEOUT)
def equals(self, expected_output: str):
for line in self.readline():
if line == expected_output:
return
@timeout_decorator(MAX_TIMEOUT)
def expect(self, expected_output: str):
for line in self.readline():
if fnmatch.fnmatch(line, expected_output):
return
@timeout_decorator(MAX_TIMEOUT)
def contains(self, expected_output: str):
for line in self.readline():
if expected_output in line:
return
@timeout_decorator(MAX_TIMEOUT)
def starts_with(self, expected_output: str):
for line in self.readline():
if line.startswith(expected_output):
return
@timeout_decorator(MAX_TIMEOUT)
def check_output(self, callback):
if not callback:
raise ValueError("Callback function is required")
for line in self.readline():
if callback(line) == True:
return
def readline(self):
if not self.process:
raise RuntimeError("Stockfish process is not started")
while True:
self._check_process_alive()
line = self.process.stdout.readline().strip()
self.output.append(line)
yield line
def clear_output(self):
self.output = []
def get_output(self) -> List[str]:
return self.output
def quit(self):
self.send_command("quit")
def close(self):
if self.process:
self.process.stdin.close()
self.process.stdout.close()
return self.process.wait()
return 0