Merge branch 'master' into trainer

This commit is contained in:
noobpwnftw
2020-09-09 08:48:59 +08:00
43 changed files with 297 additions and 692 deletions
+169 -150
View File
@@ -1,154 +1,173 @@
Contributors with >10,000 CPU hours as of January 7, 2020 Contributors with >10,000 CPU hours as of Sept 2, 2020
Thank you! Thank you!
Username CPU Hours Games played Username CPU Hours Games played
-------------------------------------------------- --------------------------------------------------
noobpwnftw 9305707 695548021 noobpwnftw 19352969 1231459677
mlang 780050 61648867 mlang 957168 61657446
dew 621626 43921547 dew 949885 56893432
mibere 524702 42238645 mibere 703817 46865007
crunchy 354587 27344275 crunchy 427035 27344275
cw 354495 27274181 cw 416006 27521077
fastgm 332801 22804359 JojoM 415904 24479564
JojoM 295750 20437451 fastgm 404873 23953472
CSU_Dynasty 262015 21828122 CSU_Dynasty 335774 22850550
Fisherman 232181 18939229 tvijlbrief 335199 21871270
ctoks 218866 17622052 Fisherman 325053 21786603
glinscott 201989 13780820 gvreuls 311480 20751516
tvijlbrief 201204 15337115 ctoks 275877 18710423
velislav 188630 14348485 velislav 241267 15596372
gvreuls 187164 15149976 glinscott 217799 13780820
bking_US 180289 11876016 nordlandia 211692 13484886
nordlandia 172076 13467830 bcross 206213 14934233
leszek 157152 11443978 bking_US 198894 11876016
Thanar 148021 12365359 leszek 189170 11446821
spams 141975 10319326 mgrabiak 183896 11778092
drabel 138073 11121749 drabel 181408 12489478
vdv 137850 9394330 TueRens 181349 12192000
mgrabiak 133578 10454324 Thanar 179852 12365359
TueRens 132485 10878471 vdv 175171 9881246
bcross 129683 11557084 robal 166948 10702862
marrco 126078 9356740 spams 157128 10319326
sqrt2 125830 9724586 marrco 149947 9376421
robal 122873 9593418 sqrt2 147963 9724586
vdbergh 120766 8926915 vdbergh 137041 8926915
malala 115926 8002293 CoffeeOne 136294 5004100
CoffeeOne 114241 5004100 malala 136182 8002293
dsmith 113189 7570238 mhoram 128934 8177193
BrunoBanani 104644 7436849 davar 122092 7960001
Data 92328 8220352 dsmith 122059 7570238
mhoram 89333 6695109 xoto 119696 8222144
davar 87924 7009424 grandphish2 116481 7582197
xoto 81094 6869316 Data 113305 8220352
ElbertoOne 80899 7023771 BrunoBanani 112960 7436849
grandphish2 78067 6160199 ElbertoOne 99028 7023771
brabos 77212 6186135 MaZePallas 98571 6362619
psk 75733 5984901 brabos 92118 6186135
BRAVONE 73875 5054681 psk 89957 5984901
sunu 70771 5597972 sunu 88463 6007033
sterni1971 70605 5590573 sterni1971 86948 5613788
MaZePallas 66886 5188978 Vizvezdenec 83752 5343724
Vizvezdenec 63708 4967313 BRAVONE 81239 5054681
nssy 63462 5259388 nssy 76497 5259388
jromang 61634 4940891 teddybaer 75125 5407666
teddybaer 61231 5407666 Pking_cda 73776 5293873
Pking_cda 60099 5293873 jromang 70695 4940891
solarlight 57469 5028306 solarlight 70517 5028306
dv8silencer 56913 3883992 dv8silencer 70287 3883992
tinker 54936 4086118 Bobo1239 68515 4652287
renouve 49732 3501516 racerschmacer 67468 4935996
Freja 49543 3733019 manap 66273 4121774
robnjr 46972 4053117 tinker 63458 4213726
rap 46563 3219146 linrock 59082 4516053
Bobo1239 46036 3817196 robnjr 57262 4053117
ttruscott 45304 3649765 Freja 56938 3733019
racerschmacer 44881 3975413 ttruscott 56005 3679485
finfish 44764 3370515 renouve 53811 3501516
eva42 41783 3599691 cuistot 52532 3014920
biffhero 40263 3111352 finfish 51360 3370515
bigpen0r 39817 3291647 eva42 51272 3599691
mhunt 38871 2691355 rkl 50759 3840947
ronaldjerum 38820 3240695 rap 49985 3219146
Antihistamine 38785 2761312 pb00067 49727 3298270
pb00067 38038 3086320 ronaldjerum 47654 3240695
speedycpu 37591 3003273 bigpen0r 47278 3291647
rkl 37207 3289580 biffhero 46564 3111352
VoyagerOne 37050 3441673 VoyagerOne 45386 3445881
jbwiebe 35320 2805433 speedycpu 43842 3003273
cuistot 34191 2146279 jbwiebe 43305 2805433
homyur 33927 2850481 Antihistamine 41788 2761312
manap 32873 2327384 mhunt 41735 2691355
gri 32538 2515779 eastorwest 40387 2812173
oryx 31267 2899051 homyur 39893 2850481
EthanOConnor 30959 2090311 gri 39871 2515779
SC 30832 2730764 oryx 38228 2941656
csnodgrass 29505 2688994 0x3C33 37773 2529097
jmdana 29458 2205261 SC 37290 2731014
strelock 28219 2067805 csnodgrass 36207 2688994
jkiiski 27832 1904470 jmdana 36108 2205261
Pyafue 27533 1902349 strelock 34716 2074055
Garf 27515 2747562 Garf 33800 2747562
eastorwest 27421 2317535 EthanOConnor 33370 2090311
slakovv 26903 2021889 slakovv 32915 2021889
Prcuvu 24835 2170122 Spprtr 32591 2139601
anst 24714 2190091 Prcuvu 30377 2170122
hyperbolic.tom 24319 2017394 anst 30301 2190091
Patrick_G 23687 1801617 jkiiski 30136 1904470
Sharaf_DG 22896 1786697 hyperbolic.tom 29840 2017394
nabildanial 22195 1519409 Pyafue 29650 1902349
chriswk 21931 1868317 OuaisBla 27629 1578000
achambord 21665 1767323 chriswk 26902 1868317
Zirie 20887 1472937 achambord 26582 1767323
team-oh 20217 1636708 Patrick_G 26276 1801617
Isidor 20096 1680691 yorkman 26193 1992080
ncfish1 19931 1520927 SFTUser 25182 1675689
nesoneg 19875 1463031 nabildanial 24942 1519409
Spprtr 19853 1548165 Sharaf_DG 24765 1786697
JanErik 19849 1703875 ncfish1 24411 1520927
agg177 19478 1395014 agg177 23890 1395014
SFTUser 19231 1567999 JanErik 23408 1703875
xor12 19017 1680165 Isidor 23388 1680691
sg4032 18431 1641865 Norabor 22976 1587862
rstoesser 18118 1293588 cisco2015 22880 1759669
MazeOfGalious 17917 1629593 Zirie 22542 1472937
j3corre 17743 941444 team-oh 22272 1636708
cisco2015 17725 1690126 MazeOfGalious 21978 1629593
ianh2105 17706 1632562 sg4032 21945 1643065
dex 17678 1467203 ianh2105 21725 1632562
jundery 17194 1115855 xor12 21628 1680365
iisiraider 17019 1101015 dex 21612 1467203
horst.prack 17012 1465656 nesoneg 21494 1463031
Adrian.Schmidt123 16563 1281436 horst.prack 20878 1465656
purplefishies 16342 1092533 0xB00B1ES 20590 1208666
wei 16274 1745989 j3corre 20405 941444
ville 16144 1384026 Adrian.Schmidt123 20316 1281436
eudhan 15712 1283717 wei 19973 1745989
OuaisBla 15581 972000 rstoesser 19569 1293588
DragonLord 15559 1162790 eudhan 19274 1283717
dju 14716 875569 Ente 19070 1373058
chris 14479 1487385 jundery 18445 1115855
0xB00B1ES 14079 1001120 iisiraider 18247 1101015
OssumOpossum 13776 1007129 ville 17883 1384026
enedene 13460 905279 chris 17698 1487385
bpfliegel 13346 884523 purplefishies 17595 1092533
Ente 13198 1156722 DragonLord 17014 1162790
IgorLeMasson 13087 1147232 dju 16515 929427
jpulman 13000 870599 IgorLeMasson 16064 1147232
ako027ako 12775 1173203 ako027ako 15671 1173203
Nikolay.IT 12352 1068349 Nikolay.IT 15154 1068349
Andrew Grant 12327 895539 Andrew Grant 15114 895539
joster 12008 950160 yurikvelo 15027 1165616
AdrianSA 11996 804972 OssumOpossum 14857 1007129
Nesa92 11455 1111993 enedene 14476 905279
fatmurphy 11345 853210 bpfliegel 14298 884523
Dark_wizzie 11108 1007152 jpulman 13982 870599
modolief 10869 896470 joster 13794 950160
mschmidt 10757 803401 Nesa92 13786 1114691
infinity 10594 727027 Dark_wizzie 13422 1007152
mabichito 10524 749391 Hjax 13350 900887
Thomas A. Anderson 10474 732094 Fifis 13313 965473
thijsk 10431 719357 mabichito 12903 749391
Flopzee 10339 894821 thijsk 12886 722107
crocogoat 10104 1013854 crocogoat 12876 1048802
SapphireBrand 10104 969604 AdrianSA 12860 804972
stocky 10017 699440 Flopzee 12698 894821
fatmurphy 12547 853210
SapphireBrand 12416 969604
modolief 12386 896470
scuzzi 12362 833465
pgontarz 12151 848794
stocky 11954 699440
mschmidt 11941 803401
infinity 11470 727027
torbjo 11387 728873
Thomas A. Anderson 11372 732094
snicolet 11106 869170
amicic 10779 733593
rpngn 10712 688203
d64 10680 771144
basepi 10637 744851
jjoshua2 10559 670905
dzjp 10343 732529
ols 10259 570669
lbraesch 10252 647825
+3 -3
View File
@@ -915,7 +915,7 @@ icc-profile-use:
learn: config-sanity learn: config-sanity
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS=' -DEVAL_LEARN -DEVAL_NNUE -DENABLE_TEST_CMD -DUSE_BLAS $(BLASCXXFLAGS) -fopenmp ' \ EXTRACXXFLAGS=' -DEVAL_LEARN -DNNUE_EMBEDDING_OFF -DENABLE_TEST_CMD -DUSE_BLAS $(BLASCXXFLAGS) -fopenmp ' \
EXTRALDFLAGS=' $(BLASLDFLAGS) -fopenmp ' \ EXTRALDFLAGS=' $(BLASLDFLAGS) -fopenmp ' \
all all
@@ -923,7 +923,7 @@ profile-learn: config-sanity objclean profileclean
@echo "" @echo ""
@echo "Step 1/4. Building instrumented executable ..." @echo "Step 1/4. Building instrumented executable ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make) \ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make) \
LEARNCXXFLAGS=' -DEVAL_LEARN -DEVAL_NNUE -DENABLE_TEST_CMD -DUSE_BLAS $(BLASCXXFLAGS) -fopenmp ' \ LEARNCXXFLAGS=' -DEVAL_LEARN -DNNUE_EMBEDDING_OFF -DENABLE_TEST_CMD -DUSE_BLAS $(BLASCXXFLAGS) -fopenmp ' \
LEARNLDFLAGS=' $(BLASLDFLAGS) -fopenmp ' LEARNLDFLAGS=' $(BLASLDFLAGS) -fopenmp '
@echo "" @echo ""
@echo "Step 2/4. Running benchmark for pgo-build ..." @echo "Step 2/4. Running benchmark for pgo-build ..."
@@ -932,7 +932,7 @@ profile-learn: config-sanity objclean profileclean
@echo "Step 3/4. Building optimized executable ..." @echo "Step 3/4. Building optimized executable ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean $(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use) \ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use) \
LEARNCXXFLAGS=' -DEVAL_LEARN -DEVAL_NNUE -DENABLE_TEST_CMD -DUSE_BLAS $(BLASCXXFLAGS) -fopenmp ' \ LEARNCXXFLAGS=' -DEVAL_LEARN -DNNUE_EMBEDDING_OFF -DENABLE_TEST_CMD -DUSE_BLAS $(BLASCXXFLAGS) -fopenmp ' \
LEARNLDFLAGS=' $(BLASLDFLAGS) -fopenmp ' LEARNLDFLAGS=' $(BLASLDFLAGS) -fopenmp '
@echo "" @echo ""
@echo "Step 4/4. Deleting profile data ..." @echo "Step 4/4. Deleting profile data ..."
+2
View File
@@ -164,5 +164,7 @@ vector<string> setup_bench(const Position& current, istream& is) {
++posCounter; ++posCounter;
} }
list.emplace_back("setoption name Use NNUE value true");
return list; return list;
} }
+2 -24
View File
@@ -1,20 +1,8 @@
#ifndef _EVALUATE_COMMON_H_ #ifndef _EVALUATE_COMMON_H_
#define _EVALUATE_COMMON_H_ #define _EVALUATE_COMMON_H_
// A common header-like function for modern evaluation functions (EVAL_KPPT and EVAL_KPP_KKPT).
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
#include <functional> #include <functional>
// KK file name
#define KK_BIN "KK_synthesized.bin"
// KKP file name
#define KKP_BIN "KKP_synthesized.bin"
// KPP file name
#define KPP_BIN "KPP_synthesized.bin"
#include "../position.h" #include "../position.h"
namespace Eval namespace Eval
@@ -46,19 +34,11 @@ namespace Eval
void init_grad(double eta1, uint64_t eta_epoch, double eta2, uint64_t eta2_epoch, double eta3); void init_grad(double eta1, uint64_t eta_epoch, double eta2, uint64_t eta2_epoch, double eta3);
// Add the gradient difference value to the gradient array for all features that appear in the current phase. // Add the gradient difference value to the gradient array for all features that appear in the current phase.
// freeze[0]: Flag that kk does not learn void add_grad(Position& pos, Color rootColor, double delt_grad);
// freeze[1]: Flag that kkp does not learn
// freeze[2]: Flag that kpp does not learn
// freeze[3]: Flag that kppp does not learn
void add_grad(Position& pos, Color rootColor, double delt_grad, const std::array<bool, 4>& freeze);
// Do SGD or AdaGrad or something based on the current gradient. // Do SGD or AdaGrad or something based on the current gradient.
// epoch: Generation counter (starting from 0) // epoch: Generation counter (starting from 0)
// freeze[0]: Flag that kk does not learn void update_weights(uint64_t epoch);
// freeze[1]: Flag that kkp does not learn
// freeze[2]: Flag that kpp does not learn
// freeze[3]: Flag that kppp does not learn
void update_weights(uint64_t epoch, const std::array<bool, 4>& freeze);
// Save the evaluation function parameters to a file. // Save the evaluation function parameters to a file.
// You can specify the extension added to the end of the file. // You can specify the extension added to the end of the file.
@@ -79,6 +59,4 @@ namespace Eval
} }
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
#endif // _EVALUATE_KPPT_COMMON_H_ #endif // _EVALUATE_KPPT_COMMON_H_
+11 -2
View File
@@ -1014,8 +1014,10 @@ make_v:
/// evaluation of the position from the point of view of the side to move. /// evaluation of the position from the point of view of the side to move.
Value Eval::evaluate(const Position& pos) { Value Eval::evaluate(const Position& pos) {
if (Options["Training"]) { if (Options["Training"]) {
Value v = NNUE::evaluate(pos); Value v = NNUE::evaluate(pos);
// Damp down the evaluation linearly when shuffling // Damp down the evaluation linearly when shuffling
v = v * (100 - pos.rule50_count()) / 100; v = v * (100 - pos.rule50_count()) / 100;
@@ -1024,12 +1026,19 @@ Value Eval::evaluate(const Position& pos) {
return v; return v;
} else { } else {
// Use classical eval if there is a large imbalance
// If there is a moderate imbalance, use classical eval with probability (1/8),
// as derived from the node counter.
bool useClassical = abs(eg_value(pos.psq_score())) * 16 > NNUEThreshold1 * (16 + pos.rule50_count());
bool classical = !Eval::useNNUE bool classical = !Eval::useNNUE
|| abs(eg_value(pos.psq_score())) * 16 > NNUEThreshold1 * (16 + pos.rule50_count()); || useClassical
|| (abs(eg_value(pos.psq_score())) > PawnValueMg / 4 && !(pos.this_thread()->nodes & 0xB));
Value v = classical ? Evaluation<NO_TRACE>(pos).value() Value v = classical ? Evaluation<NO_TRACE>(pos).value()
: NNUE::evaluate(pos) * 5 / 4 + Tempo; : NNUE::evaluate(pos) * 5 / 4 + Tempo;
if (classical && Eval::useNNUE && abs(v) * 16 < NNUEThreshold2 * (16 + pos.rule50_count())) if ( useClassical
&& Eval::useNNUE
&& abs(v) * 16 < NNUEThreshold2 * (16 + pos.rule50_count()))
v = NNUE::evaluate(pos) * 5 / 4 + Tempo; v = NNUE::evaluate(pos) * 5 / 4 + Tempo;
// Damp down the evaluation linearly when shuffling // Damp down the evaluation linearly when shuffling
+1 -3
View File
@@ -38,13 +38,11 @@ namespace Eval {
// The default net name MUST follow the format nn-[SHA256 first 12 digits].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 // 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. // name of the macro, as it is used in the Makefile.
#define EvalFileDefaultName "nn-82215d0fd0df.nnue" #define EvalFileDefaultName "nn.bin"
namespace NNUE { namespace NNUE {
Value evaluate(const Position& pos); Value evaluate(const Position& pos);
Value compute_eval(const Position& pos);
void update_eval(const Position& pos);
bool load_eval(std::string streamName, std::istream& stream); bool load_eval(std::string streamName, std::istream& stream);
} // namespace NNUE } // namespace NNUE
+1 -4
View File
@@ -36,7 +36,7 @@
#include <dirent.h> #include <dirent.h>
#endif #endif
#if defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../nnue/evaluate_nnue_learner.h" #include "../nnue/evaluate_nnue_learner.h"
#include <climits> #include <climits>
#include <shared_mutex> #include <shared_mutex>
@@ -839,9 +839,6 @@ namespace Learner
} }
pos.do_move(next_move, states[ply]); pos.do_move(next_move, states[ply]);
// Call node evaluate() for each difference calculation.
Eval::NNUE::update_eval(pos);
} // for (int ply = 0; ; ++ply) } // for (int ply = 0; ; ++ply)
} // while(!quit) } // while(!quit)
+2 -68
View File
@@ -59,12 +59,12 @@
// The objective function is the sum of squares of the difference in winning percentage // The objective function is the sum of squares of the difference in winning percentage
// See learner.cpp for more information. // See learner.cpp for more information.
//#define LOSS_FUNCTION_IS_WINNING_PERCENTAGE // #define LOSS_FUNCTION_IS_WINNING_PERCENTAGE
// Objective function is cross entropy // Objective function is cross entropy
// See learner.cpp for more information. // See learner.cpp for more information.
// So-called ordinary "rag cloth squeezer" // So-called ordinary "rag cloth squeezer"
//#define LOSS_FUNCTION_IS_CROSS_ENTOROPY // #define LOSS_FUNCTION_IS_CROSS_ENTOROPY
// A version in which the objective function is cross entropy, but the win rate function is not passed // A version in which the objective function is cross entropy, but the win rate function is not passed
// #define LOSS_FUNCTION_IS_CROSS_ENTOROPY_FOR_VALUE // #define LOSS_FUNCTION_IS_CROSS_ENTOROPY_FOR_VALUE
@@ -83,19 +83,6 @@
// rmse calculation is done in one thread, so it takes some time, so reducing the output is effective. // rmse calculation is done in one thread, so it takes some time, so reducing the output is effective.
#define LEARN_RMSE_OUTPUT_INTERVAL 1 #define LEARN_RMSE_OUTPUT_INTERVAL 1
// ----------------------
// learning from zero vector
// ----------------------
// Start learning the evaluation function parameters from the zero vector.
// Initialize to zero, generate a game, learn from zero vector,
// Game generation → If you repeat learning, you will get parameters that do not depend on the professional game. (maybe)
// (very time consuming)
//#define RESET_TO_ZERO_VECTOR
// ---------------------- // ----------------------
// Floating point for learning // Floating point for learning
// ---------------------- // ----------------------
@@ -114,59 +101,6 @@ typedef float LearnFloatType;
//#include "half_float.h" //#include "half_float.h"
//typedef HalfFloat::float16 LearnFloatType; //typedef HalfFloat::float16 LearnFloatType;
// ----------------------
// save memory
// ----------------------
// Use a triangular array for the Weight array (of which is KPP) to save memory.
// If this is used, the weight array for learning will be about 3 times as large as the evaluation function file.
#define USE_TRIANGLE_WEIGHT_ARRAY
// ----------------------
// dimension down
// ----------------------
// Dimension reduction for mirrors (left/right symmetry) and inverse (forward/backward symmetry).
// All on by default.
// Dimension reduction using mirror and inverse for KK. (Unclear effect)
// USE_KK_MIRROR_WRITE must be on when USE_KK_INVERSE_WRITE is on.
#define USE_KK_MIRROR_WRITE
#define USE_KK_INVERSE_WRITE
// Dimension reduction using Mirror and Inverse for KKP. (Inverse is not so effective)
// When USE_KKP_INVERSE_WRITE is turned on, USE_KKP_MIRROR_WRITE must also be turned on.
#define USE_KKP_MIRROR_WRITE
#define USE_KKP_INVERSE_WRITE
// Perform dimension reduction using a mirror for KPP. (Turning this off requires double the teacher position)
// KPP has no inverse. (Because there is only K on the front side)
#define USE_KPP_MIRROR_WRITE
// Perform a dimension reduction using a mirror for KPPP. (Turning this off requires double the teacher position)
// KPPP has no inverse. (Because there is only K on the front side)
#define USE_KPPP_MIRROR_WRITE
// Reduce the dimension by KPP for learning the KKPP component.
// Learning is very slow.
// Do not use as it is not debugged.
//#define USE_KKPP_LOWER_DIM
// ======================
// Settings for creating teacher phases
// ======================
// ----------------------
// write out the draw
// ----------------------
// When you reach a draw, write it out as a teacher position
// It's subtle whether it's better to do this.
// #define LEARN_GENSFEN_USE_DRAW_RESULT
// ====================== // ======================
// configure // configure
// ====================== // ======================
+18 -227
View File
@@ -54,7 +54,7 @@
#include <dirent.h> #include <dirent.h>
#endif #endif
#if defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../nnue/evaluate_nnue_learner.h" #include "../nnue/evaluate_nnue_learner.h"
#include <climits> #include <climits>
#include <shared_mutex> #include <shared_mutex>
@@ -172,7 +172,7 @@ namespace Learner
// When the objective function is the sum of squares of the difference in winning percentage // When the objective function is the sum of squares of the difference in winning percentage
#if defined (LOSS_FUNCTION_IS_WINNING_PERCENTAGE) #if defined (LOSS_FUNCTION_IS_WINNING_PERCENTAGE)
// function to calculate the gradient // function to calculate the gradient
double calc_grad(Value deep, Value shallow, PackedSfenValue& psv) double calc_grad(Value deep, Value shallow, const PackedSfenValue& psv)
{ {
// The square of the win rate difference minimizes it in the objective function. // The square of the win rate difference minimizes it in the objective function.
// Objective function J = 1/2m Σ (win_rate(shallow)-win_rate(deep) )^2 // Objective function J = 1/2m Σ (win_rate(shallow)-win_rate(deep) )^2
@@ -667,14 +667,12 @@ namespace Learner
learn_sum_entropy_win = 0.0; learn_sum_entropy_win = 0.0;
learn_sum_entropy = 0.0; learn_sum_entropy = 0.0;
#endif #endif
#if defined(EVAL_NNUE)
newbob_scale = 1.0; newbob_scale = 1.0;
newbob_decay = 1.0; newbob_decay = 1.0;
newbob_num_trials = 2; newbob_num_trials = 2;
best_loss = std::numeric_limits<double>::infinity(); best_loss = std::numeric_limits<double>::infinity();
latest_loss_sum = 0.0; latest_loss_sum = 0.0;
latest_loss_count = 0; latest_loss_count = 0;
#endif
} }
virtual void thread_worker(size_t thread_id); virtual void thread_worker(size_t thread_id);
@@ -696,15 +694,9 @@ namespace Learner
bool stop_flag; bool stop_flag;
// Discount rate
double discount_rate;
// Option to exclude early stage from learning // Option to exclude early stage from learning
int reduction_gameply; int reduction_gameply;
// Option not to learn kk/kkp/kpp/kppp
std::array<bool, 4> freeze;
// If the absolute value of the evaluation value of the deep search of the teacher phase exceeds this value, discard the teacher phase. // If the absolute value of the evaluation value of the deep search of the teacher phase exceeds this value, discard the teacher phase.
int eval_limit; int eval_limit;
@@ -724,7 +716,6 @@ namespace Learner
atomic<double> learn_sum_entropy; atomic<double> learn_sum_entropy;
#endif #endif
#if defined(EVAL_NNUE)
shared_timed_mutex nn_mutex; shared_timed_mutex nn_mutex;
double newbob_scale; double newbob_scale;
double newbob_decay; double newbob_decay;
@@ -733,7 +724,6 @@ namespace Learner
double latest_loss_sum; double latest_loss_sum;
uint64_t latest_loss_count; uint64_t latest_loss_count;
std::string best_nn_directory; std::string best_nn_directory;
#endif
uint64_t eval_save_interval; uint64_t eval_save_interval;
uint64_t loss_output_interval; uint64_t loss_output_interval;
@@ -753,13 +743,10 @@ namespace Learner
// It doesn't matter if you have disabled the substitution table. // It doesn't matter if you have disabled the substitution table.
TT.new_search(); TT.new_search();
#if defined(EVAL_NNUE)
std::cout << "PROGRESS: " << now_string() << ", "; std::cout << "PROGRESS: " << now_string() << ", ";
std::cout << sr.total_done << " sfens"; std::cout << sr.total_done << " sfens";
std::cout << ", iteration " << epoch; std::cout << ", iteration " << epoch;
std::cout << ", eta = " << Eval::get_eta() << ", "; std::cout << ", eta = " << Eval::get_eta() << ", ";
#endif
#if !defined(LOSS_FUNCTION_IS_ELMO_METHOD) #if !defined(LOSS_FUNCTION_IS_ELMO_METHOD)
double sum_error = 0; double sum_error = 0;
@@ -813,6 +800,7 @@ namespace Learner
auto task = auto task =
[ [
&ps, &ps,
#if defined (LOSS_FUNCTION_IS_ELMO_METHOD)
&test_sum_cross_entropy_eval, &test_sum_cross_entropy_eval,
&test_sum_cross_entropy_win, &test_sum_cross_entropy_win,
&test_sum_cross_entropy, &test_sum_cross_entropy,
@@ -820,6 +808,11 @@ namespace Learner
&test_sum_entropy_win, &test_sum_entropy_win,
&test_sum_entropy, &test_sum_entropy,
&sum_norm, &sum_norm,
#else
&sum_error,
&sum_error2,
&sum_error3,
#endif
&task_count, &task_count,
&move_accord_count &move_accord_count
](size_t task_thread_id) ](size_t task_thread_id)
@@ -841,19 +834,6 @@ namespace Learner
auto task_search_result = qsearch(task_pos); auto task_search_result = qsearch(task_pos);
auto shallow_value = task_search_result.first; auto shallow_value = task_search_result.first;
{
const auto rootColor = task_pos.side_to_move();
const auto pv = task_search_result.second;
std::vector<StateInfo, AlignedAllocator<StateInfo>> states(pv.size());
for (size_t i = 0; i < pv.size(); ++i)
{
task_pos.do_move(pv[i], states[i]);
Eval::NNUE::update_eval(task_pos);
}
shallow_value = (rootColor == task_pos.side_to_move()) ? Eval::evaluate(task_pos) : -Eval::evaluate(task_pos);
for (auto it = pv.rbegin(); it != pv.rend(); ++it)
task_pos.undo_move(*it);
}
// Evaluation value of deep search // Evaluation value of deep search
auto deep_value = (Value)ps.score; auto deep_value = (Value)ps.score;
@@ -917,18 +897,17 @@ namespace Learner
#if !defined(LOSS_FUNCTION_IS_ELMO_METHOD) #if !defined(LOSS_FUNCTION_IS_ELMO_METHOD)
// rmse = root mean square error: mean square error // rmse = root mean square error: mean square error
// mae = mean absolute error: mean absolute error // mae = mean absolute error: mean absolute error
auto dsig_rmse = std::sqrt(sum_error / (sfen_for_mse.size() + epsilon)); constexpr double epsilon = 0.000001;
auto dsig_mae = sum_error2 / (sfen_for_mse.size() + epsilon); auto dsig_rmse = std::sqrt(sum_error / (sr.sfen_for_mse.size() + epsilon));
auto eval_mae = sum_error3 / (sfen_for_mse.size() + epsilon); auto dsig_mae = sum_error2 / (sr.sfen_for_mse.size() + epsilon);
auto eval_mae = sum_error3 / (sr.sfen_for_mse.size() + epsilon);
cout << " , dsig rmse = " << dsig_rmse << " , dsig mae = " << dsig_mae cout << " , dsig rmse = " << dsig_rmse << " , dsig mae = " << dsig_mae
<< " , eval mae = " << eval_mae; << " , eval mae = " << eval_mae << endl;
#endif #endif
#if defined ( LOSS_FUNCTION_IS_ELMO_METHOD ) #if defined ( LOSS_FUNCTION_IS_ELMO_METHOD )
#if defined(EVAL_NNUE)
latest_loss_sum += test_sum_cross_entropy - test_sum_entropy; latest_loss_sum += test_sum_cross_entropy - test_sum_entropy;
latest_loss_count += sr.sfen_for_mse.size(); latest_loss_count += sr.sfen_for_mse.size();
#endif
// learn_cross_entropy may be called train cross entropy in the world of machine learning, // learn_cross_entropy may be called train cross entropy in the world of machine learning,
// When omitting the acronym, it is nice to be able to distinguish it from test cross entropy(tce) by writing it as lce. // When omitting the acronym, it is nice to be able to distinguish it from test cross entropy(tce) by writing it as lce.
@@ -967,8 +946,6 @@ namespace Learner
learn_sum_entropy_eval = 0.0; learn_sum_entropy_eval = 0.0;
learn_sum_entropy_win = 0.0; learn_sum_entropy_win = 0.0;
learn_sum_entropy = 0.0; learn_sum_entropy = 0.0;
#else
<< endl;
#endif #endif
} }
@@ -987,14 +964,10 @@ namespace Learner
// display mse (this is sometimes done only for thread 0) // display mse (this is sometimes done only for thread 0)
// Immediately after being read from the file... // Immediately after being read from the file...
#if defined(EVAL_NNUE) // Lock the evaluation function so that it is not used during updating.
// Lock the evaluation function so that it is not used during updating.
shared_lock<shared_timed_mutex> read_lock(nn_mutex, defer_lock); shared_lock<shared_timed_mutex> read_lock(nn_mutex, defer_lock);
if (sr.next_update_weights <= sr.total_done || if (sr.next_update_weights <= sr.total_done ||
(thread_id != 0 && !read_lock.try_lock())) (thread_id != 0 && !read_lock.try_lock()))
#else
if (sr.next_update_weights <= sr.total_done)
#endif
{ {
if (thread_id != 0) if (thread_id != 0)
{ {
@@ -1018,16 +991,6 @@ namespace Learner
continue; continue;
} }
#if !defined(EVAL_NNUE)
// Output the current time. Output every time.
std::cout << sr.total_done << " sfens , at " << now_string() << std::endl;
// Reflect the gradient in the weight array at this timing. The calculation of the gradient is just right for each 1M phase in terms of mini-batch.
Eval::update_weights(epoch, freeze);
// Display epoch and current eta for debugging.
std::cout << "epoch = " << epoch << " , eta = " << Eval::get_eta() << std::endl;
#else
{ {
// update parameters // update parameters
@@ -1035,7 +998,6 @@ namespace Learner
lock_guard<shared_timed_mutex> write_lock(nn_mutex); lock_guard<shared_timed_mutex> write_lock(nn_mutex);
Eval::NNUE::UpdateParameters(epoch); Eval::NNUE::UpdateParameters(epoch);
} }
#endif
++epoch; ++epoch;
// Save once every 1 billion phases. // Save once every 1 billion phases.
@@ -1069,9 +1031,7 @@ namespace Learner
// loss calculation // loss calculation
calc_loss(thread_id, done); calc_loss(thread_id, done);
#if defined(EVAL_NNUE)
Eval::NNUE::CheckHealth(); Eval::NNUE::CheckHealth();
#endif
// Make a note of how far you have totaled. // Make a note of how far you have totaled.
sr.last_done = sr.total_done; sr.last_done = sr.total_done;
@@ -1125,26 +1085,11 @@ namespace Learner
cout << "Error! : illigal packed sfen = " << pos.fen() << endl; cout << "Error! : illigal packed sfen = " << pos.fen() << endl;
goto RetryRead; goto RetryRead;
} }
#if !defined(EVAL_NNUE)
{
auto key = pos.key();
// Exclude the phase used for rmse calculation.
if (sr.is_for_rmse(key) && skip_duplicated_positions_in_training)
goto RetryRead;
// Exclude the most recently used aspect.
auto hash_index = size_t(key & (sr.READ_SFEN_HASH_SIZE - 1));
auto key2 = sr.hash[hash_index];
if (key == key2 && skip_duplicated_positions_in_training)
goto RetryRead;
sr.hash[hash_index] = key; // Replace with the current key.
}
#endif
// There is a possibility that all the pieces are blocked and stuck. // There is a possibility that all the pieces are blocked and stuck.
// Also, the declaration win phase is excluded from learning because you cannot go to leaf with PV moves. // Also, the declaration win phase is excluded from learning because you cannot go to leaf with PV moves.
// (shouldn't write out such teacher aspect itself, but may have written it out with an old generation routine) // (shouldn't write out such teacher aspect itself, but may have written it out with an old generation routine)
// Skip the position if there are no legal moves (=checkmated or stalemate). // Skip the position if there are no legal moves (=checkmated or stalemate).
if (MoveList<LEGAL>(pos).size() == 0) if (MoveList<LEGAL>(pos).size() == 0)
goto RetryRead; goto RetryRead;
@@ -1163,32 +1108,6 @@ namespace Learner
auto rootColor = pos.side_to_move(); auto rootColor = pos.side_to_move();
// If the initial PV is different, it is better not to use it for learning.
// If it is the result of searching a completely different place, it may become noise.
// It may be better not to study where the difference in evaluation values is too large.
#if 0
// If you do this, about 13% of the phases will be excluded from the learning target. Good and bad are subtle.
if (pv.size() >= 1 && (uint16_t)pv[0] != ps.move)
{
// dbg_hit_on(false);
continue;
}
#endif
#if 0
// It may be better not to study where the difference in evaluation values is too large.
// → It's okay because it passes the win rate function... About 30% of the phases are out of the scope of learning...
if (abs((int16_t)r.first - ps.score) >= Eval::PawnValue * 4)
{
// dbg_hit_on(false);
continue;
}
// dbg_hit_on(true);
#endif
int ply = 0;
// A helper function that adds the gradient to the current phase. // A helper function that adds the gradient to the current phase.
auto pos_add_grad = [&]() { auto pos_add_grad = [&]() {
// Use the value of evaluate in leaf as shallow_value. // Use the value of evaluate in leaf as shallow_value.
@@ -1197,13 +1116,11 @@ namespace Learner
// I don't think this is a very desirable property, as the aspect that gives that gradient will be different. // I don't think this is a very desirable property, as the aspect that gives that gradient will be different.
// I have turned off the substitution table, but since the pv array has not been updated due to one stumbling block etc... // I have turned off the substitution table, but since the pv array has not been updated due to one stumbling block etc...
Value shallow_value = (rootColor == pos.side_to_move()) ? Eval::evaluate(pos) : -Eval::evaluate(pos);
#if defined (LOSS_FUNCTION_IS_ELMO_METHOD) #if defined (LOSS_FUNCTION_IS_ELMO_METHOD)
// Calculate loss for training data // Calculate loss for training data
double learn_cross_entropy_eval, learn_cross_entropy_win, learn_cross_entropy; double learn_cross_entropy_eval, learn_cross_entropy_win, learn_cross_entropy;
double learn_entropy_eval, learn_entropy_win, learn_entropy; double learn_entropy_eval, learn_entropy_win, learn_entropy;
calc_cross_entropy(deep_value, shallow_value, ps, learn_cross_entropy_eval, learn_cross_entropy_win, learn_cross_entropy, learn_entropy_eval, learn_entropy_win, learn_entropy); calc_cross_entropy(deep_value, r.first, ps, learn_cross_entropy_eval, learn_cross_entropy_win, learn_cross_entropy, learn_entropy_eval, learn_entropy_win, learn_entropy);
learn_sum_cross_entropy_eval += learn_cross_entropy_eval; learn_sum_cross_entropy_eval += learn_cross_entropy_eval;
learn_sum_cross_entropy_win += learn_cross_entropy_win; learn_sum_cross_entropy_win += learn_cross_entropy_win;
learn_sum_cross_entropy += learn_cross_entropy; learn_sum_cross_entropy += learn_cross_entropy;
@@ -1212,73 +1129,14 @@ namespace Learner
learn_sum_entropy += learn_entropy; learn_sum_entropy += learn_entropy;
#endif #endif
#if !defined(EVAL_NNUE) Eval::NNUE::AddExample(pos, rootColor, ps, 1.0);
// Slope
double dj_dw = calc_grad(deep_value, shallow_value, ps);
// Add jd_dw as the gradient (∂J/∂Wj) for the feature vector currently appearing in the leaf node.
// If it is not PV termination, apply a discount rate.
if (discount_rate != 0 && ply != (int)pv.size())
dj_dw *= discount_rate;
// Since we have reached leaf, add the gradient to the features that appear in this phase.
// Update based on gradient later.
Eval::add_grad(pos, rootColor, dj_dw, freeze);
#else
const double example_weight =
(discount_rate != 0 && ply != (int)pv.size()) ? discount_rate : 1.0;
Eval::NNUE::AddExample(pos, rootColor, ps, example_weight);
#endif
// Since the processing is completed, the counter of the processed number is incremented // Since the processing is completed, the counter of the processed number is incremented
sr.total_done++; sr.total_done++;
}; };
StateInfo state[MAX_PLY]; // PV of qsearch cannot be so long.
bool illegal_move = false;
for (auto m : pv)
{
// I shouldn't be an illegal player.
// An illegal move sometimes comes here...
if (!pos.pseudo_legal(m) || !pos.legal(m))
{
//cout << pos << m << endl;
//assert(false);
illegal_move = true;
break;
}
// Processing when adding the gradient to the node on each PV.
//If discount_rate is 0, this process is not performed.
if (discount_rate != 0)
pos_add_grad();
pos.do_move(m, state[ply++]);
// Since the value of evaluate in leaf is used, the difference is updated.
Eval::NNUE::update_eval(pos);
}
if (illegal_move) {
sync_cout << "An illical move was detected... Excluded the position from the learning data..." << sync_endl;
continue;
}
// Since we have reached the end phase of PV, add the slope here.
pos_add_grad(); pos_add_grad();
// rewind the phase
for (auto it = pv.rbegin(); it != pv.rend(); ++it)
pos.undo_move(*it);
#if 0
// When adding the gradient to the root phase
shallow_value = (rootColor == pos.side_to_move()) ? Eval::evaluate(pos) : -Eval::evaluate(pos);
dj_dw = calc_grad(deep_value, shallow_value, ps);
Eval::add_grad(pos, rootColor, dj_dw, without_kpp);
#endif
} }
} }
@@ -1303,7 +1161,6 @@ namespace Learner
static int dir_number = 0; static int dir_number = 0;
const std::string dir_name = std::to_string(dir_number++); const std::string dir_name = std::to_string(dir_number++);
Eval::save_eval(dir_name); Eval::save_eval(dir_name);
#if defined(EVAL_NNUE)
if (newbob_decay != 1.0 && latest_loss_count > 0) { if (newbob_decay != 1.0 && latest_loss_count > 0) {
static int trials = newbob_num_trials; static int trials = newbob_num_trials;
const double latest_loss = latest_loss_sum / latest_loss_count; const double latest_loss = latest_loss_sum / latest_loss_count;
@@ -1338,7 +1195,6 @@ namespace Learner
return true; return true;
} }
} }
#endif
} }
return false; return false;
} }
@@ -1652,23 +1508,15 @@ namespace Learner
ELMO_LAMBDA_LIMIT = 32000; ELMO_LAMBDA_LIMIT = 32000;
#endif #endif
// Discount rate. If this is set to a value other than 0, the slope will be added even at other than the PV termination. (At that time, apply this discount rate)
double discount_rate = 0;
// if (gamePly <rand(reduction_gameply)) continue; // if (gamePly <rand(reduction_gameply)) continue;
// An option to exclude the early stage from the learning target moderately like // An option to exclude the early stage from the learning target moderately like
// If set to 1, rand(1)==0, so nothing is excluded. // If set to 1, rand(1)==0, so nothing is excluded.
int reduction_gameply = 1; int reduction_gameply = 1;
// Optional item that does not let you learn KK/KKP/KPP/KPPP
array<bool, 4> freeze = {};
#if defined(EVAL_NNUE)
uint64_t nn_batch_size = 1000; uint64_t nn_batch_size = 1000;
double newbob_decay = 1.0; double newbob_decay = 1.0;
int newbob_num_trials = 2; int newbob_num_trials = 2;
string nn_options; string nn_options;
#endif
uint64_t eval_save_interval = LEARN_EVAL_SAVE_INTERVAL; uint64_t eval_save_interval = LEARN_EVAL_SAVE_INTERVAL;
uint64_t loss_output_interval = 0; uint64_t loss_output_interval = 0;
@@ -1718,24 +1566,9 @@ namespace Learner
// Accept also the old option name. // Accept also the old option name.
else if (option == "use_hash_in_training" || option == "skip_duplicated_positions_in_training") is >> skip_duplicated_positions_in_training; else if (option == "use_hash_in_training" || option == "skip_duplicated_positions_in_training") is >> skip_duplicated_positions_in_training;
else if (option == "winning_probability_coefficient") is >> winning_probability_coefficient; else if (option == "winning_probability_coefficient") is >> winning_probability_coefficient;
// Discount rate
else if (option == "discount_rate") is >> discount_rate;
// Using WDL with win rate model instead of sigmoid // Using WDL with win rate model instead of sigmoid
else if (option == "use_wdl") is >> use_wdl; else if (option == "use_wdl") is >> use_wdl;
// No learning of KK/KKP/KPP/KPPP.
else if (option == "freeze_kk") is >> freeze[0];
else if (option == "freeze_kkp") is >> freeze[1];
else if (option == "freeze_kpp") is >> freeze[2];
#if defined(EVAL_KPPT) || defined(EVAL_KPP_KKPT) || defined(EVAL_KPP_KKPT_FV_VAR) || defined(EVAL_NABLA)
#elif defined(EVAL_KPPPT) || defined(EVAL_KPPP_KKPT) || defined(EVAL_HELICES)
else if (option == "freeze_kppp") is >> freeze[3];
#elif defined(EVAL_KKPP_KKPT) || defined(EVAL_KKPPT)
else if (option == "freeze_kkpp") is >> freeze[3];
#endif
#if defined (LOSS_FUNCTION_IS_ELMO_METHOD) #if defined (LOSS_FUNCTION_IS_ELMO_METHOD)
// LAMBDA // LAMBDA
else if (option == "lambda") is >> ELMO_LAMBDA; else if (option == "lambda") is >> ELMO_LAMBDA;
@@ -1756,12 +1589,11 @@ namespace Learner
else if (option == "save_only_once") save_only_once = true; else if (option == "save_only_once") save_only_once = true;
else if (option == "no_shuffle") no_shuffle = true; else if (option == "no_shuffle") no_shuffle = true;
#if defined(EVAL_NNUE)
else if (option == "nn_batch_size") is >> nn_batch_size; else if (option == "nn_batch_size") is >> nn_batch_size;
else if (option == "newbob_decay") is >> newbob_decay; else if (option == "newbob_decay") is >> newbob_decay;
else if (option == "newbob_num_trials") is >> newbob_num_trials; else if (option == "newbob_num_trials") is >> newbob_num_trials;
else if (option == "nn_options") is >> nn_options; else if (option == "nn_options") is >> nn_options;
#endif
else if (option == "eval_save_interval") is >> eval_save_interval; else if (option == "eval_save_interval") is >> eval_save_interval;
else if (option == "loss_output_interval") is >> loss_output_interval; else if (option == "loss_output_interval") is >> loss_output_interval;
else if (option == "mirror_percentage") is >> mirror_percentage; else if (option == "mirror_percentage") is >> mirror_percentage;
@@ -1924,21 +1756,15 @@ namespace Learner
for (auto it = filenames.rbegin(); it != filenames.rend(); ++it) for (auto it = filenames.rbegin(); it != filenames.rend(); ++it)
sr.filenames.push_back(Path::Combine(base_dir, *it)); sr.filenames.push_back(Path::Combine(base_dir, *it));
#if !defined(EVAL_NNUE)
cout << "Gradient Method : " << LEARN_UPDATE << endl;
#endif
cout << "Loss Function : " << LOSS_FUNCTION << endl; cout << "Loss Function : " << LOSS_FUNCTION << endl;
cout << "mini-batch size : " << mini_batch_size << endl; cout << "mini-batch size : " << mini_batch_size << endl;
#if defined(EVAL_NNUE)
cout << "nn_batch_size : " << nn_batch_size << endl; cout << "nn_batch_size : " << nn_batch_size << endl;
cout << "nn_options : " << nn_options << endl; cout << "nn_options : " << nn_options << endl;
#endif
cout << "learning rate : " << eta1 << " , " << eta2 << " , " << eta3 << endl; cout << "learning rate : " << eta1 << " , " << eta2 << " , " << eta3 << endl;
cout << "eta_epoch : " << eta1_epoch << " , " << eta2_epoch << endl; cout << "eta_epoch : " << eta1_epoch << " , " << eta2_epoch << endl;
cout << "use_draw_games_in_training : " << use_draw_games_in_training << endl; cout << "use_draw_games_in_training : " << use_draw_games_in_training << endl;
cout << "use_draw_games_in_validation : " << use_draw_games_in_validation << endl; cout << "use_draw_games_in_validation : " << use_draw_games_in_validation << endl;
cout << "skip_duplicated_positions_in_training : " << skip_duplicated_positions_in_training << endl; cout << "skip_duplicated_positions_in_training : " << skip_duplicated_positions_in_training << endl;
#if defined(EVAL_NNUE)
if (newbob_decay != 1.0) { if (newbob_decay != 1.0) {
cout << "scheduling : newbob with decay = " << newbob_decay cout << "scheduling : newbob with decay = " << newbob_decay
<< ", " << newbob_num_trials << " trials" << endl; << ", " << newbob_num_trials << " trials" << endl;
@@ -1946,8 +1772,6 @@ namespace Learner
else { else {
cout << "scheduling : default" << endl; cout << "scheduling : default" << endl;
} }
#endif
cout << "discount rate : " << discount_rate << endl;
// If reduction_gameply is set to 0, rand(0) will be divided by 0, so correct it to 1. // If reduction_gameply is set to 0, rand(0) will be divided by 0, so correct it to 1.
reduction_gameply = max(reduction_gameply, 1); reduction_gameply = max(reduction_gameply, 1);
@@ -1962,14 +1786,6 @@ namespace Learner
cout << "eval_save_interval : " << eval_save_interval << " sfens" << endl; cout << "eval_save_interval : " << eval_save_interval << " sfens" << endl;
cout << "loss_output_interval: " << loss_output_interval << " sfens" << endl; cout << "loss_output_interval: " << loss_output_interval << " sfens" << endl;
#if defined(EVAL_KPPT) || defined(EVAL_KPP_KKPT) || defined(EVAL_KPP_KKPT_FV_VAR) || defined(EVAL_NABLA)
cout << "freeze_kk/kkp/kpp : " << freeze[0] << " , " << freeze[1] << " , " << freeze[2] << endl;
#elif defined(EVAL_KPPPT) || defined(EVAL_KPPP_KKPT) || defined(EVAL_HELICES)
cout << "freeze_kk/kkp/kpp/kppp : " << freeze[0] << " , " << freeze[1] << " , " << freeze[2] << " , " << freeze[3] << endl;
#elif defined(EVAL_KKPP_KKPT) || defined(EVAL_KKPPT)
cout << "freeze_kk/kkp/kpp/kkpp : " << freeze[0] << " , " << freeze[1] << " , " << freeze[2] << " , " << freeze[3] << endl;
#endif
// ----------------------------------- // -----------------------------------
// various initialization // various initialization
// ----------------------------------- // -----------------------------------
@@ -1979,12 +1795,6 @@ namespace Learner
// Read evaluation function parameters // Read evaluation function parameters
Eval::init_NNUE(); Eval::init_NNUE();
#if !defined(EVAL_NNUE)
cout << "init_grad.." << endl;
// Initialize gradient array of merit function parameters
Eval::init_grad(eta1, eta1_epoch, eta2, eta2_epoch, eta3);
#else
cout << "init_training.." << endl; cout << "init_training.." << endl;
Eval::NNUE::InitializeTraining(eta1, eta1_epoch, eta2, eta2_epoch, eta3); Eval::NNUE::InitializeTraining(eta1, eta1_epoch, eta2, eta2_epoch, eta3);
Eval::NNUE::SetBatchSize(nn_batch_size); Eval::NNUE::SetBatchSize(nn_batch_size);
@@ -1992,34 +1802,17 @@ namespace Learner
if (newbob_decay != 1.0 && !Options["SkipLoadingEval"]) { if (newbob_decay != 1.0 && !Options["SkipLoadingEval"]) {
learn_think.best_nn_directory = std::string(Options["EvalDir"]); learn_think.best_nn_directory = std::string(Options["EvalDir"]);
} }
#endif
#if 0
// A test to give a gradient of 1.0 to the initial stage of Hirate.
pos.set_hirate();
cout << Eval::evaluate(pos) << endl;
//Eval::print_eval_stat(pos);
Eval::add_grad(pos, BLACK, 32.0, false);
Eval::update_weights(1);
pos.state()->sum.p[2][0] = VALUE_NOT_EVALUATED;
cout << Eval::evaluate(pos) << endl;
//Eval::print_eval_stat(pos);
#endif
cout << "init done." << endl; cout << "init done." << endl;
// Reflect other option settings. // Reflect other option settings.
learn_think.discount_rate = discount_rate;
learn_think.eval_limit = eval_limit; learn_think.eval_limit = eval_limit;
learn_think.save_only_once = save_only_once; learn_think.save_only_once = save_only_once;
learn_think.sr.no_shuffle = no_shuffle; learn_think.sr.no_shuffle = no_shuffle;
learn_think.freeze = freeze;
learn_think.reduction_gameply = reduction_gameply; learn_think.reduction_gameply = reduction_gameply;
#if defined(EVAL_NNUE)
learn_think.newbob_scale = 1.0; learn_think.newbob_scale = 1.0;
learn_think.newbob_decay = newbob_decay; learn_think.newbob_decay = newbob_decay;
learn_think.newbob_num_trials = newbob_num_trials; learn_think.newbob_num_trials = newbob_num_trials;
#endif
learn_think.eval_save_interval = eval_save_interval; learn_think.eval_save_interval = eval_save_interval;
learn_think.loss_output_interval = loss_output_interval; learn_think.loss_output_interval = loss_output_interval;
learn_think.mirror_percentage = mirror_percentage; learn_think.mirror_percentage = mirror_percentage;
@@ -2040,7 +1833,6 @@ namespace Learner
// Calculate rmse once at this point (timing of 0 sfen) // Calculate rmse once at this point (timing of 0 sfen)
// sr.calc_rmse(); // sr.calc_rmse();
#if defined(EVAL_NNUE)
if (newbob_decay != 1.0) { if (newbob_decay != 1.0) {
learn_think.calc_loss(0, -1); learn_think.calc_loss(0, -1);
learn_think.best_loss = learn_think.latest_loss_sum / learn_think.latest_loss_count; learn_think.best_loss = learn_think.latest_loss_sum / learn_think.latest_loss_count;
@@ -2048,7 +1840,6 @@ namespace Learner
learn_think.latest_loss_count = 0; learn_think.latest_loss_count = 0;
cout << "initial loss: " << learn_think.best_loss << endl; cout << "initial loss: " << learn_think.best_loss << endl;
} }
#endif
// ----------------------------------- // -----------------------------------
// start learning evaluation function parameters // start learning evaluation function parameters
-5
View File
@@ -6,11 +6,6 @@
#include "learn.h" #include "learn.h"
#if defined (EVAL_LEARN) #if defined (EVAL_LEARN)
#include <array> #include <array>
#if defined(SGD_UPDATE) || defined(USE_KPPP_MIRROR_WRITE)
#include "../misc.h" // PRNG , my_insertion_sort
#endif
#include <cmath> // std::sqrt() #include <cmath> // std::sqrt()
namespace EvalLearningTools namespace EvalLearningTools
+4 -36
View File
@@ -142,7 +142,6 @@ namespace Eval::NNUE {
if (!Detail::ReadParameters(stream, network)) return false; if (!Detail::ReadParameters(stream, network)) return false;
return stream && stream.peek() == std::ios::traits_type::eof(); return stream && stream.peek() == std::ios::traits_type::eof();
} }
// write evaluation function parameters // write evaluation function parameters
bool WriteParameters(std::ostream& stream) { bool WriteParameters(std::ostream& stream) {
if (!WriteHeader(stream, kHashValue, GetArchitectureString())) return false; if (!WriteHeader(stream, kHashValue, GetArchitectureString())) return false;
@@ -150,32 +149,16 @@ namespace Eval::NNUE {
if (!Detail::WriteParameters(stream, network)) return false; if (!Detail::WriteParameters(stream, network)) return false;
return !stream.fail(); return !stream.fail();
} }
// Evaluation function. Perform differential calculation.
// Proceed with the difference calculation if possible Value evaluate(const Position& pos) {
static void UpdateAccumulatorIfPossible(const Position& pos) {
feature_transformer->UpdateAccumulatorIfPossible(pos);
}
// Calculate the evaluation value
static Value ComputeScore(const Position& pos, bool refresh) {
auto& accumulator = pos.state()->accumulator;
if (!refresh && accumulator.computed_score) {
return accumulator.score;
}
alignas(kCacheLineSize) TransformedFeatureType alignas(kCacheLineSize) TransformedFeatureType
transformed_features[FeatureTransformer::kBufferSize]; transformed_features[FeatureTransformer::kBufferSize];
feature_transformer->Transform(pos, transformed_features, refresh); feature_transformer->Transform(pos, transformed_features);
alignas(kCacheLineSize) char buffer[Network::kBufferSize]; alignas(kCacheLineSize) char buffer[Network::kBufferSize];
const auto output = network->Propagate(transformed_features, buffer); const auto output = network->Propagate(transformed_features, buffer);
auto score = static_cast<Value>(output[0] / FV_SCALE); return static_cast<Value>(output[0] / FV_SCALE);
accumulator.score = score;
accumulator.computed_score = true;
return accumulator.score;
} }
// Load eval, from a file stream or a memory stream // Load eval, from a file stream or a memory stream
@@ -191,19 +174,4 @@ namespace Eval::NNUE {
return ReadParameters(stream); return ReadParameters(stream);
} }
// Evaluation function. Perform differential calculation.
Value evaluate(const Position& pos) {
return ComputeScore(pos, false);
}
// Evaluation function. Perform full calculation.
Value compute_eval(const Position& pos) {
return ComputeScore(pos, true);
}
// Proceed with the difference calculation if possible
void update_eval(const Position& pos) {
UpdateAccumulatorIfPossible(pos);
}
} // namespace Eval::NNUE } // namespace Eval::NNUE
+3 -5
View File
@@ -1,6 +1,6 @@
// Code for learning NNUE evaluation function // Code for learning NNUE evaluation function
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include <random> #include <random>
#include <fstream> #include <fstream>
@@ -115,7 +115,6 @@ void RestoreParameters(const std::string& dir_name) {
std::ifstream stream(file_name, std::ios::binary); std::ifstream stream(file_name, std::ios::binary);
bool result = ReadParameters(stream); bool result = ReadParameters(stream);
assert(result); assert(result);
SendMessages({{"reset"}}); SendMessages({{"reset"}});
} }
@@ -216,9 +215,8 @@ void save_eval(std::string dir_name) {
const std::string file_name = Path::Combine(eval_dir, NNUE::savedfileName); const std::string file_name = Path::Combine(eval_dir, NNUE::savedfileName);
std::ofstream stream(file_name, std::ios::binary); std::ofstream stream(file_name, std::ios::binary);
const bool result = NNUE::WriteParameters(stream); bool result = NNUE::WriteParameters(stream);
assert(result); assert(result);
std::cout << "save_eval() finished. folder = " << eval_dir << std::endl; std::cout << "save_eval() finished. folder = " << eval_dir << std::endl;
} }
@@ -229,4 +227,4 @@ double get_eta() {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
+2 -2
View File
@@ -3,7 +3,7 @@
#ifndef _EVALUATE_NNUE_LEARNER_H_ #ifndef _EVALUATE_NNUE_LEARNER_H_
#define _EVALUATE_NNUE_LEARNER_H_ #define _EVALUATE_NNUE_LEARNER_H_
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../learn/learn.h" #include "../learn/learn.h"
@@ -41,6 +41,6 @@ void CheckHealth();
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
#endif #endif
+2 -6
View File
@@ -1,7 +1,5 @@
//Definition of input feature quantity K of NNUE evaluation function //Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "castling_right.h" #include "castling_right.h"
#include "index_list.h" #include "index_list.h"
@@ -28,7 +26,7 @@ namespace Eval {
& ((castling_rights >> 2) & 3); & ((castling_rights >> 2) & 3);
} }
for (int i = 0; i <kDimensions; ++i) { for (unsigned int i = 0; i <kDimensions; ++i) {
if (relative_castling_rights & (i << 1)) { if (relative_castling_rights & (i << 1)) {
active->push_back(i); active->push_back(i);
} }
@@ -56,7 +54,7 @@ namespace Eval {
& ((current_castling_rights >> 2) & 3); & ((current_castling_rights >> 2) & 3);
} }
for (int i = 0; i < kDimensions; ++i) { for (unsigned int i = 0; i < kDimensions; ++i) {
if ((relative_previous_castling_rights & (i << 1)) && if ((relative_previous_castling_rights & (i << 1)) &&
(relative_current_castling_rights & (i << 1)) == 0) { (relative_current_castling_rights & (i << 1)) == 0) {
removed->push_back(i); removed->push_back(i);
@@ -69,5 +67,3 @@ namespace Eval {
} // namespace NNUE } // namespace NNUE
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
-4
View File
@@ -3,8 +3,6 @@
#ifndef _NNUE_FEATURES_CASTLING_RIGHT_H_ #ifndef _NNUE_FEATURES_CASTLING_RIGHT_H_
#define _NNUE_FEATURES_CASTLING_RIGHT_H_ #define _NNUE_FEATURES_CASTLING_RIGHT_H_
#if defined(EVAL_NNUE)
#include "../../evaluate.h" #include "../../evaluate.h"
#include "features_common.h" #include "features_common.h"
@@ -43,6 +41,4 @@ namespace Eval {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
-4
View File
@@ -1,7 +1,5 @@
//Definition of input feature quantity K of NNUE evaluation function //Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "enpassant.h" #include "enpassant.h"
#include "index_list.h" #include "index_list.h"
@@ -43,5 +41,3 @@ namespace Eval {
} // namespace NNUE } // namespace NNUE
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
-4
View File
@@ -3,8 +3,6 @@
#ifndef _NNUE_FEATURES_ENPASSANT_H_ #ifndef _NNUE_FEATURES_ENPASSANT_H_
#define _NNUE_FEATURES_ENPASSANT_H_ #define _NNUE_FEATURES_ENPASSANT_H_
#if defined(EVAL_NNUE)
#include "../../evaluate.h" #include "../../evaluate.h"
#include "features_common.h" #include "features_common.h"
@@ -43,6 +41,4 @@ namespace Eval {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
-4
View File
@@ -1,7 +1,5 @@
//Definition of input features HalfRelativeKP of NNUE evaluation function //Definition of input features HalfRelativeKP of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "half_relative_kp.h" #include "half_relative_kp.h"
#include "index_list.h" #include "index_list.h"
@@ -74,5 +72,3 @@ template class HalfRelativeKP<Side::kEnemy>;
} // namespace NNUE } // namespace NNUE
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
-4
View File
@@ -3,8 +3,6 @@
#ifndef _NNUE_FEATURES_HALF_RELATIVE_KP_H_ #ifndef _NNUE_FEATURES_HALF_RELATIVE_KP_H_
#define _NNUE_FEATURES_HALF_RELATIVE_KP_H_ #define _NNUE_FEATURES_HALF_RELATIVE_KP_H_
#if defined(EVAL_NNUE)
#include "../../evaluate.h" #include "../../evaluate.h"
#include "features_common.h" #include "features_common.h"
@@ -60,6 +58,4 @@ class HalfRelativeKP {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
-4
View File
@@ -1,7 +1,5 @@
//Definition of input feature quantity K of NNUE evaluation function //Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "k.h" #include "k.h"
#include "index_list.h" #include "index_list.h"
@@ -54,5 +52,3 @@ void K::AppendChangedIndices(
} // namespace NNUE } // namespace NNUE
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
-4
View File
@@ -3,8 +3,6 @@
#ifndef _NNUE_FEATURES_K_H_ #ifndef _NNUE_FEATURES_K_H_
#define _NNUE_FEATURES_K_H_ #define _NNUE_FEATURES_K_H_
#if defined(EVAL_NNUE)
#include "../../evaluate.h" #include "../../evaluate.h"
#include "features_common.h" #include "features_common.h"
@@ -47,6 +45,4 @@ private:
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
-4
View File
@@ -1,7 +1,5 @@
//Definition of input feature P of NNUE evaluation function //Definition of input feature P of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "p.h" #include "p.h"
#include "index_list.h" #include "index_list.h"
@@ -52,5 +50,3 @@ void P::AppendChangedIndices(
} // namespace NNUE } // namespace NNUE
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
-4
View File
@@ -3,8 +3,6 @@
#ifndef _NNUE_FEATURES_P_H_ #ifndef _NNUE_FEATURES_P_H_
#define _NNUE_FEATURES_P_H_ #define _NNUE_FEATURES_P_H_
#if defined(EVAL_NNUE)
#include "../../evaluate.h" #include "../../evaluate.h"
#include "features_common.h" #include "features_common.h"
@@ -47,6 +45,4 @@ class P {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
-4
View File
@@ -3,8 +3,6 @@
#ifndef _NNUE_LAYERS_SUM_H_ #ifndef _NNUE_LAYERS_SUM_H_
#define _NNUE_LAYERS_SUM_H_ #define _NNUE_LAYERS_SUM_H_
#if defined(EVAL_NNUE)
#include "../nnue_common.h" #include "../nnue_common.h"
namespace Eval { namespace Eval {
@@ -158,6 +156,4 @@ class Sum<PreviousLayer> {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
-2
View File
@@ -29,9 +29,7 @@ namespace Eval::NNUE {
struct alignas(kCacheLineSize) Accumulator { struct alignas(kCacheLineSize) Accumulator {
std::int16_t std::int16_t
accumulation[2][kRefreshTriggers.size()][kTransformedFeatureDimensions]; accumulation[2][kRefreshTriggers.size()][kTransformedFeatureDimensions];
Value score;
bool computed_accumulation; bool computed_accumulation;
bool computed_score;
}; };
} // namespace Eval::NNUE } // namespace Eval::NNUE
+25 -33
View File
@@ -50,6 +50,7 @@ namespace Eval::NNUE {
// Hash value embedded in the evaluation file // Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t GetHashValue() {
return RawFeatures::kHashValue ^ kOutputDimensions; return RawFeatures::kHashValue ^ kOutputDimensions;
} }
@@ -62,6 +63,7 @@ namespace Eval::NNUE {
// Read network parameters // Read network parameters
bool ReadParameters(std::istream& stream) { bool ReadParameters(std::istream& stream) {
for (std::size_t i = 0; i < kHalfDimensions; ++i) for (std::size_t i = 0; i < kHalfDimensions; ++i)
biases_[i] = read_little_endian<BiasType>(stream); biases_[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < kHalfDimensions * kInputDimensions; ++i) for (std::size_t i = 0; i < kHalfDimensions * kInputDimensions; ++i)
@@ -80,23 +82,26 @@ namespace Eval::NNUE {
// Proceed with the difference calculation if possible // Proceed with the difference calculation if possible
bool UpdateAccumulatorIfPossible(const Position& pos) const { bool UpdateAccumulatorIfPossible(const Position& pos) const {
const auto now = pos.state(); const auto now = pos.state();
if (now->accumulator.computed_accumulation) { if (now->accumulator.computed_accumulation)
return true; return true;
}
const auto prev = now->previous; const auto prev = now->previous;
if (prev && prev->accumulator.computed_accumulation) { if (prev && prev->accumulator.computed_accumulation) {
UpdateAccumulator(pos); UpdateAccumulator(pos);
return true; return true;
} }
return false; return false;
} }
// Convert input features // Convert input features
void Transform(const Position& pos, OutputType* output, bool refresh) const { void Transform(const Position& pos, OutputType* output) const {
if (refresh || !UpdateAccumulatorIfPossible(pos)) {
if (!UpdateAccumulatorIfPossible(pos))
RefreshAccumulator(pos); RefreshAccumulator(pos);
}
const auto& accumulation = pos.state()->accumulator.accumulation; const auto& accumulation = pos.state()->accumulator.accumulation;
#if defined(USE_AVX2) #if defined(USE_AVX2)
@@ -193,6 +198,7 @@ namespace Eval::NNUE {
private: private:
// Calculate cumulative value without using difference calculation // Calculate cumulative value without using difference calculation
void RefreshAccumulator(const Position& pos) const { void RefreshAccumulator(const Position& pos) const {
auto& accumulator = pos.state()->accumulator; auto& accumulator = pos.state()->accumulator;
IndexType i = 0; IndexType i = 0;
Features::IndexList active_indices[2]; Features::IndexList active_indices[2];
@@ -232,9 +238,8 @@ namespace Eval::NNUE {
&accumulator.accumulation[perspective][i][0]); &accumulator.accumulation[perspective][i][0]);
auto column = reinterpret_cast<const __m64*>(&weights_[offset]); auto column = reinterpret_cast<const __m64*>(&weights_[offset]);
constexpr IndexType kNumChunks = kHalfDimensions / (kSimdWidth / 2); constexpr IndexType kNumChunks = kHalfDimensions / (kSimdWidth / 2);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = _mm_add_pi16(accumulation[j], column[j]); accumulation[j] = _mm_add_pi16(accumulation[j], column[j]);
}
#elif defined(USE_NEON) #elif defined(USE_NEON)
auto accumulation = reinterpret_cast<int16x8_t*>( auto accumulation = reinterpret_cast<int16x8_t*>(
@@ -256,11 +261,11 @@ namespace Eval::NNUE {
#endif #endif
accumulator.computed_accumulation = true; accumulator.computed_accumulation = true;
accumulator.computed_score = false;
} }
// Calculate cumulative value using difference calculation // Calculate cumulative value using difference calculation
void UpdateAccumulator(const Position& pos) const { void UpdateAccumulator(const Position& pos) const {
const auto prev_accumulator = pos.state()->previous->accumulator; const auto prev_accumulator = pos.state()->previous->accumulator;
auto& accumulator = pos.state()->accumulator; auto& accumulator = pos.state()->accumulator;
IndexType i = 0; IndexType i = 0;
@@ -304,33 +309,27 @@ namespace Eval::NNUE {
#if defined(USE_AVX2) #if defined(USE_AVX2)
auto column = reinterpret_cast<const __m256i*>(&weights_[offset]); auto column = reinterpret_cast<const __m256i*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = _mm256_sub_epi16(accumulation[j], column[j]); accumulation[j] = _mm256_sub_epi16(accumulation[j], column[j]);
}
#elif defined(USE_SSE2) #elif defined(USE_SSE2)
auto column = reinterpret_cast<const __m128i*>(&weights_[offset]); auto column = reinterpret_cast<const __m128i*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = _mm_sub_epi16(accumulation[j], column[j]); accumulation[j] = _mm_sub_epi16(accumulation[j], column[j]);
}
#elif defined(USE_MMX) #elif defined(USE_MMX)
auto column = reinterpret_cast<const __m64*>(&weights_[offset]); auto column = reinterpret_cast<const __m64*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = _mm_sub_pi16(accumulation[j], column[j]); accumulation[j] = _mm_sub_pi16(accumulation[j], column[j]);
}
#elif defined(USE_NEON) #elif defined(USE_NEON)
auto column = reinterpret_cast<const int16x8_t*>(&weights_[offset]); auto column = reinterpret_cast<const int16x8_t*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = vsubq_s16(accumulation[j], column[j]); accumulation[j] = vsubq_s16(accumulation[j], column[j]);
}
#else #else
for (IndexType j = 0; j < kHalfDimensions; ++j) { for (IndexType j = 0; j < kHalfDimensions; ++j)
accumulator.accumulation[perspective][i][j] -= accumulator.accumulation[perspective][i][j] -= weights_[offset + j];
weights_[offset + j];
}
#endif #endif
} }
@@ -341,33 +340,27 @@ namespace Eval::NNUE {
#if defined(USE_AVX2) #if defined(USE_AVX2)
auto column = reinterpret_cast<const __m256i*>(&weights_[offset]); auto column = reinterpret_cast<const __m256i*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = _mm256_add_epi16(accumulation[j], column[j]); accumulation[j] = _mm256_add_epi16(accumulation[j], column[j]);
}
#elif defined(USE_SSE2) #elif defined(USE_SSE2)
auto column = reinterpret_cast<const __m128i*>(&weights_[offset]); auto column = reinterpret_cast<const __m128i*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = _mm_add_epi16(accumulation[j], column[j]); accumulation[j] = _mm_add_epi16(accumulation[j], column[j]);
}
#elif defined(USE_MMX) #elif defined(USE_MMX)
auto column = reinterpret_cast<const __m64*>(&weights_[offset]); auto column = reinterpret_cast<const __m64*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = _mm_add_pi16(accumulation[j], column[j]); accumulation[j] = _mm_add_pi16(accumulation[j], column[j]);
}
#elif defined(USE_NEON) #elif defined(USE_NEON)
auto column = reinterpret_cast<const int16x8_t*>(&weights_[offset]); auto column = reinterpret_cast<const int16x8_t*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) { for (IndexType j = 0; j < kNumChunks; ++j)
accumulation[j] = vaddq_s16(accumulation[j], column[j]); accumulation[j] = vaddq_s16(accumulation[j], column[j]);
}
#else #else
for (IndexType j = 0; j < kHalfDimensions; ++j) { for (IndexType j = 0; j < kHalfDimensions; ++j)
accumulator.accumulation[perspective][i][j] += accumulator.accumulation[perspective][i][j] += weights_[offset + j];
weights_[offset + j];
}
#endif #endif
} }
@@ -378,7 +371,6 @@ namespace Eval::NNUE {
#endif #endif
accumulator.computed_accumulation = true; accumulator.computed_accumulation = true;
accumulator.computed_score = false;
} }
using BiasType = std::int16_t; using BiasType = std::int16_t;
+2 -2
View File
@@ -1,6 +1,6 @@
// USI extended command for NNUE evaluation function // USI extended command for NNUE evaluation function
#if defined(ENABLE_TEST_CMD) && defined(EVAL_NNUE) #if defined(ENABLE_TEST_CMD)
#include "../thread.h" #include "../thread.h"
#include "../uci.h" #include "../uci.h"
@@ -198,4 +198,4 @@ void TestCommand(Position& pos, std::istream& stream) {
} // namespace Eval } // namespace Eval
#endif // defined(ENABLE_TEST_CMD) && defined(EVAL_NNUE) #endif // defined(ENABLE_TEST_CMD)
+2 -2
View File
@@ -3,7 +3,7 @@
#ifndef _NNUE_TEST_COMMAND_H_ #ifndef _NNUE_TEST_COMMAND_H_
#define _NNUE_TEST_COMMAND_H_ #define _NNUE_TEST_COMMAND_H_
#if defined(ENABLE_TEST_CMD) && defined(EVAL_NNUE) #if defined(ENABLE_TEST_CMD)
namespace Eval { namespace Eval {
@@ -16,6 +16,6 @@ void TestCommand(Position& pos, std::istream& stream);
} // namespace Eval } // namespace Eval
#endif // defined(ENABLE_TEST_CMD) && defined(EVAL_NNUE) #endif // defined(ENABLE_TEST_CMD)
#endif #endif
-4
View File
@@ -3,8 +3,6 @@
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_H_ #ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_H_
#define _NNUE_TRAINER_FEATURES_FACTORIZER_H_ #define _NNUE_TRAINER_FEATURES_FACTORIZER_H_
#if defined(EVAL_NNUE)
#include "../../nnue_common.h" #include "../../nnue_common.h"
#include "../trainer.h" #include "../trainer.h"
@@ -105,6 +103,4 @@ constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
@@ -3,8 +3,6 @@
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_ #ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_
#define _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_ #define _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_
#if defined(EVAL_NNUE)
#include "../../features/feature_set.h" #include "../../features/feature_set.h"
#include "factorizer.h" #include "factorizer.h"
@@ -99,6 +97,4 @@ public:
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
@@ -3,8 +3,6 @@
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_ #ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_
#define _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_ #define _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_
#if defined(EVAL_NNUE)
#include "../../features/half_kp.h" #include "../../features/half_kp.h"
#include "../../features/p.h" #include "../../features/p.h"
#include "../../features/half_relative_kp.h" #include "../../features/half_relative_kp.h"
@@ -98,6 +96,4 @@ constexpr FeatureProperties Factorizer<HalfKP<AssociatedKing>>::kProperties[];
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_NNUE)
#endif #endif
+4 -4
View File
@@ -3,7 +3,7 @@
#ifndef _NNUE_TRAINER_H_ #ifndef _NNUE_TRAINER_H_
#define _NNUE_TRAINER_H_ #define _NNUE_TRAINER_H_
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../nnue_common.h" #include "../nnue_common.h"
#include "../features/index_list.h" #include "../features/index_list.h"
@@ -70,8 +70,8 @@ struct Example {
// Message used for setting hyperparameters // Message used for setting hyperparameters
struct Message { struct Message {
Message(const std::string& name, const std::string& value = ""): Message(const std::string& in_name, const std::string& in_value = ""):
name(name), value(value), num_peekers(0), num_receivers(0) {} name(in_name), value(in_value), num_peekers(0), num_receivers(0) {}
const std::string name; const std::string name;
const std::string value; const std::string value;
std::uint32_t num_peekers; std::uint32_t num_peekers;
@@ -120,6 +120,6 @@ std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments) {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
#endif #endif
+2 -2
View File
@@ -3,7 +3,7 @@
#ifndef _NNUE_TRAINER_AFFINE_TRANSFORM_H_ #ifndef _NNUE_TRAINER_AFFINE_TRANSFORM_H_
#define _NNUE_TRAINER_AFFINE_TRANSFORM_H_ #define _NNUE_TRAINER_AFFINE_TRANSFORM_H_
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../../learn/learn.h" #include "../../learn/learn.h"
#include "../layers/affine_transform.h" #include "../layers/affine_transform.h"
@@ -296,6 +296,6 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
#endif #endif
+2 -2
View File
@@ -3,7 +3,7 @@
#ifndef _NNUE_TRAINER_CLIPPED_RELU_H_ #ifndef _NNUE_TRAINER_CLIPPED_RELU_H_
#define _NNUE_TRAINER_CLIPPED_RELU_H_ #define _NNUE_TRAINER_CLIPPED_RELU_H_
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../../learn/learn.h" #include "../../learn/learn.h"
#include "../layers/clipped_relu.h" #include "../layers/clipped_relu.h"
@@ -137,6 +137,6 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
#endif #endif
@@ -3,7 +3,7 @@
#ifndef _NNUE_TRAINER_FEATURE_TRANSFORMER_H_ #ifndef _NNUE_TRAINER_FEATURE_TRANSFORMER_H_
#define _NNUE_TRAINER_FEATURE_TRANSFORMER_H_ #define _NNUE_TRAINER_FEATURE_TRANSFORMER_H_
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../../learn/learn.h" #include "../../learn/learn.h"
#include "../nnue_feature_transformer.h" #include "../nnue_feature_transformer.h"
@@ -372,6 +372,6 @@ class Trainer<FeatureTransformer> {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
#endif #endif
+2 -2
View File
@@ -3,7 +3,7 @@
#ifndef _NNUE_TRAINER_INPUT_SLICE_H_ #ifndef _NNUE_TRAINER_INPUT_SLICE_H_
#define _NNUE_TRAINER_INPUT_SLICE_H_ #define _NNUE_TRAINER_INPUT_SLICE_H_
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../../learn/learn.h" #include "../../learn/learn.h"
#include "../layers/input_slice.h" #include "../layers/input_slice.h"
@@ -246,6 +246,6 @@ class Trainer<Layers::InputSlice<OutputDimensions, Offset>> {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
#endif #endif
+2 -2
View File
@@ -3,7 +3,7 @@
#ifndef _NNUE_TRAINER_SUM_H_ #ifndef _NNUE_TRAINER_SUM_H_
#define _NNUE_TRAINER_SUM_H_ #define _NNUE_TRAINER_SUM_H_
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN)
#include "../../learn/learn.h" #include "../../learn/learn.h"
#include "../layers/sum.h" #include "../layers/sum.h"
@@ -185,6 +185,6 @@ class Trainer<Layers::Sum<PreviousLayer>> {
} // namespace Eval } // namespace Eval
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN)
#endif #endif
-2
View File
@@ -704,7 +704,6 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// Used by NNUE // Used by NNUE
st->accumulator.computed_accumulation = false; st->accumulator.computed_accumulation = false;
st->accumulator.computed_score = false;
auto& dp = st->dirtyPiece; auto& dp = st->dirtyPiece;
dp.dirty_num = 1; dp.dirty_num = 1;
@@ -1000,7 +999,6 @@ void Position::do_null_move(StateInfo& newSt) {
if (Eval::useNNUE) if (Eval::useNNUE)
{ {
std::memcpy(&newSt, st, sizeof(StateInfo)); std::memcpy(&newSt, st, sizeof(StateInfo));
st->accumulator.computed_score = false;
} }
else else
std::memcpy(&newSt, st, offsetof(StateInfo, accumulator)); std::memcpy(&newSt, st, offsetof(StateInfo, accumulator));
+27 -39
View File
@@ -597,7 +597,7 @@ namespace {
Move ttMove, move, excludedMove, bestMove; Move ttMove, move, excludedMove, bestMove;
Depth extension, newDepth; Depth extension, newDepth;
Value bestValue, value, ttValue, eval, maxValue, probCutBeta; Value bestValue, value, ttValue, eval, maxValue, probCutBeta;
bool ttHit, formerPv, givesCheck, improving, didLMR, priorCapture; bool formerPv, givesCheck, improving, didLMR, priorCapture;
bool captureOrPromotion, doFullDepthSearch, moveCountPruning, bool captureOrPromotion, doFullDepthSearch, moveCountPruning,
ttCapture, singularQuietLMR; ttCapture, singularQuietLMR;
Piece movedPiece; Piece movedPiece;
@@ -664,12 +664,12 @@ namespace {
// position key in case of an excluded move. // position key in case of an excluded move.
excludedMove = ss->excludedMove; excludedMove = ss->excludedMove;
posKey = excludedMove == MOVE_NONE ? pos.key() : pos.key() ^ make_key(excludedMove); posKey = excludedMove == MOVE_NONE ? pos.key() : pos.key() ^ make_key(excludedMove);
tte = TT.probe(posKey, ttHit); tte = TT.probe(posKey, ss->ttHit);
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE; ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0] ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
: ttHit ? tte->move() : MOVE_NONE; : ss->ttHit ? tte->move() : MOVE_NONE;
if (!excludedMove) if (!excludedMove)
ss->ttPv = PvNode || (ttHit && tte->is_pv()); ss->ttPv = PvNode || (ss->ttHit && tte->is_pv());
formerPv = ss->ttPv && !PvNode; formerPv = ss->ttPv && !PvNode;
if ( ss->ttPv if ( ss->ttPv
@@ -681,11 +681,11 @@ namespace {
// thisThread->ttHitAverage can be used to approximate the running average of ttHit // thisThread->ttHitAverage can be used to approximate the running average of ttHit
thisThread->ttHitAverage = (TtHitAverageWindow - 1) * thisThread->ttHitAverage / TtHitAverageWindow thisThread->ttHitAverage = (TtHitAverageWindow - 1) * thisThread->ttHitAverage / TtHitAverageWindow
+ TtHitAverageResolution * ttHit; + TtHitAverageResolution * ss->ttHit;
// At non-PV nodes we check for an early TT cutoff // At non-PV nodes we check for an early TT cutoff
if ( !PvNode if ( !PvNode
&& ttHit && ss->ttHit
&& tte->depth() >= depth && tte->depth() >= depth
&& ttValue != VALUE_NONE // Possible in case of TT access race && ttValue != VALUE_NONE // Possible in case of TT access race
&& (ttValue >= beta ? (tte->bound() & BOUND_LOWER) && (ttValue >= beta ? (tte->bound() & BOUND_LOWER)
@@ -778,7 +778,7 @@ namespace {
improving = false; improving = false;
goto moves_loop; goto moves_loop;
} }
else if (ttHit) else if (ss->ttHit)
{ {
// Never assume anything about values stored in TT // Never assume anything about values stored in TT
ss->staticEval = eval = tte->eval(); ss->staticEval = eval = tte->eval();
@@ -882,14 +882,14 @@ namespace {
// there and in further interactions with transposition table cutoff depth is set to depth - 3 // there and in further interactions with transposition table cutoff depth is set to depth - 3
// because probCut search has depth set to depth - 4 but we also do a move before it // because probCut search has depth set to depth - 4 but we also do a move before it
// so effective depth is equal to depth - 3 // so effective depth is equal to depth - 3
&& !( ttHit && !( ss->ttHit
&& tte->depth() >= depth - 3 && tte->depth() >= depth - 3
&& ttValue != VALUE_NONE && ttValue != VALUE_NONE
&& ttValue < probCutBeta)) && ttValue < probCutBeta))
{ {
// if ttMove is a capture and value from transposition table is good enough produce probCut // if ttMove is a capture and value from transposition table is good enough produce probCut
// cutoff without digging into actual probCut search // cutoff without digging into actual probCut search
if ( ttHit if ( ss->ttHit
&& tte->depth() >= depth - 3 && tte->depth() >= depth - 3
&& ttValue != VALUE_NONE && ttValue != VALUE_NONE
&& ttValue >= probCutBeta && ttValue >= probCutBeta
@@ -933,7 +933,7 @@ namespace {
if (value >= probCutBeta) if (value >= probCutBeta)
{ {
// if transposition table doesn't have equal or more deep info write probCut data into it // if transposition table doesn't have equal or more deep info write probCut data into it
if ( !(ttHit if ( !(ss->ttHit
&& tte->depth() >= depth - 3 && tte->depth() >= depth - 3
&& ttValue != VALUE_NONE)) && ttValue != VALUE_NONE))
tte->save(posKey, value_to_tt(value, ss->ply), ttPv, tte->save(posKey, value_to_tt(value, ss->ply), ttPv,
@@ -1018,7 +1018,6 @@ moves_loop: // When in check, search starts from here
// Step 13. Pruning at shallow depth (~200 Elo) // Step 13. Pruning at shallow depth (~200 Elo)
if ( !rootNode if ( !rootNode
&& !(Options["Training"] && PvNode)
&& pos.non_pawn_material(us) && pos.non_pawn_material(us)
&& bestValue > VALUE_TB_LOSS_IN_MAX_PLY) && bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
{ {
@@ -1173,13 +1172,6 @@ moves_loop: // When in check, search starts from here
{ {
Depth r = reduction(improving, depth, moveCount); Depth r = reduction(improving, depth, moveCount);
// Decrease reduction at non-check cut nodes for second move at low depths
if ( cutNode
&& depth <= 10
&& moveCount <= 2
&& !ss->inCheck)
r--;
// Decrease reduction if the ttHit running average is large // Decrease reduction if the ttHit running average is large
if (thisThread->ttHitAverage > 509 * TtHitAverageResolution * TtHitAverageWindow / 1024) if (thisThread->ttHitAverage > 509 * TtHitAverageResolution * TtHitAverageWindow / 1024)
r--; r--;
@@ -1201,7 +1193,7 @@ moves_loop: // When in check, search starts from here
// Decrease reduction if ttMove has been singularly extended (~3 Elo) // Decrease reduction if ttMove has been singularly extended (~3 Elo)
if (singularQuietLMR) if (singularQuietLMR)
r -= 1 + formerPv; r--;
if (!captureOrPromotion) if (!captureOrPromotion)
{ {
@@ -1435,7 +1427,7 @@ moves_loop: // When in check, search starts from here
Move ttMove, move, bestMove; Move ttMove, move, bestMove;
Depth ttDepth; Depth ttDepth;
Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha; Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha;
bool ttHit, pvHit, givesCheck, captureOrPromotion; bool pvHit, givesCheck, captureOrPromotion;
int moveCount; int moveCount;
if (PvNode) if (PvNode)
@@ -1465,13 +1457,13 @@ moves_loop: // When in check, search starts from here
: DEPTH_QS_NO_CHECKS; : DEPTH_QS_NO_CHECKS;
// Transposition table lookup // Transposition table lookup
posKey = pos.key(); posKey = pos.key();
tte = TT.probe(posKey, ttHit); tte = TT.probe(posKey, ss->ttHit);
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE; ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = ttHit ? tte->move() : MOVE_NONE; ttMove = ss->ttHit ? tte->move() : MOVE_NONE;
pvHit = ttHit && tte->is_pv(); pvHit = ss->ttHit && tte->is_pv();
if ( !PvNode if ( !PvNode
&& ttHit && ss->ttHit
&& tte->depth() >= ttDepth && tte->depth() >= ttDepth
&& ttValue != VALUE_NONE // Only in case of TT access race && ttValue != VALUE_NONE // Only in case of TT access race
&& (ttValue >= beta ? (tte->bound() & BOUND_LOWER) && (ttValue >= beta ? (tte->bound() & BOUND_LOWER)
@@ -1486,7 +1478,7 @@ moves_loop: // When in check, search starts from here
} }
else else
{ {
if (ttHit) if (ss->ttHit)
{ {
// Never assume anything about values stored in TT // Never assume anything about values stored in TT
if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE) if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE)
@@ -1505,7 +1497,7 @@ moves_loop: // When in check, search starts from here
// Stand pat. Return immediately if static value is at least beta // Stand pat. Return immediately if static value is at least beta
if (bestValue >= beta) if (bestValue >= beta)
{ {
if (!ttHit) if (!ss->ttHit)
tte->save(posKey, value_to_tt(bestValue, ss->ply), false, BOUND_LOWER, tte->save(posKey, value_to_tt(bestValue, ss->ply), false, BOUND_LOWER,
DEPTH_NONE, MOVE_NONE, ss->staticEval); DEPTH_NONE, MOVE_NONE, ss->staticEval);
@@ -1569,20 +1561,16 @@ moves_loop: // When in check, search starts from here
} }
// Do not search moves with negative SEE values // Do not search moves with negative SEE values
if ( !ss->inCheck && !pos.see_ge(move)) if ( !ss->inCheck
&& !(givesCheck && pos.is_discovery_check_on_king(~pos.side_to_move(), move))
&& !pos.see_ge(move))
continue; continue;
// Speculative prefetch as early as possible // Speculative prefetch as early as possible
prefetch(TT.first_entry(pos.key_after(move))); prefetch(TT.first_entry(pos.key_after(move)));
// Check for legality just before making the move // Check for legality just before making the move
if ( if (!pos.legal(move))
#if defined(EVAL_LEARN)
// HACK: pos.piece_on(from_sq(m)) sometimes will be NO_PIECE during machine learning.
!pos.pseudo_legal(move) ||
#endif // EVAL_LEARN
!pos.legal(move)
)
{ {
moveCount--; moveCount--;
continue; continue;
@@ -1727,8 +1715,8 @@ moves_loop: // When in check, search starts from here
else else
captureHistory[moved_piece][to_sq(bestMove)][captured] << bonus1; captureHistory[moved_piece][to_sq(bestMove)][captured] << bonus1;
// Extra penalty for a quiet TT or main killer move in previous ply when it gets refuted // Extra penalty for a quiet early move that was not a TT move or main killer move in previous ply when it gets refuted
if ( ((ss-1)->moveCount == 1 || ((ss-1)->currentMove == (ss-1)->killers[0])) if ( ((ss-1)->moveCount == 1 + (ss-1)->ttHit || ((ss-1)->currentMove == (ss-1)->killers[0]))
&& !pos.captured_piece()) && !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -bonus1); update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -bonus1);
@@ -2276,7 +2264,7 @@ namespace Learner
} }
// Pass PV_is(ok) to eliminate this PV, there may be NULL_MOVE in the middle. // Pass PV_is(ok) to eliminate this PV, there may be NULL_MOVE in the middle.
// ¨ PV should not be NULL_MOVE because it is PV // ?¡L PV should not be NULL_MOVE because it is PV
// MOVE_WIN has never been thrust. (For now) // MOVE_WIN has never been thrust. (For now)
for (Move move : rootMoves[0].pv) for (Move move : rootMoves[0].pv)
{ {
+1
View File
@@ -49,6 +49,7 @@ struct Stack {
int moveCount; int moveCount;
bool inCheck; bool inCheck;
bool ttPv; bool ttPv;
bool ttHit;
}; };
+2
View File
@@ -223,7 +223,9 @@ public:
*mapping = statbuf.st_size; *mapping = statbuf.st_size;
*baseAddress = mmap(nullptr, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); *baseAddress = mmap(nullptr, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
#if defined(MADV_RANDOM)
madvise(*baseAddress, statbuf.st_size, MADV_RANDOM); madvise(*baseAddress, statbuf.st_size, MADV_RANDOM);
#endif
::close(fd); ::close(fd);
if (*baseAddress == MAP_FAILED) if (*baseAddress == MAP_FAILED)
+1
View File
@@ -115,6 +115,7 @@ void TranspositionTable::clear() {
/// TTEntry t2 if its replace value is greater than that of t2. /// TTEntry t2 if its replace value is greater than that of t2.
TTEntry* TranspositionTable::probe(const Key key, bool& found) const { TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
if (Options["Training"]) { if (Options["Training"]) {
return found = false, first_entry(0); return found = false, first_entry(0);
} }
+3 -11
View File
@@ -32,7 +32,7 @@
#include "uci.h" #include "uci.h"
#include "syzygy/tbprobe.h" #include "syzygy/tbprobe.h"
#if defined(EVAL_NNUE) && defined(ENABLE_TEST_CMD) #if defined(ENABLE_TEST_CMD)
#include "nnue/nnue_test_command.h" #include "nnue/nnue_test_command.h"
#endif #endif
@@ -53,10 +53,6 @@ namespace Learner
// Learning from the generated game record // Learning from the generated game record
void learn(Position& pos, istringstream& is); void learn(Position& pos, istringstream& is);
#if defined(GENSFEN2019)
// Automatic generation command of teacher phase under development
void gen_sfen2019(Position& pos, istringstream& is);
#endif
// A pair of reader and evaluation value. Returned by Learner::search(),Learner::qsearch(). // A pair of reader and evaluation value. Returned by Learner::search(),Learner::qsearch().
typedef std::pair<Value, std::vector<Move> > ValueAndPV; typedef std::pair<Value, std::vector<Move> > ValueAndPV;
@@ -67,7 +63,7 @@ namespace Learner
} }
#endif #endif
#if defined(EVAL_NNUE) && defined(ENABLE_TEST_CMD) #if defined(ENABLE_TEST_CMD)
void test_cmd(Position& pos, istringstream& is) void test_cmd(Position& pos, istringstream& is)
{ {
// Initialize as it may be searched. // Initialize as it may be searched.
@@ -363,17 +359,13 @@ void UCI::loop(int argc, char* argv[]) {
else if (token == "gensfen") Learner::gen_sfen(pos, is); else if (token == "gensfen") Learner::gen_sfen(pos, is);
else if (token == "learn") Learner::learn(pos, is); else if (token == "learn") Learner::learn(pos, is);
#if defined (GENSFEN2019)
// Command to generate teacher phase under development
else if (token == "gensfen2019") Learner::gen_sfen2019(pos, is);
#endif
// Command to call qsearch(),search() directly for testing // Command to call qsearch(),search() directly for testing
else if (token == "qsearch") qsearch_cmd(pos); else if (token == "qsearch") qsearch_cmd(pos);
else if (token == "search") search_cmd(pos, is); else if (token == "search") search_cmd(pos, is);
#endif #endif
#if defined(EVAL_NNUE) && defined(ENABLE_TEST_CMD) #if defined(ENABLE_TEST_CMD)
// test command // test command
else if (token == "test") test_cmd(pos, is); else if (token == "test") test_cmd(pos, is);
#endif #endif