eval pieces

Discussion of chess software programming and technical issues.

Moderators: bob, hgm, Harvey Williamson

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
Daniel Anulliero
Posts: 688
Joined: Fri Jan 04, 2013 3:55 pm
Location: Nice

eval pieces

Post by Daniel Anulliero » Mon Jun 15, 2015 6:39 pm

I read somewhere (can't remember where exactly) It's better to have in our eval () separate functions for white and black

Code: Select all

For exemple:
eval_white_pawn ()
Eval_black_pawn ()
eval_white_knight ()
eval_black_knight ()
And so on...
Instead of :

Code: Select all

eval_pawn ()
eval_knight ()
If it's better can you explain why?
Bests
Dany

bob
Posts: 20555
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: eval pieces

Post by bob » Mon Jun 15, 2015 7:12 pm

Daniel Anulliero wrote:I read somewhere (can't remember where exactly) It's better to have in our eval () separate functions for white and black

Code: Select all

For exemple:
eval_white_pawn ()
Eval_black_pawn ()
eval_white_knight ()
eval_black_knight ()
And so on...
Instead of :

Code: Select all

eval_pawn ()
eval_knight ()
If it's better can you explain why?
Bests
Dany
Not sure why it would be good. You might eliminate a few branches by doing that, but you double the cache footprint. My program gained speed when I got rid of all the duplicated code for black and white. I don't have any, now.

Daniel Anulliero
Posts: 688
Joined: Fri Jan 04, 2013 3:55 pm
Location: Nice

Re: eval pieces

Post by Daniel Anulliero » Mon Jun 15, 2015 8:05 pm

bob wrote:
Daniel Anulliero wrote:I read somewhere (can't remember where exactly) It's better to have in our eval () separate functions for white and black

Code: Select all

For exemple:
eval_white_pawn ()
Eval_black_pawn ()
eval_white_knight ()
eval_black_knight ()
And so on...
Instead of :

Code: Select all

eval_pawn ()
eval_knight ()
If it's better can you explain why?
Bests
Dany
Not sure why it would be good. You might eliminate a few branches by doing that, but you double the cache footprint. My program gained speed when I got rid of all the duplicated code for black and white. I don't have any, now.
iirc , it was marco costalba who recommended (somewhere in the forum) to make like that
Anyway , thanks for the answer !

jdart
Posts: 3824
Joined: Fri Mar 10, 2006 4:23 am
Location: http://www.arasanchess.org

Re: eval pieces

Post by jdart » Mon Jun 15, 2015 8:05 pm

It is less error-prone to have one set of code.

If you use C++ templates as Stockfish does, and use the side as the template argument, then the compiler (usually) will generate two functions, one for each side. If you have conditional code for Black/White in the function the unused branches will get optimized out. So this is a way to get the benefits of separate functions (performance-wise) while still consolidating most of the code in one place.

--Jon

User avatar
hgm
Posts: 23718
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: eval pieces

Post by hgm » Mon Jun 15, 2015 8:23 pm

In my experience efficient cache usage is the all-important factor in optimizing code. So I would never duplicate code just to safe a couple of branches.

Besides, I hardly ever need branches. If you have an stm variable that has value 0 or 1 (say), you can use (2*stm-1) to generate a factor +/-1 with which you can multiply an evaluation that you coded for the white point-of-view, or use it as an extra index to the piece list to acces black or white pieces, or calculate 16*stm-8 to generate a step in the forward direction, etc.

bob
Posts: 20555
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: eval pieces

Post by bob » Mon Jun 15, 2015 10:08 pm

Daniel Anulliero wrote:
bob wrote:
Daniel Anulliero wrote:I read somewhere (can't remember where exactly) It's better to have in our eval () separate functions for white and black

Code: Select all

For exemple:
eval_white_pawn ()
Eval_black_pawn ()
eval_white_knight ()
eval_black_knight ()
And so on...
Instead of :

Code: Select all

eval_pawn ()
eval_knight ()
If it's better can you explain why?
Bests
Dany
Not sure why it would be good. You might eliminate a few branches by doing that, but you double the cache footprint. My program gained speed when I got rid of all the duplicated code for black and white. I don't have any, now.
iirc , it was marco costalba who recommended (somewhere in the forum) to make like that
Anyway , thanks for the answer !
I think they do some of this via templates. You should test it, but I found one copy was faster than two. More cache friendly + only half as much code to read from memory into cache when you need it and it is not there.

bob
Posts: 20555
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: eval pieces

Post by bob » Mon Jun 15, 2015 10:20 pm

hgm wrote:In my experience efficient cache usage is the all-important factor in optimizing code. So I would never duplicate code just to safe a couple of branches.

Besides, I hardly ever need branches. If you have an stm variable that has value 0 or 1 (say), you can use (2*stm-1) to generate a factor +/-1 with which you can multiply an evaluation that you coded for the white point-of-view, or use it as an extra index to the piece list to acces black or white pieces, or calculate 16*stm-8 to generate a step in the forward direction, etc.
I think worrying about branches today is pointless. In the evaluation, all the if (stm) branches will be correctly predicted by the correlated part of the branch predictor hardware. It will notice that there are "sets" of branches that all go the same way, and after the first few it will "get 'em all" every time anyway. I agree with you about cache. Doubling code is halving cache.

User avatar
lucasart
Posts: 3040
Joined: Mon May 31, 2010 11:29 am
Full name: lucasart
Contact:

Re: eval pieces

Post by lucasart » Tue Jun 16, 2015 10:37 pm

Daniel Anulliero wrote:I read somewhere (can't remember where exactly) It's better to have in our eval () separate functions for white and black

Code: Select all

For exemple:
eval_white_pawn ()
Eval_black_pawn ()
eval_white_knight ()
eval_black_knight ()
And so on...
Instead of :

Code: Select all

eval_pawn ()
eval_knight ()
If it's better can you explain why?
Bests
Dany
In my experience there's no yes/no answer in general to that question. It's not that clear cut, so don't listen to Bob and HGM's hand waving arguments about cache efficiency and branch-prediction.
=> Measure it yourself.

Sometimes the increased cache pressure is overkill, sometimes the saved branches are what matters. It's not obvious just by looking at the code. I've found some of Stockfish's templatizations to be useless and even counter-productive, but many of them are still beneficial.
  • In C++ it's pretty trivial to experiment. First write the code with a function parameter, then make that a template argument, and do some speed test of both versions (verify first that they are functionally equal, obviously).
  • In C you can do that with some ugly recursive inclusion and macros (see Robbolito).
  • But one thing you should NEVER do is duplicate code explicitely. It's a recipie for disaster and unmaintainable code (so easy to modify one without the other and endup with subtle asymmetric bugs).
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.

bob
Posts: 20555
Joined: Mon Feb 27, 2006 6:30 pm
Location: Birmingham, AL

Re: eval pieces

Post by bob » Wed Jun 17, 2015 3:12 am

lucasart wrote:
Daniel Anulliero wrote:I read somewhere (can't remember where exactly) It's better to have in our eval () separate functions for white and black

Code: Select all

For exemple:
eval_white_pawn ()
Eval_black_pawn ()
eval_white_knight ()
eval_black_knight ()
And so on...
Instead of :

Code: Select all

eval_pawn ()
eval_knight ()
If it's better can you explain why?
Bests
Dany
In my experience there's no yes/no answer in general to that question. It's not that clear cut, so don't listen to Bob and HGM's hand waving arguments about cache efficiency and branch-prediction.
=> Measure it yourself.

Sometimes the increased cache pressure is overkill, sometimes the saved branches are what matters. It's not obvious just by looking at the code. I've found some of Stockfish's templatizations to be useless and even counter-productive, but many of them are still beneficial.
  • In C++ it's pretty trivial to experiment. First write the code with a function parameter, then make that a template argument, and do some speed test of both versions (verify first that they are functionally equal, obviously).
  • In C you can do that with some ugly recursive inclusion and macros (see Robbolito).
  • But one thing you should NEVER do is duplicate code explicitely. It's a recipie for disaster and unmaintainable code (so easy to modify one without the other and endup with subtle asymmetric bugs).
I can guarantee you that the if (wtm) type branches will be predicted perfectly after the first 10 are handled. So they are completely irrelevant. All that is left is cache issues. You should avoid topics you don't understand, just because you like to get in a personal dig here and there for unknown reasons.

If you look at the OP, it was about duplicated code for black and white. That is simply a bad idea for the very reasons HGM and I gave, regardless of your nonsensical comments to the contrary.

Many of us here have done this stuff enough that we don't give pointless advice. You should try that yourself.

User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 6:43 pm

Re: eval pieces

Post by sje » Wed Jun 17, 2015 6:11 am

The best way is to use a single routine for both colors; this will likely be faster, will certainly be easier to maintain, and will be less likely to attract bugs.

Symbolic doesn't have a side-to-move color variable stm. Instead, it has the color-on-the-move good and the color-not-on-the-move evil. I had thought about using the identifiers angel and demon.

Post Reply