1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-07-11 19:49:14 +00:00

Merge pull request #24 from FireFather/master

Comment translation
This commit is contained in:
nodchip 2020-06-28 11:43:53 +09:00 committed by GitHub
commit 9dc62809c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 1903 additions and 1905 deletions

View file

@ -1,75 +1,75 @@
#ifndef _EVALUATE_COMMON_H_ #ifndef _EVALUATE_COMMON_H_
#define _EVALUATE_COMMON_H_ #define _EVALUATE_COMMON_H_
// いまどきの手番つき評価関数(EVAL_KPPTとEVAL_KPP_KKPT)の共用header的なもの。 // A common header-like function for modern evaluation functions (EVAL_KPPT and EVAL_KPP_KKPT).
#if defined(EVAL_NNUE) || defined(EVAL_LEARN) #if defined(EVAL_NNUE) || defined(EVAL_LEARN)
#include <functional> #include <functional>
// KKファイル名 // KK file name
#define KK_BIN "KK_synthesized.bin" #define KK_BIN "KK_synthesized.bin"
// KKPファイル名 // KKP file name
#define KKP_BIN "KKP_synthesized.bin" #define KKP_BIN "KKP_synthesized.bin"
// KPPファイル名 // KPP file name
#define KPP_BIN "KPP_synthesized.bin" #define KPP_BIN "KPP_synthesized.bin"
namespace Eval namespace Eval
{ {
#if defined(USE_EVAL_HASH) #if defined(USE_EVAL_HASH)
// prefetchする関数 // prefetch function
void prefetch_evalhash(const Key key); void prefetch_evalhash(const Key key);
#endif #endif
// 評価関数のそれぞれのパラメーターに対して関数fを適用してくれるoperator。 // An operator that applies the function f to each parameter of the evaluation function.
// パラメーターの分析などに用いる。 // Used for parameter analysis etc.
// typeは調査対象を表す。 // type indicates the survey target.
// type = -1 : KK,KKP,KPPすべて // type = -1 :KK,KKP,KPP all
// type = 0 : KK のみ // type = 0: KK only
// type = 1 : KKPのみ // type = 1: KKP only
// type = 2 : KPPのみ // type = 2: KPP only
void foreach_eval_param(std::function<void(int32_t, int32_t)>f, int type = -1); void foreach_eval_param(std::function<void(int32_t, int32_t)>f, int type = -1);
// -------------------------- // --------------------------
// 学習用 // for learning
// -------------------------- // --------------------------
#if defined(EVAL_LEARN) #if defined(EVAL_LEARN)
// 学習のときの勾配配列の初期化 // Initialize the gradient array during learning
// 学習率を引数に渡しておく。0.0なら、defaultの値を採用する。 // Pass the learning rate as an argument. If 0.0, the default value is used.
// update_weights()のepochが、eta_epochまでetaから徐々にeta2に変化する。 // The epoch of update_weights() gradually changes from eta to eta2 until eta_epoch.
// eta2_epoch以降は、eta2から徐々にeta3に変化する。 // After eta2_epoch, gradually change from eta2 to eta3.
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.
// freeze[0] : kkは学習させないフラグ // freeze[0]: Flag that kk does not learn
// freeze[1] : kkpは学習させないフラグ // freeze[1]: Flag that kkp does not learn
// freeze[2] : kppは学習させないフラグ // freeze[2]: Flag that kpp does not learn
// freeze[3] : kpppは学習させないフラグ // freeze[3]: Flag that kppp does not learn
void add_grad(Position& pos, Color rootColor, double delt_grad, const std::array<bool, 4>& freeze); void add_grad(Position& pos, Color rootColor, double delt_grad, const std::array<bool, 4>& freeze);
// 現在の勾配をもとにSGDかAdaGradか何かする。 // Do SGD or AdaGrad or something based on the current gradient.
// epoch : 世代カウンター(0から始まる) // epoch: Generation counter (starting from 0)
// freeze[0] : kkは学習させないフラグ // freeze[0]: Flag that kk does not learn
// freeze[1] : kkpは学習させないフラグ // freeze[1]: Flag that kkp does not learn
// freeze[2] : kppは学習させないフラグ // freeze[2]: Flag that kpp does not learn
// freeze[3] : kpppは学習させないフラグ // freeze[3]: Flag that kppp does not learn
void update_weights(uint64_t epoch, const std::array<bool,4>& freeze); void update_weights(uint64_t epoch, const std::array<bool, 4>& freeze);
// 評価関数パラメーターをファイルに保存する。 // Save the evaluation function parameters to a file.
// ファイルの末尾につける拡張子を指定できる。 // You can specify the extension added to the end of the file.
void save_eval(std::string suffix); void save_eval(std::string suffix);
// 現在のetaを取得する。 // Get the current eta.
double get_eta(); double get_eta();
// -- 学習に関連したコマンド // --learning related commands
// KKを正規化する関数。元の評価関数と完全に等価にはならないので注意。 // A function that normalizes KK. Note that it is not completely equivalent to the original evaluation function.
// kkp,kppの値をなるべくゼロに近づけることで、学習中に出現しなかった特徴因子の値(ゼロになっている)が // By making the values of kkp and kpp as close to zero as possible, the value of the feature factor (which is zero) that did not appear during learning
// 妥当であることを保証しようという考え。 // The idea of ensuring it is valid.
void regularize_kk(); void regularize_kk();
#endif #endif

View file

@ -7,35 +7,35 @@ namespace Eval
// --- tables // --- tables
// あるBonaPieceを相手側から見たときの値 // Value when a certain BonaPiece is seen from the other side
// BONA_PIECE_INITが-1なので符号型で持つ必要がある。 // BONA_PIECE_INIT is -1, so it must be a signed type.
// KPPTを拡張しても当面、BonaPieceが2^15を超えることはないのでint16_tで良しとする。 // Even if KPPT is expanded, BonaPiece will not exceed 2^15 for the time being, so int16_t is good.
int16_t inv_piece_[Eval::fe_end]; int16_t inv_piece_[Eval::fe_end];
// 盤面上のあるBonaPieceをミラーした位置にあるものを返す。 // Returns the one at the position where a BonaPiece on the board is mirrored.
int16_t mir_piece_[Eval::fe_end]; int16_t mir_piece_[Eval::fe_end];
// --- methods // --- methods
// あるBonaPieceを相手側から見たときの値を返す // Returns the value when a certain BonaPiece is seen from the other side
Eval::BonaPiece inv_piece(Eval::BonaPiece p) { return (Eval::BonaPiece)inv_piece_[p]; } Eval::BonaPiece inv_piece(Eval::BonaPiece p) { return (Eval::BonaPiece)inv_piece_[p]; }
// 盤面上のあるBonaPieceをミラーした位置にあるものを返す。 // Returns the one at the position where a BonaPiece on the board is mirrored.
Eval::BonaPiece mir_piece(Eval::BonaPiece p) { return (Eval::BonaPiece)mir_piece_[p]; } Eval::BonaPiece mir_piece(Eval::BonaPiece p) { return (Eval::BonaPiece)mir_piece_[p]; }
std::function<void()> mir_piece_init_function; std::function<void()> mir_piece_init_function;
void init_mir_inv_tables() void init_mir_inv_tables()
{ {
// mirrorとinverseのテーブルの初期化。 // Initialize the mirror and inverse tables.
// 初期化は1回に限る。 // Initialization is limited to once.
static bool first = true; static bool first = true;
if (!first) return; if (!first) return;
first = false; first = false;
// fとeとの交換 // exchange f and e
int t[] = { int t[] = {
f_pawn , e_pawn , f_pawn , e_pawn ,
f_knight , e_knight , f_knight , e_knight ,
@ -44,12 +44,12 @@ namespace Eval
f_queen , e_queen , f_queen , e_queen ,
}; };
// 未初期化の値を突っ込んでおく。 // Insert uninitialized value.
for (BonaPiece p = BONA_PIECE_ZERO; p < fe_end; ++p) for (BonaPiece p = BONA_PIECE_ZERO; p < fe_end; ++p)
{ {
inv_piece_[p] = BONA_PIECE_NOT_INIT; inv_piece_[p] = BONA_PIECE_NOT_INIT;
// mirrorは手駒に対しては機能しない。元の値を返すだけ。 // mirror does not work for hand pieces. Just return the original value.
mir_piece_[p] = (p < f_pawn) ? p : BONA_PIECE_NOT_INIT; mir_piece_[p] = (p < f_pawn) ? p : BONA_PIECE_NOT_INIT;
} }
@ -61,26 +61,26 @@ namespace Eval
{ {
Square sq = (Square)(p - t[i]); Square sq = (Square)(p - t[i]);
// 見つかった!! // found!!
BonaPiece q = (p < fe_hand_end) ? BonaPiece(sq + t[i + 1]) : (BonaPiece)(Inv(sq) + t[i + 1]); BonaPiece q = (p < fe_hand_end) ? BonaPiece(sq + t[i + 1]) : (BonaPiece)(Inv(sq) + t[i + 1]);
inv_piece_[p] = q; inv_piece_[p] = q;
inv_piece_[q] = p; inv_piece_[q] = p;
/* /*
pに関して盤上の駒は It's a bit tricky, but regarding p
p >= fe_hand_end p >= fe_hand_end
When.
pに対してnを整数として(iは偶数しかとらない) For this p, let n be an integer (i in the above code can only be an even number),
a) t[2n + 0] <= p < t[2n + 1] a) When t[2n + 0] <= p <t[2n + 1], the first piece
b) t[2n + 1] <= p < t[2n + 2] b) When t[2n + 1] <= p <t[2n + 2], the back piece
  Is.
a)pをq = Inv(p-t[2n+0]) + t[2n+1] 180 Therefore, if p in the range of a) is set to q = Inv(p-t[2n+0]) + t[2n+1], it becomes the back piece in the box rotated 180 degrees.
pとqをswapさせてinv_piece[ ] So inv_piece[] is initialized by swapping p and q.
*/ */
// 手駒に関してはmirrorなど存在しない。 // There is no mirror for hand pieces.
if (p < fe_hand_end) if (p < fe_hand_end)
continue; continue;
@ -103,28 +103,28 @@ namespace Eval
for (BonaPiece p = BONA_PIECE_ZERO; p < fe_end; ++p) for (BonaPiece p = BONA_PIECE_ZERO; p < fe_end; ++p)
{ {
// 未初期化のままになっている。上のテーブルの初期化コードがおかしい。 // It remains uninitialized. The initialization code in the table above is incorrect.
assert(mir_piece_[p] != BONA_PIECE_NOT_INIT && mir_piece_[p] < fe_end); assert(mir_piece_[p] != BONA_PIECE_NOT_INIT && mir_piece_[p] < fe_end);
assert(inv_piece_[p] != BONA_PIECE_NOT_INIT && inv_piece_[p] < fe_end); assert(inv_piece_[p] != BONA_PIECE_NOT_INIT && inv_piece_[p] < fe_end);
// mirとinvは、2回適用したら元の座標に戻る。 // mir and inv return to their original coordinates after being applied twice.
assert(mir_piece_[mir_piece_[p]] == p); assert(mir_piece_[mir_piece_[p]] == p);
assert(inv_piece_[inv_piece_[p]] == p); assert(inv_piece_[inv_piece_[p]] == p);
// mir->inv->mir->invは元の場所でなければならない。 // mir->inv->mir->inv must be the original location.
assert(p == inv_piece(mir_piece(inv_piece(mir_piece(p))))); assert(p == inv_piece(mir_piece(inv_piece(mir_piece(p)))));
// inv->mir->inv->mirは元の場所でなければならない。 // inv->mir->inv->mir must be the original location.
assert(p == mir_piece(inv_piece(mir_piece(inv_piece(p))))); assert(p == mir_piece(inv_piece(mir_piece(inv_piece(p)))));
} }
#if 0 #if 0
// 評価関数のミラーをしても大丈夫であるかの事前検証 // Pre-verification that it is okay to mirror the evaluation function
// 値を書き込んだときにassertionがあるので、ミラーしてダメである場合、 // When writing a value, there is an assertion, so if you can't mirror it,
// そのassertに引っかかるはず。 // Should get caught in the assert.
// AperyのWCSC26の評価関数、kppのp1==0とかp1==20(後手の0枚目の歩)とかの // Apery's WCSC26 evaluation function, kpp p1==0 or p1==20 (0th step on the back)
// ところにゴミが入っていて、これを回避しないとassertに引っかかる。 // There is dust in it, and if you don't avoid it, it will get caught in the assert.
std::unordered_set<BonaPiece> s; std::unordered_set<BonaPiece> s;
vector<int> a = { vector<int> a = {
@ -139,24 +139,24 @@ namespace Eval
for (auto b : a) for (auto b : a)
s.insert((BonaPiece)b); s.insert((BonaPiece)b);
// さらに出現しない升の盤上の歩、香、桂も除外(Aperyはここにもゴミが入っている) // Excludes walks, incense, and katsura on the board that do not appear further (Apery also contains garbage here)
for (Rank r = RANK_1; r <= RANK_2; ++r) for (Rank r = RANK_1; r <= RANK_2; ++r)
for (File f = FILE_1; f <= FILE_9; ++f) for (File f = FILE_1; f <= FILE_9; ++f)
{ {
if (r == RANK_1) if (r == RANK_1)
{ {
// 1段目の歩 // first step
BonaPiece b1 = BonaPiece(f_pawn + (f | r)); BonaPiece b1 = BonaPiece(f_pawn + (f | r));
s.insert(b1); s.insert(b1);
s.insert(inv_piece[b1]); s.insert(inv_piece[b1]);
// 1段目の香 // 1st stage incense
BonaPiece b2 = BonaPiece(f_lance + (f | r)); BonaPiece b2 = BonaPiece(f_lance + (f | r));
s.insert(b2); s.insert(b2);
s.insert(inv_piece[b2]); s.insert(inv_piece[b2]);
} }
// 1,2段目の桂 // Katsura on the 1st and 2nd steps
BonaPiece b = BonaPiece(f_knight + (f | r)); BonaPiece b = BonaPiece(f_knight + (f | r));
s.insert(b); s.insert(b);
s.insert(inv_piece[b]); s.insert(inv_piece[b]);

View file

@ -3,7 +3,7 @@
#if defined(EVAL_NNUE) || defined(EVAL_LEARN) #if defined(EVAL_NNUE) || defined(EVAL_LEARN)
// BonaPieceのmirror(左右反転)やinverse(盤上の180度回転)させた駒を得るためのツール類。 // BonaPiece's mirror (horizontal flip) and inverse (180° on the board) tools to get pieces.
#include "../types.h" #include "../types.h"
#include "../evaluate.h" #include "../evaluate.h"
@ -15,33 +15,33 @@ namespace Eval
// tables // tables
// ------------------------------------------------- // -------------------------------------------------
// --- BonaPieceに対してMirrorとInverseを提供する。 // --- Provide Mirror and Inverse to BonaPiece.
// これらの配列は、init()かinit_mir_inv_tables();を呼び出すと初期化される。 // These arrays are initialized by calling init() or init_mir_inv_tables();.
// このテーブルのみを評価関数のほうから使いたいときは、評価関数の初期化のときに // If you want to use only this table from the evaluation function,
// init_mir_inv_tables()を呼び出すと良い。 // Call init_mir_inv_tables().
// これらの配列は、以下のKK/KKP/KPPクラスから参照される。 // These arrays are referenced from the KK/KKP/KPP classes below.
// あるBonaPieceを相手側から見たときの値を返す // Returns the value when a certain BonaPiece is seen from the other side
extern Eval::BonaPiece inv_piece(Eval::BonaPiece p); extern Eval::BonaPiece inv_piece(Eval::BonaPiece p);
// 盤面上のあるBonaPieceをミラーした位置にあるものを返す。 // Returns the one at the position where a BonaPiece on the board is mirrored.
extern Eval::BonaPiece mir_piece(Eval::BonaPiece p); extern Eval::BonaPiece mir_piece(Eval::BonaPiece p);
// mir_piece/inv_pieceの初期化のときに呼び出されるcallback // callback called when initializing mir_piece/inv_piece
// fe_endをユーザー側で拡張するときに用いる。 // Used when extending fe_end on the user side.
// この初期化のときに必要なのでinv_piece_とinv_piece_を公開している。 // Inv_piece_ and inv_piece_ are exposed because they are necessary for this initialization.
// mir_piece_init_functionが呼び出されたタイミングで、fe_old_endまでは // At the timing when mir_piece_init_function is called, until fe_old_end
// これらのテーブルの初期化が完了していることが保証されている。 // It is guaranteed that these tables have been initialized.
extern std::function<void()> mir_piece_init_function; extern std::function<void()> mir_piece_init_function;
extern int16_t mir_piece_[Eval::fe_end]; extern int16_t mir_piece_[Eval::fe_end];
extern int16_t inv_piece_[Eval::fe_end]; extern int16_t inv_piece_[Eval::fe_end];
// この関数を明示的に呼び出すか、init()を呼び出すかしたときに、上のテーブルが初期化される。 // The table above will be initialized when you call this function explicitly or call init().
extern void init_mir_inv_tables(); extern void init_mir_inv_tables();
} }
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN) #endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義 // Definition of input features and network structure used in NNUE evaluation function
#ifndef HALFKP_CR_EP_256X2_32_32_H #ifndef HALFKP_CR_EP_256X2_32_32_H
#define HALFKP_CR_EP_256X2_32_32_H #define HALFKP_CR_EP_256X2_32_32_H
@ -16,17 +16,17 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価関数で用いる入力特徴量 // Input features used in evaluation function
using RawFeatures = Features::FeatureSet< using RawFeatures = Features::FeatureSet<
Features::HalfKP<Features::Side::kFriend>, Features::CastlingRight, Features::HalfKP<Features::Side::kFriend>, Features::CastlingRight,
Features::EnPassant>; Features::EnPassant>;
// 変換後の入力特徴量の次元数 // Number of input feature dimensions after conversion
constexpr IndexType kTransformedFeatureDimensions = 256; constexpr IndexType kTransformedFeatureDimensions = 256;
namespace Layers { namespace Layers {
// ネットワーク構造の定義 // define network structure
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>; using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>; using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>; using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;

View file

@ -1,4 +1,4 @@
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義 // Definition of input features and network structure used in NNUE evaluation function
#ifndef HALFKP_256X2_32_32_H #ifndef HALFKP_256X2_32_32_H
#define HALFKP_256X2_32_32_H #define HALFKP_256X2_32_32_H
@ -14,16 +14,16 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価関数で用いる入力特徴量 // Input features used in evaluation function
using RawFeatures = Features::FeatureSet< using RawFeatures = Features::FeatureSet<
Features::HalfKP<Features::Side::kFriend>>; Features::HalfKP<Features::Side::kFriend>>;
// 変換後の入力特徴量の次元数 // Number of input feature dimensions after conversion
constexpr IndexType kTransformedFeatureDimensions = 256; constexpr IndexType kTransformedFeatureDimensions = 256;
namespace Layers { namespace Layers {
// ネットワーク構造の定義 // define network structure
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>; using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>; using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>; using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;

View file

@ -1,4 +1,4 @@
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義 // Definition of input features and network structure used in NNUE evaluation function
#ifndef K_P_CR_EP_256X2_32_32_H #ifndef K_P_CR_EP_256X2_32_32_H
#define K_P_CR_EP_256X2_32_32_H #define K_P_CR_EP_256X2_32_32_H
@ -17,16 +17,16 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価関数で用いる入力特徴量 // Input features used in evaluation function
using RawFeatures = Features::FeatureSet<Features::K, Features::P, using RawFeatures = Features::FeatureSet<Features::K, Features::P,
Features::CastlingRight, Features::EnPassant>; Features::CastlingRight, Features::EnPassant>;
// 変換後の入力特徴量の次元数 // Number of input feature dimensions after conversion
constexpr IndexType kTransformedFeatureDimensions = 256; constexpr IndexType kTransformedFeatureDimensions = 256;
namespace Layers { namespace Layers {
// ネットワーク構造の定義 // define network structure
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>; using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>; using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>; using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;

View file

@ -1,4 +1,4 @@
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義 // Definition of input features and network structure used in NNUE evaluation function
#ifndef K_P_CR_256X2_32_32_H #ifndef K_P_CR_256X2_32_32_H
#define K_P_CR_256X2_32_32_H #define K_P_CR_256X2_32_32_H
@ -16,16 +16,16 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価関数で用いる入力特徴量 // Input features used in evaluation function
using RawFeatures = Features::FeatureSet<Features::K, Features::P, using RawFeatures = Features::FeatureSet<Features::K, Features::P,
Features::CastlingRight>; Features::CastlingRight>;
// 変換後の入力特徴量の次元数 // Number of input feature dimensions after conversion
constexpr IndexType kTransformedFeatureDimensions = 256; constexpr IndexType kTransformedFeatureDimensions = 256;
namespace Layers { namespace Layers {
// ネットワーク構造の定義 // define network structure
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>; using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>; using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>; using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;

View file

@ -1,4 +1,4 @@
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義 // Definition of input features and network structure used in NNUE evaluation function
#ifndef K_P_256X2_32_32_H #ifndef K_P_256X2_32_32_H
#define K_P_256X2_32_32_H #define K_P_256X2_32_32_H
@ -14,15 +14,15 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価関数で用いる入力特徴量 // Input features used in evaluation function
using RawFeatures = Features::FeatureSet<Features::K, Features::P>; using RawFeatures = Features::FeatureSet<Features::K, Features::P>;
// 変換後の入力特徴量の次元数 // Number of input feature dimensions after conversion
constexpr IndexType kTransformedFeatureDimensions = 256; constexpr IndexType kTransformedFeatureDimensions = 256;
namespace Layers { namespace Layers {
// ネットワーク構造の定義 // define network structure
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>; using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>; using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>; using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;

View file

@ -1,4 +1,4 @@
// NNUE評価関数の計算に関するコード // Code for calculating NNUE evaluation function
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
@ -16,16 +16,16 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 入力特徴量変換器 // Input feature converter
AlignedPtr<FeatureTransformer> feature_transformer; AlignedPtr<FeatureTransformer> feature_transformer;
// 評価関数 // Evaluation function
AlignedPtr<Network> network; AlignedPtr<Network> network;
// 評価関数ファイル名 // Evaluation function file name
const char* const kFileName = "nn.bin"; const char* const kFileName = "nn.bin";
// 評価関数の構造を表す文字列を取得する // Get a string that represents the structure of the evaluation function
std::string GetArchitectureString() { std::string GetArchitectureString() {
return "Features=" + FeatureTransformer::GetStructureString() + return "Features=" + FeatureTransformer::GetStructureString() +
",Network=" + Network::GetStructureString(); ",Network=" + Network::GetStructureString();
@ -35,14 +35,14 @@ namespace {
namespace Detail { namespace Detail {
// 評価関数パラメータを初期化する // Initialize the evaluation function parameters
template <typename T> template <typename T>
void Initialize(AlignedPtr<T>& pointer) { void Initialize(AlignedPtr<T>& pointer) {
pointer.reset(reinterpret_cast<T*>(aligned_malloc(sizeof(T), alignof(T)))); pointer.reset(reinterpret_cast<T*>(aligned_malloc(sizeof(T), alignof(T))));
std::memset(pointer.get(), 0, sizeof(T)); std::memset(pointer.get(), 0, sizeof(T));
} }
// 評価関数パラメータを読み込む // read evaluation function parameters
template <typename T> template <typename T>
bool ReadParameters(std::istream& stream, const AlignedPtr<T>& pointer) { bool ReadParameters(std::istream& stream, const AlignedPtr<T>& pointer) {
std::uint32_t header; std::uint32_t header;
@ -51,7 +51,7 @@ bool ReadParameters(std::istream& stream, const AlignedPtr<T>& pointer) {
return pointer->ReadParameters(stream); return pointer->ReadParameters(stream);
} }
// 評価関数パラメータを書き込む // write evaluation function parameters
template <typename T> template <typename T>
bool WriteParameters(std::ostream& stream, const AlignedPtr<T>& pointer) { bool WriteParameters(std::ostream& stream, const AlignedPtr<T>& pointer) {
constexpr std::uint32_t header = T::GetHashValue(); constexpr std::uint32_t header = T::GetHashValue();
@ -61,7 +61,7 @@ bool WriteParameters(std::ostream& stream, const AlignedPtr<T>& pointer) {
} // namespace Detail } // namespace Detail
// 評価関数パラメータを初期化する // Initialize the evaluation function parameters
void Initialize() { void Initialize() {
Detail::Initialize(feature_transformer); Detail::Initialize(feature_transformer);
Detail::Initialize(network); Detail::Initialize(network);
@ -69,7 +69,7 @@ void Initialize() {
} // namespace } // namespace
// ヘッダを読み込む // read the header
bool ReadHeader(std::istream& stream, bool ReadHeader(std::istream& stream,
std::uint32_t* hash_value, std::string* architecture) { std::uint32_t* hash_value, std::string* architecture) {
std::uint32_t version, size; std::uint32_t version, size;
@ -82,7 +82,7 @@ bool ReadHeader(std::istream& stream,
return !stream.fail(); return !stream.fail();
} }
// ヘッダを書き込む // write the header
bool WriteHeader(std::ostream& stream, bool WriteHeader(std::ostream& stream,
std::uint32_t hash_value, const std::string& architecture) { std::uint32_t hash_value, const std::string& architecture) {
stream.write(reinterpret_cast<const char*>(&kVersion), sizeof(kVersion)); stream.write(reinterpret_cast<const char*>(&kVersion), sizeof(kVersion));
@ -93,7 +93,7 @@ bool WriteHeader(std::ostream& stream,
return !stream.fail(); return !stream.fail();
} }
// 評価関数パラメータを読み込む // read evaluation function parameters
bool ReadParameters(std::istream& stream) { bool ReadParameters(std::istream& stream) {
std::uint32_t hash_value; std::uint32_t hash_value;
std::string architecture; std::string architecture;
@ -104,7 +104,7 @@ bool ReadParameters(std::istream& stream) {
return stream && stream.peek() == std::ios::traits_type::eof(); return stream && stream.peek() == std::ios::traits_type::eof();
} }
// 評価関数パラメータを書き込む // 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;
if (!Detail::WriteParameters(stream, feature_transformer)) return false; if (!Detail::WriteParameters(stream, feature_transformer)) return false;
@ -112,12 +112,12 @@ bool WriteParameters(std::ostream& stream) {
return !stream.fail(); return !stream.fail();
} }
// 差分計算ができるなら進める // proceed if you can calculate the difference
static void UpdateAccumulatorIfPossible(const Position& pos) { static void UpdateAccumulatorIfPossible(const Position& pos) {
feature_transformer->UpdateAccumulatorIfPossible(pos); feature_transformer->UpdateAccumulatorIfPossible(pos);
} }
// 評価値を計算する // Calculate the evaluation value
static Value ComputeScore(const Position& pos, bool refresh = false) { static Value ComputeScore(const Position& pos, bool refresh = false) {
auto& accumulator = pos.state()->accumulator; auto& accumulator = pos.state()->accumulator;
if (!refresh && accumulator.computed_score) { if (!refresh && accumulator.computed_score) {
@ -130,22 +130,22 @@ static Value ComputeScore(const Position& pos, bool refresh = false) {
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);
// VALUE_MAX_EVALより大きな値が返ってくるとaspiration searchがfail highして // When a value larger than VALUE_MAX_EVAL is returned, aspiration search fails high
// 探索が終わらなくなるのでVALUE_MAX_EVAL以下であることを保証すべき。 // It should be guaranteed that it is less than VALUE_MAX_EVAL because the search will not end.
// この現象が起きても、対局時に秒固定などだとそこで探索が打ち切られるので、 // Even if this phenomenon occurs, if the seconds are fixed when playing, the search will be aborted there, so
// 1つ前のiterationのときの最善手がbestmoveとして指されるので見かけ上、 // The best move in the previous iteration is pointed to as bestmove, so apparently
// 問題ない。このVALUE_MAX_EVALが返ってくるような状況は、ほぼ詰みの局面であり、 // no problem. The situation in which this VALUE_MAX_EVAL is returned is almost at a dead end,
// そのような詰みの局面が出現するのは終盤で形勢に大差がついていることが多いので // Since such a jamming phase often appears at the end, there is a big difference in the situation
// 勝敗にはあまり影響しない。 // Doesn't really affect the outcome.
// しかし、教師生成時などdepth固定で探索するときに探索から戻ってこなくなるので // However, when searching with a fixed depth such as when creating a teacher, it will not return from the search
// そのスレッドの計算時間を無駄にする。またdepth固定対局でtime-outするようになる。 // Waste the computation time for that thread. Also, it will be timed out with fixed depth game.
auto score = static_cast<Value>(output[0] / FV_SCALE); auto score = static_cast<Value>(output[0] / FV_SCALE);
// 1) ここ、下手にclipすると学習時には影響があるような気もするが…。 // 1) I feel that if I clip too poorly, it will have an effect on my learning...
// 2) accumulator.scoreは、差分計算の時に用いないので書き換えて問題ない。 // 2) Since accumulator.score is not used at the time of difference calculation, it can be rewritten without any problem.
score = Math::clamp(score , -VALUE_MAX_EVAL , VALUE_MAX_EVAL); score = Math::clamp(score , -VALUE_MAX_EVAL , VALUE_MAX_EVAL);
accumulator.score = score; accumulator.score = score;
@ -153,10 +153,10 @@ static Value ComputeScore(const Position& pos, bool refresh = false) {
return accumulator.score; return accumulator.score;
} }
} // namespace NNUE } // namespace NNUE
#if defined(USE_EVAL_HASH) #if defined(USE_EVAL_HASH)
// HashTableに評価値を保存するために利用するクラス // Class used to store evaluation values in HashTable
struct alignas(16) ScoreKeyValue { struct alignas(16) ScoreKeyValue {
#if defined(USE_SSE2) #if defined(USE_SSE2)
ScoreKeyValue() = default; ScoreKeyValue() = default;
@ -171,15 +171,15 @@ struct alignas(16) ScoreKeyValue {
} }
#endif #endif
// evaluate hashでatomicに操作できる必要があるのでそのための操作子 // It is necessary to be able to operate atomically with evaluate hash, so the manipulator for that
void encode() { void encode() {
#if defined(USE_SSE2) #if defined(USE_SSE2)
// ScoreKeyValue は atomic にコピーされるので key が合っていればデータも合っている。 // ScoreKeyValue is copied to atomic, so if the key matches, the data matches.
#else #else
key ^= score; key ^= score;
#endif #endif
} }
// decode()はencode()の逆変換だが、xorなので逆変換も同じ変換。 // decode() is the reverse conversion of encode(), but since it is xor, the reverse conversion is the same.
void decode() { encode(); } void decode() { encode(); }
union { union {
@ -193,45 +193,45 @@ struct alignas(16) ScoreKeyValue {
}; };
}; };
// シンプルなHashTableの実装。 // Simple HashTable implementation.
// Sizeは2のべき乗。 // Size is a power of 2.
template <typename T, size_t Size> template <typename T, size_t Size>
struct HashTable { struct HashTable {
HashTable() { clear(); } HashTable() { clear(); }
T* operator [] (const Key k) { return entries_ + (static_cast<size_t>(k) & (Size - 1)); } T* operator [] (const Key k) { return entries_ + (static_cast<size_t>(k) & (Size - 1)); }
void clear() { memset(entries_, 0, sizeof(T)*Size); } void clear() { memset(entries_, 0, sizeof(T)*Size); }
// Size が 2のべき乗であることのチェック // Check that Size is a power of 2
static_assert((Size & (Size - 1)) == 0, ""); static_assert((Size & (Size - 1)) == 0, "");
private: private:
T entries_[Size]; T entries_[Size];
}; };
// evaluateしたものを保存しておくHashTable(俗にいうehash) //HashTable to save the evaluated ones (following ehash)
#if !defined(USE_LARGE_EVAL_HASH) #if !defined(USE_LARGE_EVAL_HASH)
// 134MB(魔女のAVX2以外の時の設定) // 134MB (setting other than witch's AVX2)
struct EvaluateHashTable : HashTable<ScoreKeyValue, 0x800000> {}; struct EvaluateHashTable : HashTable<ScoreKeyValue, 0x800000> {};
#else #else
// prefetch有りなら大きいほうが良いのでは…。 // If you have prefetch, it's better to have a big one...
// → あまり変わらないし、メモリもったいないのでデフォルトでは↑の設定で良いか…。 // → It doesn't change much and the memory is wasteful, so is it okay to set ↑ by default?
// 1GB(魔女のAVX2の時の設定) // 1GB (setting for witch's AVX2)
struct EvaluateHashTable : HashTable<ScoreKeyValue, 0x4000000> {}; struct EvaluateHashTable : HashTable<ScoreKeyValue, 0x4000000> {};
#endif #endif
EvaluateHashTable g_evalTable; EvaluateHashTable g_evalTable;
// prefetchする関数も用意しておく。 // Prepare a function to prefetch.
void prefetch_evalhash(const Key key) { void prefetch_evalhash(const Key key) {
constexpr auto mask = ~((uint64_t)0x1f); constexpr auto mask = ~((uint64_t)0x1f);
prefetch((void*)((uint64_t)g_evalTable[key] & mask)); prefetch((void*)((uint64_t)g_evalTable[key] & mask));
} }
#endif #endif
// 評価関数ファイルを読み込む // read the evaluation function file
// benchコマンドなどでOptionsを保存して復元するのでこのときEvalDirが変更されたことになって、 // Save and restore Options with bench command etc., so EvalDir is changed at this time,
// 評価関数の再読込の必要があるというフラグを立てるため、この関数は2度呼び出されることがある。 // This function may be called twice to flag that the evaluation function needs to be reloaded.
void load_eval() { void load_eval() {
NNUE::Initialize(); NNUE::Initialize();
@ -249,7 +249,7 @@ void load_eval() {
// ASSERT(result); // ASSERT(result);
if (!result) if (!result)
{ {
// 読み込みエラーのとき終了してくれないと困る。 // It's a problem if it doesn't finish when there is a read error.
std::cout << "Error! " << NNUE::kFileName << " not found or wrong format" << std::endl; std::cout << "Error! " << NNUE::kFileName << " not found or wrong format" << std::endl;
//my_exit(); //my_exit();
} }
@ -260,19 +260,19 @@ void load_eval() {
std::cout << "info string NNUE " << NNUE::kFileName << " not loaded" << std::endl; std::cout << "info string NNUE " << NNUE::kFileName << " not loaded" << std::endl;
} }
// 初期化 // Initialization
void init() { void init() {
} }
// 評価関数。差分計算ではなく全計算する。 // Evaluation function. Perform full calculation instead of difference calculation.
// Position::set()で一度だけ呼び出される。(以降は差分計算) // Called only once with Position::set(). (The difference calculation after that)
// 手番側から見た評価値を返すので注意。(他の評価関数とは設計がこの点において異なる) // Note that the evaluation value seen from the turn side is returned. (Design differs from other evaluation functions in this respect)
// なので、この関数の最適化は頑張らない。 // Since, we will not try to optimize this function.
Value compute_eval(const Position& pos) { Value compute_eval(const Position& pos) {
return NNUE::ComputeScore(pos, true); return NNUE::ComputeScore(pos, true);
} }
// 評価関数 // Evaluation function
Value evaluate(const Position& pos) { Value evaluate(const Position& pos) {
const auto& accumulator = pos.state()->accumulator; const auto& accumulator = pos.state()->accumulator;
if (accumulator.computed_score) { if (accumulator.computed_score) {
@ -280,8 +280,8 @@ Value evaluate(const Position& pos) {
} }
#if defined(USE_GLOBAL_OPTIONS) #if defined(USE_GLOBAL_OPTIONS)
// GlobalOptionsでeval hashを用いない設定になっているなら // If Global Options is set not to use eval hash
// eval hashへの照会をskipする。 // Skip the query to the eval hash.
if (!GlobalOptions.use_eval_hash) { if (!GlobalOptions.use_eval_hash) {
ASSERT_LV5(pos.state()->materialValue == Eval::material(pos)); ASSERT_LV5(pos.state()->materialValue == Eval::material(pos));
return NNUE::ComputeScore(pos); return NNUE::ComputeScore(pos);
@ -289,19 +289,19 @@ Value evaluate(const Position& pos) {
#endif #endif
#if defined(USE_EVAL_HASH) #if defined(USE_EVAL_HASH)
// evaluate hash tableにはあるかも。 // May be in the evaluate hash table.
const Key key = pos.key(); const Key key = pos.key();
ScoreKeyValue entry = *g_evalTable[key]; ScoreKeyValue entry = *g_evalTable[key];
entry.decode(); entry.decode();
if (entry.key == key) { if (entry.key == key) {
// あった! // there were!
return Value(entry.score); return Value(entry.score);
} }
#endif #endif
Value score = NNUE::ComputeScore(pos); Value score = NNUE::ComputeScore(pos);
#if defined(USE_EVAL_HASH) #if defined(USE_EVAL_HASH)
// せっかく計算したのでevaluate hash tableに保存しておく。 // Since it was calculated carefully, save it in the evaluate hash table.
entry.key = key; entry.key = key;
entry.score = score; entry.score = score;
entry.encode(); entry.encode();
@ -311,12 +311,12 @@ Value evaluate(const Position& pos) {
return score; return score;
} }
// 差分計算ができるなら進める // proceed if you can calculate the difference
void evaluate_with_no_return(const Position& pos) { void evaluate_with_no_return(const Position& pos) {
NNUE::UpdateAccumulatorIfPossible(pos); NNUE::UpdateAccumulatorIfPossible(pos);
} }
// 現在の局面の評価値の内訳を表示する // display the breakdown of the evaluation value of the current phase
void print_eval_stat(Position& /*pos*/) { void print_eval_stat(Position& /*pos*/) {
std::cout << "--- EVAL STAT: not implemented" << std::endl; std::cout << "--- EVAL STAT: not implemented" << std::endl;
} }

View file

@ -1,4 +1,4 @@
// NNUE評価関数で用いるheader // header used in NNUE evaluation function
#ifndef _EVALUATE_NNUE_H_ #ifndef _EVALUATE_NNUE_H_
#define _EVALUATE_NNUE_H_ #define _EVALUATE_NNUE_H_
@ -14,11 +14,11 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価関数の構造のハッシュ値 // hash value of evaluation function structure
constexpr std::uint32_t kHashValue = constexpr std::uint32_t kHashValue =
FeatureTransformer::GetHashValue() ^ Network::GetHashValue(); FeatureTransformer::GetHashValue() ^ Network::GetHashValue();
// メモリ領域の解放を自動化するためのデリータ // Deleter for automating release of memory area
template <typename T> template <typename T>
struct AlignedDeleter { struct AlignedDeleter {
void operator()(T* ptr) const { void operator()(T* ptr) const {
@ -29,30 +29,30 @@ struct AlignedDeleter {
template <typename T> template <typename T>
using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>; using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>;
// 入力特徴量変換器 // Input feature converter
extern AlignedPtr<FeatureTransformer> feature_transformer; extern AlignedPtr<FeatureTransformer> feature_transformer;
// 評価関数 // Evaluation function
extern AlignedPtr<Network> network; extern AlignedPtr<Network> network;
// 評価関数ファイル名 // Evaluation function file name
extern const char* const kFileName; extern const char* const kFileName;
// 評価関数の構造を表す文字列を取得する // Get a string that represents the structure of the evaluation function
std::string GetArchitectureString(); std::string GetArchitectureString();
// ヘッダを読み込む // read the header
bool ReadHeader(std::istream& stream, bool ReadHeader(std::istream& stream,
std::uint32_t* hash_value, std::string* architecture); std::uint32_t* hash_value, std::string* architecture);
// ヘッダを書き込む // write the header
bool WriteHeader(std::ostream& stream, bool WriteHeader(std::ostream& stream,
std::uint32_t hash_value, const std::string& architecture); std::uint32_t hash_value, const std::string& architecture);
// 評価関数パラメータを読み込む // read evaluation function parameters
bool ReadParameters(std::istream& stream); bool ReadParameters(std::istream& stream);
// 評価関数パラメータを書き込む // write evaluation function parameters
bool WriteParameters(std::ostream& stream); bool WriteParameters(std::ostream& stream);
} // namespace NNUE } // namespace NNUE
@ -61,4 +61,4 @@ bool WriteParameters(std::ostream& stream);
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習時用のコード // Code for learning NNUE evaluation function
#if defined(EVAL_LEARN) && defined(EVAL_NNUE) #if defined(EVAL_LEARN) && defined(EVAL_NNUE)
@ -31,30 +31,30 @@ namespace NNUE {
namespace { namespace {
// 学習データ // learning data
std::vector<Example> examples; std::vector<Example> examples;
// examplesの排他制御をするMutex // Mutex for exclusive control of examples
std::mutex examples_mutex; std::mutex examples_mutex;
// ミニバッチのサンプル数 // number of samples in mini-batch
uint64_t batch_size; uint64_t batch_size;
// 乱数生成器 // random number generator
std::mt19937 rng; std::mt19937 rng;
// 学習器 // learner
std::shared_ptr<Trainer<Network>> trainer; std::shared_ptr<Trainer<Network>> trainer;
// 学習率のスケール // Learning rate scale
double global_learning_rate_scale; double global_learning_rate_scale;
// 学習率のスケールを取得する // Get the learning rate scale
double GetGlobalLearningRateScale() { double GetGlobalLearningRateScale() {
return global_learning_rate_scale; return global_learning_rate_scale;
} }
// ハイパーパラメータなどのオプションを学習器に伝える // Tell the learner options such as hyperparameters
void SendMessages(std::vector<Message> messages) { void SendMessages(std::vector<Message> messages) {
for (auto& message : messages) { for (auto& message : messages) {
trainer->SendMessage(&message); trainer->SendMessage(&message);
@ -64,7 +64,7 @@ void SendMessages(std::vector<Message> messages) {
} // namespace } // namespace
// 学習の初期化を行う // Initialize learning
void InitializeTraining(double eta1, uint64_t eta1_epoch, void InitializeTraining(double eta1, uint64_t eta1_epoch,
double eta2, uint64_t eta2_epoch, double eta3) { double eta2, uint64_t eta2_epoch, double eta3) {
std::cout << "Initializing NN training for " std::cout << "Initializing NN training for "
@ -82,18 +82,18 @@ void InitializeTraining(double eta1, uint64_t eta1_epoch,
EvalLearningTools::Weight::init_eta(eta1, eta2, eta3, eta1_epoch, eta2_epoch); EvalLearningTools::Weight::init_eta(eta1, eta2, eta3, eta1_epoch, eta2_epoch);
} }
// ミニバッチのサンプル数を設定する // set the number of samples in the mini-batch
void SetBatchSize(uint64_t size) { void SetBatchSize(uint64_t size) {
assert(size > 0); assert(size > 0);
batch_size = size; batch_size = size;
} }
// 学習率のスケールを設定する // set the learning rate scale
void SetGlobalLearningRateScale(double scale) { void SetGlobalLearningRateScale(double scale) {
global_learning_rate_scale = scale; global_learning_rate_scale = scale;
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SetOptions(const std::string& options) { void SetOptions(const std::string& options) {
std::vector<Message> messages; std::vector<Message> messages;
for (const auto& option : Split(options, ',')) { for (const auto& option : Split(options, ',')) {
@ -108,7 +108,7 @@ void SetOptions(const std::string& options) {
SendMessages(std::move(messages)); SendMessages(std::move(messages));
} }
// 学習用評価関数パラメータをファイルから読み直す // Reread the evaluation function parameters for learning from the file
void RestoreParameters(const std::string& dir_name) { void RestoreParameters(const std::string& dir_name) {
const std::string file_name = Path::Combine(dir_name, NNUE::kFileName); const std::string file_name = Path::Combine(dir_name, NNUE::kFileName);
std::ifstream stream(file_name, std::ios::binary); std::ifstream stream(file_name, std::ios::binary);
@ -118,7 +118,7 @@ void RestoreParameters(const std::string& dir_name) {
SendMessages({{"reset"}}); SendMessages({{"reset"}});
} }
// 学習データを1サンプル追加する // Add 1 sample of learning data
void AddExample(Position& pos, Color rootColor, void AddExample(Position& pos, Color rootColor,
const Learner::PackedSfenValue& psv, double weight) { const Learner::PackedSfenValue& psv, double weight) {
Example example; Example example;
@ -162,7 +162,7 @@ void AddExample(Position& pos, Color rootColor,
examples.push_back(std::move(example)); examples.push_back(std::move(example));
} }
// 評価関数パラメーターを更新する // update the evaluation function parameters
void UpdateParameters(uint64_t epoch) { void UpdateParameters(uint64_t epoch) {
assert(batch_size > 0); assert(batch_size > 0);
@ -192,21 +192,21 @@ void UpdateParameters(uint64_t epoch) {
SendMessages({{"quantize_parameters"}}); SendMessages({{"quantize_parameters"}});
} }
// 学習に問題が生じていないかチェックする // Check if there are any problems with learning
void CheckHealth() { void CheckHealth() {
SendMessages({{"check_health"}}); SendMessages({{"check_health"}});
} }
} // namespace NNUE } // namespace NNUE
// 評価関数パラメーターをファイルに保存する // save merit function parameters to a file
void save_eval(std::string dir_name) { void save_eval(std::string dir_name) {
auto eval_dir = Path::Combine(Options["EvalSaveDir"], dir_name); auto eval_dir = Path::Combine(Options["EvalSaveDir"], dir_name);
std::cout << "save_eval() start. folder = " << eval_dir << std::endl; std::cout << "save_eval() start. folder = " << eval_dir << std::endl;
// すでにこのフォルダがあるならmkdir()に失敗するが、 // mkdir() will fail if this folder already exists, but
// 別にそれは構わない。なければ作って欲しいだけ。 // Apart from that. If not, I just want you to make it.
// また、EvalSaveDirまでのフォルダは掘ってあるものとする。 // Also, assume that the folders up to EvalSaveDir have been dug.
Dependency::mkdir(eval_dir); Dependency::mkdir(eval_dir);
if (Options["SkipLoadingEval"] && NNUE::trainer) { if (Options["SkipLoadingEval"] && NNUE::trainer) {
@ -221,7 +221,7 @@ void save_eval(std::string dir_name) {
std::cout << "save_eval() finished. folder = " << eval_dir << std::endl; std::cout << "save_eval() finished. folder = " << eval_dir << std::endl;
} }
// 現在のetaを取得する // get the current eta
double get_eta() { double get_eta() {
return NNUE::GetGlobalLearningRateScale() * EvalLearningTools::Weight::eta; return NNUE::GetGlobalLearningRateScale() * EvalLearningTools::Weight::eta;
} }

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習で用いるインターフェイス // Interface used for learning NNUE evaluation function
#ifndef _EVALUATE_NNUE_LEARNER_H_ #ifndef _EVALUATE_NNUE_LEARNER_H_
#define _EVALUATE_NNUE_LEARNER_H_ #define _EVALUATE_NNUE_LEARNER_H_
@ -11,30 +11,30 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 学習の初期化を行う // Initialize learning
void InitializeTraining(double eta1, uint64_t eta1_epoch, void InitializeTraining(double eta1, uint64_t eta1_epoch,
double eta2, uint64_t eta2_epoch, double eta3); double eta2, uint64_t eta2_epoch, double eta3);
// ミニバッチのサンプル数を設定する // set the number of samples in the mini-batch
void SetBatchSize(uint64_t size); void SetBatchSize(uint64_t size);
// 学習率のスケールを設定する // set the learning rate scale
void SetGlobalLearningRateScale(double scale); void SetGlobalLearningRateScale(double scale);
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SetOptions(const std::string& options); void SetOptions(const std::string& options);
// 学習用評価関数パラメータをファイルから読み直す // Reread the evaluation function parameters for learning from the file
void RestoreParameters(const std::string& dir_name); void RestoreParameters(const std::string& dir_name);
// 学習データを1サンプル追加する // Add 1 sample of learning data
void AddExample(Position& pos, Color rootColor, void AddExample(Position& pos, Color rootColor,
const Learner::PackedSfenValue& psv, double weight); const Learner::PackedSfenValue& psv, double weight);
// 評価関数パラメータを更新する // update the evaluation function parameters
void UpdateParameters(uint64_t epoch); void UpdateParameters(uint64_t epoch);
// 学習に問題が生じていないかチェックする // Check if there are any problems with learning
void CheckHealth(); void CheckHealth();
} // namespace NNUE } // namespace NNUE
@ -43,4 +43,4 @@ void CheckHealth();
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Kの定義 //Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
@ -11,10 +11,10 @@ namespace Eval {
namespace Features { namespace Features {
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
void CastlingRight::AppendActiveIndices( void CastlingRight::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) { const Position& pos, Color perspective, IndexList* active) {
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない // do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
int castling_rights = pos.state()->castlingRights; int castling_rights = pos.state()->castlingRights;
@ -28,14 +28,14 @@ namespace Eval {
& ((castling_rights >> 2) & 3); & ((castling_rights >> 2) & 3);
} }
for (int i = 0; i < kDimensions; ++i) { for (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);
} }
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
void CastlingRight::AppendChangedIndices( void CastlingRight::AppendChangedIndices(
const Position& pos, Color perspective, const Position& pos, Color perspective,
IndexList* removed, IndexList* added) { IndexList* removed, IndexList* added) {

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Kの定義 //Definition of input feature quantity K of NNUE evaluation function
#ifndef _NNUE_FEATURES_CASTLING_RIGHT_H_ #ifndef _NNUE_FEATURES_CASTLING_RIGHT_H_
#define _NNUE_FEATURES_CASTLING_RIGHT_H_ #define _NNUE_FEATURES_CASTLING_RIGHT_H_
@ -14,25 +14,25 @@ namespace Eval {
namespace Features { namespace Features {
// 特徴量K玉の位置 // Feature K: Ball position
class CastlingRight { class CastlingRight {
public: public:
// 特徴量名 // feature quantity name
static constexpr const char* kName = "CastlingRight"; static constexpr const char* kName = "CastlingRight";
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0x913968AAu; static constexpr std::uint32_t kHashValue = 0x913968AAu;
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = 4; static constexpr IndexType kDimensions = 4;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = 4; static constexpr IndexType kMaxActiveDimensions = 4;
// 差分計算の代わりに全計算を行うタイミング // Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective, static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active); IndexList* active);
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values ??have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective, static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added); IndexList* removed, IndexList* added);
}; };
@ -45,4 +45,4 @@ namespace Eval {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Kの定義 //Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
@ -11,10 +11,10 @@ namespace Eval {
namespace Features { namespace Features {
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
void EnPassant::AppendActiveIndices( void EnPassant::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) { const Position& pos, Color perspective, IndexList* active) {
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない // do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
auto epSquare = pos.state()->epSquare; auto epSquare = pos.state()->epSquare;
@ -30,7 +30,7 @@ namespace Eval {
active->push_back(file); active->push_back(file);
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values ??have changed from the previous one in the feature quantity
void EnPassant::AppendChangedIndices( void EnPassant::AppendChangedIndices(
const Position& pos, Color perspective, const Position& pos, Color perspective,
IndexList* removed, IndexList* added) { IndexList* removed, IndexList* added) {

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Kの定義 //Definition of input feature quantity K of NNUE evaluation function
#ifndef _NNUE_FEATURES_ENPASSANT_H_ #ifndef _NNUE_FEATURES_ENPASSANT_H_
#define _NNUE_FEATURES_ENPASSANT_H_ #define _NNUE_FEATURES_ENPASSANT_H_
@ -14,25 +14,25 @@ namespace Eval {
namespace Features { namespace Features {
// 特徴量K玉の位置 // Feature K: Ball position
class EnPassant { class EnPassant {
public: public:
// 特徴量名 // feature quantity name
static constexpr const char* kName = "EnPassant"; static constexpr const char* kName = "EnPassant";
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0x02924F91u; static constexpr std::uint32_t kHashValue = 0x02924F91u;
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = 8; static constexpr IndexType kDimensions = 8;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = 1; static constexpr IndexType kMaxActiveDimensions = 1;
// 差分計算の代わりに全計算を行うタイミング // Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kAnyPieceMoved; static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kAnyPieceMoved;
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective, static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active); IndexList* active);
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values ??have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective, static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added); IndexList* removed, IndexList* added);
}; };
@ -45,4 +45,4 @@ namespace Eval {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量セットを表すクラステンプレート // A class template that represents the input feature set of the NNUE evaluation function
#ifndef _NNUE_FEATURE_SET_H_ #ifndef _NNUE_FEATURE_SET_H_
#define _NNUE_FEATURE_SET_H_ #define _NNUE_FEATURE_SET_H_
@ -14,7 +14,7 @@ namespace NNUE {
namespace Features { namespace Features {
// 値のリストを表すクラステンプレート // A class template that represents a list of values
template <typename T, T... Values> template <typename T, T... Values>
struct CompileTimeList; struct CompileTimeList;
template <typename T, T First, T... Remaining> template <typename T, T First, T... Remaining>
@ -36,7 +36,7 @@ struct CompileTimeList<T> {
static constexpr std::array<T, 0> kValues = {{}}; static constexpr std::array<T, 0> kValues = {{}};
}; };
// リストの先頭への追加を行うクラステンプレート // Class template that adds to the beginning of the list
template <typename T, typename ListType, T Value> template <typename T, typename ListType, T Value>
struct AppendToList; struct AppendToList;
template <typename T, T... Values, T AnotherValue> template <typename T, T... Values, T AnotherValue>
@ -44,7 +44,7 @@ struct AppendToList<T, CompileTimeList<T, Values...>, AnotherValue> {
using Result = CompileTimeList<T, AnotherValue, Values...>; using Result = CompileTimeList<T, AnotherValue, Values...>;
}; };
// ソートされた重複のないリストへの追加を行うクラステンプレート // Class template for adding to a sorted, unique list
template <typename T, typename ListType, T Value> template <typename T, typename ListType, T Value>
struct InsertToSet; struct InsertToSet;
template <typename T, T First, T... Remaining, T AnotherValue> template <typename T, T First, T... Remaining, T AnotherValue>
@ -52,7 +52,7 @@ struct InsertToSet<T, CompileTimeList<T, First, Remaining...>, AnotherValue> {
using Result = std::conditional_t< using Result = std::conditional_t<
CompileTimeList<T, First, Remaining...>::Contains(AnotherValue), CompileTimeList<T, First, Remaining...>::Contains(AnotherValue),
CompileTimeList<T, First, Remaining...>, CompileTimeList<T, First, Remaining...>,
std::conditional_t<(AnotherValue < First), std::conditional_t<(AnotherValue <First),
CompileTimeList<T, AnotherValue, First, Remaining...>, CompileTimeList<T, AnotherValue, First, Remaining...>,
typename AppendToList<T, typename InsertToSet< typename AppendToList<T, typename InsertToSet<
T, CompileTimeList<T, Remaining...>, AnotherValue>::Result, T, CompileTimeList<T, Remaining...>, AnotherValue>::Result,
@ -63,21 +63,21 @@ struct InsertToSet<T, CompileTimeList<T>, Value> {
using Result = CompileTimeList<T, Value>; using Result = CompileTimeList<T, Value>;
}; };
// 特徴量セットの基底クラス // Base class of feature set
template <typename Derived> template <typename Derived>
class FeatureSetBase { class FeatureSetBase {
public: public:
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
template <typename IndexListType> template <typename IndexListType>
static void AppendActiveIndices( static void AppendActiveIndices(
const Position& pos, TriggerEvent trigger, IndexListType active[2]) { const Position& pos, TriggerEvent trigger, IndexListType active[2]) {
for (const auto perspective : Colors) { for (const auto perspective :Colors) {
Derived::CollectActiveIndices( Derived::CollectActiveIndices(
pos, trigger, perspective, &active[perspective]); pos, trigger, perspective, &active[perspective]);
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
template <typename PositionType, typename IndexListType> template <typename PositionType, typename IndexListType>
static void AppendChangedIndices( static void AppendChangedIndices(
const PositionType& pos, TriggerEvent trigger, const PositionType& pos, TriggerEvent trigger,
@ -85,7 +85,7 @@ class FeatureSetBase {
const auto& dp = pos.state()->dirtyPiece; const auto& dp = pos.state()->dirtyPiece;
if (dp.dirty_num == 0) return; if (dp.dirty_num == 0) return;
for (const auto perspective : Colors) { for (const auto perspective :Colors) {
reset[perspective] = false; reset[perspective] = false;
switch (trigger) { switch (trigger) {
case TriggerEvent::kNone: case TriggerEvent::kNone:
@ -120,8 +120,8 @@ class FeatureSetBase {
} }
}; };
// 特徴量セットを表すクラステンプレート // Class template that represents the feature set
// 実行時の計算量を線形にするために、内部の処理はテンプレート引数の逆順に行う // do internal processing in reverse order of template arguments in order to linearize the amount of calculation at runtime
template <typename FirstFeatureType, typename... RemainingFeatureTypes> template <typename FirstFeatureType, typename... RemainingFeatureTypes>
class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> : class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
public FeatureSetBase< public FeatureSetBase<
@ -131,27 +131,27 @@ class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
using Tail = FeatureSet<RemainingFeatureTypes...>; using Tail = FeatureSet<RemainingFeatureTypes...>;
public: public:
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = static constexpr std::uint32_t kHashValue =
Head::kHashValue ^ (Tail::kHashValue << 1) ^ (Tail::kHashValue >> 31); Head::kHashValue ^ (Tail::kHashValue << 1) ^ (Tail::kHashValue >> 31);
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = static constexpr IndexType kDimensions =
Head::kDimensions + Tail::kDimensions; Head::kDimensions + Tail::kDimensions;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = static constexpr IndexType kMaxActiveDimensions =
Head::kMaxActiveDimensions + Tail::kMaxActiveDimensions; Head::kMaxActiveDimensions + Tail::kMaxActiveDimensions;
// 差分計算の代わりに全計算を行うタイミングのリスト // List of timings to perform all calculations instead of difference calculation
using SortedTriggerSet = typename InsertToSet<TriggerEvent, using SortedTriggerSet = typename InsertToSet<TriggerEvent,
typename Tail::SortedTriggerSet, Head::kRefreshTrigger>::Result; typename Tail::SortedTriggerSet, Head::kRefreshTrigger>::Result;
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues; static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
// 特徴量名を取得する // Get the feature quantity name
static std::string GetName() { static std::string GetName() {
return std::string(Head::kName) + "+" + Tail::GetName(); return std::string(Head::kName) + "+" + Tail::GetName();
} }
private: private:
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
template <typename IndexListType> template <typename IndexListType>
static void CollectActiveIndices( static void CollectActiveIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective, const Position& pos, const TriggerEvent trigger, const Color perspective,
@ -166,7 +166,7 @@ class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
template <typename IndexListType> template <typename IndexListType>
static void CollectChangedIndices( static void CollectChangedIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective, const Position& pos, const TriggerEvent trigger, const Color perspective,
@ -185,36 +185,36 @@ class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
} }
} }
// 基底クラスと、自身を再帰的に利用するクラステンプレートをfriendにする // Make the base class and the class template that recursively uses itself a friend
friend class FeatureSetBase<FeatureSet>; friend class FeatureSetBase<FeatureSet>;
template <typename... FeatureTypes> template <typename... FeatureTypes>
friend class FeatureSet; friend class FeatureSet;
}; };
// 特徴量セットを表すクラステンプレート // Class template that represents the feature set
// テンプレート引数が1つの場合の特殊化 // Specialization with one template argument
template <typename FeatureType> template <typename FeatureType>
class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> { class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
public: public:
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = FeatureType::kHashValue; static constexpr std::uint32_t kHashValue = FeatureType::kHashValue;
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = FeatureType::kDimensions; static constexpr IndexType kDimensions = FeatureType::kDimensions;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = static constexpr IndexType kMaxActiveDimensions =
FeatureType::kMaxActiveDimensions; FeatureType::kMaxActiveDimensions;
// 差分計算の代わりに全計算を行うタイミングのリスト // List of timings to perform all calculations instead of difference calculation
using SortedTriggerSet = using SortedTriggerSet =
CompileTimeList<TriggerEvent, FeatureType::kRefreshTrigger>; CompileTimeList<TriggerEvent, FeatureType::kRefreshTrigger>;
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues; static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
// 特徴量名を取得する // Get the feature quantity name
static std::string GetName() { static std::string GetName() {
return FeatureType::kName; return FeatureType::kName;
} }
private: private:
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
static void CollectActiveIndices( static void CollectActiveIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective, const Position& pos, const TriggerEvent trigger, const Color perspective,
IndexList* const active) { IndexList* const active) {
@ -223,7 +223,7 @@ class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
static void CollectChangedIndices( static void CollectChangedIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective, const Position& pos, const TriggerEvent trigger, const Color perspective,
IndexList* const removed, IndexList* const added) { IndexList* const removed, IndexList* const added) {
@ -232,7 +232,7 @@ class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
} }
} }
// 基底クラスと、自身を再帰的に利用するクラステンプレートをfriendにする // Make the base class and the class template that recursively uses itself a friend
friend class FeatureSetBase<FeatureSet>; friend class FeatureSetBase<FeatureSet>;
template <typename... FeatureTypes> template <typename... FeatureTypes>
friend class FeatureSet; friend class FeatureSet;
@ -246,4 +246,4 @@ class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量の共通ヘッダ //Common header of input features of NNUE evaluation function
#ifndef _NNUE_FEATURES_COMMON_H_ #ifndef _NNUE_FEATURES_COMMON_H_
#define _NNUE_FEATURES_COMMON_H_ #define _NNUE_FEATURES_COMMON_H_
@ -14,26 +14,26 @@ namespace NNUE {
namespace Features { namespace Features {
// インデックスリストの型 // Index list type
class IndexList; class IndexList;
// 特徴量セットを表すクラステンプレート // Class template that represents the feature set
template <typename... FeatureTypes> template <typename... FeatureTypes>
class FeatureSet; class FeatureSet;
// 差分計算の代わりに全計算を行うタイミングの種類 // Type of timing to perform all calculations instead of difference calculation
enum class TriggerEvent { enum class TriggerEvent {
kNone, // 可能な場合は常に差分計算する kNone, // Calculate the difference whenever possible
kFriendKingMoved, // 自玉が移動した場合に全計算する kFriendKingMoved, // calculate all when own ball moves
kEnemyKingMoved, // 敵玉が移動した場合に全計算する kEnemyKingMoved, // do all calculations when enemy balls move
kAnyKingMoved, // どちらかの玉が移動した場合に全計算する kAnyKingMoved, // do all calculations if either ball moves
kAnyPieceMoved, // 常に全計算する kAnyPieceMoved, // always do all calculations
}; };
// 手番側or相手側 // turn side or other side
enum class Side { enum class Side {
kFriend, // 手番側 kFriend, // turn side
kEnemy, // 相手側 kEnemy, // opponent
}; };
} // namespace Features } // namespace Features
@ -44,4 +44,4 @@ enum class Side {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量HalfKPの定義 //Definition of input features HalfKP of NNUE evaluation function
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
@ -11,13 +11,13 @@ namespace NNUE {
namespace Features { namespace Features {
// 玉の位置とBonaPieceから特徴量のインデックスを求める // Find the index of the feature quantity from the ball position and BonaPiece
template <Side AssociatedKing> template <Side AssociatedKing>
inline IndexType HalfKP<AssociatedKing>::MakeIndex(Square sq_k, BonaPiece p) { inline IndexType HalfKP<AssociatedKing>::MakeIndex(Square sq_k, BonaPiece p) {
return static_cast<IndexType>(fe_end) * static_cast<IndexType>(sq_k) + p; return static_cast<IndexType>(fe_end) * static_cast<IndexType>(sq_k) + p;
} }
// 駒の情報を取得する // Get the piece information
template <Side AssociatedKing> template <Side AssociatedKing>
inline void HalfKP<AssociatedKing>::GetPieces( inline void HalfKP<AssociatedKing>::GetPieces(
const Position& pos, Color perspective, const Position& pos, Color perspective,
@ -31,7 +31,7 @@ inline void HalfKP<AssociatedKing>::GetPieces(
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB); *sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB);
} }
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
template <Side AssociatedKing> template <Side AssociatedKing>
void HalfKP<AssociatedKing>::AppendActiveIndices( void HalfKP<AssociatedKing>::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) { const Position& pos, Color perspective, IndexList* active) {
@ -48,7 +48,7 @@ void HalfKP<AssociatedKing>::AppendActiveIndices(
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
template <Side AssociatedKing> template <Side AssociatedKing>
void HalfKP<AssociatedKing>::AppendChangedIndices( void HalfKP<AssociatedKing>::AppendChangedIndices(
const Position& pos, Color perspective, const Position& pos, Color perspective,

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量HalfKPの定義 //Definition of input features HalfKP of NNUE evaluation function
#ifndef _NNUE_FEATURES_HALF_KP_H_ #ifndef _NNUE_FEATURES_HALF_KP_H_
#define _NNUE_FEATURES_HALF_KP_H_ #define _NNUE_FEATURES_HALF_KP_H_
@ -14,39 +14,39 @@ namespace NNUE {
namespace Features { namespace Features {
// 特徴量HalfKP自玉または敵玉の位置と、玉以外の駒の位置の組み合わせ // Feature HalfKP: Combination of the position of own ball or enemy ball and the position of pieces other than balls
template <Side AssociatedKing> template <Side AssociatedKing>
class HalfKP { class HalfKP {
public: public:
// 特徴量名 // feature quantity name
static constexpr const char* kName = static constexpr const char* kName =
(AssociatedKing == Side::kFriend) ? "HalfKP(Friend)" : "HalfKP(Enemy)"; (AssociatedKing == Side::kFriend) ? "HalfKP(Friend)" : "HalfKP(Enemy)";
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = static constexpr std::uint32_t kHashValue =
0x5D69D5B9u ^ (AssociatedKing == Side::kFriend); 0x5D69D5B9u ^ (AssociatedKing == Side::kFriend);
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = static constexpr IndexType kDimensions =
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(fe_end); static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(fe_end);
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING; static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
// 差分計算の代わりに全計算を行うタイミング // Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = static constexpr TriggerEvent kRefreshTrigger =
(AssociatedKing == Side::kFriend) ? (AssociatedKing == Side::kFriend) ?
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved; TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective, static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active); IndexList* active);
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective, static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added); IndexList* removed, IndexList* added);
// 玉の位置とBonaPieceから特徴量のインデックスを求める // Find the index of the feature quantity from the ball position and BonaPiece
static IndexType MakeIndex(Square sq_k, BonaPiece p); static IndexType MakeIndex(Square sq_k, BonaPiece p);
private: private:
// 駒の情報を取得する // Get the piece information
static void GetPieces(const Position& pos, Color perspective, static void GetPieces(const Position& pos, Color perspective,
BonaPiece** pieces, Square* sq_target_k); BonaPiece** pieces, Square* sq_target_k);
}; };
@ -59,4 +59,4 @@ class HalfKP {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量HalfRelativeKPの定義 //Definition of input features HalfRelativeKP of NNUE evaluation function
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
@ -11,7 +11,7 @@ namespace NNUE {
namespace Features { namespace Features {
// 玉の位置とBonaPieceから特徴量のインデックスを求める // Find the index of the feature quantity from the ball position and BonaPiece
template <Side AssociatedKing> template <Side AssociatedKing>
inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex( inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
Square sq_k, BonaPiece p) { Square sq_k, BonaPiece p) {
@ -24,7 +24,7 @@ inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
return H * W * piece_index + H * relative_file + relative_rank; return H * W * piece_index + H * relative_file + relative_rank;
} }
// 駒の情報を取得する // Get the piece information
template <Side AssociatedKing> template <Side AssociatedKing>
inline void HalfRelativeKP<AssociatedKing>::GetPieces( inline void HalfRelativeKP<AssociatedKing>::GetPieces(
const Position& pos, Color perspective, const Position& pos, Color perspective,
@ -38,11 +38,11 @@ inline void HalfRelativeKP<AssociatedKing>::GetPieces(
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB); *sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB);
} }
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
template <Side AssociatedKing> template <Side AssociatedKing>
void HalfRelativeKP<AssociatedKing>::AppendActiveIndices( void HalfRelativeKP<AssociatedKing>::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) { const Position& pos, Color perspective, IndexList* active) {
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない // do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
BonaPiece* pieces; BonaPiece* pieces;
@ -57,7 +57,7 @@ void HalfRelativeKP<AssociatedKing>::AppendActiveIndices(
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
template <Side AssociatedKing> template <Side AssociatedKing>
void HalfRelativeKP<AssociatedKing>::AppendChangedIndices( void HalfRelativeKP<AssociatedKing>::AppendChangedIndices(
const Position& pos, Color perspective, const Position& pos, Color perspective,

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量HalfRelativeKPの定義 //Definition of input features HalfRelativeKP of NNUE evaluation function
#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_
@ -14,45 +14,45 @@ namespace NNUE {
namespace Features { namespace Features {
// 特徴量HalfRelativeKP自玉または敵玉を基準とした、玉以外の各駒の相対位置 // Feature HalfRelativeKP: Relative position of each piece other than the ball based on own ball or enemy ball
template <Side AssociatedKing> template <Side AssociatedKing>
class HalfRelativeKP { class HalfRelativeKP {
public: public:
// 特徴量名 // feature quantity name
static constexpr const char* kName = (AssociatedKing == Side::kFriend) ? static constexpr const char* kName = (AssociatedKing == Side::kFriend) ?
"HalfRelativeKP(Friend)" : "HalfRelativeKP(Enemy)"; "HalfRelativeKP(Friend)" : "HalfRelativeKP(Enemy)";
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = static constexpr std::uint32_t kHashValue =
0xF9180919u ^ (AssociatedKing == Side::kFriend); 0xF9180919u ^ (AssociatedKing == Side::kFriend);
// 玉を除いた駒種 // Piece type excluding balls
static constexpr IndexType kNumPieceKinds = (fe_end - fe_hand_end) / SQUARE_NB; static constexpr IndexType kNumPieceKinds = (fe_end - fe_hand_end) / SQUARE_NB;
// 玉を中央に置いた仮想的な盤の幅 // width of the virtual board with the ball in the center
static constexpr IndexType kBoardWidth = FILE_NB * 2 - 1; static constexpr IndexType kBoardWidth = FILE_NB * 2 - 1;
// 玉を中央に置いた仮想的な盤の高さ // height of a virtual board with balls in the center
static constexpr IndexType kBoardHeight = RANK_NB * 2 - 1; static constexpr IndexType kBoardHeight = RANK_NB * 2 - 1;
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = static constexpr IndexType kDimensions =
kNumPieceKinds * kBoardHeight * kBoardWidth; kNumPieceKinds * kBoardHeight * kBoardWidth;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING; static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
// 差分計算の代わりに全計算を行うタイミング // Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = static constexpr TriggerEvent kRefreshTrigger =
(AssociatedKing == Side::kFriend) ? (AssociatedKing == Side::kFriend) ?
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved; TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective, static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active); IndexList* active);
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective, static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added); IndexList* removed, IndexList* added);
// 玉の位置とBonaPieceから特徴量のインデックスを求める // Find the index of the feature quantity from the ball position and BonaPiece
static IndexType MakeIndex(Square sq_k, BonaPiece p); static IndexType MakeIndex(Square sq_k, BonaPiece p);
private: private:
// 駒の情報を取得する // Get the piece information
static void GetPieces(const Position& pos, Color perspective, static void GetPieces(const Position& pos, Color perspective,
BonaPiece** pieces, Square* sq_target_k); BonaPiece** pieces, Square* sq_target_k);
}; };
@ -65,4 +65,4 @@ class HalfRelativeKP {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// 入力特徴量のインデックスリストの定義 // Definition of index list of input features
#ifndef _NNUE_FEATURES_INDEX_LIST_H_ #ifndef _NNUE_FEATURES_INDEX_LIST_H_
#define _NNUE_FEATURES_INDEX_LIST_H_ #define _NNUE_FEATURES_INDEX_LIST_H_
@ -14,7 +14,7 @@ namespace NNUE {
namespace Features { namespace Features {
// 特徴量のインデックスリストに使うクラステンプレート // Class template used for feature index list
template <typename T, std::size_t MaxSize> template <typename T, std::size_t MaxSize>
class ValueList { class ValueList {
public: public:
@ -39,7 +39,7 @@ class ValueList {
std::size_t size_ = 0; std::size_t size_ = 0;
}; };
// 特徴量のインデックスリストの型 //Type of feature index list
class IndexList class IndexList
: public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> { : public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> {
}; };
@ -52,4 +52,4 @@ class IndexList
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Kの定義 //Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
@ -11,10 +11,10 @@ namespace NNUE {
namespace Features { namespace Features {
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
void K::AppendActiveIndices( void K::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) { const Position& pos, Color perspective, IndexList* active) {
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない // do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
const BonaPiece* pieces = (perspective == BLACK) ? const BonaPiece* pieces = (perspective == BLACK) ?
@ -27,7 +27,7 @@ void K::AppendActiveIndices(
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
void K::AppendChangedIndices( void K::AppendChangedIndices(
const Position& pos, Color perspective, const Position& pos, Color perspective,
IndexList* removed, IndexList* added) { IndexList* removed, IndexList* added) {

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Kの定義 //Definition of input feature quantity K of NNUE evaluation function
#ifndef _NNUE_FEATURES_K_H_ #ifndef _NNUE_FEATURES_K_H_
#define _NNUE_FEATURES_K_H_ #define _NNUE_FEATURES_K_H_
@ -14,25 +14,25 @@ namespace NNUE {
namespace Features { namespace Features {
// 特徴量K玉の位置 // Feature K: Ball position
class K { class K {
public: public:
// 特徴量名 // feature quantity name
static constexpr const char* kName = "K"; static constexpr const char* kName = "K";
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0xD3CEE169u; static constexpr std::uint32_t kHashValue = 0xD3CEE169u;
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = SQUARE_NB * 2; static constexpr IndexType kDimensions = SQUARE_NB * 2;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = 2; static constexpr IndexType kMaxActiveDimensions = 2;
// 差分計算の代わりに全計算を行うタイミング // Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective, static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active); IndexList* active);
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective, static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added); IndexList* removed, IndexList* added);
}; };
@ -45,4 +45,4 @@ class K {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Pの定義 //Definition of input feature P of NNUE evaluation function
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
@ -11,10 +11,10 @@ namespace NNUE {
namespace Features { namespace Features {
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
void P::AppendActiveIndices( void P::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) { const Position& pos, Color perspective, IndexList* active) {
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない // do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return; if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
const BonaPiece* pieces = (perspective == BLACK) ? const BonaPiece* pieces = (perspective == BLACK) ?
@ -27,7 +27,7 @@ void P::AppendActiveIndices(
} }
} }
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
void P::AppendChangedIndices( void P::AppendChangedIndices(
const Position& pos, Color perspective, const Position& pos, Color perspective,
IndexList* removed, IndexList* added) { IndexList* removed, IndexList* added) {

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量Pの定義 //Definition of input feature P of NNUE evaluation function
#ifndef _NNUE_FEATURES_P_H_ #ifndef _NNUE_FEATURES_P_H_
#define _NNUE_FEATURES_P_H_ #define _NNUE_FEATURES_P_H_
@ -14,25 +14,25 @@ namespace NNUE {
namespace Features { namespace Features {
// 特徴量P玉以外の駒のBonaPiece // Feature P: BonaPiece of pieces other than balls
class P { class P {
public: public:
// 特徴量名 // feature quantity name
static constexpr const char* kName = "P"; static constexpr const char* kName = "P";
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0x764CFB4Bu; static constexpr std::uint32_t kHashValue = 0x764CFB4Bu;
// 特徴量の次元数 // number of feature dimensions
static constexpr IndexType kDimensions = fe_end; static constexpr IndexType kDimensions = fe_end;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING; static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
// 差分計算の代わりに全計算を行うタイミング // Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone; static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
// 特徴量のうち、値が1であるインデックスのリストを取得する // Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective, static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active); IndexList* active);
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する // Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective, static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added); IndexList* removed, IndexList* added);
}; };
@ -45,4 +45,4 @@ class P {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の層AffineTransformの定義 // Definition of layer AffineTransform of NNUE evaluation function
#ifndef _NNUE_LAYERS_AFFINE_TRANSFORM_H_ #ifndef _NNUE_LAYERS_AFFINE_TRANSFORM_H_
#define _NNUE_LAYERS_AFFINE_TRANSFORM_H_ #define _NNUE_LAYERS_AFFINE_TRANSFORM_H_
@ -13,31 +13,31 @@ namespace NNUE {
namespace Layers { namespace Layers {
// アフィン変換層 // affine transformation layer
template <typename PreviousLayer, IndexType OutputDimensions> template <typename PreviousLayer, IndexType OutputDimensions>
class AffineTransform { class AffineTransform {
public: public:
// 入出力の型 // Input/output type
using InputType = typename PreviousLayer::OutputType; using InputType = typename PreviousLayer::OutputType;
using OutputType = std::int32_t; using OutputType = std::int32_t;
static_assert(std::is_same<InputType, std::uint8_t>::value, ""); static_assert(std::is_same<InputType, std::uint8_t>::value, "");
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = static constexpr IndexType kInputDimensions =
PreviousLayer::kOutputDimensions; PreviousLayer::kOutputDimensions;
static constexpr IndexType kOutputDimensions = OutputDimensions; static constexpr IndexType kOutputDimensions = OutputDimensions;
static constexpr IndexType kPaddedInputDimensions = static constexpr IndexType kPaddedInputDimensions =
CeilToMultiple<IndexType>(kInputDimensions, kMaxSimdWidth); CeilToMultiple<IndexType>(kInputDimensions, kMaxSimdWidth);
// この層で使用する順伝播用バッファのサイズ // Size of forward propagation buffer used in this layer
static constexpr std::size_t kSelfBufferSize = static constexpr std::size_t kSelfBufferSize =
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize); CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
// 入力層からこの層までで使用する順伝播用バッファのサイズ // Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize = static constexpr std::size_t kBufferSize =
PreviousLayer::kBufferSize + kSelfBufferSize; PreviousLayer::kBufferSize + kSelfBufferSize;
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0xCC03DAE4u; std::uint32_t hash_value = 0xCC03DAE4u;
hash_value += kOutputDimensions; hash_value += kOutputDimensions;
@ -46,7 +46,7 @@ class AffineTransform {
return hash_value; return hash_value;
} }
// 入力層からこの層までの構造を表す文字列 // A string that represents the structure from the input layer to this layer
static std::string GetStructureString() { static std::string GetStructureString() {
return "AffineTransform[" + return "AffineTransform[" +
std::to_string(kOutputDimensions) + "<-" + std::to_string(kOutputDimensions) + "<-" +
@ -54,7 +54,7 @@ class AffineTransform {
PreviousLayer::GetStructureString() + ")"; PreviousLayer::GetStructureString() + ")";
} }
// パラメータを読み込む // read parameters
bool ReadParameters(std::istream& stream) { bool ReadParameters(std::istream& stream) {
if (!previous_layer_.ReadParameters(stream)) return false; if (!previous_layer_.ReadParameters(stream)) return false;
stream.read(reinterpret_cast<char*>(biases_), stream.read(reinterpret_cast<char*>(biases_),
@ -65,7 +65,7 @@ class AffineTransform {
return !stream.fail(); return !stream.fail();
} }
// パラメータを書き込む // write parameters
bool WriteParameters(std::ostream& stream) const { bool WriteParameters(std::ostream& stream) const {
if (!previous_layer_.WriteParameters(stream)) return false; if (!previous_layer_.WriteParameters(stream)) return false;
stream.write(reinterpret_cast<const char*>(biases_), stream.write(reinterpret_cast<const char*>(biases_),
@ -76,7 +76,7 @@ class AffineTransform {
return !stream.fail(); return !stream.fail();
} }
// 順伝播 // forward propagation
const OutputType* Propagate( const OutputType* Propagate(
const TransformedFeatureType* transformed_features, char* buffer) const { const TransformedFeatureType* transformed_features, char* buffer) const {
const auto input = previous_layer_.Propagate( const auto input = previous_layer_.Propagate(
@ -151,17 +151,17 @@ class AffineTransform {
} }
private: private:
// パラメータの型 // parameter type
using BiasType = OutputType; using BiasType = OutputType;
using WeightType = std::int8_t; using WeightType = std::int8_t;
// 学習用クラスをfriendにする // Make the learning class a friend
friend class Trainer<AffineTransform>; friend class Trainer<AffineTransform>;
// この層の直前の層 // the layer immediately before this layer
PreviousLayer previous_layer_; PreviousLayer previous_layer_;
// パラメータ // parameter
alignas(kCacheLineSize) BiasType biases_[kOutputDimensions]; alignas(kCacheLineSize) BiasType biases_[kOutputDimensions];
alignas(kCacheLineSize) alignas(kCacheLineSize)
WeightType weights_[kOutputDimensions * kPaddedInputDimensions]; WeightType weights_[kOutputDimensions * kPaddedInputDimensions];
@ -175,4 +175,4 @@ class AffineTransform {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の層ClippedReLUの定義 // Definition of layer ClippedReLU of NNUE evaluation function
#ifndef _NNUE_LAYERS_CLIPPED_RELU_H_ #ifndef _NNUE_LAYERS_CLIPPED_RELU_H_
#define _NNUE_LAYERS_CLIPPED_RELU_H_ #define _NNUE_LAYERS_CLIPPED_RELU_H_
@ -17,49 +17,49 @@ namespace Layers {
template <typename PreviousLayer> template <typename PreviousLayer>
class ClippedReLU { class ClippedReLU {
public: public:
// 入出力の型 // Input/output type
using InputType = typename PreviousLayer::OutputType; using InputType = typename PreviousLayer::OutputType;
using OutputType = std::uint8_t; using OutputType = std::uint8_t;
static_assert(std::is_same<InputType, std::int32_t>::value, ""); static_assert(std::is_same<InputType, std::int32_t>::value, "");
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = static constexpr IndexType kInputDimensions =
PreviousLayer::kOutputDimensions; PreviousLayer::kOutputDimensions;
static constexpr IndexType kOutputDimensions = kInputDimensions; static constexpr IndexType kOutputDimensions = kInputDimensions;
// この層で使用する順伝播用バッファのサイズ // Size of forward propagation buffer used in this layer
static constexpr std::size_t kSelfBufferSize = static constexpr std::size_t kSelfBufferSize =
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize); CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
// 入力層からこの層までで使用する順伝播用バッファのサイズ // Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize = static constexpr std::size_t kBufferSize =
PreviousLayer::kBufferSize + kSelfBufferSize; PreviousLayer::kBufferSize + kSelfBufferSize;
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0x538D24C7u; std::uint32_t hash_value = 0x538D24C7u;
hash_value += PreviousLayer::GetHashValue(); hash_value += PreviousLayer::GetHashValue();
return hash_value; return hash_value;
} }
// 入力層からこの層までの構造を表す文字列 // A string that represents the structure from the input layer to this layer
static std::string GetStructureString() { static std::string GetStructureString() {
return "ClippedReLU[" + return "ClippedReLU[" +
std::to_string(kOutputDimensions) + "](" + std::to_string(kOutputDimensions) + "](" +
PreviousLayer::GetStructureString() + ")"; PreviousLayer::GetStructureString() + ")";
} }
// パラメータを読み込む // read parameters
bool ReadParameters(std::istream& stream) { bool ReadParameters(std::istream& stream) {
return previous_layer_.ReadParameters(stream); return previous_layer_.ReadParameters(stream);
} }
// パラメータを書き込む // write parameters
bool WriteParameters(std::ostream& stream) const { bool WriteParameters(std::ostream& stream) const {
return previous_layer_.WriteParameters(stream); return previous_layer_.WriteParameters(stream);
} }
// 順伝播 // forward propagation
const OutputType* Propagate( const OutputType* Propagate(
const TransformedFeatureType* transformed_features, char* buffer) const { const TransformedFeatureType* transformed_features, char* buffer) const {
const auto input = previous_layer_.Propagate( const auto input = previous_layer_.Propagate(
@ -150,10 +150,10 @@ class ClippedReLU {
} }
private: private:
// 学習用クラスをfriendにする // Make the learning class a friend
friend class Trainer<ClippedReLU>; friend class Trainer<ClippedReLU>;
// この層の直前の層 // the layer immediately before this layer
PreviousLayer previous_layer_; PreviousLayer previous_layer_;
}; };
@ -165,4 +165,4 @@ class ClippedReLU {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の層InputSliceの定義 // NNUE evaluation function layer InputSlice definition
#ifndef _NNUE_LAYERS_INPUT_SLICE_H_ #ifndef _NNUE_LAYERS_INPUT_SLICE_H_
#define _NNUE_LAYERS_INPUT_SLICE_H_ #define _NNUE_LAYERS_INPUT_SLICE_H_
@ -13,47 +13,47 @@ namespace NNUE {
namespace Layers { namespace Layers {
// 入力層 // input layer
template <IndexType OutputDimensions, IndexType Offset = 0> template <IndexType OutputDimensions, IndexType Offset = 0>
class InputSlice { class InputSlice {
public: public:
// アライメントを維持する必要がある // need to maintain alignment
static_assert(Offset % kMaxSimdWidth == 0, ""); static_assert(Offset % kMaxSimdWidth == 0, "");
// 出力の型 // output type
using OutputType = TransformedFeatureType; using OutputType = TransformedFeatureType;
// 出力の次元数 // output dimensionality
static constexpr IndexType kOutputDimensions = OutputDimensions; static constexpr IndexType kOutputDimensions = OutputDimensions;
// 入力層からこの層までで使用する順伝播用バッファのサイズ // Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize = 0; static constexpr std::size_t kBufferSize = 0;
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0xEC42E90Du; std::uint32_t hash_value = 0xEC42E90Du;
hash_value ^= kOutputDimensions ^ (Offset << 10); hash_value ^= kOutputDimensions ^ (Offset << 10);
return hash_value; return hash_value;
} }
// 入力層からこの層までの構造を表す文字列 // A string that represents the structure from the input layer to this layer
static std::string GetStructureString() { static std::string GetStructureString() {
return "InputSlice[" + std::to_string(kOutputDimensions) + "(" + return "InputSlice[" + std::to_string(kOutputDimensions) + "(" +
std::to_string(Offset) + ":" + std::to_string(Offset) + ":" +
std::to_string(Offset + kOutputDimensions) + ")]"; std::to_string(Offset + kOutputDimensions) + ")]";
} }
// パラメータを読み込む // read parameters
bool ReadParameters(std::istream& /*stream*/) { bool ReadParameters(std::istream& /*stream*/) {
return true; return true;
} }
// パラメータを書き込む // write parameters
bool WriteParameters(std::ostream& /*stream*/) const { bool WriteParameters(std::ostream& /*stream*/) const {
return true; return true;
} }
// 順伝播 // forward propagation
const OutputType* Propagate( const OutputType* Propagate(
const TransformedFeatureType* transformed_features, const TransformedFeatureType* transformed_features,
char* /*buffer*/) const { char* /*buffer*/) const {
@ -71,4 +71,4 @@ class InputSlice {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の層Sumの定義 // Definition of layer Sum of NNUE evaluation function
#ifndef _NNUE_LAYERS_SUM_H_ #ifndef _NNUE_LAYERS_SUM_H_
#define _NNUE_LAYERS_SUM_H_ #define _NNUE_LAYERS_SUM_H_
@ -13,7 +13,7 @@ namespace NNUE {
namespace Layers { namespace Layers {
// 複数の層の出力の和を取る層 // Layer that sums the output of multiple layers
template <typename FirstPreviousLayer, typename... RemainingPreviousLayers> template <typename FirstPreviousLayer, typename... RemainingPreviousLayers>
class Sum : public Sum<RemainingPreviousLayers...> { class Sum : public Sum<RemainingPreviousLayers...> {
private: private:
@ -21,25 +21,25 @@ class Sum : public Sum<RemainingPreviousLayers...> {
using Tail = Sum<RemainingPreviousLayers...>; using Tail = Sum<RemainingPreviousLayers...>;
public: public:
// 入出力の型 // Input/output type
using InputType = typename Head::OutputType; using InputType = typename Head::OutputType;
using OutputType = InputType; using OutputType = InputType;
static_assert(std::is_same<InputType, typename Tail::InputType>::value, ""); static_assert(std::is_same<InputType, typename Tail::InputType>::value, "");
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = Head::kOutputDimensions; static constexpr IndexType kInputDimensions = Head::kOutputDimensions;
static constexpr IndexType kOutputDimensions = kInputDimensions; static constexpr IndexType kOutputDimensions = kInputDimensions;
static_assert(kInputDimensions == Tail::kInputDimensions , ""); static_assert(kInputDimensions == Tail::kInputDimensions ,"");
// この層で使用する順伝播用バッファのサイズ // Size of forward propagation buffer used in this layer
static constexpr std::size_t kSelfBufferSize = static constexpr std::size_t kSelfBufferSize =
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize); CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
// 入力層からこの層までで使用する順伝播用バッファのサイズ // Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize = static constexpr std::size_t kBufferSize =
std::max(Head::kBufferSize + kSelfBufferSize, Tail::kBufferSize); std::max(Head::kBufferSize + kSelfBufferSize, Tail::kBufferSize);
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0xBCE400B4u; std::uint32_t hash_value = 0xBCE400B4u;
hash_value ^= Head::GetHashValue() >> 1; hash_value ^= Head::GetHashValue() >> 1;
@ -49,67 +49,67 @@ class Sum : public Sum<RemainingPreviousLayers...> {
return hash_value; return hash_value;
} }
// 入力層からこの層までの構造を表す文字列 // A string that represents the structure from the input layer to this layer
static std::string GetStructureString() { static std::string GetStructureString() {
return "Sum[" + return "Sum[" +
std::to_string(kOutputDimensions) + "](" + GetSummandsString() + ")"; std::to_string(kOutputDimensions) + "](" + GetSummandsString() + ")";
} }
// パラメータを読み込む // read parameters
bool ReadParameters(std::istream& stream) { bool ReadParameters(std::istream& stream) {
if (!Tail::ReadParameters(stream)) return false; if (!Tail::ReadParameters(stream)) return false;
return previous_layer_.ReadParameters(stream); return previous_layer_.ReadParameters(stream);
} }
// パラメータを書き込む // write parameters
bool WriteParameters(std::ostream& stream) const { bool WriteParameters(std::ostream& stream) const {
if (!Tail::WriteParameters(stream)) return false; if (!Tail::WriteParameters(stream)) return false;
return previous_layer_.WriteParameters(stream); return previous_layer_.WriteParameters(stream);
} }
// 順伝播 // forward propagation
const OutputType* Propagate( const OutputType* Propagate(
const TransformedFeatureType* transformed_features, char* buffer) const { const TransformedFeatureType* transformed_features, char* buffer) const {
Tail::Propagate(transformed_features, buffer); Tail::Propagate(transformed_features, buffer);
const auto head_output = previous_layer_.Propagate( const auto head_output = previous_layer_.Propagate(
transformed_features, buffer + kSelfBufferSize); transformed_features, buffer + kSelfBufferSize);
const auto output = reinterpret_cast<OutputType*>(buffer); const auto output = reinterpret_cast<OutputType*>(buffer);
for (IndexType i = 0; i < kOutputDimensions; ++i) { for (IndexType i = 0; i <kOutputDimensions; ++i) {
output[i] += head_output[i]; output[i] += head_output[i];
} }
return output; return output;
} }
protected: protected:
// 和を取る対象となる層のリストを表す文字列 // A string that represents the list of layers to be summed
static std::string GetSummandsString() { static std::string GetSummandsString() {
return Head::GetStructureString() + "," + Tail::GetSummandsString(); return Head::GetStructureString() + "," + Tail::GetSummandsString();
} }
// 学習用クラスをfriendにする // Make the learning class a friend
friend class Trainer<Sum>; friend class Trainer<Sum>;
// この層の直前の層 // the layer immediately before this layer
FirstPreviousLayer previous_layer_; FirstPreviousLayer previous_layer_;
}; };
// 複数の層の出力の和を取る層テンプレート引数が1つの場合 // Layer that sums the output of multiple layers (when there is one template argument)
template <typename PreviousLayer> template <typename PreviousLayer>
class Sum<PreviousLayer> { class Sum<PreviousLayer> {
public: public:
// 入出力の型 // Input/output type
using InputType = typename PreviousLayer::OutputType; using InputType = typename PreviousLayer::OutputType;
using OutputType = InputType; using OutputType = InputType;
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = static constexpr IndexType kInputDimensions =
PreviousLayer::kOutputDimensions; PreviousLayer::kOutputDimensions;
static constexpr IndexType kOutputDimensions = kInputDimensions; static constexpr IndexType kOutputDimensions = kInputDimensions;
// 入力層からこの層までで使用する順伝播用バッファのサイズ // Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize = PreviousLayer::kBufferSize; static constexpr std::size_t kBufferSize = PreviousLayer::kBufferSize;
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0xBCE400B4u; std::uint32_t hash_value = 0xBCE400B4u;
hash_value ^= PreviousLayer::GetHashValue() >> 1; hash_value ^= PreviousLayer::GetHashValue() >> 1;
@ -117,38 +117,38 @@ class Sum<PreviousLayer> {
return hash_value; return hash_value;
} }
// 入力層からこの層までの構造を表す文字列 // A string that represents the structure from the input layer to this layer
static std::string GetStructureString() { static std::string GetStructureString() {
return "Sum[" + return "Sum[" +
std::to_string(kOutputDimensions) + "](" + GetSummandsString() + ")"; std::to_string(kOutputDimensions) + "](" + GetSummandsString() + ")";
} }
// パラメータを読み込む // read parameters
bool ReadParameters(std::istream& stream) { bool ReadParameters(std::istream& stream) {
return previous_layer_.ReadParameters(stream); return previous_layer_.ReadParameters(stream);
} }
// パラメータを書き込む // write parameters
bool WriteParameters(std::ostream& stream) const { bool WriteParameters(std::ostream& stream) const {
return previous_layer_.WriteParameters(stream); return previous_layer_.WriteParameters(stream);
} }
// 順伝播 // forward propagation
const OutputType* Propagate( const OutputType* Propagate(
const TransformedFeatureType* transformed_features, char* buffer) const { const TransformedFeatureType* transformed_features, char* buffer) const {
return previous_layer_.Propagate(transformed_features, buffer); return previous_layer_.Propagate(transformed_features, buffer);
} }
protected: protected:
// 和を取る対象となる層のリストを表す文字列 // A string that represents the list of layers to be summed
static std::string GetSummandsString() { static std::string GetSummandsString() {
return PreviousLayer::GetStructureString(); return PreviousLayer::GetStructureString();
} }
// 学習用クラスをfriendにする // Make the learning class a friend
friend class Trainer<Sum>; friend class Trainer<Sum>;
// この層の直前の層 // the layer immediately before this layer
PreviousLayer previous_layer_; PreviousLayer previous_layer_;
}; };
@ -160,4 +160,4 @@ class Sum<PreviousLayer> {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の差分計算用のクラス // Class for difference calculation of NNUE evaluation function
#ifndef _NNUE_ACCUMULATOR_H_ #ifndef _NNUE_ACCUMULATOR_H_
#define _NNUE_ACCUMULATOR_H_ #define _NNUE_ACCUMULATOR_H_
@ -11,8 +11,8 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 入力特徴量をアフィン変換した結果を保持するクラス // Class that holds the result of affine transformation of input features
// 最終的な出力である評価値も一緒に持たせておく // Keep the evaluation value that is the final output together
struct alignas(32) Accumulator { struct alignas(32) Accumulator {
std::int16_t std::int16_t
accumulation[2][kRefreshTriggers.size()][kTransformedFeatureDimensions]; accumulation[2][kRefreshTriggers.size()][kTransformedFeatureDimensions];
@ -27,4 +27,4 @@ struct alignas(32) Accumulator {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,11 +1,11 @@
// NNUE評価関数で用いる入力特徴量とネットワーク構造 // Input features and network structure used in NNUE evaluation function
#ifndef _NNUE_ARCHITECTURE_H_ #ifndef _NNUE_ARCHITECTURE_H_
#define _NNUE_ARCHITECTURE_H_ #define _NNUE_ARCHITECTURE_H_
#if defined(EVAL_NNUE) #if defined(EVAL_NNUE)
// 入力特徴量とネットワーク構造が定義されたヘッダをincludeする // include a header that defines the input features and network structure
//#include "architectures/k-p_256x2-32-32.h" //#include "architectures/k-p_256x2-32-32.h"
//#include "architectures/k-p-cr_256x2-32-32.h" //#include "architectures/k-p-cr_256x2-32-32.h"
//#include "architectures/k-p-cr-ep_256x2-32-32.h" //#include "architectures/k-p-cr-ep_256x2-32-32.h"
@ -20,7 +20,7 @@ static_assert(kTransformedFeatureDimensions % kMaxSimdWidth == 0, "");
static_assert(Network::kOutputDimensions == 1, ""); static_assert(Network::kOutputDimensions == 1, "");
static_assert(std::is_same<Network::OutputType, std::int32_t>::value, ""); static_assert(std::is_same<Network::OutputType, std::int32_t>::value, "");
// 差分計算の代わりに全計算を行うタイミングのリスト // List of timings to perform all calculations instead of difference calculation
constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers; constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers;
} // namespace NNUE } // namespace NNUE
@ -29,4 +29,4 @@ constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers;
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数で用いる定数など // Constants used in NNUE evaluation function
#ifndef _NNUE_COMMON_H_ #ifndef _NNUE_COMMON_H_
#define _NNUE_COMMON_H_ #define _NNUE_COMMON_H_
@ -17,17 +17,17 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価関数ファイルのバージョンを表す定数 // A constant that represents the version of the evaluation function file
constexpr std::uint32_t kVersion = 0x7AF32F16u; constexpr std::uint32_t kVersion = 0x7AF32F16u;
// 評価値の計算で利用する定数 // Constant used in evaluation value calculation
constexpr int FV_SCALE = 16; constexpr int FV_SCALE = 16;
constexpr int kWeightScaleBits = 6; constexpr int kWeightScaleBits = 6;
// キャッシュラインのサイズ(バイト単位) // Size of cache line (in bytes)
constexpr std::size_t kCacheLineSize = 64; constexpr std::size_t kCacheLineSize = 64;
// SIMD幅(バイト単位) // SIMD width (in bytes)
#if defined(USE_AVX2) #if defined(USE_AVX2)
constexpr std::size_t kSimdWidth = 32; constexpr std::size_t kSimdWidth = 32;
#elif defined(USE_SSE2) #elif defined(USE_SSE2)
@ -37,17 +37,17 @@ constexpr std::size_t kSimdWidth = 16;
#endif #endif
constexpr std::size_t kMaxSimdWidth = 32; constexpr std::size_t kMaxSimdWidth = 32;
// 変換後の入力特徴量の型 // Type of input feature after conversion
using TransformedFeatureType = std::uint8_t; using TransformedFeatureType = std::uint8_t;
// インデックスの型 // index type
using IndexType = std::uint32_t; using IndexType = std::uint32_t;
// 学習用クラステンプレートの前方宣言 // Forward declaration of learning class template
template <typename Layer> template <typename Layer>
class Trainer; class Trainer;
// n以上で最小のbaseの倍数を求める // find the smallest multiple of n and above
template <typename IntType> template <typename IntType>
constexpr IntType CeilToMultiple(IntType n, IntType base) { constexpr IntType CeilToMultiple(IntType n, IntType base) {
return (n + base - 1) / base * base; return (n + base - 1) / base * base;

View file

@ -1,4 +1,4 @@
// NNUE評価関数の入力特徴量の変換を行うクラス // A class that converts the input features of the NNUE evaluation function
#ifndef _NNUE_FEATURE_TRANSFORMER_H_ #ifndef _NNUE_FEATURE_TRANSFORMER_H_
#define _NNUE_FEATURE_TRANSFORMER_H_ #define _NNUE_FEATURE_TRANSFORMER_H_
@ -15,37 +15,37 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 入力特徴量変換器 // Input feature converter
class FeatureTransformer { class FeatureTransformer {
private: private:
// 片側分の出力の次元数 // number of output dimensions for one side
static constexpr IndexType kHalfDimensions = kTransformedFeatureDimensions; static constexpr IndexType kHalfDimensions = kTransformedFeatureDimensions;
public: public:
// 出力の型 // output type
using OutputType = TransformedFeatureType; using OutputType = TransformedFeatureType;
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = RawFeatures::kDimensions; static constexpr IndexType kInputDimensions = RawFeatures::kDimensions;
static constexpr IndexType kOutputDimensions = kHalfDimensions * 2; static constexpr IndexType kOutputDimensions = kHalfDimensions * 2;
// 順伝播用バッファのサイズ // size of forward propagation buffer
static constexpr std::size_t kBufferSize = static constexpr std::size_t kBufferSize =
kOutputDimensions * sizeof(OutputType); kOutputDimensions * sizeof(OutputType);
// 評価関数ファイルに埋め込むハッシュ値 // Hash value embedded in the evaluation function file
static constexpr std::uint32_t GetHashValue() { static constexpr std::uint32_t GetHashValue() {
return RawFeatures::kHashValue ^ kOutputDimensions; return RawFeatures::kHashValue ^ kOutputDimensions;
} }
// 構造を表す文字列 // a string representing the structure
static std::string GetStructureString() { static std::string GetStructureString() {
return RawFeatures::GetName() + "[" + return RawFeatures::GetName() + "[" +
std::to_string(kInputDimensions) + "->" + std::to_string(kInputDimensions) + "->" +
std::to_string(kHalfDimensions) + "x2]"; std::to_string(kHalfDimensions) + "x2]";
} }
// パラメータを読み込む // read parameters
bool ReadParameters(std::istream& stream) { bool ReadParameters(std::istream& stream) {
stream.read(reinterpret_cast<char*>(biases_), stream.read(reinterpret_cast<char*>(biases_),
kHalfDimensions * sizeof(BiasType)); kHalfDimensions * sizeof(BiasType));
@ -54,7 +54,7 @@ class FeatureTransformer {
return !stream.fail(); return !stream.fail();
} }
// パラメータを書き込む // write parameters
bool WriteParameters(std::ostream& stream) const { bool WriteParameters(std::ostream& stream) const {
stream.write(reinterpret_cast<const char*>(biases_), stream.write(reinterpret_cast<const char*>(biases_),
kHalfDimensions * sizeof(BiasType)); kHalfDimensions * sizeof(BiasType));
@ -63,7 +63,7 @@ class FeatureTransformer {
return !stream.fail(); return !stream.fail();
} }
// 可能なら差分計算を進める // 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) {
@ -77,7 +77,7 @@ class FeatureTransformer {
return false; return false;
} }
// 入力特徴量を変換する // convert input features
void Transform(const Position& pos, OutputType* output, bool refresh) const { void Transform(const Position& pos, OutputType* output, bool refresh) const {
if (refresh || !UpdateAccumulatorIfPossible(pos)) { if (refresh || !UpdateAccumulatorIfPossible(pos)) {
RefreshAccumulator(pos); RefreshAccumulator(pos);
@ -174,7 +174,7 @@ class FeatureTransformer {
} }
private: private:
// 差分計算を用いずに累積値を計算する // 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;
for (IndexType i = 0; i < kRefreshTriggers.size(); ++i) { for (IndexType i = 0; i < kRefreshTriggers.size(); ++i) {
@ -232,7 +232,7 @@ class FeatureTransformer {
accumulator.computed_score = false; accumulator.computed_score = false;
} }
// 差分計算を用いて累積値を計算する // 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;
@ -263,7 +263,7 @@ class FeatureTransformer {
std::memset(accumulator.accumulation[perspective][i], 0, std::memset(accumulator.accumulation[perspective][i], 0,
kHalfDimensions * sizeof(BiasType)); kHalfDimensions * sizeof(BiasType));
} }
} else { // 1から0に変化した特徴量に関する差分計算 } else {// Difference calculation for the feature amount changed from 1 to 0
std::memcpy(accumulator.accumulation[perspective][i], std::memcpy(accumulator.accumulation[perspective][i],
prev_accumulator.accumulation[perspective][i], prev_accumulator.accumulation[perspective][i],
kHalfDimensions * sizeof(BiasType)); kHalfDimensions * sizeof(BiasType));
@ -292,7 +292,7 @@ class FeatureTransformer {
#endif #endif
} }
} }
{ // 0から1に変化した特徴量に関する差分計算 {// Difference calculation for features that changed from 0 to 1
for (const auto index : added_indices[perspective]) { for (const auto index : added_indices[perspective]) {
const IndexType offset = kHalfDimensions * index; const IndexType offset = kHalfDimensions * index;
#if defined(USE_AVX2) #if defined(USE_AVX2)
@ -325,14 +325,14 @@ class FeatureTransformer {
accumulator.computed_score = false; accumulator.computed_score = false;
} }
// パラメータの型 // parameter type
using BiasType = std::int16_t; using BiasType = std::int16_t;
using WeightType = std::int16_t; using WeightType = std::int16_t;
// 学習用クラスをfriendにする // Make the learning class a friend
friend class Trainer<FeatureTransformer>; friend class Trainer<FeatureTransformer>;
// パラメータ // parameter
alignas(kCacheLineSize) BiasType biases_[kHalfDimensions]; alignas(kCacheLineSize) BiasType biases_[kHalfDimensions];
alignas(kCacheLineSize) alignas(kCacheLineSize)
WeightType weights_[kHalfDimensions * kInputDimensions]; WeightType weights_[kHalfDimensions * kInputDimensions];
@ -344,4 +344,4 @@ class FeatureTransformer {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数に関するUSI拡張コマンド // USI extended command for NNUE evaluation function
#if defined(ENABLE_TEST_CMD) && defined(EVAL_NNUE) #if defined(ENABLE_TEST_CMD) && defined(EVAL_NNUE)
@ -19,15 +19,15 @@ namespace NNUE {
namespace { namespace {
// 主に差分計算に関するRawFeaturesのテスト // Testing RawFeatures mainly for difference calculation
void TestFeatures(Position& pos) { void TestFeatures(Position& pos) {
const std::uint64_t num_games = 1000; const std::uint64_t num_games = 1000;
StateInfo si; StateInfo si;
pos.set(StartFEN, false, &si, Threads.main()); pos.set(StartFEN, false, &si, Threads.main());
const int MAX_PLY = 256; // 256手までテスト const int MAX_PLY = 256; // test up to 256 hands
StateInfo state[MAX_PLY]; // StateInfoを最大手数分だけ StateInfo state[MAX_PLY]; // StateInfo only for the maximum number of steps
int ply; // 初期局面からの手数 int ply; // Trouble from the initial phase
PRNG prng(20171128); PRNG prng(20171128);
@ -96,13 +96,13 @@ void TestFeatures(Position& pos) {
for (std::uint64_t i = 0; i < num_games; ++i) { for (std::uint64_t i = 0; i < num_games; ++i) {
auto index_sets = make_index_sets(pos); auto index_sets = make_index_sets(pos);
for (ply = 0; ply < MAX_PLY; ++ply) { for (ply = 0; ply < MAX_PLY; ++ply) {
MoveList<LEGAL> mg(pos); // 全合法手の生成 MoveList<LEGAL> mg(pos); // Generate all legal hands
// 合法な指し手がなかった == 詰み // There was no legal move == Clog
if (mg.size() == 0) if (mg.size() == 0)
break; break;
// 生成された指し手のなかからランダムに選び、その指し手で局面を進める。 // Randomly choose from the generated moves and advance the phase with the moves.
Move m = mg.begin()[prng.rand(mg.size())]; Move m = mg.begin()[prng.rand(mg.size())];
pos.do_move(m, state[ply]); pos.do_move(m, state[ply]);
@ -113,7 +113,7 @@ void TestFeatures(Position& pos) {
pos.set(StartFEN, false, &si, Threads.main()); pos.set(StartFEN, false, &si, Threads.main());
// 100回に1回ごとに'.'を出力(進んでいることがわかるように) // Output'.' every 100 times (so you can see that it's progressing)
if ((i % 100) == 0) if ((i % 100) == 0)
std::cout << "." << std::flush; std::cout << "." << std::flush;
} }
@ -141,7 +141,7 @@ void TestFeatures(Position& pos) {
<< ") features" << std::endl; << ") features" << std::endl;
} }
// 評価関数の構造を表す文字列を出力する // Output a string that represents the structure of the evaluation function
void PrintInfo(std::istream& stream) { void PrintInfo(std::istream& stream) {
std::cout << "network architecture: " << GetArchitectureString() << std::endl; std::cout << "network architecture: " << GetArchitectureString() << std::endl;
@ -178,7 +178,7 @@ void PrintInfo(std::istream& stream) {
} // namespace } // namespace
// NNUE評価関数に関するUSI拡張コマンド // USI extended command for NNUE evaluation function
void TestCommand(Position& pos, std::istream& stream) { void TestCommand(Position& pos, std::istream& stream) {
std::string sub_command; std::string sub_command;
stream >> sub_command; stream >> sub_command;

View file

@ -1,4 +1,4 @@
// NNUE評価関数に関するUSI拡張コマンドのインターフェイス // USI extended command interface for NNUE evaluation function
#ifndef _NNUE_TEST_COMMAND_H_ #ifndef _NNUE_TEST_COMMAND_H_
#define _NNUE_TEST_COMMAND_H_ #define _NNUE_TEST_COMMAND_H_
@ -9,7 +9,7 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// NNUE評価関数に関するUSI拡張コマンド // USI extended command for NNUE evaluation function
void TestCommand(Position& pos, std::istream& stream); void TestCommand(Position& pos, std::istream& stream);
} // namespace NNUE } // namespace NNUE

View file

@ -1,4 +1,4 @@
// NNUE評価関数の特徴量変換クラステンプレート // NNUE evaluation function feature conversion class template
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_H_ #ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_H_
#define _NNUE_TRAINER_FEATURES_FACTORIZER_H_ #define _NNUE_TRAINER_FEATURES_FACTORIZER_H_
@ -14,31 +14,31 @@ namespace NNUE {
namespace Features { namespace Features {
// 入力特徴量を学習用特徴量に変換するクラステンプレート // Class template that converts input features into learning features
// デフォルトでは学習用特徴量は元の入力特徴量と同じとし、必要に応じて特殊化する // By default, the learning feature is the same as the original input feature, and specialized as necessary
template <typename FeatureType> template <typename FeatureType>
class Factorizer { class Factorizer {
public: public:
// 学習用特徴量の次元数を取得する // Get the dimensionality of the learning feature
static constexpr IndexType GetDimensions() { static constexpr IndexType GetDimensions() {
return FeatureType::kDimensions; return FeatureType::kDimensions;
} }
// 学習用特徴量のインデックスと学習率のスケールを取得する // Get index of learning feature and scale of learning rate
static void AppendTrainingFeatures( static void AppendTrainingFeatures(
IndexType base_index, std::vector<TrainingFeature>* training_features) { IndexType base_index, std::vector<TrainingFeature>* training_features) {
assert(base_index < FeatureType::kDimensions); assert(base_index <FeatureType::kDimensions);
training_features->emplace_back(base_index); training_features->emplace_back(base_index);
} }
}; };
// 学習用特徴量の情報 // Learning feature information
struct FeatureProperties { struct FeatureProperties {
bool active; bool active;
IndexType dimensions; IndexType dimensions;
}; };
// 元の入力特徴量を学習用特徴量に追加する // Add the original input features to the learning features
template <typename FeatureType> template <typename FeatureType>
IndexType AppendBaseFeature( IndexType AppendBaseFeature(
FeatureProperties properties, IndexType base_index, FeatureProperties properties, IndexType base_index,
@ -49,7 +49,7 @@ IndexType AppendBaseFeature(
return properties.dimensions; return properties.dimensions;
} }
// 学習率のスケールが0でなければ他の種類の学習用特徴量を引き継ぐ // If the learning rate scale is not 0, inherit other types of learning features
template <typename FeatureType> template <typename FeatureType>
IndexType InheritFeaturesIfRequired( IndexType InheritFeaturesIfRequired(
IndexType index_offset, FeatureProperties properties, IndexType base_index, IndexType index_offset, FeatureProperties properties, IndexType base_index,
@ -70,8 +70,8 @@ IndexType InheritFeaturesIfRequired(
return properties.dimensions; return properties.dimensions;
} }
// 学習用特徴量を追加せず、必要に応じてインデックスの差分を返す // Return the index difference as needed, without adding learning features
// 対応する特徴量がない場合にInheritFeaturesIfRequired()の代わりに呼ぶ // Call instead of InheritFeaturesIfRequired() if there are no corresponding features
IndexType SkipFeatures(FeatureProperties properties) { IndexType SkipFeatures(FeatureProperties properties) {
if (!properties.active) { if (!properties.active) {
return 0; return 0;
@ -79,7 +79,7 @@ IndexType SkipFeatures(FeatureProperties properties) {
return properties.dimensions; return properties.dimensions;
} }
// 学習用特徴量の次元数を取得する // Get the dimensionality of the learning feature
template <std::size_t N> template <std::size_t N>
constexpr IndexType GetActiveDimensions( constexpr IndexType GetActiveDimensions(
const FeatureProperties (&properties)[N]) { const FeatureProperties (&properties)[N]) {
@ -93,7 +93,7 @@ constexpr IndexType GetActiveDimensions(
return dimensions; return dimensions;
} }
// 配列の要素数を取得する // get the number of elements in the array
template <typename T, std::size_t N> template <typename T, std::size_t N>
constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) { constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) {
return N; return N;
@ -107,4 +107,4 @@ constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の特徴量変換クラステンプレートのFeatureSet用特殊化 // Specialization for feature set of feature conversion class template of NNUE evaluation function
#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_
@ -14,8 +14,8 @@ namespace NNUE {
namespace Features { namespace Features {
// 入力特徴量を学習用特徴量に変換するクラステンプレート // Class template that converts input features into learning features
// FeatureSet用特殊化 // Specialization for FeatureSet
template <typename FirstFeatureType, typename... RemainingFeatureTypes> template <typename FirstFeatureType, typename... RemainingFeatureTypes>
class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> { class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
private: private:
@ -23,16 +23,16 @@ class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
using Tail = Factorizer<FeatureSet<RemainingFeatureTypes...>>; using Tail = Factorizer<FeatureSet<RemainingFeatureTypes...>>;
public: public:
// 元の入力特徴量の次元数 // number of dimensions of original input features
static constexpr IndexType kBaseDimensions = static constexpr IndexType kBaseDimensions =
FeatureSet<FirstFeatureType, RemainingFeatureTypes...>::kDimensions; FeatureSet<FirstFeatureType, RemainingFeatureTypes...>::kDimensions;
// 学習用特徴量の次元数を取得する // Get the dimensionality of the learning feature
static constexpr IndexType GetDimensions() { static constexpr IndexType GetDimensions() {
return Head::GetDimensions() + Tail::GetDimensions(); return Head::GetDimensions() + Tail::GetDimensions();
} }
// 学習用特徴量のインデックスと学習率のスケールを取得する // Get index of learning feature and scale of learning rate
static void AppendTrainingFeatures( static void AppendTrainingFeatures(
IndexType base_index, std::vector<TrainingFeature>* training_features, IndexType base_index, std::vector<TrainingFeature>* training_features,
IndexType base_dimensions = kBaseDimensions) { IndexType base_dimensions = kBaseDimensions) {
@ -62,20 +62,20 @@ class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
} }
}; };
// 入力特徴量を学習用特徴量に変換するクラステンプレート // Class template that converts input features into learning features
// FeatureSetのテンプレート引数が1つの場合の特殊化 // Specialization when FeatureSet has one template argument
template <typename FeatureType> template <typename FeatureType>
class Factorizer<FeatureSet<FeatureType>> { class Factorizer<FeatureSet<FeatureType>> {
public: public:
// 元の入力特徴量の次元数 // number of dimensions of original input features
static constexpr IndexType kBaseDimensions = FeatureType::kDimensions; static constexpr IndexType kBaseDimensions = FeatureType::kDimensions;
// 学習用特徴量の次元数を取得する // Get the dimensionality of the learning feature
static constexpr IndexType GetDimensions() { static constexpr IndexType GetDimensions() {
return Factorizer<FeatureType>::GetDimensions(); return Factorizer<FeatureType>::GetDimensions();
} }
// 学習用特徴量のインデックスと学習率のスケールを取得する // Get index of learning feature and scale of learning rate
static void AppendTrainingFeatures( static void AppendTrainingFeatures(
IndexType base_index, std::vector<TrainingFeature>* training_features, IndexType base_index, std::vector<TrainingFeature>* training_features,
IndexType base_dimensions = kBaseDimensions) { IndexType base_dimensions = kBaseDimensions) {
@ -101,4 +101,4 @@ public:
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の特徴量変換クラステンプレートのHalfKP用特殊化 // Specialization of NNUE evaluation function feature conversion class template for HalfKP
#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_
@ -16,18 +16,18 @@ namespace NNUE {
namespace Features { namespace Features {
// 入力特徴量を学習用特徴量に変換するクラステンプレート // Class template that converts input features into learning features
// HalfKP用特殊化 // Specialization for HalfKP
template <Side AssociatedKing> template <Side AssociatedKing>
class Factorizer<HalfKP<AssociatedKing>> { class Factorizer<HalfKP<AssociatedKing>> {
private: private:
using FeatureType = HalfKP<AssociatedKing>; using FeatureType = HalfKP<AssociatedKing>;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値 // The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = static constexpr IndexType kMaxActiveDimensions =
FeatureType::kMaxActiveDimensions; FeatureType::kMaxActiveDimensions;
// 学習用特徴量の種類 // Type of learning feature
enum TrainingFeatureType { enum TrainingFeatureType {
kFeaturesHalfKP, kFeaturesHalfKP,
kFeaturesHalfK, kFeaturesHalfK,
@ -36,7 +36,7 @@ class Factorizer<HalfKP<AssociatedKing>> {
kNumTrainingFeatureTypes, kNumTrainingFeatureTypes,
}; };
// 学習用特徴量の情報 // Learning feature information
static constexpr FeatureProperties kProperties[] = { static constexpr FeatureProperties kProperties[] = {
// kFeaturesHalfKP // kFeaturesHalfKP
{true, FeatureType::kDimensions}, {true, FeatureType::kDimensions},
@ -50,12 +50,12 @@ class Factorizer<HalfKP<AssociatedKing>> {
static_assert(GetArrayLength(kProperties) == kNumTrainingFeatureTypes, ""); static_assert(GetArrayLength(kProperties) == kNumTrainingFeatureTypes, "");
public: public:
// 学習用特徴量の次元数を取得する // Get the dimensionality of the learning feature
static constexpr IndexType GetDimensions() { static constexpr IndexType GetDimensions() {
return GetActiveDimensions(kProperties); return GetActiveDimensions(kProperties);
} }
// 学習用特徴量のインデックスと学習率のスケールを取得する // Get index of learning feature and scale of learning rate
static void AppendTrainingFeatures( static void AppendTrainingFeatures(
IndexType base_index, std::vector<TrainingFeature>* training_features) { IndexType base_index, std::vector<TrainingFeature>* training_features) {
// kFeaturesHalfKP // kFeaturesHalfKP
@ -100,4 +100,4 @@ constexpr FeatureProperties Factorizer<HalfKP<AssociatedKing>>::kProperties[];
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習用クラステンプレートの共通ヘッダ // Common header of class template for learning NNUE evaluation function
#ifndef _NNUE_TRAINER_H_ #ifndef _NNUE_TRAINER_H_
#define _NNUE_TRAINER_H_ #define _NNUE_TRAINER_H_
@ -18,10 +18,10 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 評価値と勝率の関係式で用いるPonanza定数 // Ponanza constant used in the relation between evaluation value and winning percentage
constexpr double kPonanzaConstant = 600.0; constexpr double kPonanzaConstant = 600.0;
// 学習用特徴量のインデックス1つを表すクラス // Class that represents one index of learning feature
class TrainingFeature { class TrainingFeature {
using StorageType = std::uint32_t; using StorageType = std::uint32_t;
static_assert(std::is_unsigned<StorageType>::value, ""); static_assert(std::is_unsigned<StorageType>::value, "");
@ -60,7 +60,7 @@ class TrainingFeature {
StorageType index_and_count_; StorageType index_and_count_;
}; };
// 学習データ1サンプルを表す構造体 // Structure that represents one sample of training data
struct Example { struct Example {
std::vector<TrainingFeature> training_features[2]; std::vector<TrainingFeature> training_features[2];
Learner::PackedSfenValue psv; Learner::PackedSfenValue psv;
@ -68,9 +68,9 @@ struct Example {
double weight; double weight;
}; };
// ハイパーパラメータの設定などに使用するメッセージ // Message used for setting hyperparameters
struct Message { struct Message {
Message(const std::string& name, const std::string& value = "") : Message(const std::string& name, const std::string& value = ""):
name(name), value(value), num_peekers(0), num_receivers(0) {} name(name), value(value), num_peekers(0), num_receivers(0) {}
const std::string name; const std::string name;
const std::string value; const std::string value;
@ -78,7 +78,7 @@ struct Message {
std::uint32_t num_receivers; std::uint32_t num_receivers;
}; };
// メッセージを受理するかどうかを判定する // determine whether to accept the message
bool ReceiveMessage(const std::string& name, Message* message) { bool ReceiveMessage(const std::string& name, Message* message) {
const auto subscript = "[" + std::to_string(message->num_peekers) + "]"; const auto subscript = "[" + std::to_string(message->num_peekers) + "]";
if (message->name.substr(0, name.size() + 1) == name + "[") { if (message->name.substr(0, name.size() + 1) == name + "[") {
@ -91,7 +91,7 @@ bool ReceiveMessage(const std::string& name, Message* message) {
return false; return false;
} }
// 文字列を分割する // split the string
std::vector<std::string> Split(const std::string& input, char delimiter) { std::vector<std::string> Split(const std::string& input, char delimiter) {
std::istringstream stream(input); std::istringstream stream(input);
std::string field; std::string field;
@ -102,13 +102,13 @@ std::vector<std::string> Split(const std::string& input, char delimiter) {
return fields; return fields;
} }
// 浮動小数点数を整数に丸める // round a floating point number to an integer
template <typename IntType> template <typename IntType>
IntType Round(double value) { IntType Round(double value) {
return static_cast<IntType>(std::floor(value + 0.5)); return static_cast<IntType>(std::floor(value + 0.5));
} }
// アライメント付きmake_shared // make_shared with alignment
template <typename T, typename... ArgumentTypes> template <typename T, typename... ArgumentTypes>
std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments) { std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments) {
const auto ptr = new(aligned_malloc(sizeof(T), alignof(T))) const auto ptr = new(aligned_malloc(sizeof(T), alignof(T)))
@ -122,4 +122,4 @@ std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments) {
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習クラステンプレートのAffineTransform用特殊化 // Specialization of NNUE evaluation function learning class template for AffineTransform
#ifndef _NNUE_TRAINER_AFFINE_TRANSFORM_H_ #ifndef _NNUE_TRAINER_AFFINE_TRANSFORM_H_
#define _NNUE_TRAINER_AFFINE_TRANSFORM_H_ #define _NNUE_TRAINER_AFFINE_TRANSFORM_H_
@ -15,22 +15,22 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 学習:アフィン変換層 // Learning: Affine transformation layer
template <typename PreviousLayer, IndexType OutputDimensions> template <typename PreviousLayer, IndexType OutputDimensions>
class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> { class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
private: private:
// 学習対象の層の型 // Type of layer to learn
using LayerType = Layers::AffineTransform<PreviousLayer, OutputDimensions>; using LayerType = Layers::AffineTransform<PreviousLayer, OutputDimensions>;
public: public:
// ファクトリ関数 // factory function
static std::shared_ptr<Trainer> Create( static std::shared_ptr<Trainer> Create(
LayerType* target_layer, FeatureTransformer* feature_transformer) { LayerType* target_layer, FeatureTransformer* feature_transformer) {
return std::shared_ptr<Trainer>( return std::shared_ptr<Trainer>(
new Trainer(target_layer, feature_transformer)); new Trainer(target_layer, feature_transformer));
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SendMessage(Message* message) { void SendMessage(Message* message) {
previous_layer_trainer_->SendMessage(message); previous_layer_trainer_->SendMessage(message);
if (ReceiveMessage("momentum", message)) { if (ReceiveMessage("momentum", message)) {
@ -48,19 +48,19 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
} }
} }
// パラメータを乱数で初期化する // Initialize the parameters with random numbers
template <typename RNG> template <typename RNG>
void Initialize(RNG& rng) { void Initialize(RNG& rng) {
previous_layer_trainer_->Initialize(rng); previous_layer_trainer_->Initialize(rng);
if (kIsOutputLayer) { if (kIsOutputLayer) {
// 出力層は0で初期化する // Initialize output layer with 0
std::fill(std::begin(biases_), std::end(biases_), std::fill(std::begin(biases_), std::end(biases_),
static_cast<LearnFloatType>(0.0)); static_cast<LearnFloatType>(0.0));
std::fill(std::begin(weights_), std::end(weights_), std::fill(std::begin(weights_), std::end(weights_),
static_cast<LearnFloatType>(0.0)); static_cast<LearnFloatType>(0.0));
} else { } else {
// 入力の分布が各ユニット平均0.5、等分散であることを仮定し、 // Assuming that the input distribution is unit-mean 0.5, equal variance,
// 出力の分布が各ユニット平均0.5、入力と同じ等分散になるように初期化する // Initialize the output distribution so that each unit has a mean of 0.5 and the same variance as the input
const double kSigma = 1.0 / std::sqrt(kInputDimensions); const double kSigma = 1.0 / std::sqrt(kInputDimensions);
auto distribution = std::normal_distribution<double>(0.0, kSigma); auto distribution = std::normal_distribution<double>(0.0, kSigma);
for (IndexType i = 0; i < kOutputDimensions; ++i) { for (IndexType i = 0; i < kOutputDimensions; ++i) {
@ -76,7 +76,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
QuantizeParameters(); QuantizeParameters();
} }
// 順伝播 // forward propagation
const LearnFloatType* Propagate(const std::vector<Example>& batch) { const LearnFloatType* Propagate(const std::vector<Example>& batch) {
if (output_.size() < kOutputDimensions * batch.size()) { if (output_.size() < kOutputDimensions * batch.size()) {
output_.resize(kOutputDimensions * batch.size()); output_.resize(kOutputDimensions * batch.size());
@ -111,7 +111,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
return output_.data(); return output_.data();
} }
// 逆伝播 // backpropagation
void Backpropagate(const LearnFloatType* gradients, void Backpropagate(const LearnFloatType* gradients,
LearnFloatType learning_rate) { LearnFloatType learning_rate) {
const LearnFloatType local_learning_rate = const LearnFloatType local_learning_rate =
@ -185,7 +185,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
} }
private: private:
// コンストラクタ // constructor
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) : Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) :
batch_size_(0), batch_size_(0),
batch_input_(nullptr), batch_input_(nullptr),
@ -201,7 +201,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
DequantizeParameters(); DequantizeParameters();
} }
// 重みの飽和とパラメータの整数化 // Weight saturation and parameterization
void QuantizeParameters() { void QuantizeParameters() {
for (IndexType i = 0; i < kOutputDimensions * kInputDimensions; ++i) { for (IndexType i = 0; i < kOutputDimensions * kInputDimensions; ++i) {
weights_[i] = std::max(-kMaxWeightMagnitude, weights_[i] = std::max(-kMaxWeightMagnitude,
@ -222,7 +222,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
} }
} }
// 整数化されたパラメータの読み込み // read parameterized integer
void DequantizeParameters() { void DequantizeParameters() {
for (IndexType i = 0; i < kOutputDimensions; ++i) { for (IndexType i = 0; i < kOutputDimensions; ++i) {
biases_[i] = static_cast<LearnFloatType>( biases_[i] = static_cast<LearnFloatType>(
@ -242,14 +242,14 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
static_cast<LearnFloatType>(0.0)); static_cast<LearnFloatType>(0.0));
} }
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = LayerType::kInputDimensions; static constexpr IndexType kInputDimensions = LayerType::kInputDimensions;
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions; static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
// 出力の次元数が1なら出力層 // If the output dimensionality is 1, the output layer
static constexpr bool kIsOutputLayer = kOutputDimensions == 1; static constexpr bool kIsOutputLayer = kOutputDimensions == 1;
// パラメータの整数化で用いる係数 // Coefficient used for parameterization
static constexpr LearnFloatType kActivationScale = static constexpr LearnFloatType kActivationScale =
std::numeric_limits<std::int8_t>::max(); std::numeric_limits<std::int8_t>::max();
static constexpr LearnFloatType kBiasScale = kIsOutputLayer ? static constexpr LearnFloatType kBiasScale = kIsOutputLayer ?
@ -257,37 +257,37 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
((1 << kWeightScaleBits) * kActivationScale); ((1 << kWeightScaleBits) * kActivationScale);
static constexpr LearnFloatType kWeightScale = kBiasScale / kActivationScale; static constexpr LearnFloatType kWeightScale = kBiasScale / kActivationScale;
// パラメータの整数化でオーバーフローさせないために用いる重みの絶対値の上限 // Upper limit of absolute value of weight used to prevent overflow when parameterizing integers
static constexpr LearnFloatType kMaxWeightMagnitude = static constexpr LearnFloatType kMaxWeightMagnitude =
std::numeric_limits<typename LayerType::WeightType>::max() / kWeightScale; std::numeric_limits<typename LayerType::WeightType>::max() / kWeightScale;
// ミニバッチのサンプル数 // number of samples in mini-batch
IndexType batch_size_; IndexType batch_size_;
// ミニバッチの入力 // Input mini batch
const LearnFloatType* batch_input_; const LearnFloatType* batch_input_;
// 直前の層のTrainer // Trainer of the previous layer
const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_; const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_;
// 学習対象の層 // layer to learn
LayerType* const target_layer_; LayerType* const target_layer_;
// パラメータ // parameter
LearnFloatType biases_[kOutputDimensions]; LearnFloatType biases_[kOutputDimensions];
LearnFloatType weights_[kOutputDimensions * kInputDimensions]; LearnFloatType weights_[kOutputDimensions * kInputDimensions];
// パラメータの更新で用いるバッファ // Buffer used for updating parameters
LearnFloatType biases_diff_[kOutputDimensions]; LearnFloatType biases_diff_[kOutputDimensions];
LearnFloatType weights_diff_[kOutputDimensions * kInputDimensions]; LearnFloatType weights_diff_[kOutputDimensions * kInputDimensions];
// 順伝播用バッファ // Forward propagation buffer
std::vector<LearnFloatType> output_; std::vector<LearnFloatType> output_;
// 逆伝播用バッファ // buffer for back propagation
std::vector<LearnFloatType> gradients_; std::vector<LearnFloatType> gradients_;
// ハイパーパラメータ // hyper parameter
LearnFloatType momentum_; LearnFloatType momentum_;
LearnFloatType learning_rate_scale_; LearnFloatType learning_rate_scale_;
}; };

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習クラステンプレートのClippedReLU用特殊化 // Specialization of NNUE evaluation function learning class template for ClippedReLU
#ifndef _NNUE_TRAINER_CLIPPED_RELU_H_ #ifndef _NNUE_TRAINER_CLIPPED_RELU_H_
#define _NNUE_TRAINER_CLIPPED_RELU_H_ #define _NNUE_TRAINER_CLIPPED_RELU_H_
@ -13,22 +13,22 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 学習:アフィン変換層 // Learning: Affine transformation layer
template <typename PreviousLayer> template <typename PreviousLayer>
class Trainer<Layers::ClippedReLU<PreviousLayer>> { class Trainer<Layers::ClippedReLU<PreviousLayer>> {
private: private:
// 学習対象の層の型 // Type of layer to learn
using LayerType = Layers::ClippedReLU<PreviousLayer>; using LayerType = Layers::ClippedReLU<PreviousLayer>;
public: public:
// ファクトリ関数 // factory function
static std::shared_ptr<Trainer> Create( static std::shared_ptr<Trainer> Create(
LayerType* target_layer, FeatureTransformer* feature_transformer) { LayerType* target_layer, FeatureTransformer* feature_transformer) {
return std::shared_ptr<Trainer>( return std::shared_ptr<Trainer>(
new Trainer(target_layer, feature_transformer)); new Trainer(target_layer, feature_transformer));
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SendMessage(Message* message) { void SendMessage(Message* message) {
previous_layer_trainer_->SendMessage(message); previous_layer_trainer_->SendMessage(message);
if (ReceiveMessage("check_health", message)) { if (ReceiveMessage("check_health", message)) {
@ -36,13 +36,13 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
} }
} }
// パラメータを乱数で初期化する // Initialize the parameters with random numbers
template <typename RNG> template <typename RNG>
void Initialize(RNG& rng) { void Initialize(RNG& rng) {
previous_layer_trainer_->Initialize(rng); previous_layer_trainer_->Initialize(rng);
} }
// 順伝播 // forward propagation
const LearnFloatType* Propagate(const std::vector<Example>& batch) { const LearnFloatType* Propagate(const std::vector<Example>& batch) {
if (output_.size() < kOutputDimensions * batch.size()) { if (output_.size() < kOutputDimensions * batch.size()) {
output_.resize(kOutputDimensions * batch.size()); output_.resize(kOutputDimensions * batch.size());
@ -62,7 +62,7 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
return output_.data(); return output_.data();
} }
// 逆伝播 // backpropagation
void Backpropagate(const LearnFloatType* gradients, void Backpropagate(const LearnFloatType* gradients,
LearnFloatType learning_rate) { LearnFloatType learning_rate) {
for (IndexType b = 0; b < batch_size_; ++b) { for (IndexType b = 0; b < batch_size_; ++b) {
@ -77,7 +77,7 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
} }
private: private:
// コンストラクタ // constructor
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) : Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) :
batch_size_(0), batch_size_(0),
previous_layer_trainer_(Trainer<PreviousLayer>::Create( previous_layer_trainer_(Trainer<PreviousLayer>::Create(
@ -89,7 +89,7 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
std::numeric_limits<LearnFloatType>::lowest()); std::numeric_limits<LearnFloatType>::lowest());
} }
// 学習に問題が生じていないかチェックする // Check if there are any problems with learning
void CheckHealth() { void CheckHealth() {
const auto largest_min_activation = *std::max_element( const auto largest_min_activation = *std::max_element(
std::begin(min_activations_), std::end(min_activations_)); std::begin(min_activations_), std::end(min_activations_));
@ -105,30 +105,30 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
std::numeric_limits<LearnFloatType>::lowest()); std::numeric_limits<LearnFloatType>::lowest());
} }
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = LayerType::kOutputDimensions; static constexpr IndexType kInputDimensions = LayerType::kOutputDimensions;
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions; static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
// LearnFloatTypeの定数 // LearnFloatType constant
static constexpr LearnFloatType kZero = static_cast<LearnFloatType>(0.0); static constexpr LearnFloatType kZero = static_cast<LearnFloatType>(0.0);
static constexpr LearnFloatType kOne = static_cast<LearnFloatType>(1.0); static constexpr LearnFloatType kOne = static_cast<LearnFloatType>(1.0);
// ミニバッチのサンプル数 // number of samples in mini-batch
IndexType batch_size_; IndexType batch_size_;
// 直前の層のTrainer // Trainer of the previous layer
const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_; const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_;
// 学習対象の層 // layer to learn
LayerType* const target_layer_; LayerType* const target_layer_;
// 順伝播用バッファ // Forward propagation buffer
std::vector<LearnFloatType> output_; std::vector<LearnFloatType> output_;
// 逆伝播用バッファ // buffer for back propagation
std::vector<LearnFloatType> gradients_; std::vector<LearnFloatType> gradients_;
// ヘルスチェック用統計値 // Health check statistics
LearnFloatType min_activations_[kOutputDimensions]; LearnFloatType min_activations_[kOutputDimensions];
LearnFloatType max_activations_[kOutputDimensions]; LearnFloatType max_activations_[kOutputDimensions];
}; };
@ -139,4 +139,4 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習クラステンプレートのFeatureTransformer用特殊化 // Specialization for feature transformer of learning class template of NNUE evaluation function
#ifndef _NNUE_TRAINER_FEATURE_TRANSFORMER_H_ #ifndef _NNUE_TRAINER_FEATURE_TRANSFORMER_H_
#define _NNUE_TRAINER_FEATURE_TRANSFORMER_H_ #define _NNUE_TRAINER_FEATURE_TRANSFORMER_H_
@ -24,11 +24,11 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 学習:入力特徴量変換器 // Learning: Input feature converter
template <> template <>
class Trainer<FeatureTransformer> { class Trainer<FeatureTransformer> {
private: private:
// 学習対象の層の型 // Type of layer to learn
using LayerType = FeatureTransformer; using LayerType = FeatureTransformer;
public: public:
@ -37,12 +37,12 @@ class Trainer<FeatureTransformer> {
template <typename T, typename... ArgumentTypes> template <typename T, typename... ArgumentTypes>
friend std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments); friend std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments);
// ファクトリ関数 // factory function
static std::shared_ptr<Trainer> Create(LayerType* target_layer) { static std::shared_ptr<Trainer> Create(LayerType* target_layer) {
return MakeAlignedSharedPtr<Trainer>(target_layer); return MakeAlignedSharedPtr<Trainer>(target_layer);
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SendMessage(Message* message) { void SendMessage(Message* message) {
if (ReceiveMessage("momentum", message)) { if (ReceiveMessage("momentum", message)) {
momentum_ = static_cast<LearnFloatType>(std::stod(message->value)); momentum_ = static_cast<LearnFloatType>(std::stod(message->value));
@ -65,7 +65,7 @@ class Trainer<FeatureTransformer> {
} }
} }
// パラメータを乱数で初期化する // Initialize the parameters with random numbers
template <typename RNG> template <typename RNG>
void Initialize(RNG& rng) { void Initialize(RNG& rng) {
std::fill(std::begin(weights_), std::end(weights_), +kZero); std::fill(std::begin(weights_), std::end(weights_), +kZero);
@ -81,7 +81,7 @@ class Trainer<FeatureTransformer> {
QuantizeParameters(); QuantizeParameters();
} }
// 順伝播 // forward propagation
const LearnFloatType* Propagate(const std::vector<Example>& batch) { const LearnFloatType* Propagate(const std::vector<Example>& batch) {
if (output_.size() < kOutputDimensions * batch.size()) { if (output_.size() < kOutputDimensions * batch.size()) {
output_.resize(kOutputDimensions * batch.size()); output_.resize(kOutputDimensions * batch.size());
@ -131,7 +131,7 @@ class Trainer<FeatureTransformer> {
return output_.data(); return output_.data();
} }
// 逆伝播 // backpropagation
void Backpropagate(const LearnFloatType* gradients, void Backpropagate(const LearnFloatType* gradients,
LearnFloatType learning_rate) { LearnFloatType learning_rate) {
const LearnFloatType local_learning_rate = const LearnFloatType local_learning_rate =
@ -144,8 +144,8 @@ class Trainer<FeatureTransformer> {
((output_[index] > kZero) * (output_[index] < kOne)); ((output_[index] > kZero) * (output_[index] < kOne));
} }
} }
// 重み行列は入力に出現した特徴量に対応する列のみを更新するため、 // Since the weight matrix updates only the columns corresponding to the features that appeared in the input,
// momentumを使用せず、学習率を補正してスケールを合わせる // Correct the learning rate and adjust the scale without using momentum
const LearnFloatType effective_learning_rate = const LearnFloatType effective_learning_rate =
static_cast<LearnFloatType>(local_learning_rate / (1.0 - momentum_)); static_cast<LearnFloatType>(local_learning_rate / (1.0 - momentum_));
#if defined(USE_BLAS) #if defined(USE_BLAS)
@ -227,7 +227,7 @@ class Trainer<FeatureTransformer> {
} }
private: private:
// コンストラクタ // constructor
Trainer(LayerType* target_layer) : Trainer(LayerType* target_layer) :
batch_(nullptr), batch_(nullptr),
target_layer_(target_layer), target_layer_(target_layer),
@ -245,7 +245,7 @@ class Trainer<FeatureTransformer> {
DequantizeParameters(); DequantizeParameters();
} }
// 重みの飽和とパラメータの整数化 // Weight saturation and parameterization
void QuantizeParameters() { void QuantizeParameters() {
for (IndexType i = 0; i < kHalfDimensions; ++i) { for (IndexType i = 0; i < kHalfDimensions; ++i) {
target_layer_->biases_[i] = target_layer_->biases_[i] =
@ -268,7 +268,7 @@ class Trainer<FeatureTransformer> {
} }
} }
// 整数化されたパラメータの読み込み // read parameterized integer
void DequantizeParameters() { void DequantizeParameters() {
for (IndexType i = 0; i < kHalfDimensions; ++i) { for (IndexType i = 0; i < kHalfDimensions; ++i) {
biases_[i] = static_cast<LearnFloatType>( biases_[i] = static_cast<LearnFloatType>(
@ -282,7 +282,7 @@ class Trainer<FeatureTransformer> {
std::fill(std::begin(biases_diff_), std::end(biases_diff_), +kZero); std::fill(std::begin(biases_diff_), std::end(biases_diff_), +kZero);
} }
// 学習データに出現していない特徴量に対応する重みを0にする // Set the weight corresponding to the feature that does not appear in the learning data to 0
void ClearUnobservedFeatureWeights() { void ClearUnobservedFeatureWeights() {
for (IndexType i = 0; i < kInputDimensions; ++i) { for (IndexType i = 0; i < kInputDimensions; ++i) {
if (!observed_features.test(i)) { if (!observed_features.test(i)) {
@ -293,7 +293,7 @@ class Trainer<FeatureTransformer> {
QuantizeParameters(); QuantizeParameters();
} }
// 学習に問題が生じていないかチェックする // Check if there are any problems with learning
void CheckHealth() { void CheckHealth() {
std::cout << "INFO: observed " << observed_features.count() std::cout << "INFO: observed " << observed_features.count()
<< " (out of " << kInputDimensions << ") features" << std::endl; << " (out of " << kInputDimensions << ") features" << std::endl;
@ -320,48 +320,48 @@ class Trainer<FeatureTransformer> {
std::numeric_limits<LearnFloatType>::lowest()); std::numeric_limits<LearnFloatType>::lowest());
} }
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = static constexpr IndexType kInputDimensions =
Features::Factorizer<RawFeatures>::GetDimensions(); Features::Factorizer<RawFeatures>::GetDimensions();
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions; static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
static constexpr IndexType kHalfDimensions = LayerType::kHalfDimensions; static constexpr IndexType kHalfDimensions = LayerType::kHalfDimensions;
// パラメータの整数化で用いる係数 // Coefficient used for parameterization
static constexpr LearnFloatType kActivationScale = static constexpr LearnFloatType kActivationScale =
std::numeric_limits<std::int8_t>::max(); std::numeric_limits<std::int8_t>::max();
static constexpr LearnFloatType kBiasScale = kActivationScale; static constexpr LearnFloatType kBiasScale = kActivationScale;
static constexpr LearnFloatType kWeightScale = kActivationScale; static constexpr LearnFloatType kWeightScale = kActivationScale;
// LearnFloatTypeの定数 // LearnFloatType constant
static constexpr LearnFloatType kZero = static_cast<LearnFloatType>(0.0); static constexpr LearnFloatType kZero = static_cast<LearnFloatType>(0.0);
static constexpr LearnFloatType kOne = static_cast<LearnFloatType>(1.0); static constexpr LearnFloatType kOne = static_cast<LearnFloatType>(1.0);
// ミニバッチ // mini batch
const std::vector<Example>* batch_; const std::vector<Example>* batch_;
// 学習対象の層 // layer to learn
LayerType* const target_layer_; LayerType* const target_layer_;
// パラメータ // parameter
alignas(kCacheLineSize) LearnFloatType biases_[kHalfDimensions]; alignas(kCacheLineSize) LearnFloatType biases_[kHalfDimensions];
alignas(kCacheLineSize) alignas(kCacheLineSize)
LearnFloatType weights_[kHalfDimensions * kInputDimensions]; LearnFloatType weights_[kHalfDimensions * kInputDimensions];
// パラメータの更新で用いるバッファ // Buffer used for updating parameters
LearnFloatType biases_diff_[kHalfDimensions]; LearnFloatType biases_diff_[kHalfDimensions];
std::vector<LearnFloatType> gradients_; std::vector<LearnFloatType> gradients_;
// 順伝播用バッファ // Forward propagation buffer
std::vector<LearnFloatType> output_; std::vector<LearnFloatType> output_;
// 学習データに出現した特徴量 // Features that appeared in the training data
std::bitset<kInputDimensions> observed_features; std::bitset<kInputDimensions> observed_features;
// ハイパーパラメータ // hyper parameter
LearnFloatType momentum_; LearnFloatType momentum_;
LearnFloatType learning_rate_scale_; LearnFloatType learning_rate_scale_;
// ヘルスチェック用統計値 // Health check statistics
LearnFloatType min_pre_activation_; LearnFloatType min_pre_activation_;
LearnFloatType max_pre_activation_; LearnFloatType max_pre_activation_;
LearnFloatType min_activations_[kHalfDimensions]; LearnFloatType min_activations_[kHalfDimensions];
@ -374,4 +374,4 @@ class Trainer<FeatureTransformer> {
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
#endif #endif

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習クラステンプレートのInputSlice用特殊化 // Specialization of NNUE evaluation function learning class template for InputSlice
#ifndef _NNUE_TRAINER_INPUT_SLICE_H_ #ifndef _NNUE_TRAINER_INPUT_SLICE_H_
#define _NNUE_TRAINER_INPUT_SLICE_H_ #define _NNUE_TRAINER_INPUT_SLICE_H_
@ -13,10 +13,10 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 学習:入力層 // Learning: Input layer
class SharedInputTrainer { class SharedInputTrainer {
public: public:
// ファクトリ関数 // factory function
static std::shared_ptr<SharedInputTrainer> Create( static std::shared_ptr<SharedInputTrainer> Create(
FeatureTransformer* feature_transformer) { FeatureTransformer* feature_transformer) {
static std::shared_ptr<SharedInputTrainer> instance; static std::shared_ptr<SharedInputTrainer> instance;
@ -27,7 +27,7 @@ class SharedInputTrainer {
return instance; return instance;
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SendMessage(Message* message) { void SendMessage(Message* message) {
if (num_calls_ == 0) { if (num_calls_ == 0) {
current_operation_ = Operation::kSendMessage; current_operation_ = Operation::kSendMessage;
@ -40,7 +40,7 @@ class SharedInputTrainer {
} }
} }
// パラメータを乱数で初期化する // Initialize the parameters with random numbers
template <typename RNG> template <typename RNG>
void Initialize(RNG& rng) { void Initialize(RNG& rng) {
if (num_calls_ == 0) { if (num_calls_ == 0) {
@ -54,7 +54,7 @@ class SharedInputTrainer {
} }
} }
// 順伝播 // forward propagation
const LearnFloatType* Propagate(const std::vector<Example>& batch) { const LearnFloatType* Propagate(const std::vector<Example>& batch) {
if (gradients_.size() < kInputDimensions * batch.size()) { if (gradients_.size() < kInputDimensions * batch.size()) {
gradients_.resize(kInputDimensions * batch.size()); gradients_.resize(kInputDimensions * batch.size());
@ -72,7 +72,7 @@ class SharedInputTrainer {
return output_; return output_;
} }
// 逆伝播 // backpropagation
void Backpropagate(const LearnFloatType* gradients, void Backpropagate(const LearnFloatType* gradients,
LearnFloatType learning_rate) { LearnFloatType learning_rate) {
if (num_referrers_ == 1) { if (num_referrers_ == 1) {
@ -104,7 +104,7 @@ class SharedInputTrainer {
} }
private: private:
// コンストラクタ // constructor
SharedInputTrainer(FeatureTransformer* feature_transformer) : SharedInputTrainer(FeatureTransformer* feature_transformer) :
batch_size_(0), batch_size_(0),
num_referrers_(0), num_referrers_(0),
@ -115,11 +115,11 @@ class SharedInputTrainer {
output_(nullptr) { output_(nullptr) {
} }
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = static constexpr IndexType kInputDimensions =
FeatureTransformer::kOutputDimensions; FeatureTransformer::kOutputDimensions;
// 処理の種類 // type of processing
enum class Operation { enum class Operation {
kNone, kNone,
kSendMessage, kSendMessage,
@ -128,55 +128,55 @@ class SharedInputTrainer {
kBackPropagate, kBackPropagate,
}; };
// ミニバッチのサンプル数 // number of samples in mini-batch
IndexType batch_size_; IndexType batch_size_;
// この層を入力として共有する層の数 // number of layers sharing this layer as input
std::uint32_t num_referrers_; std::uint32_t num_referrers_;
// 現在の処理が呼び出された回数 // Number of times the current process has been called
std::uint32_t num_calls_; std::uint32_t num_calls_;
// 現在の処理の種類 // current processing type
Operation current_operation_; Operation current_operation_;
// 入力特徴量変換器のTrainer // Trainer of input feature converter
const std::shared_ptr<Trainer<FeatureTransformer>> const std::shared_ptr<Trainer<FeatureTransformer>>
feature_transformer_trainer_; feature_transformer_trainer_;
// 順伝播用に共有する出力のポインタ // pointer to output shared for forward propagation
const LearnFloatType* output_; const LearnFloatType* output_;
// 逆伝播用バッファ // buffer for back propagation
std::vector<LearnFloatType> gradients_; std::vector<LearnFloatType> gradients_;
}; };
// 学習:入力層 // Learning: Input layer
template <IndexType OutputDimensions, IndexType Offset> template <IndexType OutputDimensions, IndexType Offset>
class Trainer<Layers::InputSlice<OutputDimensions, Offset>> { class Trainer<Layers::InputSlice<OutputDimensions, Offset>> {
private: private:
// 学習対象の層の型 // Type of layer to learn
using LayerType = Layers::InputSlice<OutputDimensions, Offset>; using LayerType = Layers::InputSlice<OutputDimensions, Offset>;
public: public:
// ファクトリ関数 // factory function
static std::shared_ptr<Trainer> Create( static std::shared_ptr<Trainer> Create(
LayerType* /*target_layer*/, FeatureTransformer* feature_transformer) { LayerType* /*target_layer*/, FeatureTransformer* feature_transformer) {
return std::shared_ptr<Trainer>(new Trainer(feature_transformer)); return std::shared_ptr<Trainer>(new Trainer(feature_transformer));
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SendMessage(Message* message) { void SendMessage(Message* message) {
shared_input_trainer_->SendMessage(message); shared_input_trainer_->SendMessage(message);
} }
// パラメータを乱数で初期化する // Initialize the parameters with random numbers
template <typename RNG> template <typename RNG>
void Initialize(RNG& rng) { void Initialize(RNG& rng) {
shared_input_trainer_->Initialize(rng); shared_input_trainer_->Initialize(rng);
} }
// 順伝播 // forward propagation
const LearnFloatType* Propagate(const std::vector<Example>& batch) { const LearnFloatType* Propagate(const std::vector<Example>& batch) {
if (output_.size() < kOutputDimensions * batch.size()) { if (output_.size() < kOutputDimensions * batch.size()) {
output_.resize(kOutputDimensions * batch.size()); output_.resize(kOutputDimensions * batch.size());
@ -199,7 +199,7 @@ class Trainer<Layers::InputSlice<OutputDimensions, Offset>> {
return output_.data(); return output_.data();
} }
// 逆伝播 // backpropagation
void Backpropagate(const LearnFloatType* gradients, void Backpropagate(const LearnFloatType* gradients,
LearnFloatType learning_rate) { LearnFloatType learning_rate) {
for (IndexType b = 0; b < batch_size_; ++b) { for (IndexType b = 0; b < batch_size_; ++b) {
@ -217,28 +217,28 @@ class Trainer<Layers::InputSlice<OutputDimensions, Offset>> {
} }
private: private:
// コンストラクタ // constructor
Trainer(FeatureTransformer* feature_transformer) : Trainer(FeatureTransformer* feature_transformer):
batch_size_(0), batch_size_(0),
shared_input_trainer_(SharedInputTrainer::Create(feature_transformer)) { shared_input_trainer_(SharedInputTrainer::Create(feature_transformer)) {
} }
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kInputDimensions = static constexpr IndexType kInputDimensions =
FeatureTransformer::kOutputDimensions; FeatureTransformer::kOutputDimensions;
static constexpr IndexType kOutputDimensions = OutputDimensions; static constexpr IndexType kOutputDimensions = OutputDimensions;
static_assert(Offset + kOutputDimensions <= kInputDimensions, ""); static_assert(Offset + kOutputDimensions <= kInputDimensions, "");
// ミニバッチのサンプル数 // number of samples in mini-batch
IndexType batch_size_; IndexType batch_size_;
// 共有入力層のTrainer // Trainer of shared input layer
const std::shared_ptr<SharedInputTrainer> shared_input_trainer_; const std::shared_ptr<SharedInputTrainer> shared_input_trainer_;
// 順伝播用バッファ // Forward propagation buffer
std::vector<LearnFloatType> output_; std::vector<LearnFloatType> output_;
// 逆伝播用バッファ // buffer for back propagation
std::vector<LearnFloatType> gradients_; std::vector<LearnFloatType> gradients_;
}; };

View file

@ -1,4 +1,4 @@
// NNUE評価関数の学習クラステンプレートのSum用特殊化 // Specialization of NNUE evaluation function learning class template for Sum
#ifndef _NNUE_TRAINER_SUM_H_ #ifndef _NNUE_TRAINER_SUM_H_
#define _NNUE_TRAINER_SUM_H_ #define _NNUE_TRAINER_SUM_H_
@ -13,40 +13,40 @@ namespace Eval {
namespace NNUE { namespace NNUE {
// 学習:複数の層の出力の和を取る層 // Learning: A layer that sums the outputs of multiple layers
template <typename FirstPreviousLayer, typename... RemainingPreviousLayers> template <typename FirstPreviousLayer, typename... RemainingPreviousLayers>
class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> : class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
Trainer<Layers::Sum<RemainingPreviousLayers...>> { Trainer<Layers::Sum<RemainingPreviousLayers...>> {
private: private:
// 学習対象の層の型 // Type of layer to learn
using LayerType = Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>; using LayerType = Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>;
using Tail = Trainer<Layers::Sum<RemainingPreviousLayers...>>; using Tail = Trainer<Layers::Sum<RemainingPreviousLayers...>>;
public: public:
// ファクトリ関数 // factory function
static std::shared_ptr<Trainer> Create( static std::shared_ptr<Trainer> Create(
LayerType* target_layer, FeatureTransformer* feature_transformer) { LayerType* target_layer, FeatureTransformer* feature_transformer) {
return std::shared_ptr<Trainer>( return std::shared_ptr<Trainer>(
new Trainer(target_layer, feature_transformer)); new Trainer(target_layer, feature_transformer));
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SendMessage(Message* message) { void SendMessage(Message* message) {
// 他のメンバ関数の結果は処理の順番に依存しないため、 // The results of other member functions do not depend on the processing order, so
// 実装をシンプルにすることを目的としてTailを先に処理するが、 // Tail is processed first for the purpose of simplifying the implementation, but
// SendMessageは添字の対応を分かりやすくするためにHeadを先に処理する // SendMessage processes Head first to make it easier to understand subscript correspondence
previous_layer_trainer_->SendMessage(message); previous_layer_trainer_->SendMessage(message);
Tail::SendMessage(message); Tail::SendMessage(message);
} }
// パラメータを乱数で初期化する // Initialize the parameters with random numbers
template <typename RNG> template <typename RNG>
void Initialize(RNG& rng) { void Initialize(RNG& rng) {
Tail::Initialize(rng); Tail::Initialize(rng);
previous_layer_trainer_->Initialize(rng); previous_layer_trainer_->Initialize(rng);
} }
// 順伝播 // forward propagation
/*const*/ LearnFloatType* Propagate(const std::vector<Example>& batch) { /*const*/ LearnFloatType* Propagate(const std::vector<Example>& batch) {
batch_size_ = static_cast<IndexType>(batch.size()); batch_size_ = static_cast<IndexType>(batch.size());
auto output = Tail::Propagate(batch); auto output = Tail::Propagate(batch);
@ -65,7 +65,7 @@ class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
return output; return output;
} }
// 逆伝播 // backpropagation
void Backpropagate(const LearnFloatType* gradients, void Backpropagate(const LearnFloatType* gradients,
LearnFloatType learning_rate) { LearnFloatType learning_rate) {
Tail::Backpropagate(gradients, learning_rate); Tail::Backpropagate(gradients, learning_rate);
@ -73,8 +73,8 @@ class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
} }
private: private:
// コンストラクタ // constructor
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) : Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer):
Tail(target_layer, feature_transformer), Tail(target_layer, feature_transformer),
batch_size_(0), batch_size_(0),
previous_layer_trainer_(Trainer<FirstPreviousLayer>::Create( previous_layer_trainer_(Trainer<FirstPreviousLayer>::Create(
@ -82,51 +82,51 @@ class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
target_layer_(target_layer) { target_layer_(target_layer) {
} }
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions; static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
// サブクラスをfriendにする // make subclass friend
template <typename SumLayer> template <typename SumLayer>
friend class Trainer; friend class Trainer;
// ミニバッチのサンプル数 // number of samples in mini-batch
IndexType batch_size_; IndexType batch_size_;
// 直前の層のTrainer // Trainer of the previous layer
const std::shared_ptr<Trainer<FirstPreviousLayer>> previous_layer_trainer_; const std::shared_ptr<Trainer<FirstPreviousLayer>> previous_layer_trainer_;
// 学習対象の層 // layer to learn
LayerType* const target_layer_; LayerType* const target_layer_;
}; };
// 学習複数の層の出力の和を取る層テンプレート引数が1つの場合 // Learning: Layer that takes the sum of the outputs of multiple layers (when there is one template argument)
template <typename PreviousLayer> template <typename PreviousLayer>
class Trainer<Layers::Sum<PreviousLayer>> { class Trainer<Layers::Sum<PreviousLayer>> {
private: private:
// 学習対象の層の型 // Type of layer to learn
using LayerType = Layers::Sum<PreviousLayer>; using LayerType = Layers::Sum<PreviousLayer>;
public: public:
// ファクトリ関数 // factory function
static std::shared_ptr<Trainer> Create( static std::shared_ptr<Trainer> Create(
LayerType* target_layer, FeatureTransformer* feature_transformer) { LayerType* target_layer, FeatureTransformer* feature_transformer) {
return std::shared_ptr<Trainer>( return std::shared_ptr<Trainer>(
new Trainer(target_layer, feature_transformer)); new Trainer(target_layer, feature_transformer));
} }
// ハイパーパラメータなどのオプションを設定する // Set options such as hyperparameters
void SendMessage(Message* message) { void SendMessage(Message* message) {
previous_layer_trainer_->SendMessage(message); previous_layer_trainer_->SendMessage(message);
} }
// パラメータを乱数で初期化する // Initialize the parameters with random numbers
template <typename RNG> template <typename RNG>
void Initialize(RNG& rng) { void Initialize(RNG& rng) {
previous_layer_trainer_->Initialize(rng); previous_layer_trainer_->Initialize(rng);
} }
// 順伝播 // forward propagation
/*const*/ LearnFloatType* Propagate(const std::vector<Example>& batch) { /*const*/ LearnFloatType* Propagate(const std::vector<Example>& batch) {
if (output_.size() < kOutputDimensions * batch.size()) { if (output_.size() < kOutputDimensions * batch.size()) {
output_.resize(kOutputDimensions * batch.size()); output_.resize(kOutputDimensions * batch.size());
@ -146,14 +146,14 @@ class Trainer<Layers::Sum<PreviousLayer>> {
return output_.data(); return output_.data();
} }
// 逆伝播 // backpropagation
void Backpropagate(const LearnFloatType* gradients, void Backpropagate(const LearnFloatType* gradients,
LearnFloatType learning_rate) { LearnFloatType learning_rate) {
previous_layer_trainer_->Backpropagate(gradients, learning_rate); previous_layer_trainer_->Backpropagate(gradients, learning_rate);
} }
private: private:
// コンストラクタ // constructor
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) : Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) :
batch_size_(0), batch_size_(0),
previous_layer_trainer_(Trainer<PreviousLayer>::Create( previous_layer_trainer_(Trainer<PreviousLayer>::Create(
@ -161,23 +161,23 @@ class Trainer<Layers::Sum<PreviousLayer>> {
target_layer_(target_layer) { target_layer_(target_layer) {
} }
// 入出力の次元数 // number of input/output dimensions
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions; static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
// サブクラスをfriendにする // make subclass friend
template <typename SumLayer> template <typename SumLayer>
friend class Trainer; friend class Trainer;
// ミニバッチのサンプル数 // number of samples in mini-batch
IndexType batch_size_; IndexType batch_size_;
// 直前の層のTrainer // Trainer of the previous layer
const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_; const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_;
// 学習対象の層 // layer to learn
LayerType* const target_layer_; LayerType* const target_layer_;
// 順伝播用バッファ // Forward propagation buffer
std::vector<LearnFloatType> output_; std::vector<LearnFloatType> output_;
}; };
@ -187,4 +187,4 @@ class Trainer<Layers::Sum<PreviousLayer>> {
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE) #endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
#endif #endif

View file

@ -5,33 +5,33 @@
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <cstring> // std::memset() #include <cstring> // std::memset()
using namespace std; using namespace std;
// ----------------------------------- // -----------------------------------
// 局面の圧縮・解凍 // stage compression/decompression
// ----------------------------------- // -----------------------------------
// ビットストリームを扱うクラス // Class that handles bitstream
// 局面の符号化を行なうときに、これがあると便利 // useful when doing aspect encoding
struct BitStream struct BitStream
{ {
// データを格納するメモリを事前にセットする。 // Set the memory to store the data in advance.
// そのメモリは0クリアされているものとする。 // Assume that memory is cleared to 0.
void set_data(uint8_t* data_) { data = data_; reset(); } void set_data(uint8_t* data_) { data = data_; reset(); }
// set_data()で渡されたポインタの取得。 // Get the pointer passed in set_data().
uint8_t* get_data() const { return data; } uint8_t* get_data() const { return data; }
// カーソルの取得。 // Get the cursor.
int get_cursor() const { return bit_cursor; } int get_cursor() const { return bit_cursor; }
// カーソルのリセット // reset the cursor
void reset() { bit_cursor = 0; } void reset() { bit_cursor = 0; }
// ストリームに1bit書き出す。 // Write 1bit to the stream.
// bは非0なら1を書き出す。0なら0を書き出す。 // If b is non-zero, write out 1. If 0, write 0.
void write_one_bit(int b) void write_one_bit(int b)
{ {
if (b) if (b)
@ -40,7 +40,7 @@ struct BitStream
++bit_cursor; ++bit_cursor;
} }
// ストリームから1ビット取り出す。 // Get 1 bit from the stream.
int read_one_bit() int read_one_bit()
{ {
int b = (data[bit_cursor / 8] >> (bit_cursor & 7)) & 1; int b = (data[bit_cursor / 8] >> (bit_cursor & 7)) & 1;
@ -49,16 +49,16 @@ struct BitStream
return b; return b;
} }
// nビットのデータを書き出す // write n bits of data
// データはdの下位から順に書き出されるものとする。 // Data shall be written out from the lower order of d.
void write_n_bit(int d, int n) void write_n_bit(int d, int n)
{ {
for (int i = 0; i < n; ++i) for (int i = 0; i <n; ++i)
write_one_bit(d & (1 << i)); write_one_bit(d & (1 << i));
} }
// nビットのデータを読み込む // read n bits of data
// write_n_bit()の逆変換。 // Reverse conversion of write_n_bit().
int read_n_bit(int n) int read_n_bit(int n)
{ {
int result = 0; int result = 0;
@ -69,46 +69,46 @@ struct BitStream
} }
private: private:
// 次に読み書きすべきbit位置。 // Next bit position to read/write.
int bit_cursor; int bit_cursor;
// データの実体 // data entity
uint8_t* data; uint8_t* data;
}; };
// ハフマン符号化 // Huffman coding
// ※  なのはminiの符号化から、変換が楽になるように単純化。 // * is simplified from mini encoding to make conversion easier.
// //
// 盤上の1升(NO_PIECE以外) = 26bit ( + 成りフラグ1bit+ 先後1bit ) // 1 box on the board (other than NO_PIECE) = 2 to 6 bits (+ 1-bit flag + 1-bit forward and backward)
// 手駒の1枚 = 15bit ( + 成りフラグ1bit+ 先後1bit ) // 1 piece of hand piece = 1-5bit (+ 1-bit flag + 1bit ahead and behind)
// //
// 空 xxxxx0 + 0 (none) // empty xxxxx0 + 0 (none)
// 歩 xxxx01 + 2 xxxx0 + 2 // step xxxx01 + 2 xxxx0 + 2
// 香 xx0011 + 2 xx001 + 2 // incense xx0011 + 2 xx001 + 2
// 桂 xx1011 + 2 xx101 + 2 // Katsura xx1011 + 2 xx101 + 2
// 銀 xx0111 + 2 xx011 + 2 // silver xx0111 + 2 xx011 + 2
// 金 x01111 + 1 x0111 + 1 // 金は成りフラグはない。 // Gold x01111 + 1 x0111 + 1 // Gold is valid and has no flags.
// 角 011111 + 2 01111 + 2 // corner 011111 + 2 01111 + 2
// 飛 111111 + 2 11111 + 2 // Fly 111111 + 2 11111 + 2
// //
// すべての駒が盤上にあるとして、 // Assuming all pieces are on the board,
// 空 81 - 40駒 = 41升 = 41bit // Sky 81-40 pieces = 41 boxes = 41bit
// 歩 4bit*18駒 = 72bit // Walk 4bit*18 pieces = 72bit
// 香 6bit* 4駒 = 24bit // Incense 6bit*4 pieces = 24bit
// 桂 6bit* 4駒 = 24bit // Katsura 6bit*4 pieces = 24bit
// 銀 6bit* 4駒 = 24bit // Silver 6bit*4 pieces = 24bit
// 金 6bit* 4駒 = 24bit // Gold 6bit* 4 pieces = 24bit
// 角 8bit* 2駒 = 16bit // corner 8bit* 2 pieces = 16bit
// 飛 8bit* 2駒 = 16bit // Fly 8bit* 2 pieces = 16bit
// ------- // -------
// 241bit + 1bit(手番) + 7bit×2(王の位置先後) = 256bit // 241bit + 1bit (turn) + 7bit × 2 (King's position after) = 256bit
// //
// 盤上の駒が手駒に移動すると盤上の駒が空になるので盤上のその升は1bitで表現でき、 // When the piece on the board moves to the hand piece, the piece on the board becomes empty, so the box on the board can be expressed with 1 bit,
// 手駒は、盤上の駒より1bit少なく表現できるので結局、全体のbit数に変化はない。 // Since the hand piece can be expressed by 1 bit less than the piece on the board, the total number of bits does not change in the end.
// ゆえに、この表現において、どんな局面でもこのbit数で表現できる。 // Therefore, in this expression, any aspect can be expressed by this bit number.
// 手駒に成りフラグは不要だが、これも含めておくと盤上の駒のbit数-1になるので // It is a hand piece and no flag is required, but if you include this, the bit number of the piece on the board will be -1
// 全体のbit数が固定化できるのでこれも含めておくことにする。 // Since the total number of bits can be fixed, we will include this as well.
// Huffman Encoding // Huffman Encoding
// //
@ -120,8 +120,8 @@ private:
struct HuffmanedPiece struct HuffmanedPiece
{ {
int code; // どうコード化されるか int code; // how it will be coded
int bits; // 何bit専有するのか int bits; // How many bits do you have
}; };
HuffmanedPiece huffman_table[] = HuffmanedPiece huffman_table[] =
@ -134,11 +134,11 @@ HuffmanedPiece huffman_table[] =
{0b1001,4}, // QUEEN {0b1001,4}, // QUEEN
}; };
// sfenを圧縮/解凍するためのクラス // Class for compressing/decompressing sfen
// sfenはハフマン符号化をすることで256bit(32bytes)にpackできる。 // sfen can be packed to 256bit (32bytes) by Huffman coding.
// このことはなのはminiにより証明された。上のハフマン符号化である。 // This is proven by mini. The above is Huffman coding.
// //
// 内部フォーマット = 手番1bit+王の位置7bit*2 + 盤上の駒(ハフマン符号化) + 手駒(ハフマン符号化) // Internal format = 1-bit turn + 7-bit king position *2 + piece on board (Huffman coding) + hand piece (Huffman coding)
// Side to move (White = 0, Black = 1) (1bit) // Side to move (White = 0, Black = 1) (1bit)
// White King Position (6 bits) // White King Position (6 bits)
// Black King Position (6 bits) // Black King Position (6 bits)
@ -152,21 +152,21 @@ HuffmanedPiece huffman_table[] =
// //
struct SfenPacker struct SfenPacker
{ {
// sfenをpackしてdata[32]に格納する。 // Pack sfen and store in data[32].
void pack(const Position& pos) void pack(const Position& pos)
{ {
// cout << pos; // cout << pos;
memset(data, 0, 32 /* 256bit */); memset(data, 0, 32 /* 256bit */);
stream.set_data(data); stream.set_data(data);
// 手番 // turn
// Side to move. // Side to move.
stream.write_one_bit((int)(pos.side_to_move())); stream.write_one_bit((int)(pos.side_to_move()));
// 先手玉、後手玉の位置、それぞれ7bit // 7-bit positions for leading and trailing balls
// White king and black king, 6 bits for each. // White king and black king, 6 bits for each.
for(auto c : Colors) for(auto c: Colors)
stream.write_n_bit(pos.king_square(c), 6); stream.write_n_bit(pos.king_square(c), 6);
// Write the pieces on the board other than the kings. // Write the pieces on the board other than the kings.
@ -197,24 +197,24 @@ struct SfenPacker
stream.write_n_bit(pos.state()->rule50, 6); stream.write_n_bit(pos.state()->rule50, 6);
stream.write_n_bit(1 + (pos.game_ply() - (pos.side_to_move() == BLACK)) / 2, 8); stream.write_n_bit(1 + (pos.game_ply()-(pos.side_to_move() == BLACK)) / 2, 8);
assert(stream.get_cursor() <= 256); assert(stream.get_cursor() <= 256);
} }
// pack()でpackされたsfen(256bit = 32bytes) // sfen packed by pack() (256bit = 32bytes)
// もしくはunpack()でdecodeするsfen // Or sfen to decode with unpack()
uint8_t *data; // uint8_t[32]; uint8_t *data; // uint8_t[32];
//private: //private:
// Position::set_from_packed_sfen(uint8_t data[32])でこれらの関数を使いたいので筋は悪いがpublicにしておく。 // Position::set_from_packed_sfen(uint8_t data[32]) I want to use these functions, so the line is bad, but I want to keep it public.
BitStream stream; BitStream stream;
// 盤面の駒をstreamに出力する。 // Output the board pieces to stream.
void write_board_piece_to_stream(Piece pc) void write_board_piece_to_stream(Piece pc)
{ {
// 駒種 // piece type
PieceType pr = type_of(pc); PieceType pr = type_of(pc);
auto c = huffman_table[pr]; auto c = huffman_table[pr];
stream.write_n_bit(c.code, c.bits); stream.write_n_bit(c.code, c.bits);
@ -222,11 +222,11 @@ struct SfenPacker
if (pc == NO_PIECE) if (pc == NO_PIECE)
return; return;
// 先後フラグ // first and second flag
stream.write_one_bit(color_of(pc)); stream.write_one_bit(color_of(pc));
} }
// 盤面の駒を1枚streamから読み込む // Read one board piece from stream
Piece read_board_piece_from_stream() Piece read_board_piece_from_stream()
{ {
PieceType pr = NO_PIECE_TYPE; PieceType pr = NO_PIECE_TYPE;
@ -238,7 +238,7 @@ struct SfenPacker
assert(bits <= 6); assert(bits <= 6);
for (pr = NO_PIECE_TYPE; pr < KING; ++pr) for (pr = NO_PIECE_TYPE; pr <KING; ++pr)
if (huffman_table[pr].code == code if (huffman_table[pr].code == code
&& huffman_table[pr].bits == bits) && huffman_table[pr].bits == bits)
goto Found; goto Found;
@ -247,7 +247,7 @@ struct SfenPacker
if (pr == NO_PIECE_TYPE) if (pr == NO_PIECE_TYPE)
return NO_PIECE; return NO_PIECE;
// 先後フラグ // first and second flag
Color c = (Color)stream.read_one_bit(); Color c = (Color)stream.read_one_bit();
return make_piece(c, pr); return make_piece(c, pr);
@ -256,12 +256,12 @@ struct SfenPacker
// ----------------------------------- // -----------------------------------
// Positionクラスに追加 // Add to Position class
// ----------------------------------- // -----------------------------------
// 高速化のために直接unpackする関数を追加。かなりしんどい。 // Add a function that directly unpacks for speed. It's pretty tough.
// packer::unpack()とPosition::set()とを合体させて書く。 // Write it by combining packer::unpack() and Position::set().
// 渡された局面に問題があって、エラーのときは非0を返す。 // If there is a problem with the passed phase and there is an error, non-zero is returned.
int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thread* th, bool mirror) int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thread* th, bool mirror)
{ {
SfenPacker packer; SfenPacker packer;
@ -276,17 +276,17 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
// Active color // Active color
sideToMove = (Color)stream.read_one_bit(); sideToMove = (Color)stream.read_one_bit();
// evalListのclear。上でmemsetでゼロクリアしたときにクリアされているが…。 // clear evalList. It is cleared when memset is cleared to zero above...
evalList.clear(); evalList.clear();
// PieceListを更新する上で、どの駒がどこにあるかを設定しなければならないが、 // In updating the PieceList, we have to set which piece is where,
// それぞれの駒をどこまで使ったかのカウンター // A counter of how much each piece has been used
PieceNumber next_piece_number = PIECE_NUMBER_ZERO; PieceNumber next_piece_number = PIECE_NUMBER_ZERO;
pieceList[W_KING][0] = SQUARE_NB; pieceList[W_KING][0] = SQUARE_NB;
pieceList[B_KING][0] = SQUARE_NB; pieceList[B_KING][0] = SQUARE_NB;
// まず玉の位置 // First the position of the ball
if (mirror) if (mirror)
{ {
for (auto c : Colors) for (auto c : Colors)
@ -308,7 +308,7 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
sq = Mir(sq); sq = Mir(sq);
} }
// すでに玉がいるようだ // it seems there are already balls
Piece pc; Piece pc;
if (type_of(board[sq]) != KING) if (type_of(board[sq]) != KING)
{ {
@ -318,26 +318,26 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
else else
{ {
pc = board[sq]; pc = board[sq];
board[sq] = NO_PIECE; // いっかい取り除いておかないとput_piece()でASSERTに引っかかる。 board[sq] = NO_PIECE; // put_piece() will catch ASSERT unless you remove it all.
} }
// 駒がない場合もあるのでその場合はスキップする。 // There may be no pieces, so skip in that case.
if (pc == NO_PIECE) if (pc == NO_PIECE)
continue; continue;
put_piece(Piece(pc), sq); put_piece(Piece(pc), sq);
// evalListの更新 // update evalList
PieceNumber piece_no = PieceNumber piece_no =
(pc == B_KING) ? PIECE_NUMBER_BKING : // 先手玉 (pc == B_KING) ?PIECE_NUMBER_BKING :// Move ball
(pc == W_KING) ? PIECE_NUMBER_WKING : // 後手玉 (pc == W_KING) ?PIECE_NUMBER_WKING :// Backing ball
next_piece_number++; // それ以外 next_piece_number++; // otherwise
evalList.put_piece(piece_no, sq, pc); // sqの升にpcの駒を配置する evalList.put_piece(piece_no, sq, pc); // Place the pc piece in the sq box
//cout << sq << ' ' << board[sq] << ' ' << stream.get_cursor() << endl; //cout << sq << ' ' << board[sq] << ' ' << stream.get_cursor() << endl;
if (stream.get_cursor() > 256) if (stream.get_cursor()> 256)
return 1; return 1;
//assert(stream.get_cursor() <= 256); //assert(stream.get_cursor() <= 256);
@ -397,7 +397,7 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
chess960 = false; chess960 = false;
thisThread = th; thisThread = th;
set_state(st); set_state(st);
//std::cout << *this << std::endl; //std::cout << *this << std::endl;
@ -409,11 +409,11 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
return 0; return 0;
} }
// 盤面と手駒、手番を与えて、そのsfenを返す。 // Give the board, hand piece, and turn, and return the sfen.
//std::string Position::sfen_from_rawdata(Piece board[81], Hand hands[2], Color turn, int gamePly_) //std::string Position::sfen_from_rawdata(Piece board[81], Hand hands[2], Color turn, int gamePly_)
//{ //{
// // 内部的な構造体にコピーして、sfen()を呼べば、変換過程がそこにしか依存していないならば // // Copy it to an internal structure and call sfen() if the conversion process depends only on it
// // これで正常に変換されるのでは…。 // // Maybe it will be converted normally...
// Position pos; // Position pos;
// //
// memcpy(pos.board, board, sizeof(Piece) * 81); // memcpy(pos.board, board, sizeof(Piece) * 81);
@ -423,11 +423,11 @@ int Position::set_from_packed_sfen(const PackedSfen& sfen , StateInfo * si, Thre
// //
// return pos.sfen(); // return pos.sfen();
// //
// // ↑の実装、美しいが、いかんせん遅い。 // // Implementation of ↑ is beautiful, but slow.
// // 棋譜を大量に読み込ませて学習させるときにここがボトルネックになるので直接unpackする関数を書く。 // // This is a bottleneck when learning a large amount of game records, so write a function to unpack directly.
//} //}
// packされたsfenを得る。引数に指定したバッファに返す。 // Get the packed sfen. Returns to the buffer specified in the argument.
void Position::sfen_pack(PackedSfen& sfen) void Position::sfen_pack(PackedSfen& sfen)
{ {
SfenPacker sp; SfenPacker sp;
@ -435,14 +435,13 @@ void Position::sfen_pack(PackedSfen& sfen)
sp.pack(*this); sp.pack(*this);
} }
//// packされたsfenを解凍する。sfen文字列が返る。 //// Unpack the packed sfen. Returns an sfen string.
//std::string Position::sfen_unpack(const PackedSfen& sfen) //std::string Position::sfen_unpack(const PackedSfen& sfen)
//{ //{
// SfenPacker sp; // SfenPacker sp;
// sp.data = (uint8_t*)&sfen; // sp.data = (uint8_t*)&sfen;
// return sp.unpack(); // return sp.unpack();
//} //}
#endif // USE_SFEN_PACKER #endif // USE_SFEN_PACKER

View file

@ -4,8 +4,8 @@
// Half Float Library by yaneurao // Half Float Library by yaneurao
// (16-bit float) // (16-bit float)
// 16bit型による浮動小数点演算 // Floating point operation by 16bit type
// コンパイラの生成するfloat型のコードがIEEE 754の形式であると仮定して、それを利用する。 // Assume that the float type code generated by the compiler is in IEEE 754 format and use it.
#include "../types.h" #include "../types.h"
@ -99,7 +99,7 @@ namespace HalfFloat
return c.f; return c.f;
} }
// unit testになってないが、一応計算が出来ることは確かめた。コードはあとでなおす(かも)。 // It is not a unit test, but I confirmed that it can be calculated. I'll fix the code later (maybe).
static void unit_test() static void unit_test()
{ {
float16 a, b, c, d; float16 a, b, c, d;
@ -130,4 +130,4 @@ namespace HalfFloat
} }
#endif // __HALF_FLOAT_H__ #endif // __HALF_FLOAT_H__

View file

@ -6,173 +6,173 @@
#include <vector> #include <vector>
// ===================== // =====================
// 学習時の設定 // Settings for learning
// ===================== // =====================
// 以下のいずれかを選択すれば、そのあとの細々したものは自動的に選択される。 // If you select one of the following, the details after that will be automatically selected.
// いずれも選択しない場合は、そのあとの細々したものをひとつひとつ設定する必要がある。 // If you don't select any of them, you need to set the subsequent details one by one.
// elmo方式での学習設定。これをデフォルト設定とする。 // Learning setting by elmo method. This is the default setting.
// 標準の雑巾絞りにするためにはlearnコマンドで "lambda 1"を指定してやれば良い。 // To make a standard squeeze diaphragm, specify "lambda 1" with the learn command.
#define LEARN_ELMO_METHOD #define LEARN_ELMO_METHOD
// ---------------------- // ----------------------
// 更新式 // update formula
// ---------------------- // ----------------------
// AdaGrad。これが安定しているのでお勧め。 // Ada Grad. Recommended because it is stable.
// #define ADA_GRAD_UPDATE // #define ADA_GRAD_UPDATE
// 勾配の符号だけ見るSGD。省メモリで済むが精度は…。 // SGD looking only at the sign of the gradient. It requires less memory, but the accuracy is...
// #define SGD_UPDATE // #define SGD_UPDATE
// ---------------------- // ----------------------
// 学習時の設定 // Settings for learning
// ---------------------- // ----------------------
// mini-batchサイズ。 // mini-batch size.
// この数だけの局面をまとめて勾配を計算する。 // Calculate the gradient by combining this number of phases.
// 小さくするとupdate_weights()の回数が増えるので収束が速くなる。勾配が不正確になる。 // If you make it smaller, the number of update_weights() will increase and the convergence will be faster. The gradient is incorrect.
// 大きくするとupdate_weights()の回数が減るので収束が遅くなる。勾配は正確に出るようになる。 // If you increase it, the number of update_weights() decreases, so the convergence will be slow. The slope will come out accurately.
// 多くの場合において、この値を変更する必要はないと思う。 // I don't think you need to change this value in most cases.
#define LEARN_MINI_BATCH_SIZE (1000 * 1000 * 1) #define LEARN_MINI_BATCH_SIZE (1000 * 1000 * 1)
// ファイルから1回に読み込む局面数。これだけ読み込んだあとshuffleする。 // The number of phases to read from the file at one time. After reading this much, shuffle.
// ある程度大きいほうが良いが、この数×40byte×3倍ぐらいのメモリを消費する。10M局面なら400MB*3程度消費する。 // It is better to have a certain size, but this number x 40 bytes x 3 times as much memory is consumed. 400MB*3 is consumed in the 10M phase.
// THREAD_BUFFER_SIZE(=10000)の倍数にすること。 // Must be a multiple of THREAD_BUFFER_SIZE(=10000).
#define LEARN_SFEN_READ_SIZE (1000 * 1000 * 10) #define LEARN_SFEN_READ_SIZE (1000 * 1000 * 10)
// 学習時の評価関数の保存間隔。この局面数だけ学習させるごとに保存。 // Saving interval of evaluation function at learning. Save each time you learn this number of phases.
// 当然ながら、保存間隔を長くしたほうが学習時間は短くなる。 // Needless to say, the longer the saving interval, the shorter the learning time.
// フォルダ名は 0/ , 1/ , 2/ ...のように保存ごとにインクリメントされていく。 // Folder name is incremented for each save like 0/, 1/, 2/...
// デフォルトでは10億局面に1回。 // By default, once every 1 billion phases.
#define LEARN_EVAL_SAVE_INTERVAL (1000000000ULL) #define LEARN_EVAL_SAVE_INTERVAL (1000000000ULL)
// ---------------------- // ----------------------
// 目的関数の選択 // Select the objective function
// ---------------------- // ----------------------
// 目的関数が勝率の差の二乗和 // The objective function is the sum of squares of the difference in winning percentage
// 詳しい説明は、learner.cppを見ること。 // See learner.cpp for more information.
//#define LOSS_FUNCTION_IS_WINNING_PERCENTAGE //#define LOSS_FUNCTION_IS_WINNING_PERCENTAGE
// 目的関数が交差エントロピー // Objective function is cross entropy
// 詳しい説明は、learner.cppを見ること。 // See learner.cpp for more information.
// いわゆる、普通の「雑巾絞り」 // 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
// #define LOSS_FUNCTION_IS_CROSS_ENTOROPY_FOR_VALUE // #define LOSS_FUNCTION_IS_CROSS_ENTOROPY_FOR_VALUE
// elmo(WCSC27)の方式 // elmo (WCSC27) method
// #define LOSS_FUNCTION_IS_ELMO_METHOD // #define LOSS_FUNCTION_IS_ELMO_METHOD
// ※ 他、色々追加するかも。 // ※ Other things may be added.
// ---------------------- // ----------------------
// 学習に関するデバッグ設定 // debug settings for learning
// ---------------------- // ----------------------
// 学習時のrmseの出力をこの回数に1回に減らす。 // Reduce the output of rmse during learning to 1 for this number of times.
// rmseの計算は1スレッドで行なうためそこそこ時間をとられるので出力を減らすと効果がある。 // 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 //#define RESET_TO_ZERO_VECTOR
// ---------------------- // ----------------------
// 学習のときの浮動小数 // Floating point for learning
// ---------------------- // ----------------------
// これをdoubleにしたほうが計算精度は上がるが、重み配列絡みのメモリが倍必要になる。 // If this is set to double, the calculation accuracy will be higher, but the weight array entangled memory will be doubled.
// 現状、ここをfloatにした場合、評価関数ファイルに対して、重み配列はその4.5倍のサイズ。(KPPTで4.5GB程度) // Currently, if this is float, the weight array is 4.5 times the size of the evaluation function file. (About 4.5GB with KPPT)
// double型にしても収束の仕方にほとんど差異がなかったのでfloatに固定する。 // Even if it is a double type, there is almost no difference in the way of convergence, so fix it to float.
// floatを使う場合 // when using float
typedef float LearnFloatType; typedef float LearnFloatType;
// doubleを使う場合 // when using double
//typedef double LearnFloatType; //typedef double LearnFloatType;
// float16を使う場合 // when using float16
//#include "half_float.h" //#include "half_float.h"
//typedef HalfFloat::float16 LearnFloatType; //typedef HalfFloat::float16 LearnFloatType;
// ---------------------- // ----------------------
// 省メモリ化 // save memory
// ---------------------- // ----------------------
// Weight配列(のうちのKPP)に三角配列を用いて省メモリ化する。 // Use a triangular array for the Weight array (of which is KPP) to save memory.
// これを用いると、学習用の重み配列は評価関数ファイルの3倍程度で済むようになる。 // 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 #define USE_TRIANGLE_WEIGHT_ARRAY
// ---------------------- // ----------------------
// 次元下げ // dimension down
// ---------------------- // ----------------------
// ミラー(左右対称性)、インバース(先後対称性)に関して次元下げを行なう。 // Dimension reduction for mirrors (left/right symmetry) and inverse (forward/backward symmetry).
// デフォルトではすべてオン。 // All on by default.
// KKに対してミラー、インバースを利用した次元下げを行なう。(効果のほどは不明) // Dimension reduction using mirror and inverse for KK. (Unclear effect)
// USE_KK_INVERSE_WRITEをオンにするときはUSE_KK_MIRROR_WRITEもオンでなければならない。 // USE_KK_MIRROR_WRITE must be on when USE_KK_INVERSE_WRITE is on.
#define USE_KK_MIRROR_WRITE #define USE_KK_MIRROR_WRITE
#define USE_KK_INVERSE_WRITE #define USE_KK_INVERSE_WRITE
// KKPに対してミラー、インバースを利用した次元下げを行なう。(インバースのほうは効果のほどは不明) // Dimension reduction using Mirror and Inverse for KKP. (Inverse is not so effective)
// USE_KKP_INVERSE_WRITEをオンにするときは、USE_KKP_MIRROR_WRITEもオンになっていなければならない。 // 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_MIRROR_WRITE
#define USE_KKP_INVERSE_WRITE #define USE_KKP_INVERSE_WRITE
// KPPに対してミラーを利用した次元下げを行なう。(これをオフにすると教師局面が倍ぐらい必要になる) // Perform dimension reduction using a mirror for KPP. (Turning this off requires double the teacher position)
// KPPにはインバースはない。(先手側のKしかないので) // KPP has no inverse. (Because there is only K on the front side)
#define USE_KPP_MIRROR_WRITE #define USE_KPP_MIRROR_WRITE
// KPPPに対してミラーを利用した次元下げを行なう。(これをオフにすると教師局面が倍ぐらい必要になる) // Perform a dimension reduction using a mirror for KPPP. (Turning this off requires double the teacher position)
// KPPPにもインバースはない。(先手側のKしかないので) // KPPP has no inverse. (Because there is only K on the front side)
#define USE_KPPP_MIRROR_WRITE #define USE_KPPP_MIRROR_WRITE
// KKPP成分に対して学習時にKPPによる次元下げを行なう。 // 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 //#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 // #define LEARN_GENSFEN_USE_DRAW_RESULT
// ====================== // ======================
// configure // configure
// ====================== // ======================
// ---------------------- // ----------------------
// elmo(WCSC27)の方法での学習 // Learning with the method of elmo (WCSC27)
// ---------------------- // ----------------------
#if defined( LEARN_ELMO_METHOD ) #if defined( LEARN_ELMO_METHOD )
@ -182,49 +182,49 @@ typedef float LearnFloatType;
// ---------------------- // ----------------------
// Learnerで用いるstructの定義 // Definition of struct used in Learner
// ---------------------- // ----------------------
#include "../position.h" #include "../position.h"
namespace Learner namespace Learner
{ {
// PackedSfenと評価値が一体化した構造体 //Structure in which PackedSfen and evaluation value are integrated
// オプションごとに書き出す内容が異なると教師棋譜を再利用するときに困るので // If you write different contents for each option, it will be a problem when reusing the teacher game
// とりあえず、以下のメンバーはオプションによらずすべて書き出しておく。 // For the time being, write all the following members regardless of the options.
struct PackedSfenValue struct PackedSfenValue
{ {
// 局面 // phase
PackedSfen sfen; PackedSfen sfen;
// Learner::search()から返ってきた評価値 // Evaluation value returned from Learner::search()
int16_t score; int16_t score;
// PVの初手 // PV first move
// 教師との指し手一致率を求めるときなどに用いる // Used when finding the match rate with the teacher
uint16_t move; uint16_t move;
// 初期局面からの局面の手数。 // Trouble of the phase from the initial phase.
uint16_t gamePly; uint16_t gamePly;
// この局面の手番側が、ゲームを最終的に勝っているなら1。負けているなら-1。 // 1 if the player on this side ultimately wins the game. -1 if you are losing.
// 引き分けに至った場合は、0。 // 0 if a draw is reached.
// 引き分けは、教師局面生成コマンドgensfenにおいて、 // The draw is in the teacher position generation command gensfen,
// LEARN_GENSFEN_DRAW_RESULTが有効なときにだけ書き出す。 // Only write if LEARN_GENSFEN_DRAW_RESULT is enabled.
int8_t game_result; int8_t game_result;
// 教師局面を書き出したファイルを他の人とやりとりするときに // When exchanging the file that wrote the teacher aspect with other people
// この構造体サイズが不定だと困るため、paddingしてどの環境でも必ず40bytesになるようにしておく。 //Because this structure size is not fixed, pad it so that it is 40 bytes in any environment.
uint8_t padding; uint8_t padding;
// 32 + 2 + 2 + 2 + 1 + 1 = 40bytes // 32 + 2 + 2 + 2 + 1 + 1 = 40bytes
}; };
// 読み筋とそのときの評価値を返す型 // Type that returns the reading line and the evaluation value at that time
// Learner::search() , Learner::qsearch()で用いる。 // Used in Learner::search(), Learner::qsearch().
typedef std::pair<Value, std::vector<Move> > ValueAndPV; typedef std::pair<Value, std::vector<Move> > ValueAndPV;
// いまのところ、やねうら王2018 Otafukuしか、このスタブを持っていないが // So far, only Yaneura King 2018 Otafuku has this stub
// EVAL_LEARNをdefineするなら、このスタブが必須。 // This stub is required if EVAL_LEARN is defined.
extern Learner::ValueAndPV search(Position& pos, int depth , size_t multiPV = 1 , uint64_t NodesLimit = 0); extern Learner::ValueAndPV search(Position& pos, int depth , size_t multiPV = 1 , uint64_t NodesLimit = 0);
extern Learner::ValueAndPV qsearch(Position& pos); extern Learner::ValueAndPV qsearch(Position& pos);
@ -234,4 +234,4 @@ namespace Learner
#endif #endif
#endif // ifndef _LEARN_H_ #endif // ifndef _LEARN_H_

File diff suppressed because it is too large Load diff

View file

@ -23,15 +23,15 @@ namespace EvalLearningTools
std::vector<bool> min_index_flag; std::vector<bool> min_index_flag;
// --- 個別のテーブルごとの初期化 // --- initialization for each individual table
void init_min_index_flag() void init_min_index_flag()
{ {
// mir_piece、inv_pieceの初期化が終わっていなければならない。 // Initialization of mir_piece and inv_piece must be completed.
assert(mir_piece(Eval::f_pawn) == Eval::e_pawn); assert(mir_piece(Eval::f_pawn) == Eval::e_pawn);
// 次元下げ用フラグ配列の初期化 // Initialize the flag array for dimension reduction
// KPPPに関しては関与しない。 // Not involved in KPPP.
KK g_kk; KK g_kk;
g_kk.set(SQUARE_NB, Eval::fe_end, 0); g_kk.set(SQUARE_NB, Eval::fe_end, 0);
@ -46,9 +46,9 @@ namespace EvalLearningTools
#pragma omp parallel #pragma omp parallel
{ {
#if defined(_OPENMP) #if defined(_OPENMP)
// Windows環境下でCPUがつあるときに、論理64コアまでしか使用されないのを防ぐために // To prevent the logical 64 cores from being used when there are two CPUs under Windows
// ここで明示的にCPUに割り当てる // explicitly assign to CPU here
int thread_index = omp_get_thread_num(); // 自分のthread numberを取得 int thread_index = omp_get_thread_num(); // get your thread number
WinProcGroup::bindThisThread(thread_index); WinProcGroup::bindThisThread(thread_index);
#endif #endif
@ -56,20 +56,20 @@ namespace EvalLearningTools
for (int64_t index_ = 0; index_ < (int64_t)size; ++index_) for (int64_t index_ = 0; index_ < (int64_t)size; ++index_)
{ {
// OpenMPの制約からループ変数は符号型でないといけないらしいのだが、 // It seems that the loop variable must be a sign type due to OpenMP restrictions, but
// さすがに使いにくい。 // It's really difficult to use.
uint64_t index = (uint64_t)index_; uint64_t index = (uint64_t)index_;
if (g_kk.is_ok(index)) if (g_kk.is_ok(index))
{ {
// indexからの変換と逆変換によって元のindexに戻ることを確認しておく。 // Make sure that the original index will be restored by conversion from index and reverse conversion.
// 起動時に1回しか実行しない処理なのでassertで書いておく。 // It is a process that is executed only once at startup, so write it in assert.
assert(g_kk.fromIndex(index).toIndex() == index); assert(g_kk.fromIndex(index).toIndex() == index);
KK a[KK_LOWER_COUNT]; KK a[KK_LOWER_COUNT];
g_kk.fromIndex(index).toLowerDimensions(a); g_kk.fromIndex(index).toLowerDimensions(a);
// 次元下げの1つ目の要素が元のindexと同一であることを確認しておく。 // Make sure that the first element of dimension reduction is the same as the original index.
assert(a[0].toIndex() == index); assert(a[0].toIndex() == index);
uint64_t min_index = UINT64_MAX; uint64_t min_index = UINT64_MAX;
@ -118,9 +118,9 @@ namespace EvalLearningTools
void learning_tools_unit_test_kpp() void learning_tools_unit_test_kpp()
{ {
// KPPの三角配列化にバグがないかテストする // test KPP triangulation for bugs
// k-p0-p1のすべての組み合わせがきちんとKPPの扱う対象になっていかと、そのときの次元下げが // All combinations of k-p0-p1 are properly handled by KPP, and the dimension reduction at that time is
// 正しいかを判定する。 // Determine if it is correct.
KK g_kk; KK g_kk;
g_kk.set(SQUARE_NB, Eval::fe_end, 0); g_kk.set(SQUARE_NB, Eval::fe_end, 0);
@ -159,24 +159,24 @@ namespace EvalLearningTools
f[index - g_kpp.min_index()] = f[index2-g_kpp.min_index()] = true; f[index - g_kpp.min_index()] = f[index2-g_kpp.min_index()] = true;
} }
// 抜けてるindexがなかったかの確認。 // Check if there is no missing index.
for(size_t index = 0 ; index < f.size(); index++) for(size_t index = 0 ; index < f.size(); index++)
if (!f[index]) if (!f[index])
{ {
std::cout << index << g_kpp.fromIndex(index + g_kpp.min_index()) << std::endl; std::cout << index << g_kpp.fromIndex(index + g_kpp.min_index()) << std::endl;
} }
} }
void learning_tools_unit_test_kppp() void learning_tools_unit_test_kppp()
{ {
// KPPPの計算に抜けがないかをテストする // Test for missing KPPP calculations
KPPP g_kppp; KPPP g_kppp;
g_kppp.set(15, Eval::fe_end,0); g_kppp.set(15, Eval::fe_end,0);
uint64_t min_index = g_kppp.min_index(); uint64_t min_index = g_kppp.min_index();
uint64_t max_index = g_kppp.max_index(); uint64_t max_index = g_kppp.max_index();
// 最後の要素の確認。 // Confirm last element.
//KPPP x = KPPP::fromIndex(max_index-1); //KPPP x = KPPP::fromIndex(max_index-1);
//std::cout << x << std::endl; //std::cout << x << std::endl;
@ -208,10 +208,10 @@ namespace EvalLearningTools
void learning_tools_unit_test_kkpp() void learning_tools_unit_test_kkpp()
{ {
KKPP g_kkpp; KKPP g_kkpp;
g_kkpp.set(SQUARE_NB, 10000 , 0); g_kkpp.set(SQUARE_NB, 10000, 0);
uint64_t n = 0; uint64_t n = 0;
for (int k = 0; k<SQUARE_NB; ++k) for (int k = 0; k<SQUARE_NB; ++k)
for (int i = 0; i<10000; ++i) // 試しに、かなり大きなfe_endを想定して10000で回してみる。 for (int i = 0; i<10000; ++i) // As a test, assuming a large fe_end, try turning at 10000.
for (int j = 0; j < i; ++j) for (int j = 0; j < i; ++j)
{ {
auto kkpp = g_kkpp.fromKKPP(k, (BonaPiece)i, (BonaPiece)j); auto kkpp = g_kkpp.fromKKPP(k, (BonaPiece)i, (BonaPiece)j);
@ -222,27 +222,27 @@ namespace EvalLearningTools
} }
} }
// このEvalLearningTools全体の初期化 // Initialize this entire EvalLearningTools
void init() void init()
{ {
// 初期化は、起動後1回限りで良いのでそのためのフラグ。 // Initialization is required only once after startup, so a flag for that.
static bool first = true; static bool first = true;
if (first) if (first)
{ {
std::cout << "EvalLearningTools init.."; std::cout << "EvalLearningTools init..";
// mir_piece()とinv_piece()を利用可能にする。 // Make mir_piece() and inv_piece() available.
// このあとmin_index_flagの初期化を行なうが、そこが // After this, the min_index_flag is initialized, but
// これに依存しているので、こちらを先に行なう必要がある。 // It depends on this, so you need to do this first.
init_mir_inv_tables(); init_mir_inv_tables();
//learning_tools_unit_test_kpp(); //learning_tools_unit_test_kpp();
//learning_tools_unit_test_kppp(); //learning_tools_unit_test_kppp();
//learning_tools_unit_test_kkpp(); //learning_tools_unit_test_kkpp();
// UnitTestを実行するの最後でも良いのだが、init_min_index_flag()にとても時間がかかるので // It may be the last time to execute UnitTest, but since init_min_index_flag() takes a long time,
// デバッグ時はこのタイミングで行いたい。 // I want to do this at the time of debugging.
init_min_index_flag(); init_min_index_flag();
@ -253,4 +253,4 @@ namespace EvalLearningTools
} }
} }
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -10,67 +10,67 @@
void MultiThink::go_think() void MultiThink::go_think()
{ {
// あとでOptionsの設定を復元するためにコピーで保持しておく。 // Keep a copy to restore the Options settings later.
auto oldOptions = Options; auto oldOptions = Options;
// 定跡を用いる場合、on the flyで行なうとすごく時間がかかるファイルアクセスを行なう部分が // When using the constant track, it takes a lot of time to perform on the fly & the part to access the file is
// thread safeではないので、メモリに丸読みされている状態であることをここで保証する。 // Since it is not thread safe, it is guaranteed here that it is being completely read in memory.
Options["BookOnTheFly"] = std::string("false"); Options["BookOnTheFly"] = std::string("false");
// 評価関数の読み込み等 // Read evaluation function, etc.
// learnコマンドの場合、評価関数読み込み後に評価関数の値を補正している可能性があるので、 // In the case of the learn command, the value of the evaluation function may be corrected after reading the evaluation function, so
// メモリの破損チェックは省略する。 // Skip memory corruption check.
is_ready(true); is_ready(true);
// 派生クラスのinit()を呼び出す。 // Call the derived class's init().
init(); init();
// ループ上限はset_loop_max()で設定されているものとする。 // The loop upper limit is set with set_loop_max().
loop_count = 0; loop_count = 0;
done_count = 0; done_count = 0;
// threadをOptions["Threads"]の数だけ生成して思考開始。 // Create threads as many as Options["Threads"] and start thinking.
std::vector<std::thread> threads; std::vector<std::thread> threads;
auto thread_num = (size_t)Options["Threads"]; auto thread_num = (size_t)Options["Threads"];
// worker threadの終了フラグの確保 // Secure end flag of worker thread
thread_finished.resize(thread_num); thread_finished.resize(thread_num);
// worker threadの起動 // start worker thread
for (size_t i = 0; i < thread_num; ++i) for (size_t i = 0; i < thread_num; ++i)
{ {
thread_finished[i] = 0; thread_finished[i] = 0;
threads.push_back(std::thread([i, this] threads.push_back(std::thread([i, this]
{ {
// プロセッサの全スレッドを使い切る。 // exhaust all processor threads.
WinProcGroup::bindThisThread(i); WinProcGroup::bindThisThread(i);
// オーバーライドされている処理を実行 // execute the overridden process
this->thread_worker(i); this->thread_worker(i);
// スレッドが終了したので終了フラグを立てる // Set the end flag because the thread has ended
this->thread_finished[i] = 1; this->thread_finished[i] = 1;
})); }));
} }
// すべてのthreadの終了待ちを // wait for all threads to finish
// for (auto& th : threads) // for (auto& th :threads)
// th.join(); // th.join();
// のように書くとスレッドがまだ仕事をしている状態でここに突入するので、 // If you write like, the thread will rush here while it is still working,
// その間、callback_func()が呼び出せず、セーブできなくなる。 // During that time, callback_func() cannot be called and you cannot save.
// そこで終了フラグを自前でチェックする必要がある。 // Therefore, you need to check the end flag yourself.
// すべてのスレッドが終了したかを判定する関数 // function to determine if all threads have finished
auto threads_done = [&]() auto threads_done = [&]()
{ {
// ひとつでも終了していなければfalseを返す // returns false if no one is finished
for (auto& f : thread_finished) for (auto& f : thread_finished)
if (!f) if (!f)
return false; return false;
return true; return true;
}; };
// コールバック関数が設定されているならコールバックする。 // Call back if the callback function is set.
auto do_a_callback = [&]() auto do_a_callback = [&]()
{ {
if (callback_func) if (callback_func)
@ -80,44 +80,44 @@ void MultiThink::go_think()
for (uint64_t i = 0 ; ; ) for (uint64_t i = 0 ; ; )
{ {
// 全スレッドが終了していたら、ループを抜ける。 // If all threads have finished, exit the loop.
if (threads_done()) if (threads_done())
break; break;
sleep(1000); sleep(1000);
// callback_secondsごとにcallback_func()が呼び出される。 // callback_func() is called every callback_seconds.
if (++i == callback_seconds) if (++i == callback_seconds)
{ {
do_a_callback(); do_a_callback();
// ↑から戻ってきてからカウンターをリセットしているので、 // Since I am returning from ↑, I reset the counter, so
// do_a_callback()のなかでsave()などにどれだけ時間がかかろうと // no matter how long it takes to save() etc. in do_a_callback()
// 次に呼び出すのは、そこから一定時間の経過を要する。 // The next call will take a certain amount of time.
i = 0; i = 0;
} }
} }
// 最後の保存。 // Last save.
std::cout << std::endl << "finalize.."; std::cout << std::endl << "finalize..";
// do_a_callback(); // do_a_callback();
// → 呼び出し元で保存するはずで、ここでは要らない気がする。 // → It should be saved by the caller, so I feel that it is not necessary here.
// 終了したフラグは立っているがスレッドの終了コードの実行中であるということはありうるので // It is possible that the exit code of the thread is running but the exit code of the thread is running, so
// join()でその終了を待つ必要がある。 // We need to wait for the end with join().
for (auto& th : threads) for (auto& th : threads)
th.join(); th.join();
// 全スレッドが終了しただけでfileの書き出しスレッドなどはまだ動いていて // The file writing thread etc. are still running only when all threads are finished
// 作業自体は完了していない可能性があるのでスレッドがすべて終了したことだけ出力する。 // Since the work itself may not have completed, output only that all threads have finished.
std::cout << "all threads are joined." << std::endl; std::cout << "all threads are joined." << std::endl;
// Optionsを書き換えたので復元。 // Restored because Options were rewritten.
// 値を代入しないとハンドラが起動しないのでこうやって復元する。 // Restore the handler because the handler will not start unless you assign a value.
for (auto& s : oldOptions) for (auto& s : oldOptions)
Options[s.first] = std::string(s.second); Options[s.first] = std::string(s.second);
} }
#endif // defined(EVAL_LEARN) #endif // defined(EVAL_LEARN)

View file

@ -11,9 +11,9 @@
#include <atomic> #include <atomic>
// 棋譜からの学習や、自ら思考させて定跡を生成するときなど、 // Learning from a game record, when making yourself think and generating a fixed track, etc.
// 複数スレッドが個別にSearch::think()を呼び出したいときに用いるヘルパクラス。 // Helper class used when multiple threads want to call Search::think() individually.
// このクラスを派生させて用いる。 // Derive and use this class.
struct MultiThink struct MultiThink
{ {
MultiThink() : prng(21120903) MultiThink() : prng(21120903)
@ -21,43 +21,43 @@ struct MultiThink
loop_count = 0; loop_count = 0;
} }
// マスタースレッドからこの関数を呼び出すと、スレッドがそれぞれ思考して、 // Call this function from the master thread, each thread will think,
// 思考終了条件を満たしたところで制御を返す。 // Return control when the thought ending condition is satisfied.
// 他にやってくれること。 // Do something else.
// ・各スレッドがLearner::search(),qsearch()を呼び出しても安全なように // ・It is safe for each thread to call Learner::search(),qsearch()
//  置換表をスレッドごとに分離してくれる。(終了後、元に戻してくれる。) // Separates the substitution table for each thread. (It will be restored after the end.)
// ・bookはon the flyモードだとthread safeではないので、このモードを一時的に // ・Book is not thread safe when in on the fly mode, so temporarily change this mode.
//  オフにしてくれる。 // Turn it off.
// [要件] // [Requirements]
// 1) thread_worker()のオーバーライド // 1) Override thread_worker()
// 2) set_loop_max()でループ回数の設定 // 2) Set the loop count with set_loop_max()
// 3) 定期的にcallbackされる関数を設定する(必要なら) // 3) set a function to be called back periodically (if necessary)
// callback_funcとcallback_interval // callback_func and callback_interval
void go_think(); void go_think();
// 派生クラス側で初期化したいものがあればこれをoverrideしておけば、 // If there is something you want to initialize on the derived class side, override this,
// go_think()で初期化が終わったタイミングで呼び出される。 // Called when initialization is completed with go_think().
// 定跡の読み込みなどはそのタイミングで行うと良い。 // It is better to read the fixed trace at that timing.
virtual void init() {} virtual void init() {}
// go_think()したときにスレッドを生成して呼び出されるthread worker // A thread worker that is called by creating a thread when you go_think()
// これをoverrideして用いる。 // Override and use this.
virtual void thread_worker(size_t thread_id) = 0; virtual void thread_worker(size_t thread_id) = 0;
// go_think()したときにcallback_seconds[秒]ごとにcallbackされる。 // Called back every callback_seconds [seconds] when go_think().
std::function<void()> callback_func; std::function<void()> callback_func;
uint64_t callback_seconds = 600; uint64_t callback_seconds = 600;
// workerが処理する(Search::think()を呼び出す)回数を設定する。 // Set the number of times worker processes (calls Search::think()).
void set_loop_max(uint64_t loop_max_) { loop_max = loop_max_; } void set_loop_max(uint64_t loop_max_) { loop_max = loop_max_; }
// set_loop_max()で設定した値を取得する。 // Get the value set by set_loop_max().
uint64_t get_loop_max() const { return loop_max; } uint64_t get_loop_max() const { return loop_max; }
// [ASYNC] ループカウンターの値を取り出して、取り出し後にループカウンターを加算する。 // [ASYNC] Take the value of the loop counter and add the loop counter after taking it out.
// もしループカウンターがloop_maxに達していたらUINT64_MAXを返す。 // If the loop counter has reached loop_max, return UINT64_MAX.
// 局面を生成する場合などは、局面を生成するタイミングでこの関数を呼び出すようにしないと、 // If you want to generate a phase, you must call this function at the time of generating the phase,
// 生成した局面数と、カウンターの値が一致しなくなってしまうので注意すること。 // Please note that the number of generated phases and the value of the counter will not match.
uint64_t get_next_loop_count() { uint64_t get_next_loop_count() {
std::unique_lock<std::mutex> lk(loop_mutex); std::unique_lock<std::mutex> lk(loop_mutex);
if (loop_count >= loop_max) if (loop_count >= loop_max)
@ -65,46 +65,46 @@ struct MultiThink
return loop_count++; return loop_count++;
} }
// [ASYNC] 処理した個数を返す用。呼び出されるごとにインクリメントされたカウンターが返る。 // [ASYNC] For returning the processed number. Each time it is called, it returns a counter that is incremented.
uint64_t get_done_count() { uint64_t get_done_count() {
std::unique_lock<std::mutex> lk(loop_mutex); std::unique_lock<std::mutex> lk(loop_mutex);
return ++done_count; return ++done_count;
} }
// worker threadがI/Oにアクセスするときのmutex // Mutex when worker thread accesses I/O
std::mutex io_mutex; std::mutex io_mutex;
protected: protected:
// 乱数発生器本体 // Random number generator body
AsyncPRNG prng; AsyncPRNG prng;
private: private:
// workerが処理する(Search::think()を呼び出す)回数 // number of times worker processes (calls Search::think())
std::atomic<uint64_t> loop_max; std::atomic<uint64_t> loop_max;
// workerが処理した(Search::think()を呼び出した)回数 // number of times the worker has processed (calls Search::think())
std::atomic<uint64_t> loop_count; std::atomic<uint64_t> loop_count;
// 処理した回数を返す用。 // To return the number of times it has been processed.
std::atomic<uint64_t> done_count; std::atomic<uint64_t> done_count;
// ↑の変数を変更するときのmutex // Mutex when changing the variables in ↑
std::mutex loop_mutex; std::mutex loop_mutex;
// スレッドの終了フラグ。 // Thread end flag.
// vector<bool>にすると複数スレッドから書き換えようとしたときに正しく反映されないことがある…はず。 // vector<bool> may not be reflected properly when trying to rewrite from multiple threads...
typedef uint8_t Flag; typedef uint8_t Flag;
std::vector<Flag> thread_finished; std::vector<Flag> thread_finished;
}; };
// idle時間にtaskを処理する仕組み。 // Mechanism to process task during idle time.
// masterは好きなときにpush_task_async()でtaskを渡す。 // master passes the task with push_task_async() whenever you like.
// slaveは暇なときにon_idle()を実行すると、taskを一つ取り出してqueueがなくなるまで実行を続ける。 // When slave executes on_idle() in its spare time, it retrieves one task and continues execution until there is no queue.
// MultiThinkのthread workerをmaster-slave方式で書きたいときに用いると便利。 // Convenient to use when you want to write MultiThink thread worker in master-slave method.
struct TaskDispatcher struct TaskDispatcher
{ {
typedef std::function<void(size_t /* thread_id */)> Task; typedef std::function<void(size_t /* thread_id */)> Task;
// slaveはidle中にこの関数を呼び出す。 // slave calls this function during idle.
void on_idle(size_t thread_id) void on_idle(size_t thread_id)
{ {
Task task; Task task;
@ -114,24 +114,24 @@ struct TaskDispatcher
sleep(1); sleep(1);
} }
// [ASYNC] taskを一つ積む。 // Stack [ASYNC] task.
void push_task_async(Task task) void push_task_async(Task task)
{ {
std::unique_lock<std::mutex> lk(task_mutex); std::unique_lock<std::mutex> lk(task_mutex);
tasks.push_back(task); tasks.push_back(task);
} }
// task用の配列の要素をsize分だけ事前に確保する。 // Allocate size array elements for task in advance.
void task_reserve(size_t size) void task_reserve(size_t size)
{ {
tasks.reserve(size); tasks.reserve(size);
} }
protected: protected:
// taskの集合 // set of tasks
std::vector<Task> tasks; std::vector<Task> tasks;
// [ASYNC] taskを一つ取り出す。on_idle()から呼び出される。 // Take out one [ASYNC] task. Called from on_idle().
Task get_task_async() Task get_task_async()
{ {
std::unique_lock<std::mutex> lk(task_mutex); std::unique_lock<std::mutex> lk(task_mutex);
@ -142,10 +142,10 @@ protected:
return task; return task;
} }
// tasksにアクセスするとき用のmutex // a mutex for accessing tasks
std::mutex task_mutex; std::mutex task_mutex;
}; };
#endif // defined(EVAL_LEARN) && defined(YANEURAOU_2018_OTAFUKU_ENGINE) #endif // defined(EVAL_LEARN) && defined(YANEURAOU_2018_OTAFUKU_ENGINE)
#endif #endif