Add "seed" option to gensfen and learn

This commit is contained in:
Tomasz Sobczyk
2020-09-16 14:43:21 +02:00
committed by nodchip
parent efca5d561f
commit 184bde47dc
3 changed files with 32 additions and 22 deletions

View File

@@ -355,7 +355,8 @@ namespace Learner
// It must be 2**N because it will be used as the mask to calculate hash_index.
static_assert((GENSFEN_HASH_SIZE& (GENSFEN_HASH_SIZE - 1)) == 0);
MultiThinkGenSfen(int search_depth_min_, int search_depth_max_, SfenWriter& sw_) :
MultiThinkGenSfen(int search_depth_min_, int search_depth_max_, SfenWriter& sw_, const std::string& seed) :
MultiThink(seed),
search_depth_min(search_depth_min_),
search_depth_max(search_depth_max_),
sfen_writer(sw_)
@@ -1055,6 +1056,7 @@ namespace Learner
bool random_file_name = false;
std::string sfen_format;
std::string seed;
while (true)
{
@@ -1111,6 +1113,8 @@ namespace Learner
is >> detect_draw_by_insufficient_mating_material;
else if (token == "sfen_format")
is >> sfen_format;
else if (token == "seed")
is >> seed;
else
cout << "Error! : Illegal token " << token << endl;
}
@@ -1137,7 +1141,7 @@ namespace Learner
{
// Give a random number to output_file_name at this point.
// Do not use std::random_device(). Because it always the same integers on MinGW.
PRNG r(std::chrono::system_clock::now().time_since_epoch().count());
PRNG r(seed);
// Just in case, reassign the random numbers.
for (int i = 0; i < 10; ++i)
r.rand(1);
@@ -1182,7 +1186,7 @@ namespace Learner
SfenWriter sfen_writer(output_file_name, thread_num);
sfen_writer.set_save_interval(save_every);
MultiThinkGenSfen multi_think(search_depth_min, search_depth_max, sfen_writer);
MultiThinkGenSfen multi_think(search_depth_min, search_depth_max, sfen_writer, seed);
multi_think.nodes = nodes;
multi_think.set_loop_max(loop_max);
multi_think.eval_limit = eval_limit;

View File

@@ -432,8 +432,8 @@ namespace Learner
// Do not use std::random_device().
// Because it always the same integers on MinGW.
SfenReader(int thread_num) :
prng(std::chrono::system_clock::now().time_since_epoch().count())
SfenReader(int thread_num, const std::string& seed) :
prng(seed)
{
packed_sfens.resize(thread_num);
total_read = 0;
@@ -742,7 +742,8 @@ namespace Learner
// Class to generate sfen with multiple threads
struct LearnerThink : public MultiThink
{
LearnerThink(SfenReader& sr_) :
LearnerThink(SfenReader& sr_, const std::string& seed) :
MultiThink(seed),
sr(sr_),
stop_flag(false),
save_only_once(false)
@@ -1437,7 +1438,7 @@ namespace Learner
// Subcontracting the teacher shuffle "learn shuffle" command.
// output_file_name: name of the output file where the shuffled teacher positions will be written
void shuffle_files(const vector<string>& filenames, const string& output_file_name, uint64_t buffer_size)
void shuffle_files(const vector<string>& filenames, const string& output_file_name, uint64_t buffer_size, const std::string& seed)
{
// The destination folder is
// tmp/ for temporary writing
@@ -1460,7 +1461,7 @@ namespace Learner
// random number to shuffle
// Do not use std::random_device(). Because it always the same integers on MinGW.
PRNG prng(std::chrono::system_clock::now().time_since_epoch().count());
PRNG prng(seed);
// generate the name of the temporary file
auto make_filename = [](uint64_t i)
@@ -1533,11 +1534,11 @@ namespace Learner
// Subcontracting the teacher shuffle "learn shuffleq" command.
// This is written in 1 pass.
// output_file_name: name of the output file where the shuffled teacher positions will be written
void shuffle_files_quick(const vector<string>& filenames, const string& output_file_name)
void shuffle_files_quick(const vector<string>& filenames, const string& output_file_name, const std::string& seed)
{
// random number to shuffle
// Do not use std::random_device(). Because it always the same integers on MinGW.
PRNG prng(std::chrono::system_clock::now().time_since_epoch().count());
PRNG prng(seed);
// number of files
const size_t file_count = filenames.size();
@@ -1573,7 +1574,7 @@ namespace Learner
// Subcontracting the teacher shuffle "learn shufflem" command.
// Read the whole memory and write it out with the specified file name.
void shuffle_files_on_memory(const vector<string>& filenames, const string output_file_name)
void shuffle_files_on_memory(const vector<string>& filenames, const string output_file_name, const std::string& seed)
{
PSVector buf;
@@ -1591,7 +1592,7 @@ namespace Learner
// shuffle from buf[0] to buf[size-1]
// Do not use std::random_device(). Because it always the same integers on MinGW.
PRNG prng(std::chrono::system_clock::now().time_since_epoch().count());
PRNG prng(seed);
uint64_t size = (uint64_t)buf.size();
std::cout << "shuffle buf.size() = " << size << std::endl;
@@ -1613,9 +1614,7 @@ namespace Learner
void learn(Position&, istringstream& is)
{
const auto thread_num = (int)Options["Threads"];
SfenReader sr(thread_num);
LearnerThink learn_think(sr);
vector<string> filenames;
// mini_batch_size 1M aspect by default. This can be increased.
@@ -1704,6 +1703,7 @@ namespace Learner
uint64_t mirror_percentage = 0;
string validation_set_file_name;
string seed;
// Assume the filenames are staggered.
while (true)
@@ -1811,7 +1811,7 @@ namespace Learner
else if (option == "dest_score_min_value") is >> dest_score_min_value;
else if (option == "dest_score_max_value") is >> dest_score_max_value;
else if (option == "convert_teacher_signal_to_winning_probability") is >> convert_teacher_signal_to_winning_probability;
else if (option == "seed") is >> seed;
// Otherwise, it's a filename.
else
filenames.push_back(option);
@@ -1829,6 +1829,9 @@ namespace Learner
cout << "Warning! OpenMP disabled." << endl;
#endif
SfenReader sr(thread_num, seed);
LearnerThink learn_think(sr, seed);
// Display learning game file
if (target_dir != "")
{
@@ -1861,21 +1864,21 @@ namespace Learner
{
cout << "buffer_size : " << buffer_size << endl;
cout << "shuffle mode.." << endl;
shuffle_files(filenames, output_file_name, buffer_size);
shuffle_files(filenames, output_file_name, buffer_size, seed);
return;
}
if (shuffle_quick)
{
cout << "quick shuffle mode.." << endl;
shuffle_files_quick(filenames, output_file_name);
shuffle_files_quick(filenames, output_file_name, seed);
return;
}
if (shuffle_on_memory)
{
cout << "shuffle on memory.." << endl;
shuffle_files_on_memory(filenames, output_file_name);
shuffle_files_on_memory(filenames, output_file_name, seed);
return;
}

View File

@@ -10,6 +10,8 @@
#include <limits>
#include <functional>
#include <mutex>
#include <string>
#include <cstdint>
// Learning from a game record, when making yourself think and generating a fixed track, etc.
@@ -19,10 +21,11 @@ struct MultiThink
{
static constexpr std::uint64_t LOOP_COUNT_FINISHED = std::numeric_limits<std::uint64_t>::max();
MultiThink() : prng(std::chrono::system_clock::now().time_since_epoch().count())
{
loop_count = 0;
}
MultiThink() : prng{}, loop_count(0) { }
MultiThink(std::uint64_t seed) : prng(seed), loop_count(0) { }
MultiThink(const std::string& seed) : prng(seed), loop_count(0) { }
// Call this function from the master thread, each thread will think,
// Return control when the thought ending condition is satisfied.