A perft faster than qperft?!

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Allard Siemelink
Posts: 297
Joined: Fri Jun 30, 2006 9:30 pm
Location: Netherlands

Re: A perft faster than qperft?!

Post by Allard Siemelink »

Very close indeed. Did you also recompile i-perft?
tvrzsky wrote:This is on Pentium Dual Core E2140 overclocked to 2.4 GHz, qperft compiled in Microsoft Visual C++ 2005 Express Edition:

Code: Select all

Quick Perft by H.G. Muller
perft(7)=          3195901860 (31.344 sec)
i-perft 1.0 (c) 2006-2008 AJ Siemelink
perft 7   3195901860    30.16s  106.0 mnps   22.7 ticks/op

qperft.exe 6 "r3r1k1/1pq2pp1/2p2n2/1PNn4/2QN2b1/6P1/3RPP2/2R3KB b - -"
Quick Perft by H.G. Muller
perft(6)=         15097513050 (102.515 sec)
i-perft 1.0 (c) 2006-2008 AJ Siemelink
perft 6  15097513050    95.16s  158.7 mnps   15.2 ticks/op
Allard Siemelink
Posts: 297
Joined: Fri Jun 30, 2006 9:30 pm
Location: Netherlands

Re: A perft faster than qperft?!

Post by Allard Siemelink »

It is basically the same move generator that I talked about before .
The bulk counting was a recent addition, for which I had to implement full legal move generation as well.
It uses a 16x16 mailbox board containing indexes into a 3x64 piecelist;
checks are detected by looking at the last move made.
For exact details you could take a look at the source code, it should be quite readable.
hgm wrote:So they get very close indeed. I seem to remember Allard told me that his move generator was very close to the mailbox (16x12) I use in qperft. Is that tstill the same move generator as is used in i-perft?

I have no idea why it performs so relatively poorly on Opteron. Might have to do with an unfortunate layout of the global data, and the small number of cache ways on AMD machines.
tvrzsky
Posts: 128
Joined: Sat Sep 23, 2006 7:10 pm
Location: Prague

Re: A perft faster than qperft?!

Post by tvrzsky »

Allard Siemelink wrote:Very close indeed. Did you also recompile i-perft?
tvrzsky wrote:This is on Pentium Dual Core E2140 overclocked to 2.4 GHz, qperft compiled in Microsoft Visual C++ 2005 Express Edition:

Code: Select all

Quick Perft by H.G. Muller
perft(7)=          3195901860 (31.344 sec)
i-perft 1.0 (c) 2006-2008 AJ Siemelink
perft 7   3195901860    30.16s  106.0 mnps   22.7 ticks/op

qperft.exe 6 "r3r1k1/1pq2pp1/2p2n2/1PNn4/2QN2b1/6P1/3RPP2/2R3KB b - -"
Quick Perft by H.G. Muller
perft(6)=         15097513050 (102.515 sec)
i-perft 1.0 (c) 2006-2008 AJ Siemelink
perft 6  15097513050    95.16s  158.7 mnps   15.2 ticks/op
No, I did not initially, so here is the recompiled version (you can see some improvement as well):

Code: Select all

i-perft 1.0 (c) 2006-2008 AJ Siemelink

perft 1           20     0.00s    1.$ mnps 7664.4 ticks/op
perft 2          400     0.00s    1.$ mnps   84.3 ticks/op
perft 3         8902     0.00s    1.$ mnps   24.8 ticks/op
perft 4       197281     0.00s    1.$ mnps   23.9 ticks/op
perft 5      4865609     0.05s  103.5 mnps   22.5 ticks/op
perft 6    119060324     1.17s  101.6 mnps   23.4 ticks/op
perft 7   3195901860    29.67s  107.7 mnps   22.3 ticks/op


iperft.exe 6 "r3r1k1/1pq2pp1/2p2n2/1PNn4/2QN2b1/6P1/3RPP2/2R3KB b - -"

perft 1           56     0.00s    1.$ mnps 2527.7 ticks/op
perft 2         2594     0.00s    1.$ mnps   31.7 ticks/op
perft 3       137198     0.00s    1.$ mnps   13.8 ticks/op
perft 4      6391735     0.03s  206.2 mnps   13.5 ticks/op
perft 5    323787902     1.84s  175.6 mnps   13.6 ticks/op
perft 6  15097513050    85.69s  176.2 mnps   13.7 ticks/op
Boogiwoogie

Re: A perft faster than qperft?!

Post by Boogiwoogie »

Hi there! Another newbie is entering the competition... ;)
For a quick start I am looking for a move generator. The i-perft compiles nicely on my machine, and regarding speed it seems to be a piece of code that I won't be able to beat.
Does it actually generate legal moves only? I had a look at the code and found the inner loop of the perft function:

Code: Select all

    for &#40;Move *m=moves; m<m2; m++) &#123;
        if (!&#40;last=do_move&#40;*m&#41;)) continue;
        if &#40;depth>1&#41; n += perft&#40;depth-1, last&#41;;
        else n++;
        undo_move&#40;*m&#41;;
        _castling = castling;
    &#125;
Now my question is, whether I can replace the second line by

Code: Select all

do_move&#40;*m&#41;;
or not. If all the generated moves are legal anyway, it should be save to just make them without looking at the result. I tried it, and the -verify test gave me a nice little assertion failure. No matter if compiled with

Code: Select all

#define GEN_LEGAL  0
or with

Code: Select all

#define GEN_LEGAL  1
or the bulk count switch set to 0 or 1. Are the generated moves pseudo legal or did I miss something important?

Hello from Germany
[/code]
Allard Siemelink
Posts: 297
Joined: Fri Jun 30, 2006 9:30 pm
Location: Netherlands

Re: A perft faster than qperft?!

Post by Allard Siemelink »

Boogiwoogie wrote:Hi there! Another newbie is entering the competition... ;)
For a quick start I am looking for a move generator. The i-perft compiles nicely on my machine, and regarding speed it seems to be a piece of code that I won't be able to beat.
Does it actually generate legal moves only? I had a look at the code and found the inner loop of the perft function:

Code: Select all

    for &#40;Move *m=moves; m<m2; m++) &#123;
        if (!&#40;last=do_move&#40;*m&#41;)) continue;
        if &#40;depth>1&#41; n += perft&#40;depth-1, last&#41;;
        else n++;
        undo_move&#40;*m&#41;;
        _castling = castling;
    &#125;
Now my question is, whether I can replace the second line by

Code: Select all

do_move&#40;*m&#41;;
or not. If all the generated moves are legal anyway, it should be save to just make them without looking at the result. I tried it, and the -verify test gave me a nice little assertion failure. No matter if compiled with

Code: Select all

#define GEN_LEGAL  0
or with

Code: Select all

#define GEN_LEGAL  1
or the bulk count switch set to 0 or 1. Are the generated moves pseudo legal or did I miss something important?

Hello from Germany
[/code]
If GEN_LEGAL==1, i-perft should only generate legal moves. And you should be able to skip the test, as do_move() will never return 0 in that case.

Perhaps you forgot to supply the correct 'last' move in the next line, e.g. (untested):

Code: Select all

     do_move&#40;*m&#41;; 
     if &#40;depth>1&#41; n += perft&#40;depth-1, *m&#41;; 
I doubt this will be any faster than the original though: if bulk counting
is enabled, this would only save a single test for all the non leaf nodes (3% or so).
Boogiwoogie

Re: A perft faster than qperft?!

Post by Boogiwoogie »

Hi again!

Code: Select all

		last=do_move&#40;*m&#41;;
        if &#40;depth>1&#41; n += perft&#40;depth-1, last&#41;;
does the trick. Thank you for quick answer!

Christian
User avatar
jshriver
Posts: 1342
Joined: Wed Mar 08, 2006 9:41 pm
Location: Morgantown, WV, USA

Re: A perft faster than qperft?!

Post by jshriver »

What functions do you use that are in windows.h?

Would like to see a linux gcc port.
-Josh
Allard Siemelink
Posts: 297
Joined: Fri Jun 30, 2006 9:30 pm
Location: Netherlands

Re: A perft faster than qperft?!

Post by Allard Siemelink »

jshriver wrote:What functions do you use that are in windows.h?

Would like to see a linux gcc port.
-Josh
I think you should be able to get it running on Linux pretty easily
as I think the only windows call is a single getTickCount() in Timer.h
User avatar
smrf
Posts: 484
Joined: Mon Mar 13, 2006 11:08 am
Location: Klein-Gerau, Germany

Re: A perft faster than qperft?!

Post by smrf »

Comparing perft results between legel move only generators and pseudolegal move generators mostly would be misleading. To make both aproaches comparable there also other move properties should be distinguished and counted as well. So I did with my old SMIRF (legal only) approach (which is about to be rewritten completely now).

Code: Select all

  +-*--b--c--d--*--f--g--*-+ MS Vis.Studio C++ 32-Bit-Vers. 14.00
8 |&#91;r&#93;&#91;n&#93;&#91;b&#93;&#91;q&#93;&#91;k&#93;&#91;b&#93;&#91;n&#93;&#91;r&#93;| &#40;Compilation&#58; Aug 31 2008&#41;
7 |&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;|
6 |   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;| Perft Testseries
5 |&#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   | &#40;with TT caching +256.0 MB / 4-fold&#41;
4 |   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;| TT Access Success +53.0%
3 |&#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   |
2 |<P><P><P><P><P><P><P><P>| Smirf Test No.&#58;  0
1 |<R><N><B><Q><K><B><N><R>|
=>+-*--b--c--d--*--f--g--*-+ Break Time&#58; +10.00 Sec.

Ply      Nodes     all &#40;x&#41;     &#40;ep&#41;    all (+)      (#)  Prom.    Cstl.    Sec.
-------------------------------------------------------------------------------
1           20           0        0          0        0      0        0       0
2          400           0        0          0        0      0        0       0
3         8902          34        0         12        0      0        0       0
4       197281        1576        0        469        8      0        0   0.007
5      4865609       82719      258      27351      347      0        0   0.093
6    119060324     2812008     5248     809099    10828      0        0   1.258
7   3195901860   108329926   319617   33103848   435767      0   883453   15.05
-------------------------------------------------------------------------------

Code: Select all

FEN&#58; rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

  +-*--b--c--d--*--f--g--*-+ MS Vis.Studio C++ 32-Bit-Vers. 14.00
8 |&#91;r&#93;&#91;n&#93;&#91;b&#93;&#91;q&#93;&#91;k&#93;&#91;b&#93;&#91;n&#93;&#91;r&#93;| &#40;Compilation&#58; Aug 31 2008&#41;
7 |&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;&#91;p&#93;|
6 |   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;| Perft Testseries
5 |&#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   |
4 |   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;| &#40;without caching&#41;
3 |&#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   &#58;&#58;&#58;   |
2 |<P><P><P><P><P><P><P><P>| Smirf Test No.&#58;  0
1 |<R><N><B><Q><K><B><N><R>|
=>+-*--b--c--d--*--f--g--*-+ Break Time&#58; +20.00 Sec.

Ply      Nodes     all &#40;x&#41;     &#40;ep&#41;    all (+)      (#)  Prom.    Cstl.    Sec.
-------------------------------------------------------------------------------
1           20           0        0          0        0      0        0       0
2          400           0        0          0        0      0        0       0
3         8902          34        0         12        0      0        0       0
4       197281        1576        0        469        8      0        0   0.007
5      4865609       82719      258      27351      347      0        0   0.184
6    119060324     2812008     5248     809099    10828      0        0   4.638
7   3195901860   108329926   319617   33103848   435767      0   883453   122.2
-------------------------------------------------------------------------------