Stockfish v1.3.1_JA running in Fritz GUI

Discussion of anything and everything relating to chess playing software and machines.

Moderator: Ras

redmecca

Stockfish v1.3.1_JA running in Fritz GUI

Post by redmecca »

I wondered if anyone had come across this issue:

When I run Stockfish 1.3.1_JA in the Chessbase GUI as an analysis engine, it offers up two different lines of analysis but scores both lines identically.
ernest
Posts: 2053
Joined: Wed Mar 08, 2006 8:30 pm

Re: Stockfish v1.3.1_JA running in Fritz GUI

Post by ernest »

Funny... and true (multi-variation analysis) for 1.3 and 1.3.1 :)

Analysis by Stockfish 1.3 JA:
1. +/= (0.56): 1.Bxa3 e5 2.Bb2 d6 3.e3 Qg5 4.Nf3 Qg6 5.Bc4 Nc6 6.0-0 Nf6 7.d4 e4 8.Nh4 Qg4 9.d5 Qxd1 10.Raxd1 Ne5 11.Bxe5 dxe5 12.Rb1
2. +/= (0.56): 1.d4 Ra4
3. +/= (0.56): 1.e3 Ra4
4. +/= (0.56): 1.Bb2 Ra4
5. +/= (0.56): 1.e4 Ra5
6. +/= (0.56): 1.Nf3 Ra5

1.2 did not have that bug.
redmecca

Re: Stockfish v1.3.1_JA running in Fritz GUI

Post by redmecca »

I assume that the top line is the optimal one!?
ernest
Posts: 2053
Joined: Wed Mar 08, 2006 8:30 pm

Re: Stockfish v1.3.1_JA running in Fritz GUI

Post by ernest »

The sample (actually illegal :D) position was:
[d]rnbqkbn1/pppppppp/8/8/8/r7/P1PPPPPP/R1BQKBNR w KQq - 0 1
zamar
Posts: 613
Joined: Sun Jan 18, 2009 7:03 am

Re: Stockfish v1.3.1_JA running in Fritz GUI

Post by zamar »

This looks like my mistake. The bug went in with new aspiration window search code. This happens when you concentrate only improving program's strength and forget to worry about other important features :(

Marco, I strongly suspect that you end up here sooner or later. Fix is oneliner:

--- a/src/search.cpp
+++ b/src/search.cpp
@@ -897,7 +897,7 @@ namespace {

if (i < MultiPV)
{
- value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
+ value = -search_pv(pos, ss, -beta, MultiPV == 1 ? -alpha : VALUE_INFINITE, newDepth, 1, 0);
// If the value has dropped a lot compared to the last iteration,
// set the boolean variable Problem to true. This variable is used
// for time managment: When Problem is true, we try to complete the
Joona Kiiski
User avatar
Eelco de Groot
Posts: 4669
Joined: Sun Mar 12, 2006 2:40 am
Full name:   Eelco de Groot

Ancalagon's version of Stockfish v1.3.1_JA search

Post by Eelco de Groot »

zamar wrote:This looks like my mistake. The bug went in with new aspiration window search code. This happens when you concentrate only improving program's strength and forget to worry about other important features :(

Marco, I strongly suspect that you end up here sooner or later. Fix is oneliner:

--- a/src/search.cpp
+++ b/src/search.cpp
@@ -897,7 +897,7 @@ namespace {

if (i < MultiPV)
{
- value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
+ value = -search_pv(pos, ss, -beta, MultiPV == 1 ? -alpha : VALUE_INFINITE, newDepth, 1, 0);
// If the value has dropped a lot compared to the last iteration,
// set the boolean variable Problem to true. This variable is used
// for time managment: When Problem is true, we try to complete the
Thanks for Stockfish 1.3.1 Joona!

It is quite by accident, but the experimental version of Stockfish's search.cpp I am using at the moment already repaired this Multi_PV window problem in a way, although I'm not sure the windows it uses are correct always and had not tested the Multi PV option yet. It is just an experiment. It does something of a second pass over your aspiration windows Joona. When I programmed it it seemed more or less clear to me but when I look at it again I have great difficulty understanding what it is all about :o :lol:
Also it uses now search_pv where most programs use the nullwindow search, and vice versa :) I don't have a CVS or something like that, but here are the changes in my search.cpp as reported by WinMerge:

Code: Select all

  const Value NullMoveMargin = Value(0x350);

Code: Select all


  // root_search() is the function which searches the root node.  It is
  // similar to search_pv except that it uses a different move ordering
  // scheme (perhaps we should try to use this at internal PV nodes, too?)
  // and prints some information to the standard output.

  Value root_search(Position &pos, SearchStack ss[], RootMoveList &rml, Value alpha, Value beta) {

    Value oldAlpha = alpha;
    Value value, oldvalue, PV_value;
    Bitboard dcCandidates = pos.discovered_check_candidates(pos.side_to_move());

    // Loop through all the moves in the root move list
    for (int i = 0; i <  rml.move_count() && !AbortSearch; i++)
    {
        if (alpha >= beta)
        {
            // We failed high, invalidate and skip next moves, leave node-counters
            // and beta-counters as they are and quickly return, we will try to do
            // a research at the next iteration with a bigger aspiration window.
            rml.set_move_score(i, -VALUE_INFINITE);
            continue;
        }
        int64_t nodes, nodes_before, nodes_after, nodes_minimum ;
        Move move;
        StateInfo st;
        Depth ext, newDepth, LateMoveDepth;

        RootMoveNumber = i + 1;
        FailHigh = false;

        // Remember the node count before the move is searched. The node counts
        // are used to sort the root moves at the next iteration.
        nodes = nodes_searched();

        // Reset beta cut-off counters
        BetaCounter.clear();

        // Pick the next root move, and print the move and the move number to
        // the standard output.
        move = ss[0].currentMove = rml.get_move(i);
        if (current_search_time() >= 1000)
            std::cout << "info currmove " << move
                      << " currmovenumber " << i + 1 << std::endl;

        // Decide search depth for this move
        bool dangerous;
        ext = extension(pos, move, true, pos.move_is_capture(move), pos.move_is_check(move), false, false, &dangerous);
        newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;

        // Make the move, and search it
        pos.do_move(move, st, dcCandidates);

        if (i < MultiPV)
        {
			if (Iteration <= 45)
			{
				Value gamma = Value(0x100);
				if (Iteration >= 6) gamma = alpha;
                value = -search(pos, ss, -gamma, newDepth + 1, 1, true, 0);
				if (value > gamma && alpha <= gamma) alpha = Value((gamma + value) >> 1);
				else alpha = Value((alpha + value - 0x300) >> 1);
			}
            value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
            // If the value has dropped a lot compared to the last iteration,
            // set the boolean variable Problem to true. This variable is used
            // for time management: When Problem is true, we try to complete the
            // current iteration before playing a move.
            Problem = (Iteration >= 2 && value <= IterationInfo[Iteration-1].value - ProblemMargin);

            if (Problem && StopOnPonderhit)
                StopOnPonderhit = false;
        }
        else
        {
            value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
			oldvalue = value;
			value = -search(pos, ss, -alpha, newDepth + 2, 1, true, 0);
            if (value > alpha)
            {
                // Fail high! Set the boolean variable FailHigh to true, and
                // re-search the move with a big window. The variable FailHigh is
                // used for time management: We try to avoid aborting the search
                // prematurely during a fail high research.
                FailHigh = true;
                value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
				value = -search(pos, ss, -alpha, newDepth + 3, 1, true, 0);
            }
			else
			{
				nodes_minimum = 0;
				PV_value = -search_pv(pos, ss, -beta, -alpha, newDepth - 1, 1, 0);
				LateMoveDepth = newDepth;
                if (value - oldvalue >= 50 || PV_value > oldvalue)
			    {
					value = -search(pos, ss, -alpha, newDepth + 3, 1, true, 0);
				    PV_value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
				    
				    if (value - oldvalue >= 75 || value > alpha || PV_value > alpha)
				    {
					    FailHigh = true;
					    oldvalue = value;
				        value = -search(pos, ss, -alpha, newDepth + 5, 1, true, 0);
				    }
			    }
				else while (nodes_minimum < 10000 && PV_value < alpha && LateMoveDepth < MaxDepth)
				{
				    nodes_before = nodes_searched();
				    PV_value = -search_pv(pos, ss, - VALUE_INFINITE, -alpha, LateMoveDepth, 1, 0);
				    nodes_after = nodes_searched();
					LateMoveDepth = LateMoveDepth + 1;
					nodes_minimum = nodes_after - nodes_before;
					if (PV_value > value) value = PV_value;
				}
				
			}
        }

        pos.undo_move(move);

        // Finished searching the move.

[caveat] :!:
It is possible though that all this does not work with more threads Joona, I have not given it any thought and can't test it yet here. Sorry!
[/caveat]


Important Vas quote in this respect - using nodes_searched() -, they have a list in the Rybka forum but this one is not in it:

Quote from GCP:

Now, in case of chess, if you split the set of moves equally between CPUs, each move is guaranteed to get pretty much the same effort spent to it. This might result in different depths, but who cares if the effort spent is equal? So, in the clustering-root-unsynchronised case, it seems totally obvious to me that you would just pick the best scoring move, ignoring depth totally.
Depth is a poor measure of search quality, time is much better.

Vas
Regards, Eelco
Debugging is twice as hard as writing the code in the first
place. Therefore, if you write the code as cleverly as possible, you
are, by definition, not smart enough to debug it.
-- Brian W. Kernighan
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Stockfish v1.3.1_JA running in Fritz GUI

Post by mcostalba »

zamar wrote: {
- value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
+ value = -search_pv(pos, ss, -beta, MultiPV == 1 ? -alpha : VALUE_INFINITE, newDepth, 1, 0);
Thanks, seems a wise thing to do ;-)

BTW do you think new aspiration window _could_ have an impact on the SMP code? As you probably have read first results _seem_ to show a regression when going SMP.
zamar
Posts: 613
Joined: Sun Jan 18, 2009 7:03 am

Re: Stockfish v1.3.1_JA running in Fritz GUI

Post by zamar »

mcostalba wrote:
zamar wrote: {
- value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
+ value = -search_pv(pos, ss, -beta, MultiPV == 1 ? -alpha : VALUE_INFINITE, newDepth, 1, 0);
Thanks, seems a wise thing to do ;-)

BTW do you think new aspiration window _could_ have an impact on the SMP code? As you probably have read first results _seem_ to show a regression when going SMP.
I've thought about a lot of this assumed SMP-regression lately and I haven't found any connection between aspiration stuff and SMP, but this is of course this is one of the things to be tested when I get my quad back from repair...

I've scanned through the Changelog between 1.2->1.3 to find the reason for (possible) SMP-regression and the only _wild_guess_ I've got is this:

* I've heard top guys talking that when the number of CPUs grows the shared memory access can become a bottleneck (top guys talk about cachelines and other stuff I know nothing about). The way we changed QSearch TT-stuff make each thread to read/write to RAM more often than what it was in 1.2. Could it be that threads get jammed trying to access same memory segments simultaneously and being on the way of each other?

Really just a wild guess and likely to be wrong :)
Joona Kiiski
zamar
Posts: 613
Joined: Sun Jan 18, 2009 7:03 am

Re: Ancalagon's version of Stockfish v1.3.1_JA search

Post by zamar »

Eelco de Groot wrote: Thanks for Stockfish 1.3.1 Joona!
I'm not the right person to thank, but you are welcome anyway :)
It is quite by accident, but the experimental version of Stockfish's search.cpp I am using at the moment already repaired this Multi_PV window problem in a way, although I'm not sure the windows it uses are correct always and had not tested the Multi PV option yet. It is just an experiment. It does something of a second pass over your aspiration windows Joona. When I programmed it it seemed more or less clear to me but when I look at it again I have great difficulty understanding what it is all about :o :lol:
Thanks! I'll try to understand your code :wink:
[caveat] :!:
It is possible though that all this does not work with more threads Joona, I have not given it any thought and can't test it yet here. Sorry!
[/caveat]
If your code improves single core stuff, it'll also improve SMP-stuff, cause we are not splitting in root.
Joona Kiiski
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Stockfish v1.3.1_JA running in Fritz GUI

Post by mcostalba »

zamar wrote:
mcostalba wrote:
zamar wrote: {
- value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
+ value = -search_pv(pos, ss, -beta, MultiPV == 1 ? -alpha : VALUE_INFINITE, newDepth, 1, 0);
Thanks, seems a wise thing to do ;-)

BTW do you think new aspiration window _could_ have an impact on the SMP code? As you probably have read first results _seem_ to show a regression when going SMP.
I've thought about a lot of this assumed SMP-regression lately and I haven't found any connection between aspiration stuff and SMP, but this is of course this is one of the things to be tested when I get my quad back from repair...

I've scanned through the Changelog between 1.2->1.3 to find the reason for (possible) SMP-regression and the only _wild_guess_ I've got is this:

* I've heard top guys talking that when the number of CPUs grows the shared memory access can become a bottleneck (top guys talk about cachelines and other stuff I know nothing about). The way we changed QSearch TT-stuff make each thread to read/write to RAM more often than what it was in 1.2. Could it be that threads get jammed trying to access same memory segments simultaneously and being on the way of each other?

Really just a wild guess and likely to be wrong :)
I could try to test speed nodes / sec with 1 and 2 threads (I have an Intel Core 2 Duo) so to see if scaling is better when disabling TT in qsearch.

What do you think?

One thing that make me think more of a bug as a possible reason is that tests report didn't talk about speed regressions.

I would think if speed is the problem, as example due to a bottleneck in memory access, then this would have been already posted by testers, for them is easy to spot a non linear increase in node count when moving from single CPU to their beefy quads....hmmmm....