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-
6454def 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 ('\n Generating %d Openings using %d Threads...' % (N * config .threads , config .threads ))
122102
103+ print ('\n Generating %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 ('\n Finished Building Opening Book in %.3f seconds' % (time .time () - start_time ))
0 commit comments