It might be that my move ordering is worse (in uMax it will certainly be), but the reason why it does not pay off for you in CUT nodes might also be because of the way you implemented it. If you do not use self-deepening, doing IID in a CUT-node runs into the inefficiency I pointed out above, revisiting the daughter ALL-node many times in a row, generating moves every time you re-enter it.bob wrote:The problem that I recognized is that PV nodes are _critical_. A wrong move first and the tree explodes. That's why I only do IID there. At ALL/CUT nodes, thanks to null-move reductions, and and LMR-type reductions, the effort expended by IID was more expensive than the savings gained. I have tried this many times, but never got better results than when simply applying IID when there is no hash move on a PV node. PV nodes are the only place where reductions don't apply. The root PV node best move usually takes 90% of the search effort if not more. Getting it right is critical. Ditto for other PV nodes along the left-most edge of the graph. For my tests, IID elsewhere made the tree larger, not smaller. Perhaps if you don't do good captures first (SEE) or killer moves, this might pay off. But at traditional CUT nodes, I get a "good enough move" ordered first 92% of the time or so at no cost in extra searching. IID would need to improve on that while not losing more than it gains, which I don't see happening in my code at least.
In Joker I prevent this by using self-deepening: the ALL-node will not return if it knows it will be immediately called again with increased depth, but will increase the depth itself (so it can continue to use the already generated and sorted move list). So the main effect of the IID is that in the cases where the first move is not cut move (i.e. your 8%) you are very likely informed before full depth is reached:
Code: Select all
Search(depth, maxDepth)
{
MoveGen();
Probehash();
bestScore = hash.score;
for(iidDepth=hash.depth+1; iidDepth <= maxDepth && (iidDepth <= depth || bestScore <= alpha); iidDept++)
{
for(ALL_MOVES)
{
Make();
score = -Search(iidDepth-1, depth-1);
UnMake();
if(score>bestScore) bestScore = score;
}
}
StoreHash();
return bestScore;
}