Skip to content

Commit 768d387

Browse files
committed
Add genfens_engine.py, to test genfens
1 parent 4674156 commit 768d387

File tree

7 files changed

+111
-55
lines changed

7 files changed

+111
-55
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ Media/PGNs/*
1919
Media/Networks/*
2020
Media/Events/*
2121

22-
*.lock
22+
*.lock
23+
*.epd

Client/genfens.py

Lines changed: 29 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
# #
1919
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2020

21-
# The sole purpose of this module is to invoke create_genfens_opening_book().
21+
# The main purpose of this module is to invoke create_genfens_opening_book().
22+
# Refer to Client/worker.py, or Scripts/genfens_engine.py for the arguments.
2223
#
23-
# This will execute engines with commands like the following:
24+
# We will execute engines with commands like the following:
2425
# ./engine "genfens N seed S book <None|Books/book.epd> <?extra>" "quit"
2526
#
2627
# This work is split over many engines. If a workload requires 1024 openings,
27-
# and there are 16 threads, then each thread will generate 64 openings. The
28-
# openings are saved to Books/openbench.genfens.epd
28+
# and there are 16 threads, then each thread will generate 64 openings.
2929
#
3030
# create_genfens_opening_book() may raise utils.OpenBenchFailedGenfensException.
3131
# This occurs when longer than 15 seconds has elapsed since getting an opening.
@@ -51,38 +51,22 @@ def genfens_required_openings_each(config):
5151

5252
return math.ceil(total_games / config.threads)
5353

54-
def genfens_command_args(config, binary_name, network):
55-
56-
binary = os.path.join('Engines', binary_name)
57-
private = config.workload['test']['dev']['private']
58-
N = genfens_required_openings_each(config)
59-
book = genfens_book_input_name(config)
60-
extra_args = config.workload['test']['genfens_args']
61-
62-
return (binary, network, private, N, book, extra_args)
63-
6454
def genfens_book_input_name(config):
6555

66-
book_name = config.workload['test']['book']['name']
67-
book_none = book_name.upper() == 'NONE'
56+
book_name = config.workload['test']['book']['name']
57+
book_none = book_name.upper() == 'NONE'
6858

6959
return 'None' if book_none else os.path.join('Books', book_name)
7060

71-
def genfens_seed(config, N_per_thread, thread_index):
72-
73-
x = config.workload['test']['book_seed']
74-
y = config.workload['test']['book_index']
75-
76-
return (x << 32) + (y + N_per_thread * thread_index)
61+
def genfens_command_builder(args, index):
7762

78-
def genfens_command_builder(binary, network, private, N, book, extra_args, seed):
63+
command = ['./%s' % (args['engine'])]
7964

80-
command = ['./%s' % (binary)]
65+
if args['network'] and args['private']:
66+
command += ['setoption name EvalFile value %s' % (args['network'])]
8167

82-
if network and private:
83-
command += ['setoption name EvalFile value %s' % (network)]
84-
85-
command += ['genfens %d seed %d book %s %s' % (N, seed, book, extra_args), 'quit']
68+
fstr = 'genfens %d seed %d book %s %s'
69+
command += [fstr % (args['N'], args['seeds'][index], args['book'], args['extra']), 'quit']
8670

8771
return command
8872

@@ -109,44 +93,39 @@ def genfens_progress_bar(curr, total):
10993
bar_text = '=' * curr_progress + ' ' * (50 - curr_progress)
11094
print ('\r[%s] %d/%d' % (bar_text, curr, total), end='', flush=True)
11195

112-
def create_genfens_opening_book(config, binary_name, network):
113-
114-
# Format: ./engine "genfens N seed S book <None|book.epd>" "quit"
115-
N = genfens_required_openings_each(config)
116-
seeds = config.workload['test']['genfens_seeds']
117-
args = genfens_command_args(config, binary_name, network)
96+
def create_genfens_opening_book(args):
11897

98+
N = args['N']
99+
threads = args['threads']
119100
start_time = time.time()
120101
output = multiprocessing.Queue()
121-
print ('\nGenerating %d Openings using %d Threads...' % (N * config.threads, config.threads))
122102

103+
print ('\nGenerating %d Openings using %d Threads...' % (N * threads, threads))
123104

124105
# Split the work over many threads. Ensure the seed varies by the thread,
125106
# number in accordance with how many openings each thread will generate
107+
126108
processes = [
127109
multiprocessing.Process(
128110
target=genfens_single_threaded,
129-
args=(genfens_command_builder(*args, seeds[ii]), output))
130-
for ii in range(config.threads)
111+
args=(genfens_command_builder(args, index), output))
112+
for index in range(threads)
131113
]
132114

133115
for process in processes:
134116
process.start()
135117

136-
# Parse the Queue and save the content into Books/openbench.genfens.epd
137-
with open(os.path.join('Books', 'openbench.genfens.epd'), 'w') as fout:
138-
139-
try: # Each process will deposit exactly N results into the Queue
140-
for iteration in range(N * config.threads):
141-
fout.write(output.get(timeout=15) + '\n')
142-
genfens_progress_bar(iteration+1, N * config.threads)
118+
try: # Each process will deposit exactly N results into the Queue
119+
for iteration in range(N * threads):
120+
args['output'].write(output.get(timeout=15) + '\n')
121+
genfens_progress_bar(iteration+1, N * threads)
143122

144-
except queue.Empty: # Force kill the engine, thus causing the processes to finish
145-
utils.kill_process_by_name(binary_name)
146-
raise utils.OpenBenchFailedGenfensException('[%s] Stalled during genfens' % (binary_name))
123+
except queue.Empty: # Force kill the engine, thus causing the processes to finish
124+
utils.kill_process_by_name(binary_name)
125+
raise utils.OpenBenchFailedGenfensException('[%s] Stalled during genfens' % (binary_name))
147126

148-
finally: # Join everything to avoid zombie processes
149-
for process in processes:
150-
process.join()
127+
finally: # Join everything to avoid zombie processes
128+
for process in processes:
129+
process.join()
151130

152131
print('\nFinished Building Opening Book in %.3f seconds' % (time.time() - start_time))

Client/worker.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,11 +1110,25 @@ def safe_download_engine(config, branch, net_path):
11101110

11111111
def safe_create_genfens_opening_book(config, dev_name, dev_network):
11121112

1113-
try: genfens.create_genfens_opening_book(config, dev_name, dev_network)
1113+
with open(os.path.join('Books', 'openbench.genfens.epd'), 'w') as fout:
1114+
1115+
args = {
1116+
'N' : genfens.genfens_required_openings_total(config),
1117+
'book' : genfens.genfens_book_input_name(config),
1118+
'seeds' : config.workload['test']['genfens_seeds'],
1119+
'extra' : config.workload['test']['genfens_args'],
1120+
'private' : config.workload['test']['dev']['private'],
1121+
'engine' : os.path.join('Engines', dev_name),
1122+
'network' : dev_network,
1123+
'threads' : config.threads,
1124+
'output' : fout,
1125+
}
11141126

1115-
except utils.OpenBenchFailedGenfensException as error:
1116-
ServerReporter.report_engine_error(config, error.message)
1117-
raise
1127+
try: genfens.create_genfens_opening_book(args)
1128+
1129+
except utils.OpenBenchFailedGenfensException as error:
1130+
ServerReporter.report_engine_error(config, error.message)
1131+
raise
11181132

11191133
def safe_run_benchmarks(config, branch, engine, network):
11201134

Scripts/archive2nps.py

100644100755
File mode changed.

Scripts/archive2pgns.py

100644100755
File mode changed.

Scripts/bench_all.py

100644100755
File mode changed.

Scripts/genfens_engine.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/bin/python3
2+
3+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4+
# #
5+
# OpenBench is a chess engine testing framework by Andrew Grant. #
6+
# <https://github.com/AndyGrant/OpenBench> <andrew@grantnet.us> #
7+
# #
8+
# OpenBench is free software: you can redistribute it and/or modify #
9+
# it under the terms of the GNU General Public License as published by #
10+
# the Free Software Foundation, either version 3 of the License, or #
11+
# (at your option) any later version. #
12+
# #
13+
# OpenBench is distributed in the hope that it will be useful, #
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
16+
# GNU General Public License for more details. #
17+
# #
18+
# You should have received a copy of the GNU General Public License #
19+
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
20+
# #
21+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
22+
23+
import argparse
24+
import os
25+
import sys
26+
import random
27+
28+
# Needed to include from ../Client/*.py
29+
PARENT = os.path.join(os.path.dirname(__file__), os.path.pardir)
30+
sys.path.append(os.path.abspath(os.path.join(PARENT, 'Client')))
31+
32+
import genfens
33+
34+
if __name__ == '__main__':
35+
36+
p = argparse.ArgumentParser()
37+
p.add_argument('--engine' , help='Binary' , required=True )
38+
p.add_argument('--threads' , help='Threads to generate with' , required=True )
39+
p.add_argument('--count-per' , help='Openings to generate per thread', required=True )
40+
p.add_argument('--book-path' , help='Path to base Book, if any' , default='None')
41+
p.add_argument('--extra' , help='Extra genfens arguments' , default='' )
42+
p.add_argument('--network' , help='Network, for Private Engines' , default=None )
43+
args = p.parse_args()
44+
45+
# Same way that get_workload.py generates seeds
46+
seeds = [random.randint(0, 2**31 - 1) for x in range(int(args.threads))]
47+
48+
with open('example_genfens.epd', 'w') as fout:
49+
50+
genfen_args = {
51+
'N' : int(args.count_per),
52+
'book' : args.book_path,
53+
'seeds' : seeds,
54+
'extra' : args.extra,
55+
'private' : args.network != None,
56+
'engine' : args.engine,
57+
'network' : args.network,
58+
'threads' : int(args.threads),
59+
'output' : fout,
60+
}
61+
62+
genfens.create_genfens_opening_book(genfen_args)

0 commit comments

Comments
 (0)