Skip to content

Commit bf9cda6

Browse files
authored
Preserving fen generator. No functional change (#267)
BENCH: 3925018
1 parent abeb25e commit bf9cda6

File tree

9 files changed

+531
-6
lines changed

9 files changed

+531
-6
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
![Logo](https://raw.githubusercontent.com/vshcherbyna/igel/master/igel.bmp)
44

5-
[![Build Status](https://api.travis-ci.org/vshcherbyna/igel.svg?branch=master)](https://travis-ci.org/vshcherbyna/igel)
65
[![Build Status](https://ci.appveyor.com/api/projects/status/github/vshcherbyna/igel?svg=true)](https://ci.appveyor.com/project/vshcherbyna/igel)
7-
[![Total alerts](https://img.shields.io/lgtm/alerts/g/vshcherbyna/igel.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/vshcherbyna/igel/alerts/)
86

97
Igel is a free UCI chess engine forked from GreKo 2018.01. It is not a complete chess program and requires some UCI compatible GUI software in order to be used.
108

@@ -72,13 +70,13 @@ I would like to thank the authors and the community involved in the creation of
7270

7371
Official compilation method involves cmake and gcc/Visual Studio 2019 and assumes a modern CPU with AVX2 support (most of the computers produced in last 8 years).
7472

75-
Using cmake/Visual Studio:
73+
Using cmake/Visual Studio 2022:
7674

7775
```
7876
git clone https://github.com/vshcherbyna/igel.git ./igel
7977
cd igel
8078
git submodule update --init --recursive
81-
cmake -DEVAL_NNUE=1 -DUSE_AVX2=1 -D_BTYPE=1 -DSYZYGY_SUPPORT=TRUE -G "Visual Studio 16 2019" -A x64 .
79+
cmake -DEVAL_NNUE=1 -DUSE_AVX2=1 -D_BTYPE=1 -DSYZYGY_SUPPORT=TRUE -G "Visual Studio 17 2022" -A x64 .
8280
```
8381

8482
Using cmake/gcc:

src/gen.cpp

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Igel - a UCI chess playing engine derived from GreKo 2018.01
3+
*
4+
* Copyright (C) 2018-2023 Volodymyr Shcherbyna <volodymyr@shcherbyna.com>
5+
*
6+
* Igel is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* Igel is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with Igel. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "gen.h"
21+
22+
#include <chrono>
23+
#include <thread>
24+
25+
using namespace std::chrono_literals;
26+
std::vector<std::list<Move>> g_movesBook;
27+
28+
Generator::Generator(int depth, int threads, int fFash):
29+
m_maxDepth(depth),
30+
m_maxThreads(threads),
31+
m_maxfHash(fFash)
32+
{
33+
std::cout << "Igel training data generator" << std::endl;
34+
std::cout << "Training depth:" << m_maxDepth << std::endl;
35+
std::cout << "Training threads:" << m_maxThreads << std::endl;
36+
std::cout << "Training fens hash:" << m_maxfHash << std::endl;
37+
38+
std::cout << "Allocating fen hash table (" << fFash << "GB) ..";
39+
FenHashTT::instance(fFash);
40+
std::cout << ". Done" << std::endl;
41+
}
42+
43+
void Generator::onGenerate()
44+
{
45+
std::ifstream t("8moves_v3.pgn");
46+
std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
47+
std::replace(str.begin(), str.end(), '\n', ' ');
48+
49+
size_t offset = 0;
50+
std::vector<std::string> book;
51+
52+
// read book into a vector
53+
while (true) {
54+
auto pos_1 = str.find("1. ", offset);
55+
if (pos_1 == std::string::npos)
56+
break;
57+
auto pos_2 = str.find(" 1/2-1/2", pos_1);
58+
if (pos_2 == std::string::npos)
59+
break;
60+
book.emplace_back(str.substr(pos_1, pos_2 - pos_1));
61+
offset = pos_2 + 1;
62+
}
63+
64+
std::cout << "Read: " << book.size() << " positions. Generating the book ..." << std::endl;
65+
66+
std::unique_ptr<Position> position(new Position);
67+
68+
for (const auto & i : book) {
69+
position->SetInitial();
70+
size_t moveIndex = 0;
71+
auto & movesList = g_movesBook.emplace_back();
72+
73+
while (true) {
74+
auto separator = i.find(". ", moveIndex);
75+
76+
if (separator == std::string::npos)
77+
break;
78+
79+
separator += 2;
80+
auto move_end = i.find(" ", separator);
81+
82+
if (move_end == std::string::npos)
83+
break;
84+
85+
auto m_1 = i.substr(separator, move_end - separator);
86+
auto m = StrToMove(m_1, *position);
87+
88+
if (position->MakeMove(m)) {
89+
movesList.emplace_back(m);
90+
auto m2 = i.find(" ", move_end);
91+
92+
if (m2 == std::string::npos)
93+
break;
94+
95+
m2++;
96+
move_end = i.find(" ", m2);
97+
auto m_2 = i.substr(m2, move_end - m2);
98+
m = StrToMove(m_2, *position);
99+
moveIndex = move_end;
100+
101+
if (position->MakeMove(m))
102+
movesList.emplace_back(m);
103+
else {
104+
std::cout << "BookGen: m2 failed (" << m_2 << ", "<< m << ")" << std::endl;
105+
std::cout << i << std::endl;
106+
abort();
107+
}
108+
}
109+
else {
110+
std::cout << "BookGen: m1 failed (" << m_1 << ")" << std::endl;
111+
abort();
112+
}
113+
}
114+
}
115+
116+
book.clear();
117+
std::cout << "The book is generated: " << g_movesBook.size() << std::endl;
118+
119+
m_workerThreads.reset(new std::thread[m_maxThreads]);
120+
m_workers.reset(new GenWorker[m_maxThreads]);
121+
122+
unsigned int fileIndex = 0;
123+
124+
std::ofstream myfile;
125+
myfile.open(std::string("data_") + std::to_string(fileIndex) + ".plain");
126+
std::mutex mutex;
127+
uint64_t fileResetFenCounter = 0;
128+
129+
for (auto i = 0; i < m_maxThreads; ++i) {
130+
m_workers[i].m_pFile = &myfile;
131+
m_workers[i].m_pMutex = &mutex;
132+
m_workers[i].m_maxDepth = m_maxDepth;
133+
m_workerThreads[i] = std::thread(&GenWorker::workerRoutine, &m_workers[i]);
134+
}
135+
136+
while (true) {
137+
138+
uint64_t before_processed = 0;
139+
uint64_t before_skipped = 0;
140+
141+
for (auto i = 0; i < m_maxThreads; ++i) {
142+
before_processed += m_workers[i].m_counter;
143+
before_skipped += m_workers[i].m_skipped;
144+
}
145+
146+
std::this_thread::sleep_for(60s);
147+
148+
uint64_t after_processed = 0;
149+
uint64_t after_skipped = 0;
150+
151+
for (auto i = 0; i < m_maxThreads; ++i) {
152+
after_processed += m_workers[i].m_counter;
153+
after_skipped += m_workers[i].m_skipped;
154+
}
155+
156+
std::cout << "[Processed " << after_processed << " FENs, " << ((after_processed - before_processed) / 60) << " per sec] [" ;
157+
std::cout << "Skipped " << after_skipped << " FENs, " << ((after_skipped - before_skipped) / 60) << " per sec]" << std::endl;
158+
159+
//
160+
// every epoch create a new data file
161+
//
162+
163+
if ((after_processed - fileResetFenCounter) >= 100000000) {
164+
std::cout << "Switch data file" << std::endl;
165+
mutex.lock();
166+
myfile.close();
167+
myfile.open(std::string("data_") + std::to_string(++fileIndex) + ".plain");
168+
mutex.unlock();
169+
fileResetFenCounter = after_processed;
170+
}
171+
}
172+
173+
for (auto i = 0; i < m_maxThreads; ++i) {
174+
if (m_workerThreads[i].joinable())
175+
m_workerThreads[i].join();
176+
}
177+
}

0 commit comments

Comments
 (0)