Which perft result is correct (and why)?

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

sluijten
Posts: 44
Joined: Wed Apr 13, 2011 12:43 pm

Re: Which perft result is correct (and why)?

Post by sluijten »

OK, it's clear now how perft is supposed to count the different types of moves.

Another test I do is to check consistency of the board structure after every (un)makemove, it is a simple call added at the end of (un)makemove, checking
- the board[64]-array versus bitboards
- white occupied bitboard vs white pieces bitboards
- black occupied bitboard vs black pieces bitboards
- total occupied bitboards versus white and black occupied bitboards
- incrementally calculated scoring values
- and more if your board struct has more variables
If an inconsistency is found, I display all the moves leading to it, so I can manually reproduce to bug. This (together with perft) greatly helped me debugging the movegenerator and (un)makemove.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Which perft result is correct (and why)?

Post by bob »

sluijten wrote:OK, it's clear now how perft is supposed to count the different types of moves.

Another test I do is to check consistency of the board structure after every (un)makemove, it is a simple call added at the end of (un)makemove, checking
- the board[64]-array versus bitboards
- white occupied bitboard vs white pieces bitboards
- black occupied bitboard vs black pieces bitboards
- total occupied bitboards versus white and black occupied bitboards
- incrementally calculated scoring values
- and more if your board struct has more variables
If an inconsistency is found, I display all the moves leading to it, so I can manually reproduce to bug. This (together with perft) greatly helped me debugging the movegenerator and (un)makemove.
I have a similar mechanism I enable with -DDEBUG, so that throughout the search, each time a move is made or unmade, the bitboards, hash signatures, material counts, etc are all checked for correctness. Helps find bugs right after a significant change...
zamar
Posts: 613
Joined: Sun Jan 18, 2009 7:03 am

Re: Which perft result is correct (and why)?

Post by zamar »

bob wrote:I know. My point was that several things I have done have become "cast in stone" even if they are sub-optimal.
But that's an honour. You are the pioneer who has actually defined the standards which others have followed.
Joona Kiiski
elcabesa
Posts: 855
Joined: Sun May 23, 2010 1:32 pm

Re: Which perft result is correct (and why)?

Post by elcabesa »

hi,

I used another one method to minimise makemove/unmakemove error the move generation.

probably my method is not the fastest ( i don't know).

Each position need not too much byte to be reapresented, so I have an array of position, when i start searching i start from array[0] and and every time i do makemove i write on array[i+1], unmake move is simply, go to the index i-1;
i doesn't do unmakemove.

i don't know if this is slowlier due to mem copying. but this eliminate unmakemove.

is this a good idea?
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: Which perft result is correct (and why)?

Post by Evert »

elcabesa wrote: Each position need not too much byte to be reapresented, so I have an array of position, when i start searching i start from array[0] and and every time i do makemove i write on array[i+1], unmake move is simply, go to the index i-1;
i doesn't do unmakemove.

i don't know if this is slowlier due to mem copying. but this eliminate unmakemove.

is this a good idea?
I do that in Jazz, but not in Sjaak. It works and performance-wise it's not horrible (it doesn't seem to make much difference from what I can tell). I haven't thought a great deal about doing a parallel search, but I think it would complicate things there. Although I do use it at the moment, I think I probably will get rid of it at some point.
A possible issue is not so much that copying the board is expensive but that having the extra variables puts more pressure on the processor cache. I have no way of testing whether that's an issue though, but I think others have tested this.
There are a few other drawbacks. For one thing you do have to make sure that the board representation is as compact as you can reasonably get away with, so that means you can't store some things that you might like to store. One example is an array, indexed by square, that gives you the piece type (assuming that's not your native board representation): it's simply too slow to copy that over on every make_move.

Bottom line: the idea is not terrible, it does work, and it won't be the main thing that's holding you back at the moment even if it is suboptimal.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Which perft result is correct (and why)?

Post by bob »

zamar wrote:
bob wrote:I know. My point was that several things I have done have become "cast in stone" even if they are sub-optimal.
But that's an honour. You are the pioneer who has actually defined the standards which others have followed.
The problem is, for some things, I did not intend to "define a standard." I was just cobbling together something to help me debug something. In the case of perft, it was the new (at the time) GenerateCheckEvasions() where I missed one really obscure case where an enpassant pawn capture could get the king out of check. Crafty lost a couple of games on ICC due to that, and one of my IM friends at the time sent me a message. In trying to figure it out, perft was born, as I "checked" every call to GenerateCheckEvasions() by calling the normal move generator and then culling illegal positions. When I did this, I found an extra EP capture that the new code failed to produce.

If I had been intending on defining a standard, I would almost certainly have counted interior nodes as well. In my case, I had perft just dump the trees where I could sort, diff, and find exactly where something was wrong and it didn't take much time.
sluijten
Posts: 44
Joined: Wed Apr 13, 2011 12:43 pm

Re: Which perft result is correct (and why)?

Post by sluijten »

bob wrote:(...) and even mis-used (some use perft as a speed measure and try to optimize the fool out of it, when it was intended to help find subtle move generator or make/unmake issues only...)
Well, I wouldn't call this a misuse.
Perft happens to also be a good speed metric to compare different implementations of the 'backbone': move generation, move storing and (un)making (excluding search/evaluation).
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Which perft result is correct (and why)?

Post by bob »

sluijten wrote:
bob wrote:(...) and even mis-used (some use perft as a speed measure and try to optimize the fool out of it, when it was intended to help find subtle move generator or make/unmake issues only...)
Well, I wouldn't call this a misuse.
Perft happens to also be a good speed metric to compare different implementations of the 'backbone': move generation, move storing and (un)making (excluding search/evaluation).
Problem is, that is a small percentage of total time and won't tell you a thing about the NPS the engine will actually search...

Sort of taking a motor out of a car, and tweaking it until it will turn 20,000 RPM. No torque until 12,000 RPM, so it is useless for any type of car. But it will definitely spin...
sluijten
Posts: 44
Joined: Wed Apr 13, 2011 12:43 pm

Re: Which perft result is correct (and why)?

Post by sluijten »

bob wrote:Problem is, that is a small percentage of total time and won't tell you a thing about the NPS the engine will actually search...

Sort of taking a motor out of a car, and tweaking it until it will turn 20,000 RPM. No torque until 12,000 RPM, so it is useless for any type of car. But it will definitely spin...
That's true for a well-written move generator+(un)makemove. If I see a perft speed of less than, say 5x the knod/s of the total speed, then I know I need to improve the move generator and/or (un)makemove, because they consume ~20% of the time.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Which perft result is correct (and why)?

Post by bob »

sluijten wrote:
bob wrote:Problem is, that is a small percentage of total time and won't tell you a thing about the NPS the engine will actually search...

Sort of taking a motor out of a car, and tweaking it until it will turn 20,000 RPM. No torque until 12,000 RPM, so it is useless for any type of car. But it will definitely spin...
That's true for a well-written move generator+(un)makemove. If I see a perft speed of less than, say 5x the knod/s of the total speed, then I know I need to improve the move generator and/or (un)makemove, because they consume ~20% of the time.
Here's my numbers:

perft 7 from starting position: total moves=119060324 time=5.44

about 22M nodes per second. Yet the search from that same position:

time=10.06 mat=0 n=22718658 fh=90% nps=2.3M

So my Make/Unmake/Movegen is 10% of total time...

Not particularly significant to make that a lot faster...