UCI: seldepth

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: UCI: seldepth

Post by mcostalba »

hgm wrote:You could even do it for free. If you have some array indexed by ply (like killers...), which is only used in full-width search, initialize it by something invalid, and after the search, check how far it was overwritten.
Yes, I thought about this trick, but I stumbled at SMP. It is not so easy to extend to SMP because you would need to collect data at each split point and track it back....
User avatar
rvida
Posts: 481
Joined: Thu Apr 16, 2009 12:00 pm
Location: Slovakia, EU

Re: UCI: seldepth

Post by rvida »

One line of code I would not call "too costly to implement".
In scout_search() and pv_search() [but not in quiesce*()] I have this:

Code: Select all

  if (board.ply > thread->stats.maxply)
    thread->stats.maxply = board.ply;
The code above compiles to one conditional jump, which is predicted correctly 99% according to intel's vtune. It makes sense because >60% of nodes are spent in q-search anyway.

when in MP mode, sending output involves collecting info from all threads:

Code: Select all

int seldepth = 0;
for &#40;i==0; i < num_threads; i++) &#123;
  if &#40;threads&#91;i&#93;.stats.maxply > seldpeth&#41;
    seldepth = threads&#91;i&#93;.stats.maxply;
&#125;
User avatar
rvida
Posts: 481
Joined: Thu Apr 16, 2009 12:00 pm
Location: Slovakia, EU

Re: UCI: seldepth

Post by rvida »

rvida wrote:

Code: Select all

int seldepth = 0;
for &#40;i==0; i < num_threads; i++) &#123;
  if &#40;threads&#91;i&#93;.stats.maxply > seldpeth&#41;
    seldepth = threads&#91;i&#93;.stats.maxply;
&#125;
Ouch, I should not post any code after 9pm ;)

Code: Select all

int seldepth = 0;
for &#40;int i=0; i < num_threads; i++) &#123;
  if &#40;threads&#91;i&#93;.stats.maxply > seldpeth&#41;
    seldepth = threads&#91;i&#93;.stats.maxply;
&#125;
User avatar
Onno Garms
Posts: 224
Joined: Mon Mar 12, 2007 7:31 pm
Location: Bonn, Germany

Re: UCI: seldepth

Post by Onno Garms »

hgm wrote:You could even do it for free. If you have some array indexed by ply (like killers...), which is only used in full-width search, initialize it by something invalid, and after the search, check how far it was overwritten.
It should be noted however that using such approaches, you can send seldepth only when you send something anyway (and therefore check the array). You don't notice immediately when the array grows. With my approach, I can send seldepth immediately when it is reached. Of course there is not much value in that behaviour.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: UCI: seldepth

Post by mcostalba »

rvida wrote:One line of code I would not call "too costly to implement".
In scout_search() and pv_search() [but not in quiesce*()] I have this:

Code: Select all

  if &#40;board.ply > thread->stats.maxply&#41;
    thread->stats.maxply = board.ply;
Yes this is the most natural and straightforward approach, I see you have direct access to Thread object by 'thread' pointer.

Currently in SF access is by an array index threads[threadID], this implies a multiplication of threadID * sizeof(Thread) when compiler resolves the address....so actually you gave me two ideas instead of one ;-)
User avatar
Onno Garms
Posts: 224
Joined: Mon Mar 12, 2007 7:31 pm
Location: Bonn, Germany

Re: UCI: seldepth

Post by Onno Garms »

Onno Garms wrote:For some reason, it can happen that the PV is shorter than depth,
I think I located what "some reason" is.

Stockfish does not track the PV. It just tries to retrieve the PV from the TT after a move is finished.

This will not always be successful. Not just because of possible early overwrites, also because moves that fail low never get written into the TT. Consequently SF might find a move in the TT that was best at shallower depth. The PV is read incorrectly then.

This can result in incorrect output of the PV. I'm not sure if this also results in an Elo loss (because the correct PV is not written back into the TT). To find an answer, an implementation where search() returns the partial PV would be needed.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: UCI: seldepth

Post by mcostalba »

Onno Garms wrote: This will not always be successful. Not just because of possible early overwrites, also because moves that fail low never get written into the TT. Consequently SF might find a move in the TT that was best at shallower depth. The PV is read incorrectly then.

This can result in incorrect output of the PV. I'm not sure if this also results in an Elo loss (because the correct PV is not written back into the TT). To find an answer, an implementation where search() returns the partial PV would be needed.
In case of a PV node the best move is always written to TT even if is not able to cut-off against beta.

It is true that if it fails low then it is not written, but in a "normal" search you return an exact score after having resolved all the fails high/low along the PV line.

BTW we have tested when we moved to this scheme from the triangular array one and result was no ELO change.
User avatar
Onno Garms
Posts: 224
Joined: Mon Mar 12, 2007 7:31 pm
Location: Bonn, Germany

Re: UCI: seldepth

Post by Onno Garms »

mcostalba wrote: It is true that if it fails low then it is not written, but in a "normal" search you return an exact score after having resolved all the fails high/low along the PV line.
In deed. But in another threat we had a discussion about printing PVs that failed high or low.
BTW we have tested when we moved to this scheme from the triangular array one and result was no ELO change.
Good to know. So the PV scheme is just a matter of an analysis friendly output.