Iteration in pondering

Discussion of chess software programming and technical issues.

Moderators: hgm, Dann Corbit, Harvey Williamson

mar
Posts: 2551
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Iteration in pondering

Post by mar »

hgm wrote: But that was the entire point: A time limit that you calculate in advance would be sub-optimal, because you don't knw how long you will be allowed to ponder yet. In the example I gave the 'never-exceed' limit would be 19 sec, and applying it after 30-sec pondering would make you abort the search immediately. Even when you had still plenty of time to resolve the fail low.

Relating the never-exceed limit to the time left on your clock also seems sub-optimal; Given that you already thought 30 sec on the move, and already know a best move from the iteration that took, (say) 20 sec, you probably would not want the time for the last move to drop below 10 sec in a critical situation. So you might want to set the tile limit 10 sec.
Well I do allocate the time in advance. I don't claim that it's optimal, there's sure a lot of space for improvements. But there's also logic which can occasionally increase the current time limit when a fail-low (i guess you mean aspiration fail-low at root, in my case if current iteration score is worse than previous iteration score than a margin) so if there was something wrong it would certainly spend more time than 19sec.
As I think about it I also have an absolute time limit which I can't exceed under any circumstances. It's only used one move before the TC is reset, i.e. before I get more time (40/4 and so on).

I think it's up to everyone to decide what to do with the extra time gained on ponder hit. I prefer to push on time. Not very clever but it's simple and seems to work well for me.
mar
Posts: 2551
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Iteration in pondering

Post by mar »

Of course it shouldn't matter to abort the search and restart, you would get lots of TT hits anyway. But unless you plan to do something really clever like readjusting time allocation at that point i see absolutely no reason to abort. In fact I think that continuing the search in easier to implement anyway.
Again this will only work if you do pondering right (you don't have to worry about that if you use uci).
If not then you're actually doing the same search your opponent does and in that case you cannot continue and must abort anyway (because it's not your turn :)
Some engines do that and I confess I have done that in my previous engine too. This only fills up hash table but you don't save any time that way.
mar
Posts: 2551
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Iteration in pondering

Post by mar »

When I think about it I have a bug in my code as the extra time condition won't trigger when failing low until all moves have been searched :)
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Iteration in pondering

Post by Sven »

mar wrote:Of course it shouldn't matter to abort the search and restart, you would get lots of TT hits anyway. But unless you plan to do something really clever like readjusting time allocation at that point i see absolutely no reason to abort. In fact I think that continuing the search in easier to implement anyway.
Again this will only work if you do pondering right (you don't have to worry about that if you use uci).
If not then you're actually doing the same search your opponent does and in that case you cannot continue and must abort anyway (because it's not your turn :)
Some engines do that and I confess I have done that in my previous engine too. This only fills up hash table but you don't save any time that way.
I see no reason to do any time allocation when starting to ponder, since the engine's clock from the external view is not running, just as in a game of human players where you analyze the position while it is the opponent's move.

Also I strongly believe that restarting the search from the root is certainly easier and safer to be implemented. When starting in the state where an engine has no pondering support at all, you can add pondering in a very simple way, without considering many different cases and without getting headache. There would be zero changes to the existing search code, apart from letting a central function that decides about signalling a timeout now return false in case the search is in "pondering mode", and from supporting a way to stop the search caused by a move made by the opponent.

I see pondering as an analysis effort that helps to improve an engine's playing strength by using resources that are available while its external clock is not running. Seeing it that way, there would be almost no difference between a "ponderhit" and a "pondermiss", both just terminate the pondering, which results in another simplification of the code at other places. Perhaps the only difference might arise from applying a different time allocation strategy after a ponderhit, I'll come back to that point further down.

It has already been made clear that doing as I proposed definitely requires a working hash table, since the improved hash table contents is the only information that the engine would keep from the whole pondering when it starts over.

Re: time control, Harm-Geert has correctly pointed out what my intention was, but I have even an extended view of it. Let's stick to his first example: 20 sec remaining on the external clock, with two moves left to make. Pondering for 19 sec, now you get the ponderhit. Without any pondering involved you would perhaps have allocated 9.5 sec for each of the two moves, leaving some buffer of 1.0 sec, that makes 2 * 9.5 + 1.0 = 20. Now why is it so obvious to assign significantly less than 9.5 seconds now in case of that ponderhit? Using 9.5 seconds from now on, where a tiny fraction is necessary to get back via TT access to the point where ponder search stopped, means that in the end you will have spent 28.5 seconds while your external clock was running for 9.5 seconds only. And you still have the other 9.5 seconds for the second move, where it is still possible to get the opportunity of a ponderhit, too.

Different models of time control are possible, of course, in case of a ponderhit. You might also use less than 9.5 seconds but more than 1.0, something in the middle, with the idea in mind that you want to take advantage of the ponderhit also by producing a faster response, not only by filling the hash table with relevant data. The faster response also helps to reduce the availability of pondering resources for the opponent, that is certainly true. But it might create some kind of imbalance in an engine's time utilization since without pondering, and assuming absence of any exceptional circumstances, each of the remaining moves would usually get assigned approximately the same amount of time on the external clock. It is a trade-off, either you prefer a quick response and more time for the next moves, or you prefer to use the "gift" of the ponderhit and search the current move a lot deeper right now. A dynamic decision about that seems to be the appropriate way.

Considering again the classical way of "twisting" a pondering implementation into the search, I don't say that this is inherently more complex and error-prone than the "starting over" approach in all cases. I only say it depends on the actual implementation, and I know some where understanding how and why the pondering code works can produce some headache at least.

Sven
mar
Posts: 2551
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Iteration in pondering

Post by mar »

Sven Schüle wrote: I see no reason to do any time allocation when starting to ponder, since the engine's clock from the external view is not running, just as in a game of human players where you analyze the position while it is the opponent's move.
If you want to continue ponder search and just switch from ponder to normal search you can do time allocation before you start pondering.
Sven Schüle wrote: Also I strongly believe that restarting the search from the root is certainly easier and safer to be implemented. When starting in the state where an engine has no pondering support at all, you can add pondering in a very simple way, without considering many different cases and without getting headache. There would be zero changes to the existing search code, apart from letting a central function that decides about signalling a timeout now return false in case the search is in "pondering mode", and from supporting a way to stop the search caused by a move made by the opponent.
I still think that continuing the search is easier to implement and don't see the reason why aborting should be safer.
Sven Schüle wrote: I see pondering as an analysis effort that helps to improve an engine's playing strength by using resources that are available while its external clock is not running. Seeing it that way, there would be almost no difference between a "ponderhit" and a "pondermiss", both just terminate the pondering, which results in another simplification of the code at other places. Perhaps the only difference might arise from applying a different time allocation strategy after a ponderhit, I'll come back to that point further down.
This is certainly true for the "stop search" approach.
Sven Schüle wrote: It has already been made clear that doing as I proposed definitely requires a working hash table, since the improved hash table contents is the only information that the engine would keep from the whole pondering when it starts over.
I assume that any engine should be already mature enough when its author decides to implement pondering. This implies having working hash table. 100% agree here.
Sven Schüle wrote: Re: time control, Harm-Geert has correctly pointed out what my intention was, but I have even an extended view of it. Let's stick to his first example: 20 sec remaining on the external clock, with two moves left to make. Pondering for 19 sec, now you get the ponderhit. Without any pondering involved you would perhaps have allocated 9.5 sec for each of the two moves, leaving some buffer of 1.0 sec, that makes 2 * 9.5 + 1.0 = 20. Now why is it so obvious to assign significantly less than 9.5 seconds now in case of that ponderhit? Using 9.5 seconds from now on, where a tiny fraction is necessary to get back via TT access to the point where ponder search stopped, means that in the end you will have spent 28.5 seconds while your external clock was running for 9.5 seconds only. And you still have the other 9.5 seconds for the second move, where it is still possible to get the opportunity of a ponderhit, too.
Yes that's one of the alternatives, to spend more time instead of playing a move fast. I prefer the latter. There is a lot of space for creativity though.
Sven Schüle wrote: Different models of time control are possible, of course, in case of a ponderhit. You might also use less than 9.5 seconds but more than 1.0, something in the middle, with the idea in mind that you want to take advantage of the ponderhit also by producing a faster response, not only by filling the hash table with relevant data.
I meant the case where you ponder from opponent's point of view (which i consider "wrong" way to implement pondering).
Sven Schüle wrote: The faster response also helps to reduce the availability of pondering resources for the opponent, that is certainly true. But it might create some kind of imbalance in an engine's time utilization since without pondering, and assuming absence of any exceptional circumstances, each of the remaining moves would usually get assigned approximately the same amount of time on the external clock. It is a trade-off, either you prefer a quick response and more time for the next moves, or you prefer to use the "gift" of the ponderhit and search the current move a lot deeper right now. A dynamic decision about that seems to be the appropriate way.
Agree :) But the imbalance can be desired sometimes. You save time you may need later.
Sven Schüle wrote: Considering again the classical way of "twisting" a pondering implementation into the search, I don't say that this is inherently more complex and error-prone than the "starting over" approach in all cases. I only say it depends on the actual implementation, and I know some where understanding how and why the pondering code works can produce some headache at least.
Sven
For sure getting it right and working will require some testing and perhaps debugging. But I think it's not that difficult yet one has to be careful.
Why I was trying to dig deeper into pondering is because i saw a lot of engines do it the wrong way. And that there are people who believe in some myths about pondering.
For example I have even heard someone believing that pondering will effectively make his engine search twice as fast.

Martin
User avatar
hgm
Posts: 27701
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Iteration in pondering

Post by hgm »

mar wrote:I still think that continuing the search is easier to implement and don't see the reason why aborting should be safer.
The reason is that when you read a command deep within the search, it might not be an opponent move, but somethig else. And then you would have to start processing commands within the search, which could interfere with it, or you would somehow have to queue the commands for execution after the search finishes, which would be inconvenient.

When you simply abort the ponder search when there is input, without actually looking at the input, you automatically fall back on your normal input loop for processing the commands at a 'search-free' time. All my engines (that ponder) do it like that.
mar
Posts: 2551
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Iteration in pondering

Post by mar »

hgm wrote: The reason is that when you read a command deep within the search, it might not be an opponent move, but somethig else. And then you would have to start processing commands within the search, which could interfere with it, or you would somehow have to queue the commands for execution after the search finishes, which would be inconvenient.

When you simply abort the ponder search when there is input, without actually looking at the input, you automatically fall back on your normal input loop for processing the commands at a 'search-free' time. All my engines (that ponder) do it like that.
Well I process commands outside search. I run search in a separate thread despite the fact that my engine doesn't do SMP. So I don't have that problem.
tpetzke
Posts: 686
Joined: Thu Mar 03, 2011 4:57 pm
Location: Germany

Re: Iteration in pondering

Post by tpetzke »

That is not a UCI problem, when the GUI tells the engine to ponder on the engine requested move only "ponderhit", "stop" or "quit" are expected commands. Everything else can safely be ignored

And if you abort search you waste effort (maybe little but you do) because you cannot store the incomplete results of the current line in the table.

Thomas...
mar
Posts: 2551
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Iteration in pondering

Post by mar »

tpetzke wrote:That is not a UCI problem, when the GUI tells the engine to ponder on the engine requested move only "ponderhit", "stop" or "quit" are expected commands. Everything else can safely be ignored

And if you abort search you waste effort (maybe little but you do) because you cannot store the incomplete results of the current line in the table.

Thomas...
True Thomas. But you should also expect "position" to come. For example polyglot does this when syncstop is false (default). So it doesn't send stop but instead position immediately and then go.
tpetzke
Posts: 686
Joined: Thu Mar 03, 2011 4:57 pm
Location: Germany

Re: Iteration in pondering

Post by tpetzke »

Thanks, I wasn't aware of that. I have to think how to handle that

Thomas...