-Contributors to Fishtest with >10,000 CPU hours, as of Jun 29, 2021.
+Contributors to Fishtest with >10,000 CPU hours, as of 2021-12-11.
Thank you!
-Username CPU Hours Games played
------------------------------------------------------
-noobpwnftw 27649494 1834734733
-mlang 1426107 89454622
-dew 1380910 82831648
-mibere 703840 46867607
-grandphish2 692707 41737913
-tvijlbrief 669642 42371594
-JojoM 597778 35297180
-TueRens 519226 31823562
-cw 458421 30307421
-fastgm 439667 25950040
-gvreuls 436599 28177460
-crunchy 427035 27344275
-CSU_Dynasty 374765 25106278
-Fisherman 326901 21822979
-ctoks 325477 21767943
-velislav 295343 18844324
-linrock 292789 10624427
-bcross 278584 19488961
-okrout 262818 13803272
-pemo 245982 11376085
-glinscott 217799 13780820
-leszek 212346 12959025
-nordlandia 211692 13484886
-bking_US 198894 11876016
-drabel 196463 13450602
-robal 195473 12375650
-mgrabiak 187226 12016564
-Dantist 183202 10990484
-Thanar 179852 12365359
-vdv 175274 9889046
-spams 157128 10319326
-marrco 150295 9402141
-sqrt2 147963 9724586
-mhoram 141278 8901241
-CoffeeOne 137100 5024116
-vdbergh 137041 8926915
-malala 136182 8002293
-xoto 133702 9156676
-davar 122092 7960001
-dsmith 122059 7570238
-Data 113305 8220352
-BrunoBanani 112960 7436849
-MaZePallas 102823 6633619
-sterni1971 100532 5880772
-ElbertoOne 99028 7023771
-brabos 92118 6186135
-oz 92100 6486640
-psk 89957 5984901
-amicic 89156 5392305
-sunu 88851 6028873
-Vizvezdenec 83761 5344740
-0x3C33 82614 5271253
-BRAVONE 81239 5054681
-racerschmacer 80899 5759262
-cuistot 80300 4606144
-nssy 76497 5259388
-teddybaer 75125 5407666
-Pking_cda 73776 5293873
-jromang 72192 5057715
-solarlight 70517 5028306
-dv8silencer 70287 3883992
-Bobo1239 68515 4652287
-manap 66273 4121774
-skiminki 65088 4023328
-tinker 64333 4268790
-sschnee 60767 3500800
-qurashee 57344 3168264
-robnjr 57262 4053117
-Freja 56938 3733019
-ttruscott 56010 3680085
-rkl 55132 4164467
-renouve 53811 3501516
-finfish 51360 3370515
-eva42 51272 3599691
-rap 49985 3219146
-pb00067 49727 3298270
-ronaldjerum 47654 3240695
-bigpen0r 47653 3335327
-eastorwest 47585 3221629
-biffhero 46564 3111352
-VoyagerOne 45476 3452465
-yurikvelo 44834 3034550
-speedycpu 43842 3003273
-jbwiebe 43305 2805433
-Spprtr 42279 2680153
-DesolatedDodo 42007 2447516
-Antihistamine 41788 2761312
-mhunt 41735 2691355
-homyur 39893 2850481
-gri 39871 2515779
-Fifis 38776 2529121
-oryx 38724 2966648
-SC 37290 2731014
-csnodgrass 36207 2688994
-jmdana 36157 2210661
-strelock 34716 2074055
-rpngn 33951 2057395
-Garf 33922 2751802
-EthanOConnor 33370 2090311
-slakovv 32915 2021889
-manapbk 30987 1810399
-Prcuvu 30377 2170122
-anst 30301 2190091
-jkiiski 30136 1904470
-hyperbolic.tom 29840 2017394
-Pyafue 29650 1902349
-Wolfgang 29260 1658936
-zeryl 28156 1579911
-OuaisBla 27636 1578800
-DMBK 27051 1999456
-chriswk 26902 1868317
-achambord 26582 1767323
-Patrick_G 26276 1801617
-yorkman 26193 1992080
-SFTUser 25182 1675689
-nabildanial 24942 1519409
-Sharaf_DG 24765 1786697
-ncfish1 24411 1520927
-rodneyc 24227 1409514
-agg177 23890 1395014
-JanErik 23408 1703875
-Isidor 23388 1680691
-Norabor 23164 1591830
-cisco2015 22897 1762669
-Zirie 22542 1472937
-team-oh 22272 1636708
-MazeOfGalious 21978 1629593
-sg4032 21947 1643265
-ianh2105 21725 1632562
-xor12 21628 1680365
-dex 21612 1467203
-nesoneg 21494 1463031
-sphinx 21211 1384728
-jjoshua2 21001 1423089
-horst.prack 20878 1465656
-Ente 20865 1477066
-0xB00B1ES 20590 1208666
-j3corre 20405 941444
-Adrian.Schmidt123 20316 1281436
-wei 19973 1745989
-MaxKlaxxMiner 19850 1009176
-rstoesser 19569 1293588
-gopeto 19491 1174952
-eudhan 19274 1283717
-jundery 18445 1115855
-megaman7de 18377 1067540
-iisiraider 18247 1101015
-ville 17883 1384026
-chris 17698 1487385
-purplefishies 17595 1092533
-dju 17353 978595
-DragonLord 17014 1162790
-IgorLeMasson 16064 1147232
-ako027ako 15671 1173203
-chuckstablers 15289 891576
-Nikolay.IT 15154 1068349
-Andrew Grant 15114 895539
-OssumOpossum 14857 1007129
-Karby 14808 867120
-enedene 14476 905279
-bpfliegel 14298 884523
-mpx86 14019 759568
-jpulman 13982 870599
-crocogoat 13803 1117422
-joster 13794 950160
-Nesa92 13786 1114691
-Hjax 13535 915487
-jsys14 13459 785000
-Dark_wizzie 13422 1007152
-mabichito 12903 749391
-thijsk 12886 722107
-AdrianSA 12860 804972
-Flopzee 12698 894821
-fatmurphy 12547 853210
-Rudolphous 12520 832340
-scuzzi 12511 845761
-SapphireBrand 12416 969604
-modolief 12386 896470
-Machariel 12335 810784
-pgontarz 12151 848794
-stocky 11954 699440
-mschmidt 11941 803401
-Maxim 11543 836024
-infinity 11470 727027
-torbjo 11395 729145
-Thomas A. Anderson 11372 732094
-savage84 11358 670860
-d64 11263 789184
-MooTheCow 11237 720174
-snicolet 11106 869170
-ali-al-zhrani 11086 767926
-AndreasKrug 10875 887457
-pirt 10806 836519
-basepi 10637 744851
-michaelrpg 10508 739039
-dzjp 10343 732529
-aga 10302 622975
-ols 10259 570669
-lbraesch 10252 647825
-FormazChar 10059 757283
+Username CPU Hours Games played
+------------------------------------------------------------------
+noobpwnftw 29832955 2061725095
+mlang 2345848 162775694
+dew 1559902 93935940
+technologov 1154365 43136020
+grandphish2 988545 60725563
+tvijlbrief 795993 51894442
+TueRens 716909 45503672
+mibere 703840 46867607
+JojoM 675708 41046762
+okrout 648513 49953162
+linrock 563226 16184599
+pemo 520578 26816487
+gvreuls 501232 32662374
+cw 495103 33171295
+fastgm 476917 28660004
+crunchy 427035 27344275
+CSU_Dynasty 407300 27580858
+ctoks 386452 25757397
+oz 343309 25441096
+Fisherman 327231 21829379
+velislav 320318 20642978
+bcross 319459 22485737
+leszek 277442 17495865
+Dantist 229980 14568674
+mgrabiak 225684 14774260
+glinscott 217799 13780820
+nordlandia 211692 13484886
+robal 209847 13427680
+drabel 200340 13727458
+bking_US 198894 11876016
+Thanar 179852 12365359
+vdv 175274 9889046
+mhoram 166293 10796647
+spams 157128 10319326
+marrco 150300 9402229
+sqrt2 147963 9724586
+vdbergh 137186 8938965
+CoffeeOne 137100 5024116
+malala 136182 8002293
+xoto 133759 9159372
+davar 122092 7960001
+dsmith 122059 7570238
+amicic 119659 7937885
+Data 113305 8220352
+BrunoBanani 112960 7436849
+rpngn 109031 7392547
+CypressChess 108321 7759588
+MaZePallas 102823 6633619
+sterni1971 100532 5880772
+sunu 100167 7040199
+ElbertoOne 99028 7023771
+skiminki 98121 6478170
+brabos 92118 6186135
+psk 89957 5984901
+cuistot 88420 5225234
+DesolatedDodo 88356 5779482
+racerschmacer 85711 6119610
+Vizvezdenec 83761 5344740
+0x3C33 82614 5271253
+BRAVONE 81239 5054681
+nssy 76497 5259388
+teddybaer 75125 5407666
+Pking_cda 73776 5293873
+jromang 72192 5057715
+solarlight 70517 5028306
+dv8silencer 70287 3883992
+Bobo1239 68515 4652287
+manap 66273 4121774
+sschnee 64563 3633680
+tinker 64333 4268790
+zeryl 63290 4179159
+qurashee 61208 3429862
+yurikvelo 60387 4169900
+robnjr 57262 4053117
+Freja 56938 3733019
+ttruscott 56010 3680085
+rkl 55132 4164467
+renouve 53811 3501516
+finfish 51360 3370515
+eva42 51272 3599691
+Wolfgang 51248 3218932
+eastorwest 50311 3409935
+rap 49985 3219146
+pb00067 49727 3298270
+bigpen0r 47667 3336927
+ronaldjerum 47654 3240695
+MaxKlaxxMiner 47584 2972142
+biffhero 46564 3111352
+Spprtr 45877 2995437
+Fifis 45843 3088497
+VoyagerOne 45476 3452465
+speedycpu 43842 3003273
+jbwiebe 43305 2805433
+Antihistamine 41788 2761312
+mhunt 41735 2691355
+megaman7de 40060 2625050
+homyur 39893 2850481
+gri 39871 2515779
+oryx 38860 2976488
+SC 37299 2731694
+csnodgrass 36207 2688994
+jmdana 36157 2210661
+Garf 36113 2897580
+strelock 34716 2074055
+EthanOConnor 33370 2090311
+slakovv 32915 2021889
+manapbk 30987 1810399
+DMBK 30675 2383552
+Prcuvu 30377 2170122
+anst 30301 2190091
+jkiiski 30136 1904470
+hyperbolic.tom 29840 2017394
+chuckstablers 29659 2093438
+Pyafue 29650 1902349
+tolkki963 28171 1716386
+OuaisBla 27636 1578800
+armo9494 27224 2221042
+chriswk 26902 1868317
+achambord 26582 1767323
+gopeto 26355 1717722
+Patrick_G 26276 1801617
+yorkman 26193 1992080
+SFTUser 25182 1675689
+nabildanial 24942 1519409
+Sharaf_DG 24765 1786697
+ncfish1 24411 1520927
+rodneyc 24275 1410450
+agg177 23890 1395014
+JanErik 23408 1703875
+Isidor 23388 1680691
+Norabor 23339 1602636
+cisco2015 22897 1762669
+Zirie 22542 1472937
+Ente 22486 1606268
+team-oh 22272 1636708
+MazeOfGalious 21978 1629593
+sg4032 21947 1643265
+ianh2105 21725 1632562
+xor12 21628 1680365
+dex 21612 1467203
+nesoneg 21494 1463031
+sphinx 21211 1384728
+jjoshua2 21001 1423089
+horst.prack 20878 1465656
+0xB00B1ES 20590 1208666
+j3corre 20405 941444
+Adrian.Schmidt123 20316 1281436
+wei 19973 1745989
+rstoesser 19569 1293588
+eudhan 19274 1283717
+vulcan 18871 1729392
+user213718 18590 1271128
+jundery 18445 1115855
+iisiraider 18247 1101015
+ville 17883 1384026
+chris 17698 1487385
+purplefishies 17595 1092533
+dju 17353 978595
+DragonLord 17014 1162790
+IgorLeMasson 16064 1147232
+ako027ako 15671 1173203
+Nikolay.IT 15154 1068349
+Andrew Grant 15114 895539
+OssumOpossum 14857 1007129
+Karby 14808 867120
+enedene 14476 905279
+jsys14 14318 843704
+bpfliegel 14298 884523
+mpx86 14019 759568
+jpulman 13982 870599
+kdave 13933 1045550
+crocogoat 13803 1117422
+joster 13794 950160
+Nesa92 13786 1114691
+mbeier 13650 1044928
+AndreasKrug 13624 1090613
+Hjax 13535 915487
+Dark_wizzie 13422 1007152
+Ulysses 13392 1021264
+Calis007 13267 873236
+Rudolphous 13244 883140
+spcc 13085 917006
+Machariel 13010 863104
+mabichito 12903 749391
+thijsk 12886 722107
+AdrianSA 12860 804972
+Flopzee 12698 894821
+fatmurphy 12547 853210
+scuzzi 12511 845761
+SapphireBrand 12416 969604
+modolief 12386 896470
+fishtester 12320 873882
+Farseer 12249 694108
+pgontarz 12151 848794
+stocky 11954 699440
+mschmidt 11941 803401
+Maxim 11543 836024
+infinity 11470 727027
+aga 11409 695071
+torbjo 11395 729145
+pirt 11392 886291
+Thomas A. Anderson 11372 732094
+savage84 11358 670860
+FormazChar 11304 847663
+d64 11263 789184
+dbernier 11258 805102
+MooTheCow 11237 720174
+snicolet 11106 869170
+ali-al-zhrani 11098 768494
+basepi 10637 744851
+Cubox 10621 826448
+michaelrpg 10509 739239
+OIVAS7572 10420 995586
+dzjp 10343 732529
+infinigon 10319 776158
+Garruk 10314 702629
+ols 10259 570669
+lbraesch 10252 647825
# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3
# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1
# avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2
+# avxvnni = yes/no --- -mavxvnni --- Use Intel Vector Neural Network Instructions AVX
# avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256
# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
# explicitly check for the list of supported architectures (as listed with make help),
# the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true`
ifeq ($(ARCH), $(filter $(ARCH), \
- x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-bmi2 x86-64-avx2 \
- x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
+ 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 apple-silicon general-64 general-32))
SUPPORTED_ARCH=true
ssse3 = no
sse41 = no
avx2 = no
+avxvnni = no
avx512 = no
vnni256 = no
vnni512 = no
neon = no
+arm_version = 0
STRIP = strip
### 2.2 Architecture specific
avx2 = yes
endif
+ifeq ($(findstring -avxvnni,$(ARCH)),-avxvnni)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ avxvnni = yes
+ pext = yes
+endif
+
ifeq ($(findstring -bmi2,$(ARCH)),-bmi2)
popcnt = yes
sse = yes
arch = armv7
prefetch = yes
bits = 32
+ arm_version = 7
endif
ifeq ($(ARCH),armv7-neon)
popcnt = yes
neon = yes
bits = 32
+ arm_version = 7
endif
ifeq ($(ARCH),armv8)
prefetch = yes
popcnt = yes
neon = yes
+ arm_version = 8
endif
ifeq ($(ARCH),apple-silicon)
prefetch = yes
popcnt = yes
neon = yes
+ arm_version = 8
endif
ifeq ($(ARCH),ppc-32)
else
profile_make = gcc-profile-make
profile_use = gcc-profile-use
+ ifeq ($(KERNEL),Darwin)
+ EXTRAPROFILEFLAGS = -fvisibility=hidden
+ endif
endif
### Travis CI script uses COMPILER to overwrite CXX
endif
endif
- ifeq ($(comp),$(filter $(comp),gcc clang icc))
- ifeq ($(KERNEL),Darwin)
- CXXFLAGS += -mdynamic-no-pic
- endif
- endif
+ ifeq ($(KERNEL),Darwin)
+ ifeq ($(comp),$(filter $(comp),clang icc))
+ CXXFLAGS += -mdynamic-no-pic
+ endif
+
+ ifeq ($(comp),gcc)
+ ifneq ($(arch),arm64)
+ CXXFLAGS += -mdynamic-no-pic
+ endif
+ endif
+ endif
ifeq ($(comp),clang)
CXXFLAGS += -fexperimental-new-pass-manager
endif
endif
+ifeq ($(avxvnni),yes)
+ CXXFLAGS += -DUSE_VNNI -DUSE_AVXVNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavxvnni
+ endif
+endif
+
ifeq ($(avx512),yes)
CXXFLAGS += -DUSE_AVX512
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
endif
ifeq ($(neon),yes)
- CXXFLAGS += -DUSE_NEON
+ CXXFLAGS += -DUSE_NEON=$(arm_version)
ifeq ($(KERNEL),Linux)
ifneq ($(COMP),ndk)
ifneq ($(arch),armv8)
@echo "x86-64-vnni512 > x86 64-bit with vnni support 512bit wide"
@echo "x86-64-vnni256 > x86 64-bit with vnni support 256bit wide"
@echo "x86-64-avx512 > x86 64-bit with avx512 support"
+ @echo "x86-64-avxvnni > x86 64-bit with avxvnni 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 "ssse3: '$(ssse3)'"
@echo "sse41: '$(sse41)'"
@echo "avx2: '$(avx2)'"
+ @echo "avxvnni: '$(avxvnni)'"
@echo "avx512: '$(avx512)'"
@echo "vnni256: '$(vnni256)'"
@echo "vnni512: '$(vnni512)'"
@echo "neon: '$(neon)'"
+ @echo "arm_version: '$(arm_version)'"
@echo ""
@echo "Flags:"
@echo "CXX: $(CXX)"
@mkdir -p profdir
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-generate=profdir' \
+ EXTRACXXFLAGS+=$(EXTRAPROFILEFLAGS) \
EXTRALDFLAGS='-lgcov' \
all
gcc-profile-use:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-use=profdir -fno-peel-loops -fno-tracer' \
+ EXTRACXXFLAGS+=$(EXTRAPROFILEFLAGS) \
EXTRALDFLAGS='-lgcov' \
all
Value v;
- // Deciding between classical and NNUE eval: for high PSQ imbalance we use classical,
+ // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical,
// but we switch to NNUE during long shuffling or with high material on the board.
+ bool classical = false;
+
if ( !useNNUE
|| abs(eg_value(pos.psq_score())) * 5 > (850 + pos.non_pawn_material() / 64) * (5 + pos.rule50_count()))
+ {
v = Evaluation<NO_TRACE>(pos).value(); // classical
- else
+ classical = abs(v) >= 300;
+ }
+
+ // If result of a classical evaluation is much lower than threshold fall back to NNUE
+ if (!classical && useNNUE)
{
- int scale = 1049
- + 8 * pos.count<PAWN>()
+ int scale = 1136
+ 20 * pos.non_pawn_material() / 1024;
Value nnue = NNUE::evaluate(pos, true); // NNUE
// 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 EvalFileDefaultName "nn-4f56ecfca5b7.nnue"
+ #define EvalFileDefaultName "nn-ac07bd334b62.nnue"
namespace NNUE {
if (!fun1)
return -1;
- // First call to GetLogicalProcessorInformationEx() to get returnLength.
+ // First call to GetLogicalProcessorInformationEx() to get returnLength.
// We expect the call to fail due to null buffer.
if (fun1(RelationAll, nullptr, &returnLength))
return -1;
if (!fun2 || !fun3)
return;
- if (!fun4 || !fun5)
+ if (!fun4 || !fun5)
{
GROUP_AFFINITY affinity;
if (fun2(node, &affinity)) // GetNumaNodeProcessorMaskEx
fun3(GetCurrentThread(), &affinity, nullptr); // SetThreadGroupAffinity
- }
- else
+ }
+ 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.
/// sigmoid(t, x0, y0, C, P, Q) implements a sigmoid-like function using only integers,
/// with the following properties:
-///
+///
/// - sigmoid is centered in (x0, y0)
/// - sigmoid has amplitude [-P/Q , P/Q] instead of [-1 , +1]
/// - limit is (y0 - P/Q) when t tends to -infinity
/// ordering is at the current node.
/// MovePicker constructor for the main search
-MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const LowPlyHistory* lp,
- const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, const Move* killers, int pl)
- : pos(p), mainHistory(mh), lowPlyHistory(lp), captureHistory(cph), continuationHistory(ch),
- ttMove(ttm), refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d), ply(pl) {
-
+MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
+ const CapturePieceToHistory* cph,
+ const PieceToHistory** ch,
+ Move cm,
+ const Move* killers)
+ : pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch),
+ ttMove(ttm), refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d)
+{
assert(d > 0);
stage = (pos.checkers() ? EVASION_TT : MAIN_TT) +
/// MovePicker constructor for quiescence search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
- const CapturePieceToHistory* cph, const PieceToHistory** ch, Square rs)
- : pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d) {
-
+ const CapturePieceToHistory* cph,
+ const PieceToHistory** ch,
+ Square rs)
+ : pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d)
+{
assert(d <= 0);
stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) +
/// MovePicker constructor for ProbCut: we generate captures with SEE greater
/// than or equal to the given threshold.
MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph)
- : pos(p), captureHistory(cph), ttMove(ttm), threshold(th) {
-
+ : pos(p), captureHistory(cph), ttMove(ttm), threshold(th)
+{
assert(!pos.checkers());
stage = PROBCUT_TT + !(ttm && pos.capture(ttm)
+ 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
- + (ply < MAX_LPH ? 6 * (*lowPlyHistory)[ply][from_to(m)] : 0);
+ + (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)];
else // Type == EVASIONS
{
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 14365, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
-/// At higher depths LowPlyHistory records successful quiet moves near the root
-/// and quiet moves which are/were in the PV (ttPv). LowPlyHistory is populated during
-/// iterative deepening and at each new search the data is shifted down by 2 plies
-constexpr int MAX_LPH = 4;
-typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB) * int(SQUARE_NB)> LowPlyHistory;
-
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
/// move, see www.chessprogramming.org/Countermove_Heuristic
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
public:
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
- MovePicker(const Position&, Move, Value, const CapturePieceToHistory*);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
- Square);
+ Move,
+ const Move*);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
- const LowPlyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
- Move,
- const Move*,
- int);
+ Square);
+ MovePicker(const Position&, Move, Value, const CapturePieceToHistory*);
Move next_move(bool skipQuiets = false);
private:
const Position& pos;
const ButterflyHistory* mainHistory;
- const LowPlyHistory* lowPlyHistory;
const CapturePieceToHistory* captureHistory;
const PieceToHistory** continuationHistory;
Move ttMove;
Square recaptureSquare;
Value threshold;
Depth depth;
- int ply;
ExtMove moves[MAX_MOVES];
};
const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto positional = network[bucket]->propagate(transformedFeatures, buffer)[0];
- // Give more value to positional evaluation when material is balanced
- if ( adjusted
- && abs(pos.non_pawn_material(WHITE) - pos.non_pawn_material(BLACK)) <= RookValueMg - BishopValueMg)
- return static_cast<Value>(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale);
+ // Give more value to positional evaluation when adjusted flag is set
+ if (adjusted)
+ return static_cast<Value>(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale);
else
- return static_cast<Value>((psqt + positional) / OutputScale);
+ return static_cast<Value>((psqt + positional) / OutputScale);
}
struct NnueEvalTrace {
const auto inputVector = reinterpret_cast<const __m64*>(input);
# elif defined(USE_NEON)
- static_assert(PaddedInputDimensions % 16 == 0);
- constexpr IndexType NumChunks = PaddedInputDimensions / 16;
+ constexpr IndexType NumChunks = (InputDimensions + 15) / 16;
const auto inputVector = reinterpret_cast<const int8x8_t*>(input);
# endif
#elif defined (USE_SSSE3)
static constexpr const IndexType InputSimdWidth = 16;
static constexpr const IndexType MaxNumOutputRegs = 8;
+#elif defined (USE_NEON)
+ static constexpr const IndexType InputSimdWidth = 8;
+ static constexpr const IndexType MaxNumOutputRegs = 8;
#else
// The fallback implementation will not have permuted weights.
// We define these to avoid a lot of ifdefs later.
OutputType* output = reinterpret_cast<OutputType*>(buffer);
#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
+ using acc_vec_t = __m512i;
+ using bias_vec_t = __m128i;
+ using weight_vec_t = __m512i;
+ using in_vec_t = __m512i;
+ #define vec_zero _mm512_setzero_si512()
#define vec_add_dpbusd_32x2 Simd::m512_add_dpbusd_epi32x2
#define vec_hadd Simd::m512_hadd
#define vec_haddx4 Simd::m512_haddx4
#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
+ using acc_vec_t = __m256i;
+ using bias_vec_t = __m128i;
+ using weight_vec_t = __m256i;
+ using in_vec_t = __m256i;
+ #define vec_zero _mm256_setzero_si256()
#define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2
#define vec_hadd Simd::m256_hadd
#define vec_haddx4 Simd::m256_haddx4
#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
+ using acc_vec_t = __m128i;
+ using bias_vec_t = __m128i;
+ using weight_vec_t = __m128i;
+ using in_vec_t = __m128i;
+ #define vec_zero _mm_setzero_si128()
#define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2
#define vec_hadd Simd::m128_hadd
#define vec_haddx4 Simd::m128_haddx4
+#elif defined (USE_NEON)
+ using acc_vec_t = int32x4_t;
+ using bias_vec_t = int32x4_t;
+ using weight_vec_t = int8x8_t;
+ using in_vec_t = int8x8_t;
+ #define vec_zero {0}
+ #define vec_add_dpbusd_32x2 Simd::neon_m128_add_dpbusd_epi32x2
+ #define vec_hadd Simd::neon_m128_hadd
+ #define vec_haddx4 Simd::neon_m128_haddx4
#endif
-#if defined (USE_SSSE3)
- const vec_t* invec = reinterpret_cast<const vec_t*>(input);
+#if defined (USE_SSSE3) || defined (USE_NEON)
+ const in_vec_t* invec = reinterpret_cast<const in_vec_t*>(input);
// Perform accumulation to registers for each big block
for (IndexType bigBlock = 0; bigBlock < NumBigBlocks; ++bigBlock)
{
- vec_t acc[NumOutputRegs] = { vec_setzero() };
+ acc_vec_t acc[NumOutputRegs] = { vec_zero };
// Each big block has NumOutputRegs small blocks in each "row", one per register.
// We process two small blocks at a time to save on one addition without VNNI.
for (IndexType smallBlock = 0; smallBlock < NumSmallBlocksPerOutput; smallBlock += 2)
{
- const vec_t* weightvec =
- reinterpret_cast<const vec_t*>(
+ const weight_vec_t* weightvec =
+ reinterpret_cast<const weight_vec_t*>(
weights
+ bigBlock * BigBlockSize
+ smallBlock * SmallBlockSize * NumOutputRegs);
- const vec_t in0 = invec[smallBlock + 0];
- const vec_t in1 = invec[smallBlock + 1];
+ const in_vec_t in0 = invec[smallBlock + 0];
+ const in_vec_t in1 = invec[smallBlock + 1];
for (IndexType k = 0; k < NumOutputRegs; ++k)
vec_add_dpbusd_32x2(acc[k], in0, weightvec[k], in1, weightvec[k + NumOutputRegs]);
// Horizontally add all accumulators.
if constexpr (NumOutputRegs % 4 == 0)
{
- __m128i* outputvec = reinterpret_cast<__m128i*>(output);
- const __m128i* biasvec = reinterpret_cast<const __m128i*>(biases);
+ bias_vec_t* outputvec = reinterpret_cast<bias_vec_t*>(output);
+ const bias_vec_t* biasvec = reinterpret_cast<const bias_vec_t*>(biases);
for (IndexType k = 0; k < NumOutputRegs; k += 4)
{
}
}
-# undef vec_setzero
-# undef vec_set_32
-# undef vec_add_dpbusd_32
+# undef vec_zero
# undef vec_add_dpbusd_32x2
# undef vec_hadd
# undef vec_haddx4
{
const IndexType offset = HalfDimensions * p;
const auto out = reinterpret_cast<int8x8_t*>(&output[offset]);
- for (IndexType j = 0; j < NumChunks; ++j)
+
+ constexpr IndexType UnrollFactor = 16;
+ static_assert(UnrollFactor % UnrollFactor == 0);
+ for (IndexType j = 0; j < NumChunks; j += UnrollFactor)
{
- int16x8_t sum = reinterpret_cast<const int16x8_t*>(accumulation[perspectives[p]])[j];
- out[j] = vmax_s8(vqmovn_s16(sum), Zero);
+ int16x8_t sums[UnrollFactor];
+ for (IndexType i = 0; i < UnrollFactor; ++i)
+ sums[i] = reinterpret_cast<const int16x8_t*>(accumulation[perspectives[p]])[j+i];
+
+ for (IndexType i = 0; i < UnrollFactor; ++i)
+ out[j+i] = vmax_s8(vqmovn_s16(sums[i]), Zero);
}
}
return psqt;
// Reductions lookup table, initialized at startup
int Reductions[MAX_MOVES]; // [depth or moveNumber]
- Depth reduction(bool i, Depth d, int mn, bool rangeReduction) {
+ Depth reduction(bool i, Depth d, int mn, bool rangeReduction, Value delta, Value rootDelta) {
int r = Reductions[d] * Reductions[mn];
- return (r + 534) / 1024 + (!i && r > 904) + rangeReduction;
+ return (r + 1358 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 904) + rangeReduction;
}
constexpr int futility_move_count(bool improving, Depth depth) {
Value value_from_tt(Value v, int ply, int r50c);
void update_pv(Move* pv, Move move, Move* childPv);
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
- void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus, int depth);
+ void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus);
void update_all_stats(const Position& pos, Stack* ss, Move bestMove, Value bestValue, Value beta, Square prevSq,
Move* quietsSearched, int quietCount, Move* capturesSearched, int captureCount, Depth depth);
bestThread = Threads.get_best_thread();
bestPreviousScore = bestThread->rootMoves[0].score;
+ bestPreviousAverageScore = bestThread->rootMoves[0].averageScore;
// Send again PV info if we have a new best thread
if (bestThread != this)
mainThread->iterValue[i] = mainThread->bestPreviousScore;
}
- std::copy(&lowPlyHistory[2][0], &lowPlyHistory.back().back() + 1, &lowPlyHistory[0][0]);
- std::fill(&lowPlyHistory[MAX_LPH - 2][0], &lowPlyHistory.back().back() + 1, 0);
-
size_t multiPV = size_t(Options["MultiPV"]);
Skill skill(Options["Skill Level"], Options["UCI_LimitStrength"] ? int(Options["UCI_Elo"]) : 0);
&& !Threads.stop
&& !mainThread->stopOnPonderhit)
{
- double fallingEval = (318 + 6 * (mainThread->bestPreviousScore - bestValue)
- + 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 825.0;
+ double fallingEval = (142 + 12 * (mainThread->bestPreviousAverageScore - bestValue)
+ + 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 825.0;
fallingEval = std::clamp(fallingEval, 0.5, 1.5);
// If the bestMove is stable over several iterations, reduce time accordingly
Depth extension, newDepth;
Value bestValue, value, ttValue, eval, maxValue, probCutBeta;
bool givesCheck, improving, didLMR, priorCapture;
- bool captureOrPromotion, doFullDepthSearch, moveCountPruning,
- ttCapture, singularQuietLMR;
+ bool captureOrPromotion, doFullDepthSearch, moveCountPruning, ttCapture;
Piece movedPiece;
int moveCount, captureCount, quietCount, bestMoveCount, improvement;
if (!excludedMove)
ss->ttPv = PvNode || (ss->ttHit && tte->is_pv());
- // Update low ply history for previous move if we are near root and position is or has been in PV
- if ( ss->ttPv
- && depth > 12
- && ss->ply - 1 < MAX_LPH
- && !priorCapture
- && is_ok((ss-1)->currentMove))
- thisThread->lowPlyHistory[ss->ply - 1][from_to((ss-1)->currentMove)] << stat_bonus(depth - 5);
-
// At non-PV nodes we check for an early TT cutoff
if ( !PvNode
&& ss->ttHit
&& (ttValue >= beta ? (tte->bound() & BOUND_LOWER)
: (tte->bound() & BOUND_UPPER)))
{
- // If ttMove is quiet, update move sorting heuristics on TT hit
+ // If ttMove is quiet, update move sorting heuristics on TT hit (~1 Elo)
if (ttMove)
{
if (ttValue >= beta)
{
- // Bonus for a quiet ttMove that fails high
+ // Bonus for a quiet ttMove that fails high (~3 Elo)
if (!ttCapture)
- update_quiet_stats(pos, ss, ttMove, stat_bonus(depth), depth);
+ update_quiet_stats(pos, ss, ttMove, stat_bonus(depth));
- // Extra penalty for early quiet moves of the previous ply
+ // Extra penalty for early quiet moves of the previous ply (~0 Elo)
if ((ss-1)->moveCount <= 2 && !priorCapture)
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + 1));
}
- // Penalty for a quiet ttMove that fails low
+ // Penalty for a quiet ttMove that fails low (~1 Elo)
else if (!ttCapture)
{
int penalty = -stat_bonus(depth);
if (eval == VALUE_DRAW)
eval = value_draw(thisThread);
- // Can ttValue be used as a better position evaluation?
+ // ttValue can be used as a better position evaluation (~4 Elo)
if ( ttValue != VALUE_NONE
&& (tte->bound() & (ttValue > eval ? BOUND_LOWER : BOUND_UPPER)))
eval = ttValue;
tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
}
- // Use static evaluation difference to improve quiet move ordering
+ // Use static evaluation difference to improve quiet move ordering (~3 Elo)
if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture)
{
int bonus = std::clamp(-16 * int((ss-1)->staticEval + ss->staticEval), -2000, 2000);
improving = improvement > 0;
- // Step 7. Futility pruning: child node (~50 Elo).
+ // Step 7. Futility pruning: child node (~25 Elo).
// The depth condition is important for mate finding.
if ( !ss->ttPv
&& depth < 9
&& eval < 15000) // 50% larger than VALUE_KNOWN_WIN, but smaller than TB wins.
return eval;
- // Step 8. Null move search with verification search (~40 Elo)
+ // Step 8. Null move search with verification search (~22 Elo)
if ( !PvNode
&& (ss-1)->currentMove != MOVE_NULL
&& (ss-1)->statScore < 23767
ss->ttPv = ttPv;
}
- // Step 10. If the position is not in TT, decrease depth by 2 or 1 depending on node type
+ // Step 10. If the position is not in TT, decrease depth by 2 or 1 depending on node type (~3 Elo)
if ( PvNode
&& depth >= 6
&& !ttMove)
int rangeReduction = 0;
- // Step 11. A small Probcut idea, when we are in check
+ // Step 11. A small Probcut idea, when we are in check (~0 Elo)
probCutBeta = beta + 409;
if ( ss->inCheck
&& !PvNode
Move countermove = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq];
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
- &thisThread->lowPlyHistory,
&captureHistory,
contHist,
countermove,
- ss->killers,
- ss->ply);
+ ss->killers);
value = bestValue;
- singularQuietLMR = moveCountPruning = false;
+ moveCountPruning = false;
// Indicate PvNodes that will probably fail low if the node was searched
// at a depth equal or greater than the current depth, and the result of this search was a fail low.
// Calculate new depth for this move
newDepth = depth - 1;
- // Step 13. Pruning at shallow depth (~200 Elo). Depth conditions are important for mate finding.
+ Value delta = beta - alpha;
+
+ // Step 13. Pruning at shallow depth (~98 Elo). Depth conditions are important for mate finding.
if ( !rootNode
&& pos.non_pawn_material(us)
&& bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
{
- // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold
+ // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold (~7 Elo)
moveCountPruning = moveCount >= futility_move_count(improving, depth);
// Reduced depth of the next LMR search
- int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount, rangeReduction > 2), 0);
+ int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount, rangeReduction > 2, delta, thisThread->rootDelta), 0);
if ( captureOrPromotion
|| givesCheck)
{
- // Capture history based pruning when the move doesn't give check
- if ( !givesCheck
- && lmrDepth < 1
- && captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] < 0)
+ // Futility pruning for captures (~0 Elo)
+ if ( !pos.empty(to_sq(move))
+ && !givesCheck
+ && !PvNode
+ && lmrDepth < 6
+ && !ss->inCheck
+ && ss->staticEval + 342 + 238 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))]
+ + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 8 < alpha)
continue;
- // SEE based pruning
- if (!pos.see_ge(move, Value(-218) * depth)) // (~25 Elo)
+ // SEE based pruning (~9 Elo)
+ if (!pos.see_ge(move, Value(-218) * depth))
continue;
}
else
+ (*contHist[1])[movedPiece][to_sq(move)]
+ (*contHist[3])[movedPiece][to_sq(move)];
- // Continuation history based pruning (~20 Elo)
+ // Continuation history based pruning (~2 Elo)
if ( lmrDepth < 5
&& history < -3000 * depth + 3000)
continue;
history += thisThread->mainHistory[us][from_to(move)];
- // Futility pruning: parent node (~5 Elo)
+ // Futility pruning: parent node (~9 Elo)
if ( !ss->inCheck
&& lmrDepth < 8
&& ss->staticEval + 142 + 139 * lmrDepth + history / 64 <= alpha)
continue;
- // Prune moves with negative SEE (~20 Elo)
+ // Prune moves with negative SEE (~3 Elo)
if (!pos.see_ge(move, Value(-21 * lmrDepth * lmrDepth - 21 * lmrDepth)))
continue;
}
}
- // Step 14. Extensions (~75 Elo)
+ // Step 14. Extensions (~66 Elo)
- // Singular extension search (~70 Elo). If all moves but one fail low on a
+ // Singular extension search (~58 Elo). If all moves but one fail low on a
// search of (alpha-s, beta-s), and just one fails high on (alpha, beta),
// then that move is singular and should be extended. To verify this we do
// a reduced search on all the other moves but the ttMove and if the
// result is lower than ttValue minus a margin, then we will extend the ttMove.
if ( !rootNode
- && depth >= 7
+ && depth >= 6 + 2 * (PvNode && tte->is_pv())
&& move == ttMove
&& !excludedMove // Avoid recursive singular search
/* && ttValue != VALUE_NONE Already implicit in the next condition */
if (value < singularBeta)
{
extension = 1;
- singularQuietLMR = !ttCapture;
// Avoid search explosion by limiting the number of double extensions
if ( !PvNode
extension = -2;
}
- // Capture extensions for PvNodes and cutNodes
- else if ( (PvNode || cutNode)
- && captureOrPromotion
- && moveCount != 1)
- extension = 1;
-
- // Check extensions
+ // Check extensions (~1 Elo)
else if ( givesCheck
&& depth > 6
&& abs(ss->staticEval) > 100)
extension = 1;
- // Quiet ttMove extensions
+ // Quiet ttMove extensions (~0 Elo)
else if ( PvNode
&& move == ttMove
&& move == ss->killers[0]
// Step 15. Make the move
pos.do_move(move, st, givesCheck);
- // Step 16. Late moves reduction / extension (LMR, ~200 Elo)
+ bool doDeeperSearch = false;
+
+ // Step 16. Late moves reduction / extension (LMR, ~98 Elo)
// We use various heuristics for the sons of a node after the first son has
// been searched. In general we would like to reduce them, but there are many
// cases where we extend a son if it has good chances to be "interesting".
|| !captureOrPromotion
|| (cutNode && (ss-1)->moveCount > 1)))
{
- Depth r = reduction(improving, depth, moveCount, rangeReduction > 2);
+ Depth r = reduction(improving, depth, moveCount, rangeReduction > 2, delta, thisThread->rootDelta);
// Decrease reduction at some PvNodes (~2 Elo)
if ( PvNode
- && bestMoveCount <= 3
- && beta - alpha >= thisThread->rootDelta / 4)
+ && bestMoveCount <= 3)
r--;
// Decrease reduction if position is or has been on the PV
&& !likelyFailLow)
r -= 2;
- // Increase reduction at non-PV nodes when the best move does not change frequently
- if ( !PvNode
- && thisThread->bestMoveChanges <= 2)
- r++;
-
// Decrease reduction if opponent's move count is high (~1 Elo)
if ((ss-1)->moveCount > 13)
r--;
- // Decrease reduction if ttMove has been singularly extended (~1 Elo)
- if (singularQuietLMR)
- r--;
-
// Increase reduction for cut nodes (~3 Elo)
if (cutNode && move != ss->killers[0])
r += 2;
// If the son is reduced and fails high it will be re-searched at full depth
doFullDepthSearch = value > alpha && d < newDepth;
+ doDeeperSearch = value > alpha + 88;
didLMR = true;
}
else
// Step 17. Full depth search when LMR is skipped or fails high
if (doFullDepthSearch)
{
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth + doDeeperSearch, !cutNode);
// If the move passed LMR update its stats
if (didLMR && !captureOrPromotion)
// Bonus for prior countermove that caused the fail low
else if ( (depth >= 3 || PvNode)
&& !priorCapture)
- update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + (PvNode || cutNode)));
+ {
+ //Assign extra bonus if current node is PvNode or cutNode
+ //or fail low was really bad
+ bool extraBonus = PvNode
+ || cutNode
+ || bestValue < alpha - 94 * depth;
+
+ update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus));
+ }
if (PvNode)
bestValue = std::min(bestValue, maxValue);
if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE)
ss->staticEval = bestValue = evaluate(pos);
- // Can ttValue be used as a better position evaluation?
+ // ttValue can be used as a better position evaluation (~7 Elo)
if ( ttValue != VALUE_NONE
&& (tte->bound() & (ttValue > bestValue ? BOUND_LOWER : BOUND_UPPER)))
bestValue = ttValue;
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions, and other checks (only if depth >= DEPTH_QS_CHECKS)
// will be generated.
+ Square prevSq = to_sq((ss-1)->currentMove);
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
&thisThread->captureHistory,
contHist,
- to_sq((ss-1)->currentMove));
+ prevSq);
// Loop through the moves until no moves remain or a beta cutoff occurs
while ((move = mp.next_move()) != MOVE_NONE)
moveCount++;
- // Futility pruning and moveCount pruning
+ // Futility pruning and moveCount pruning (~5 Elo)
if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY
&& !givesCheck
+ && to_sq(move) != prevSq
&& futilityBase > -VALUE_KNOWN_WIN
&& type_of(move) != PROMOTION)
{
}
}
- // Do not search moves with negative SEE values
+ // Do not search moves with negative SEE values (~5 Elo)
if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY
&& !pos.see_ge(move))
continue;
[pos.moved_piece(move)]
[to_sq(move)];
- // Continuation history based pruning
+ // Continuation history based pruning (~2 Elo)
if ( !captureOrPromotion
&& bestValue > VALUE_TB_LOSS_IN_MAX_PLY
&& (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold
if (!pos.capture_or_promotion(bestMove))
{
// Increase stats for the best move in case it was a quiet move
- update_quiet_stats(pos, ss, bestMove, bonus2, depth);
+ update_quiet_stats(pos, ss, bestMove, bonus2);
// Decrease stats for all non-best quiet moves
for (int i = 0; i < quietCount; ++i)
// update_quiet_stats() updates move sorting heuristics
- void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus, int depth) {
+ void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus) {
// Update killers
if (ss->killers[0] != move)
Square prevSq = to_sq((ss-1)->currentMove);
thisThread->counterMoves[pos.piece_on(prevSq)][prevSq] = move;
}
-
- // Update low ply history
- if (depth > 11 && ss->ply < MAX_LPH)
- thisThread->lowPlyHistory[ss->ply][from_to(move)] << stat_bonus(depth - 7);
}
// When playing with strength handicap, choose best move among a set of RootMoves
#define USE_INLINE_ASM
#endif
+// Use either the AVX512 or AVX-VNNI version of the VNNI instructions.
+#if defined(USE_AVXVNNI)
+#define VNNI_PREFIX "%{vex%} "
+#else
+#define VNNI_PREFIX ""
+#endif
+
namespace Stockfish::Simd {
#if defined (USE_AVX512)
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
- "vpdpbusd %[b], %[a], %[acc]\n\t"
+ VNNI_PREFIX "vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b)
);
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
- "vpdpbusd %[b0], %[a0], %[acc]\n\t"
- "vpdpbusd %[b1], %[a1], %[acc]\n\t"
+ VNNI_PREFIX "vpdpbusd %[b0], %[a0], %[acc]\n\t"
+ VNNI_PREFIX "vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
);
#endif
+#if defined (USE_NEON)
+
+ [[maybe_unused]] static int neon_m128_reduce_add_epi32(int32x4_t s) {
+# if USE_NEON >= 8
+ return vaddvq_s32(s);
+# else
+ return s[0] + s[1] + s[2] + s[3];
+# endif
+ }
+
+ [[maybe_unused]] static int neon_m128_hadd(int32x4_t sum, int bias) {
+ return neon_m128_reduce_add_epi32(sum) + bias;
+ }
+
+ [[maybe_unused]] static int32x4_t neon_m128_haddx4(
+ int32x4_t sum0, int32x4_t sum1, int32x4_t sum2, int32x4_t sum3,
+ int32x4_t bias) {
+
+ int32x4_t hsums {
+ neon_m128_reduce_add_epi32(sum0),
+ neon_m128_reduce_add_epi32(sum1),
+ neon_m128_reduce_add_epi32(sum2),
+ neon_m128_reduce_add_epi32(sum3)
+ };
+ return vaddq_s32(hsums, bias);
+ }
+
+ [[maybe_unused]] static void neon_m128_add_dpbusd_epi32x2(
+ int32x4_t& acc,
+ int8x8_t a0, int8x8_t b0,
+ int8x8_t a1, int8x8_t b1) {
+
+ int16x8_t product = vmull_s8(a0, b0);
+ product = vmlal_s8(product, a1, b1);
+ acc = vpadalq_s16(acc, product);
+ }
+
+#endif
+
}
#endif // STOCKFISH_SIMD_H_INCLUDED
counterMoves.fill(MOVE_NONE);
mainHistory.fill(0);
- lowPlyHistory.fill(0);
captureHistory.fill(0);
for (bool inCheck : { false, true })
{
for (auto& to : continuationHistory[inCheck][c])
for (auto& h : to)
- h->fill(0);
+ h->fill(-71);
continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
}
}
main()->callsCnt = 0;
main()->bestPreviousScore = VALUE_INFINITE;
+ main()->bestPreviousAverageScore = VALUE_INFINITE;
main()->previousTimeReduction = 1.0;
}
Value rootDelta;
CounterMoveHistory counterMoves;
ButterflyHistory mainHistory;
- LowPlyHistory lowPlyHistory;
CapturePieceToHistory captureHistory;
ContinuationHistory continuationHistory[2][2];
Score trend;
double previousTimeReduction;
Value bestPreviousScore;
+ Value bestPreviousAverageScore;
Value iterValue[4];
int callsCnt;
bool stopOnPonderhit;
move16 = (uint16_t)m;
// Overwrite less valuable entries (cheapest checks first)
- if (b == BOUND_EXACT
+ if ( b == BOUND_EXACT
|| (uint16_t)k != key16
- || d - DEPTH_OFFSET > depth8 - 4)
+ || d - DEPTH_OFFSET + 2 * pv > depth8 - 4)
{
assert(d > DEPTH_OFFSET);
assert(d < 256 + DEPTH_OFFSET);