WinBoard has a separate input thread for each engine, and it simply waits there in a blocking read call untill the engine produces anything. When it does, it gets it instantly, processes it, and starts reading again.
Note that on most OS the buffer associated with a pipe is quite limited, and when you flood it with output when the reader is not paying attention at the other end, it will fill up, and the writer will block in the write call that would make the buffer overflow. Thus very verbose engines might see their processes suspended when the GUI is tardy in reading their output, effectively using much less time than they were granted (when the output thread is also the search thread, which usually is the case).
UCI Engine output
Moderator: Ras
-
- Posts: 28391
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
-
- Posts: 153
- Joined: Fri Sep 30, 2011 7:48 am
Re: UCI Engine output
I like the sound of the blocking read call that waits for input, that's what I am trying to work out how to do with the UCI protocol, although I will probably support Winboard next. I think I read somewhere that memset(), strings and other array processing functions can waste a lot of cpu time, so I am trying to leave more time for the engines.hgm wrote:WinBoard has a separate input thread for each engine, and it simply waits there in a blocking read call untill the engine produces anything. When it does, it gets it instantly, processes it, and starts reading again.
Note that on most OS the buffer associated with a pipe is quite limited, and when you flood it with output when the reader is not paying attention at the other end, it will fill up, and the writer will block in the write call that would make the buffer overflow. Thus very verbose engines might see their processes suspended when the GUI is tardy in reading their output, effectively using much less time than they were granted (when the output thread is also the search thread, which usually is the case).
I suppose the pipe buffer info could be obtained from the OS (windows,linux,mac) ?
Last edited by Dave_N on Fri Oct 07, 2011 1:23 pm, edited 1 time in total.
-
- Posts: 153
- Joined: Fri Sep 30, 2011 7:48 am
Re: UCI Engine output
Working on this, thanks for the information =)ilari wrote:The better, simpler, more reliable and more efficient method is to forget about polling for input completely and use synchronized reads in a separate thread. That way you'll get any input instantly.Dave_N wrote:I suppose the time to look for input could depend on the clock increment ... If I have a time increment of 1/10th of a second then the engine will play optimally if I look every 1/20th of a second.
-
- Posts: 28391
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: UCI Engine output
The protocol you use would not make the slightest difference for how you read. Itonly starts playing a role after you read something, to decode what it means.Dave_N wrote:I like the sound of the blocking read call that waits for input, that's what I am trying to work out how to do with the UCI protocol, although I will probably support Winboard next.
-
- Posts: 153
- Joined: Fri Sep 30, 2011 7:48 am
Re: UCI Engine output
So for example in windows I would use PeekNamedPipe() then read when something is available?
I am quite interested in the special case of waiting until output has completed and sent "bestmove" after a call like "go depth 18", however perhaps PeekNamedPipe() will reply that data is available all the time from the moment the first line is sent from the engine since there is data in the stdin.
I am quite interested in the special case of waiting until output has completed and sent "bestmove" after a call like "go depth 18", however perhaps PeekNamedPipe() will reply that data is available all the time from the moment the first line is sent from the engine since there is data in the stdin.
-
- Posts: 153
- Joined: Fri Sep 30, 2011 7:48 am
Re: UCI Engine output
Of course if the pipe is going to overflow I need to parse quite often
-
- Posts: 28391
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: UCI Engine output
Indeed. The engine will produce PV lines before its bestmove, they will fill up the buffer (there could be a lot of them, especially in multi-PV mode), the engine process will be stalled by the OS, and the bestmove command would never come.Dave_N wrote:So for example in windows I would use PeekNamedPipe() then read when something is available?
I am quite interested in the special case of waiting until output has completed and sent "bestmove" after a call like "go depth 18", however perhaps PeekNamedPipe() will reply that data is available all the time from the moment the first line is sent from the engine since there is data in the stdin.
Further more, becareful with PeekNamedPipe. There seems to be some hidden buffering that makes PeekNamedPipe say there is no input, while you have not read everything there is yet, when using getchar(). Bettertouse a separate thread, and have it hang waiting for input.
-
- Posts: 686
- Joined: Thu Mar 03, 2011 4:57 pm
- Location: Germany
Re: UCI Engine output
...and I have also seen the other case where PeekNamedPipe said there is input (although there was none) and when you then try to read the non existing input your program hangs until real input appears.
Thomas...
Thomas...
-
- Posts: 750
- Joined: Mon Mar 27, 2006 7:45 pm
- Location: Finland
Re: UCI Engine output
If you read input in a separate thread with a blocking ReadFile() call you don't have to (and shouldn't) use PeekNamedPipe() anywhere. Please take a look at Cute Chess' PipeReader class to see how it can be done:tpetzke wrote:...and I have also seen the other case where PeekNamedPipe said there is input (although there was none) and when you then try to read the non existing input your program hangs until real input appears.
Thomas...
header and source
Note that you need some synchronization between the main thread and the input-reading thread. Semaphores are the most natural and portable way to do it.
-
- Posts: 153
- Joined: Fri Sep 30, 2011 7:48 am
Re: UCI Engine output
The code seems to suggest that the "isready" command is occasionally sent to "avoid signal spam" unless I am misinterpreting this:-
Code: Select all
// To avoid signal spam, send the 'readyRead' signal only
120 // if we have a whole line of new data
121 if (m_lastNewLine <= int(dwRead))
122 emit readyRead();