talk about IPP's evaluation

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
rvida
Posts: 481
Joined: Thu Apr 16, 2009 12:00 pm
Location: Slovakia, EU

Re: talk about IPP's evaluation

Post by rvida »

mcostalba wrote:
bob wrote: I think I heard someone mention that it might keep the EG and MG scores combined, 16 bits per value, so that one is left shifted 16 bits.
Yes you guessed right. It saves both mid game and end game score in a 32 bit integer with a 16 bit word for each score.

At the end the combined score is splitted and the two values merged in the usual way to get the final score.
I'm doing it almost exactly like that in new Critter, although it is hidden in ScorePair enum with overloaded operators:

Code: Select all

enum ScorePair;

inline ScorePair pair(Score mg, Score eg) {
  return ScorePair((mg << 16) + eg);
}
inline ScorePair pair(int mg, int eg) {
  return ScorePair((mg << 16) + eg);
}
inline ScorePair operator+ (ScorePair s1, ScorePair s2) { return ScorePair(int(s1) + int(s2)); }
inline ScorePair operator- (ScorePair s1, ScorePair s2) { return ScorePair(int(s1) - int(s2)); }

// same with +=; -=; *= 
One thing I dont like about it is handling overflows (when lower 16bits is negative I must correct upper 16bits by adding 1)

Code: Select all

inline Score eg_value(ScorePair s) { return Score(short(s & 0xffff)); }
inline Score mg_value(ScorePair s) { 
  return Score(short(((s >> 16) & 0xffff)) + (short(eg_value(s)) < 0));
 }
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: talk about IPP's evaluation

Post by wgarvin »

rvida wrote:One thing I dont like about it is handling overflows (when lower 16bits is negative I must correct upper 16bits by adding 1)

Code: Select all

inline Score eg_value(ScorePair s) { return Score(short(s & 0xffff)); }
inline Score mg_value(ScorePair s) { 
  return Score(short(((s >> 16) & 0xffff)) + (short(eg_value(s)) < 0));
 }
If you know that "int" is 32 bits, you could try this instead:

Code: Select all

inline Score mg_value(ScorePair s) {
  return Score((int(s) + 32768) >> 16);
 }
The idea is to generate a carry from bit 15 into bit 16, if and only if bit 15 was a 1 (i.e. the lower half had a negative value in it). If your compiler is clever, it should generate two instructions: a 32-bit ADD (or LEA) followed by a dependent arithmetic shift right (ASL). The cast to signed int will ensure that you get an arithmetic (sign-extending) shift right, instead of a logical one (SHR).

If your compiler is not clever, it might throw in another dependent instruction at the end, such as an unnecessary MOVSX, but I hope not! If you are worried about this, you could check the generated code for the release version of some function that calls mg_value, and see what it looks like.

In general, you should be careful with casts between integer types of different sizes, lest you force the compiler to insert extra instructions to zero- or sign-extend it. Even if it does, they won't necessarily slow things down.. but its something to be aware of.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: talk about IPP's evaluation

Post by mcostalba »

rvida wrote: I'm doing it almost exactly like that in new Critter, although it is hidden in ScorePair enum with overloaded operators
I am thinking to try with an union instead, somthing along the lines of:

Code: Select all

union Score {

    int64_t v64;

    struct {
      int32_t mg;
      int32_t eg;
    } v32;
};
but still didn't have the time to test it.
User avatar
rvida
Posts: 481
Joined: Thu Apr 16, 2009 12:00 pm
Location: Slovakia, EU

Re: talk about IPP's evaluation

Post by rvida »

wgarvin wrote: If you know that "int" is 32 bits, you could try this instead:

Code: Select all

inline Score mg_value(ScorePair s) {
  return Score((int(s) + 32768) >> 16);
 }
The idea is to generate a carry from bit 15 into bit 16, if and only if bit 15 was a 1 (i.e. the lower half had a negative value in it). If your compiler is clever, it should generate two instructions: a 32-bit ADD (or LEA) followed by a dependent arithmetic shift right (ASL). The cast to signed int will ensure that you get an arithmetic (sign-extending) shift right, instead of a logical one (SHR).
Thanks, this is a very clever idea. Although not much of a performance improvement (splitting to eg and mg values are called only once per eval), the code looks much simpler.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: talk about IPP's evaluation

Post by mcostalba »

wgarvin wrote:
rvida wrote:One thing I dont like about it is handling overflows (when lower 16bits is negative I must correct upper 16bits by adding 1)

Code: Select all

inline Score eg_value(ScorePair s) { return Score(short(s & 0xffff)); }
inline Score mg_value(ScorePair s) { 
  return Score(short(((s >> 16) & 0xffff)) + (short(eg_value(s)) < 0));
 }
What about this ?

Code: Select all

inline Score eg_value(ScorePair s) { return Score(short(unsigned(s))); }

wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: talk about IPP's evaluation

Post by wgarvin »

mcostalba wrote: What about this ?

Code: Select all

inline Score eg_value(ScorePair s) { return Score(short(unsigned(s))); }

eg_value is probably fine either way. The & 0xffff was unnecessary, but the compiler would probably figure that out anyways.