Passed Pawns (endgame)

Discussion of chess software programming and technical issues.

Moderator: Ras

lech
Posts: 1169
Joined: Sun Feb 14, 2010 10:02 pm

Re: Passed Pawns (endgame)

Post by lech »

mcostalba wrote: No, a double rear pawn is not passed, see pawns.cpp:

Code: Select all

      // In order to prevent doubled passed pawns from receiving a too big
      // bonus, only the frontmost passed pawn on each file is considered as
      // a true passed pawn.
      if (passed && (ourPawns & squares_in_front_of(Us, s)))
          passed = false;
Sorry. :oops:

Next doubts:

Code: Select all

Bitboard b = ei.pi->passed_pawns() & pos.pieces(PAWN, Us);
    while (b)
    {
        Square s = pop_1st_bit(&b);
        assert(pos.piece_on(s) == piece_of_color_and_type(Us, PAWN));
        assert(pos.pawn_is_passed(Us, s));
The following line has no sense:

Code: Select all

assert(pos.piece_on(s) == piece_of_color_and_type(Us, PAWN));

because “Bitboard b” contains only “Us” pawns.


One important question: Does “assert” abort all function (no step of loop)?
If yes:

Code: Select all

assert(pos.pawn_is_passed(Us, s));

is probably a big bug, because all “Us” pawns from “b” should be tested.
ELO >> :wink:


Ralph Stoesser wrote:
lech wrote: Is there any difference between passed pawns on relative RANK_2 or RANK_3 ?
Yes, one pawn is on rank 2, the other is on rank 3. :)

For instance

A pawn on rank 2 could possibly become blocked by enemy piece on rank 3, 4, 5, 6, 7 and 8.
A pawn on rank 3 can become blocked on rank 4, 5, 6, 7 and 8 only.

So it's not exactly the same.

(
It is unimportant trifle :lol:
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Passed Pawns (endgame)

Post by mcostalba »

Yes this:

Code: Select all

assert(pos.piece_on(s) == piece_of_color_and_type(Us, PAWN)); 
is useless so I will remove. Thanks !

Regarding assert it does not abort the function, it ends the program ;-)

http://www.cplusplus.com/reference/clib ... rt/assert/


Macro 'assert' is compiled away in release mode so that there is no assert instructions in the released SF and so no performance penalty associated with it. It is used only in debug mode to trigger in a loud way (it ends the program) any incoerence during program execution.

Normally you assert() something that must be always true for the program to be correct and if it is not true then this is a strong hint that there is a bug to be fixed somewhere.
Ralph Stoesser
Posts: 408
Joined: Sat Mar 06, 2010 9:28 am

Re: Passed Pawns (endgame)

Post by Ralph Stoesser »

mcostalba wrote:
Ralph Stoesser wrote: Is pos.attacks_from<QUEEN>(s) really that slow, that it would pay to mess up the code?
Sorry I'm too lazy to profile...:(
Yes it is....but I am not going to play 1000 games to prove it :-)
No problem, I've started a 20000 games match to prove it. 8-)
Ralph Stoesser
Posts: 408
Joined: Sat Mar 06, 2010 9:28 am

Re: Passed Pawns (endgame)

Post by Ralph Stoesser »

lech wrote:
Next doubts:

Code: Select all

Bitboard b = ei.pi->passed_pawns() & pos.pieces(PAWN, Us);
    while (b)
    {
        Square s = pop_1st_bit(&b);
        assert(pos.piece_on(s) == piece_of_color_and_type(Us, PAWN));
        assert(pos.pawn_is_passed(Us, s));
The following line has no sense:

Code: Select all

assert(pos.piece_on(s) == piece_of_color_and_type(Us, PAWN));

because “Bitboard b” contains only “Us” pawns.
It should contain only "Us" pawns. That's what's asserted.
Apparently this (and many other) assertion was inserted a long time ago with the goal to also test the basic functionality of the code.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Passed Pawns (endgame)

Post by mcostalba »

Ralph Stoesser wrote:
mcostalba wrote:
Ralph Stoesser wrote: Is pos.attacks_from<QUEEN>(s) really that slow, that it would pay to mess up the code?
Sorry I'm too lazy to profile...:(
Yes it is....but I am not going to play 1000 games to prove it :-)
No problem, I've started a 20000 games match to prove it. 8-)
Because functionality is the same I would suggest to try

./stockfish bench 128 1 12 default depth

and see directly how much is faster.

Hint: one run is not enough, you need some runs and take average speed and also you must lock the CPU frequency before to do the test (it is not important is locked to the fastest frequency, it is important that is stable) and of course no background processes and no network.

Good luck :-)
Ralph Stoesser
Posts: 408
Joined: Sat Mar 06, 2010 9:28 am

Re: Passed Pawns (endgame)

Post by Ralph Stoesser »

mcostalba wrote:
Ralph Stoesser wrote:
mcostalba wrote:
Ralph Stoesser wrote: Is pos.attacks_from<QUEEN>(s) really that slow, that it would pay to mess up the code?
Sorry I'm too lazy to profile...:(
Yes it is....but I am not going to play 1000 games to prove it :-)
No problem, I've started a 20000 games match to prove it. 8-)
Because functionality is the same I would suggest to try

./stockfish bench 128 1 12 default depth

and see directly how much is faster.

Hint: one run is not enough, you need some runs and take average speed and also you must lock the CPU frequency before to do the test (it is not important is locked to the fastest frequency, it is important that is stable) and of course no background processes and no network.

Good luck :-)
Thanks, but I think playing a match is easier and more accurate because the test also should average over real world positions with and without enemy heavy pieces behind the passed pawns.

If I look at the current test score, I would say 10000 games are enough. The prove is very near :)
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Passed Pawns (endgame)

Post by mcostalba »

Ralph Stoesser wrote:
mcostalba wrote:
Ralph Stoesser wrote:
mcostalba wrote:
Ralph Stoesser wrote: Is pos.attacks_from<QUEEN>(s) really that slow, that it would pay to mess up the code?
Sorry I'm too lazy to profile...:(
Yes it is....but I am not going to play 1000 games to prove it :-)
No problem, I've started a 20000 games match to prove it. 8-)
Because functionality is the same I would suggest to try

./stockfish bench 128 1 12 default depth

and see directly how much is faster.

Hint: one run is not enough, you need some runs and take average speed and also you must lock the CPU frequency before to do the test (it is not important is locked to the fastest frequency, it is important that is stable) and of course no background processes and no network.

Good luck :-)
Thanks, but I think playing a match is easier and more accurate because the test also should average over real world positions with and without enemy heavy pieces behind the passed pawns.

If I look at the current test score, I would say 10000 games are enough. The prove is very near :)
I think the only way to measure is through direct speed measurement otherwise you lose the signal in the noise. Admittely the speed up is small, you need a profiler to check it or a direct speed measure as indicated above.

It is true that you don't test on all the possible positions, but the above tests scans millions of differnt nodes, tens of milions indeed, so the difference is accurate anyhow.
Ralph Stoesser
Posts: 408
Joined: Sat Mar 06, 2010 9:28 am

Re: Passed Pawns (endgame)

Post by Ralph Stoesser »

mcostalba wrote:
Ralph Stoesser wrote:
mcostalba wrote:
Ralph Stoesser wrote:
mcostalba wrote:
Ralph Stoesser wrote: Is pos.attacks_from<QUEEN>(s) really that slow, that it would pay to mess up the code?
Sorry I'm too lazy to profile...:(
Yes it is....but I am not going to play 1000 games to prove it :-)
No problem, I've started a 20000 games match to prove it. 8-)
Because functionality is the same I would suggest to try

./stockfish bench 128 1 12 default depth

and see directly how much is faster.

Hint: one run is not enough, you need some runs and take average speed and also you must lock the CPU frequency before to do the test (it is not important is locked to the fastest frequency, it is important that is stable) and of course no background processes and no network.

Good luck :-)
Thanks, but I think playing a match is easier and more accurate because the test also should average over real world positions with and without enemy heavy pieces behind the passed pawns.

If I look at the current test score, I would say 10000 games are enough. The prove is very near :)
I think the only way to measure is through direct speed measurement otherwise you lose the signal in the noise. .
[..]
Not in this case. It's pretty clear that it's a *very good* idea to mess up the code with this tweak.

In the beginning I hated testing, but now I love my 1 sec tests. :-)
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Passed Pawns (endgame)

Post by mcostalba »

Ralph Stoesser wrote: In the beginning I hated testing, but now I love my 1 sec tests. :-)
In case you have nothing better to do I would give you a little homework :-)

Please no offence, it is something on my TODO list and I never did before beause I think the speed up is very small if any, but on this things you never know. It requires also a good code style attitude because that part is one of my favorites and I consider it very cleanly implemented.

I am talking of move generation.

Currently I have templetized move generation on piece type, but not on color, becasue the saving is just in avoiding an indirect access for each piece type loop but, on the bad side, it doubles the number of instantiated fuctions, so result is far from being a clear speed up.

Anyhow I am talking of this:

Code: Select all

--- a/src/movegen.cpp
+++ b/src/movegen.cpp
 
 namespace {
 
-  template<PieceType Piece>
-  MoveStack* generate_piece_moves(const Position& pos, MoveStack* mlist, Color us, Bitboard target) {
+  template<Color Us, PieceType Piece>
+  MoveStack* generate_piece_moves(const Position& pos, MoveStack* mlist, Bitboard target) {
 
     Bitboard b;
     Square from;
-    const Square* ptr = pos.piece_list_begin(us, Piece);
+    const Square* ptr = pos.piece_list_begin(Us, Piece);
 
     while ((from = *ptr++) != SQ_NONE)
     {

Here the only advantage is that:

Code: Select all

const Square* ptr = pos.piece_list_begin(Us, Piece);
is resolved at compile time instead of runtime. I really don't know if it is worth the trouble...

BTW there _seems_ to be an advantage also in reducing the number of calling arguments, but when PGO compiled by Intel compiler these little functions are inlined anyway, so at the end it is not a real advantage. Of course speed comparison should be done on a PGO version ;-)
Ralph Stoesser
Posts: 408
Joined: Sat Mar 06, 2010 9:28 am

Re: Passed Pawns (endgame)

Post by Ralph Stoesser »

mcostalba wrote:
Ralph Stoesser wrote: In the beginning I hated testing, but now I love my 1 sec tests. :-)
In case you have nothing better to do I would give you a little homework :-)

Please no offence, it is something on my TODO list and I never did before beause I think the speed up is very small if any, but on this things you never know. It requires also a good code style attitude because that part is one of my favorites and I consider it very cleanly implemented.

I am talking of move generation.

Currently I have templetized move generation on piece type, but not on color, becasue the saving is just in avoiding an indirect access for each piece type loop but, on the bad side, it doubles the number of instantiated fuctions, so result is far from being a clear speed up.

Anyhow I am talking of this:

Code: Select all

--- a/src/movegen.cpp
+++ b/src/movegen.cpp
 
 namespace {
 
-  template<PieceType Piece>
-  MoveStack* generate_piece_moves(const Position& pos, MoveStack* mlist, Color us, Bitboard target) {
+  template<Color Us, PieceType Piece>
+  MoveStack* generate_piece_moves(const Position& pos, MoveStack* mlist, Bitboard target) {
 
     Bitboard b;
     Square from;
-    const Square* ptr = pos.piece_list_begin(us, Piece);
+    const Square* ptr = pos.piece_list_begin(Us, Piece);
 
     while ((from = *ptr++) != SQ_NONE)
     {

Here the only advantage is that:

Code: Select all

const Square* ptr = pos.piece_list_begin(Us, Piece);
is resolved at compile time instead of runtime. I really don't know if it is worth the trouble...

BTW there _seems_ to be an advantage also in reducing the number of calling arguments, but when PGO compiled by Intel compiler these little functions are inlined anyway, so at the end it is not a real advantage. Of course speed comparison should be done on a PGO version ;-)
Ok, I will test it.

BTW: This PGO Makefile does not work for me. I have to add the compiler flag "-Wcoverage-mismatch" in the gcc-profile-use section to avoid error: "corrupted profile info: profile data is not flow-consistent". (g++ 4.4.3, Linux Ubuntu 10.04 LTS 64bit)