Marco Costalba [Fri, 1 May 2009 08:17:34 +0000 (10:17 +0200)]
Sort moves just after scoring
Instead of a delayed selection sort so that the highest
score move is picked up from the list when needed, sort all
the moves up front just after score them.
Selection sort is O(n*n) while std::sort is O(n*log n), it
is true that delayed selection allows us to just pick the move
until a cut off occurs or up to a given limit (12), but with
an average of 30 non capture-moves delayed pick become slower
just after 5-6 moves and we now pick up to 12.
Profiling seem to prove this idea and movepick.cpp is now 10%
faster.
Also tests seem to confirm this:
After 700 games at 1+0: Mod vs Orig +178 -160 =362 +9 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Thu, 30 Apr 2009 06:55:38 +0000 (08:55 +0200)]
Do not razor after a null move
We don't want to return unproven null move fails high, so
that if a position is so good that null move fails high we
want to check this with real do_move() / undo_move() test,
not just razoring the position because, from the opponent
point of view, is very bad.
These are tests results at 1+0
Mod vs Orig +252 -264 =483 49.40%
Mod vs Toga II 1.4.1SE +365 -325 =309 52.00%
So it seems a very slightly regression regarding orig version (but
withing error bar) and a nice increase against Toga that is what we
are interested most. Orig version scores 49.75% against Toga, so
we welcome this change ;-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Tue, 28 Apr 2009 06:51:11 +0000 (08:51 +0200)]
Merge Joona's razoring tweaks
After proof testing on 3 different engines these
are the results:
Stockfish - Toga II 1.4.1SE +130 -132 =132 49.75%
Stockfish - Deep Sieng 3.0 +145 -110 =150 54.45%
Stockfish - HIARCS 12 MP +94 -149 =150 43.00%
So it seems no regressions occurs, although also no
improvment. But anyhow this patch increases Stockfish
strenght against itself, so merge it.
Note that this patch not only adds back razoring at depth
one, but also increases razor depth limit from 3 to 4
because hard coded depth 4 limit is no more overwritten
by UCI parameter that otherwise defaults to 3.
Marco Costalba [Tue, 28 Apr 2009 06:47:26 +0000 (08:47 +0200)]
Hardcode depth limit for selective search
Because futility margins array has a fixed size we cannot
arbitrarly choose or change the SelectiveDepth parameter,
otherwise we have a crash for values bigger then array size.
On the other hand tweaking of this parameter requires some
modification to the hardcoded margins, so makes sense to hard
code also this very bounded one.
Who wants to experiment is of course free to change the sources.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Sun, 19 Apr 2009 16:23:30 +0000 (17:23 +0100)]
Small code tidy up and test results
When testing at 1'+0" time control results are still
reasonably good. We have made two sessions on two
different PC.
After 840 games Mod - Orig: +221 -194 =425 +10 ELO (two CPU)
After 935 games Mod - Orig: +246 -222 =467 +9 ELO (single CPU)
So it seems that with fast CPU and/or longer time controls
benefits of the patch are a bit reduced. This could be due
to the fact that only 3% of nodes are pruned by razoring at
depth one and these nodes are very swallow ones, mostly get
pruned anyway with only a slightly additional cost, even
without performing any do_move() call.
Another reason is that sometime (0,3%% of cases) a possible
good move is missed typically in positions when moving side
gives check, as example in the following one
3r2k1/pbpp1nbp/1p6/3P3q/6RP/1P4P1/P4Pb1/3Q2K1 w - -
The winning move Rxg7+ is missed.
Bottom line is that patch seems good for blitz times, perhaps
also for longer times. We should test against a third engine
(Toga ?) to have a final answer regarding this new setup.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Razor again at depth one
Some time ago it was found by Marco Costalba that it's better
to disable razoring at depth one, because given the very low
evaluation of the node, futility pruning would already do
the job at very low cost and avoiding missing important moves.
Now enable razoring there again, but only when our quickly evaluated
material advantage is more than a rook. The idea is to try razoring
only when it's extremely likely that it will succeed.
Extreme lightning speed test show promising result:
Orig - Mod: +1285 =1495 -1348
This needs to be tested with longer time controls though.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Restructure RazorMargins and FutilityMargins arrays so that their
values can be more easily tuned.
Add RazorApprMargins array which replaces razorAtDepthOne concept,
because setting RazorApprMargin very high value at ply one is
same as not razoring there at all.
Comment out setting razoring and futility margins through uci to
avoid errors while tuning.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Sat, 18 Apr 2009 13:03:33 +0000 (14:03 +0100)]
In qsearch store the cut move in TT
And upon reentering the same position try it as first.
Normally qsearch moves order is already very good, first move
is the cut off in almost 90% of cases. With this patch, we get
a cut off on TT move of 98%.
Another good side effect is that we don't generate captures
and/or checks when we already have a TT move.
Unfortunatly we found a TT move only in 1% of cases. So real
impact of this patch is relatively low.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Check all fail highs in assumed PV with greater care (fruit/Toga already does this).
Add a flag when aspiration search fails high at ply 1 to prevent search to
be terminated prematurely.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Implement a fallback system when aspiration search fails low and we are out of time.
However also this patch is immediately reverted. For three reasons:
1) the case it affects is very rare (and then we are likely to lose anyway),
so we can well live without this.
2) Because the case is so rare it's hard to test this change properly.
3) To perform fallback search, we must reset so many global variables that this
patch is very likely both buggy and extremely bad style.
Consider including this again if we clean-up global variables one day...
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Implement system where aspiration search window is calculated using
values from previous iterations.
And then some crazy experimental stuff: If search fails low at the root,
don't widen window, but continue and hope we will find a better move
with given window. If search fails high at the root, cut immediately,
add some more time and start new iteration.
Note: this patch is not complete implementation, but a first test
for this idea. There are many FIXMEs left around. Most importantly
how to deal with the situation when we don't have any move!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Sun, 12 Apr 2009 00:09:03 +0000 (01:09 +0100)]
Fix a very nasty conversion bug in Option c'tor
Sometimes C++ can be really bad!
In this case an hard coded c string selects Option c'tor
with int argument instead of the std::string one becuase
it is considered a better matching by the compiler.
Fix the bug changing the argument type from std::string to
const char* so to be a better match then the int one.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Sat, 11 Apr 2009 10:46:47 +0000 (12:46 +0200)]
Use a map instead of a vector to store UCI options
Apart from the teoretical speed increase, the main reason
of this patch is a good amount of code cleanup.
Note that now UCI options are printed in alphabetical
order and not in insertion order as before. Next patch
will take care of restoring old behaviour.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Mon, 30 Mar 2009 10:07:45 +0000 (12:07 +0200)]
Silence idiotic warning on two's complement of an unsigned
MSVC gives:
warning C4146: unary minus operator applied to unsigned type,
result still unsigned
When finds -b where b is an unsigned integer. So rewrite the two's
complement in a way to avoid the warning. Theoretically the new
version is slower, but in practice changes nothing.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Tue, 31 Mar 2009 12:57:44 +0000 (14:57 +0200)]
Revert setting a flag when TT value equals static evaluation
Strangely enough it seems that optimization doesn't work.
After 760 games at 1+0: +155 -184 =421 -13 ELO
Probably the overhead, although small, for setting the flag
is not compensated by the saved evaluation call.
This could be due to the fact that after a TT value is stored,
if and when we hit the position again the stored TT value is
actually used as a cut-off so that we don't need to go on
with another search and evaluation is avoided in any case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Mon, 30 Mar 2009 08:09:27 +0000 (09:09 +0100)]
An VALUE_TYPE_EVAL score cannot overwrite an entry
If we want to store a value of type VALUE_TYPE_EVAL for
a given position and we found an already exsisting entry
for the same position then we skip.
We don't want to overwrite a more valuable score with a
lesser one. Note that also in case the exsisting entry is
of VALUE_TYPE_EVAL type the overwrite is unuseful because
we would store the same score again.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Mon, 30 Mar 2009 07:54:09 +0000 (08:54 +0100)]
Remember when TT value equals static evaluation value
When the stored TT value equals the static value set a
proper flag so to not call evaluation() if we hit the
same position again but use the stored TT value instead.
This is another trick to avoid calling costly evaluation()
in qsearch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Sun, 29 Mar 2009 16:22:10 +0000 (17:22 +0100)]
A move needs 17 bits not 19
Fix a bug in the way a move is stored and read in a TT entry.
We use a mask of 19 bits insteaad of 17 so that the last
two bits in the TT entry end up to be random data.
This bug will bite us when we will use these two until now
unused bits.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Mon, 23 Mar 2009 14:30:20 +0000 (15:30 +0100)]
Fix a bug in insert_pv() where minimum depth is zero
We implicitly considered the minimum depth stored in TT
to be Depth(0), but because we store values in TT also in
qsearch() where depth is < 0, we need to use a negative
number as minimum depth.
Bug spotted by Joona Kiiski.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco Costalba [Mon, 23 Mar 2009 11:02:15 +0000 (12:02 +0100)]
Revert odd depths razoring
I have just made a new rule that no modification
that increases pruning is allowed if after 1000 games
ELO is not increased by at least 10 point (was +5 in this case)