Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: NPS counting and other assorted stuff..

Author: Dan Newman

Date: 15:45:17 11/30/00

Go up one level in this thread


On November 28, 2000 at 16:32:15, David Rasmussen wrote:

>I know we can't probably agree on a way to define nps that works for all
>programs, but couldn't we at least state some of the most common ways that
>people do it that are wrong?
>Maybe we should expand this a bit, and make this thread a "common mistakes in
>chessprogramming" thread. To know other peoples mistakes would be very valuable
>when writing a program yourself. I'm talking about any kind of error here, from
>the positively wrong (like not correcting for ply when storing a matescore in
>the hashtable which was an error I made when I had just added hashtables) to the
>not-so-smart things that people tend to do, like having one-ply extensions on
>everything with no bound so your search explodes.
>Coming back to nps, the biggest mistake I made was very simple, but I
>incremented my nodes counter before I went into queiscence and then incremented
>it again in the beginning of quiescence, with a ego-boosting nps as a result...
>:) When I removed that error, my nps dropped to a lowly 120 knps on a PII450
>instead of 300 knps :(
>
>Discuss amongst yourselves now.

1) Minor "mistake".  If you generate your random number table for hashcodes
using a simple 32-bit LCG based random number generator and simply fill in
the 64-bit table entries with pairs of sequential calls to that RN generator,
then you will be (effectively) getting less than 64-bit numbers.  There will
be a definite pattern to the low order bits of the 32-bit random numbers.
The lowest order bit in fact simply toggles 0 1 0 1 0 1 0 1 as the RN's are
produced.  The next bit might do something like 0 1 1 0 1 0 0 1, and so on.
What this means is that the 0th bit and the 32nd bit of the 64-bit random
numbers will be perfectly anti-correlated, and the 1st and 33rd somewhat or
completely correlated or anti-correlated, and so on.  You will get numbers
that work, but only as well as (at a guess) 62-bit numbers that are really
random.  The solution is to run the random numbers through something to
select a better set, or to use a better generator...

2) Watch out for bitwise operator precedence.  I had a bug once that took me
hours to find.  I looked directly at it numerous times, but still didn't see
it.  It looked something like this:

    if( flags & IN_CHECK == DOUBLE_CHECK ) { ... }

The trouble is the == operator goes before the &, and it ends up testing
the first bit (or perhaps no bit, depending on whether the two arguments
of the == operator are equal or not)...

3) I used to have the occasional mysterious error that resulted in long
debugging sessions that ended only when I discovered that it was just a
stack overflow.  I haven't had any of these recently.  I used to compile
for extended DOS, but now I do Windows console mode compiles.  I suspect
that for Windows programs the stack doesn't have a fixed limit.

4) I once had a long undiagnosed bug in my hash table.  I stuffed a number
of different items into a 32-bit integer in the hash table entry struct.
In a simplified form I did something like this:

    entry.misc = score | (draft << 16);

since both the score and draft would fit inside 16 bit ints.

The trouble is the score was a signed integer, and when negative the upper
16 bits were all ones...  I fixed this by adding an offset to the score
before stuffing so that the upper 16 bits were all zeros:

    entry.misc = (score+32768) | (draft << 16);

and subtracting the offset when extracting the score.

5) In one chess engine (not the current one) I neglected to realize that
a castling move could give check--I think I was doing something really
"clever" to save cpu cycles in in-check detection and just didn't consider
this possibility.  I finally noticed when an opponent engine gave mate with
O-O-O...

6) Make sure the engine always has a valid move before it makes its move.
At one point my first chess engine would always crash when it became clear
that I was about to beat it.  I'd get within a few moves of delivering mate
and *crash*.  It was almost as if it was sweeping the pieces from the board
in anger.  The way I'd written the search code, it ended up with a null
pointer to the move when all the moves gave the mated score...  This sort
of thing could still happen if you allow the engine to abort before the
best move gets set.  This could happen in an extremely fast game or in
some unusual position that really blows up the qsearch so that it takes a
long time to get the first move searched in the first iteration.  To prevent
this I disable aborts on time until I get a move.

That's all I can think of right now...

-Dan.



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.