The evaluation is not very good because I tried to focus more on the search. I didn't actually optimize the evaluation at all. I just wrote something as small as I could with the most essential features. If you want to improve it, you will most likely have to rewrite the evaluation completely. Rodent is a good example of how to do this.ZirconiumX wrote:I've been tuning my PST array in Durandal (based on Sungorus 1.4) - and CLOP has given me some absurd values - and part of me says to ignore the values because the Sungorus eval was $*%# and needs replacing.
For your entertainment - find a copy of Sungorus 1.4 read through the PST init code and replace the values of line[] with this:Yes, those were the values that I was given by CLOP. I really think I should redo the search and eval to my liking - the Sungorus author has forgotten the rule of 'Premature optimization is the root of all evil'.Code: Select all
{ 0, 46, 2076, 2595, 2890, 2312, 320, 0 }
Matthew:out
[Entertainment] When tuning goes wrong...
Moderators: hgm, Dann Corbit, Harvey Williamson
-
Pablo Vazquez
- Posts: 154
- Joined: Thu May 31, 2007 9:05 pm
- Location: Madrid, Spain
Re: [Entertainment] When tuning goes wrong...
-
mar
- Posts: 2552
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: [Entertainment] When tuning goes wrong...
Hi Ron, that's an interesting remark and an elegant solution. I wouldn't expect optimizers to be that good today.Ron Murawski wrote: Hi Martin,
I have the same square numbering and I do not consider it a mistake. I wrote a simple macro
#define CHESS_RANK(rank) (7 - (rank))
using the macro, I can compare CHESS_RANKs directly.
If you write:
if ( CHESS_RANK(a) < CHESS_RANK(b) )
the macro expands to:
if ( (7 - (a)) < (7 - (b)) )
and now, when you compile, a good optimizer will eliminate the useless subtraction transforming it to:
if ( -a < -b )
and now the optimizer is smart enough to realize that this can be transformed (ie: optimized again) into:
if ( a > b )
which means that the macro will execute with no delay. Best of all, your original source code is now clear and agrees with normal chess convention.
Ron
If I used A1=0 and H8 = 63, I wouldn't have to bother at all.
I got rid of rank comparisons like a < b and only use equality/inequality comparisons now.
The only hack I have now is relative rank conversion is passer eval, where I do something ugly now like rr = relrank(square) ^ rank1, I will probably hide it and write a separate function for that.
@Lucas: I too considered using operators as my code is C++, but I don't really want to do that for a simple enum. That's like using a hammer to kill a mosquitto IMHO. It makes sense for 3d vectors for example, but in this case I just don't know. On the other hand, using strong typing is good in that it prevents you from bugs at compile time.
I'm using full warning levels now and it too helped to catch some bugs even before I had to debug the program. It's also good to use two different compilers from time to time.
The only problem is that I had to disable one silly warning specific to msc, namely "conditional expression is constant warning" because of templates.
Also I absolutely love valgrind, which helped me to get rid of other potential problems.
Martin
-
Ron Murawski
- Posts: 397
- Joined: Sun Oct 29, 2006 4:38 am
- Location: Schenectady, NY
Re: [Entertainment] When tuning goes wrong...
Trust your compiler! It optimizes much better than you think.mar wrote:Hi Ron, that's an interesting remark and an elegant solution. I wouldn't expect optimizers to be that good today.Ron Murawski wrote: Hi Martin,
I have the same square numbering and I do not consider it a mistake. I wrote a simple macro
#define CHESS_RANK(rank) (7 - (rank))
using the macro, I can compare CHESS_RANKs directly.
If you write:
if ( CHESS_RANK(a) < CHESS_RANK(b) )
the macro expands to:
if ( (7 - (a)) < (7 - (b)) )
and now, when you compile, a good optimizer will eliminate the useless subtraction transforming it to:
if ( -a < -b )
and now the optimizer is smart enough to realize that this can be transformed (ie: optimized again) into:
if ( a > b )
which means that the macro will execute with no delay. Best of all, your original source code is now clear and agrees with normal chess convention.
Ron
But then you need to stand on your head and flip things around so you can understand the bitboard layout. I prefer code that uses the most easily understood data structures.mar wrote: If I used A1=0 and H8 = 63, I wouldn't have to bother at all.
But now you can use them again!mar wrote: I got rid of rank comparisons like a < b and only use equality/inequality comparisons now.
It's pretty easy to flip the board squaremar wrote: The only hack I have now is relative rank conversion is passer eval, where I do something ugly now like rr = relrank(square) ^ rank1, I will probably hide it and write a separate function for that.
#define FLIP(sq) ((sq) ^ 0x38) // vertical swap
and then calculate the rank of the FLIPped square.
BTW: All of these macros can be implemented as inline functions so you can enforce type-checking. I actually use inline functions rather than macros in my code, but I wanted to show comprehensible one-liners as examples.
Ron
-
mar
- Posts: 2552
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: [Entertainment] When tuning goes wrong...
Yes, today's compilers are amazing. It happened to me that the compiler produced better code than my handwritten assembly inner loop (mine was 1/2 insns better but still measurably slower, not much). Wouldn't happen 10+ years agoRon Murawski wrote:Trust your compiler! It optimizes much better than you think.
Of course one has to be careful sometimes:
Division by power of two constant is converted to right shift - only partially true. Extra work (rounding) is required when dividend is signed, -1 >>(arithmetic)n is -1, not 0. No problem for unsigned division.
I've seen cases where it was better to separate the most inner loop, otherwise the compiler tried to optimize everything together and failed (this may depend on the compiler used of course).
Not really. All I'd have to flip would be the underlying 8x8 representation, which is no problem at all, I only use it to quickly lookup piece at certain square. The only problem I can see is that mask initialization code which assumes that shl moves down would have to be rewritten (and all code that assumes the same, including hardcoded constants).Ron Murawski wrote:But then you need to stand on your head and flip things around so you can understand the bitboard layout. I prefer code that uses the most easily understood data structures.mar wrote: If I used A1=0 and H8 = 63, I wouldn't have to bother at all.
Yes, obviously. But I don't see a difference between doing a square flip, then extract rank and between extracting rank then doing the flip.Ron Murawski wrote: It's pretty easy to flip the board square
#define FLIP(sq) ((sq) ^ 0x38) // vertical swap
and then calculate the rank of the FLIPped square.
In fact, better is not to have to flip anything at all
-
lucasart
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: [Entertainment] When tuning goes wrong...
mar wrote:Isn't that why they invented the SAR operand on x86 ? SHR is only OK for unsigned, you're right. On 80386 (IIRC ?) both instructions take 1 cycle. So really you shouldn't care about that.Ron Murawski wrote: Division by power of two constant is converted to right shift - only partially true. Extra work (rounding) is required when dividend is signed, -1 >>(arithmetic)n is -1, not 0. No problem for unsigned division.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
-
hgm
- Posts: 27702
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: [Entertainment] When tuning goes wrong...
The problem is that dividing by 2 through ASR rounds towards -infinity, while dividing by 2 through the C '/' operator is expected to round towards zero.
-
mar
- Posts: 2552
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: [Entertainment] When tuning goes wrong...
I see HGM already explained, but anyway: sar does the same as shr except that it preserves sign (=the most significant bit). So for example division by 2 would work fine using sar until you get -1. -1 sar 1 remains -1, not 0 (assuming 2's complement). But I'm not sure what does the C/C++ standard say about right shifts on signed integers.lucasart wrote: Isn't that why they invented the SAR operand on x86 ? SHR is only OK for unsigned, you're right. On 80386 (IIRC ?) both instructions take 1 cycle. So really you shouldn't care about that.
-
lucasart
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: [Entertainment] When tuning goes wrong...
You're right:hgm wrote:The problem is that dividing by 2 through ASR rounds towards -infinity, while dividing by 2 through the C '/' operator is expected to round towards zero.
http://faydoc.tripod.com/cpu/sar.htm
So why did they invent SAR / SAL if it's exactly the same as SHR / SHL ?
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
-
mar
- Posts: 2552
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: [Entertainment] When tuning goes wrong...
SAL is the same as SHL (I guess it's only a different name for the same opcode), but SAR and SHR are different: SAR keeps MSBit while SHR zeroes it.lucasart wrote:You're right:hgm wrote:The problem is that dividing by 2 through ASR rounds towards -infinity, while dividing by 2 through the C '/' operator is expected to round towards zero.
http://faydoc.tripod.com/cpu/sar.htm
So why did they invent SAR / SAL if it's exactly the same as SHR / SHL ?