Special code for black and white

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
Kempelen
Posts: 620
Joined: Fri Feb 08, 2008 10:44 am
Location: Madrid - Spain

Re: Special code for black and white

Post by Kempelen »

Harald Johnsen wrote: Now, look again the assembler output, no index.

HJ.
ajaja.....
I see the point now. The trick is the 'inline' keyword!
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Special code for black and white

Post by bob »

PK-4 wrote:
I did this in the crafty version 22.0 and carefully compared to version 21.x (whatever was current at the time) to make sure the scores matched exactly. When I was done, version 22.0 was very slightly faster, most likely a result of a significantly reduced cache footprint which offset the slightly slower array accesses...
I am a little surprised. I thought the burden of indexing many variables with piece colour would cause a slowdown. But I would not argue with observation and try this sometime.
There actually are not "many variables". There are a few but the count is no more than a couple of dozen. Things like which square does a white/black sit on if it castles king-side, something like OO[2] = {G1, G8}; And the like... Squares or ranks were the only issue I had to deal with (rook on 7th for example, etc). Scores and such exist as just one value, where to compute the score for knights, I do this:

score += EvaluateKnights(white) - EvaluateKnights(black);


BTW you are not using "local data" correct? that would be a performance killer. You need to make this kind of data either global or static so that it is not constantly re-initialized each time that procedure is called...
So the compiler inserts initilisation code for local variables - is it possible to prevent this with some compiler switch rather than "static" at so many places?

Regards
I don't think so, I chose to make them all global constants since they are never modified, and that assigns them values at compile time once and for all.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Special code for black and white

Post by bob »

Harald Johnsen wrote:
PK-4 wrote: I am a little surprised. I thought the burden of indexing many variables with piece colour would cause a slowdown. But I would not argue with observation and try this sometime.
Your compiler can output the assembler listing of the source.
Oh and I repeat it, there is *no* indexing with the piece color. The compiler generates the code for the white and for the black side. There is no color indexing.

So the compiler inserts initilisation code for local variables - is it possible to prevent this with some compiler switch rather than "static" at so many places?

Regards
No. The compiler does not insert anything. There is no initialization code if your variable is not an object. Even int i = 2; is a no-op.

If you suspect compiler bad job then you can add a const modifier on all constant, add a no pointer aliasing modifier where needed. But don't do manual 'optimization' that are counter productive.

HJ.
I think the point he misses is that any reference like pawn_square[0] or pawn_square[1] does no array reference calculations at all, those are simply two memory variables with no subscript. When you inline, all the black/white indices become simple memory references with no penalty other than the memory access which was already there.

As far as local vs global, if you inline, it should not matter. int sq[2] = {G1, G8}; should produce constants when you inline the code, so that sq[1] is replaced by G8 with no memory reference needed.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Special code for black and white

Post by bob »

Kempelen wrote:
Harald Johnsen wrote: Your compiler can output the assembler listing of the source.
Oh and I repeat it, there is *no* indexing with the piece color. The compiler generates the code for the white and for the black side. There is no color indexing.
.....
HJ.
I think you are confusing...... There is indexing. The compiler can never know what color a pieze has in a square sq. That is information dynamically generated as game runs. Can the compiler know that square c2 has a black bishop in a game agains Crafty?

(also I saw the assambly code and indexes was needed).

You can see a more complete code I have posted in a reply to Bob in this thread, you will see that indexes are needed.
You are overlooking the key point. We are doing something like

score += EvaluateKnights(white) - EvaluateKnights(black);

Inside EvaluateKnights you find references like square[color] and such. But when you inline with color=white, then square[color] becomes square[1], and if it is not modified and initialized to some value locally, square[1] gets replaced by the constant value itself. Then you inline the same code for black and get the same reductions once again... zero array indexing. But only if you inline...
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Special code for black and white

Post by bob »

PK-4 wrote:
PK-4 wrote:
Bob wrote:
BTW you are not using "local data" correct? that would be a performance killer. You need to make this kind of data either global or static so that it is not constantly re-initialized each time that procedure is called...
So the compiler inserts initilisation code for local variables - is it possible to prevent this with some compiler switch rather than "static" at so many places?
My apologies for misreading 'data' as 'variable' - hurry is the surest performance killer. Of course local data would be initialised at every call.
Unless you do inlining, then things change significantly as the arrays turn into constant values in the inlined code.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Special code for black and white

Post by bob »

Kempelen wrote:
Dann Corbit wrote: The speed change should be insignificant. You introduced a bug, I think.
No Dann, there is no bug, because I get the same result in testing both versions. (evaluating 10 differents positions).
Do you compile everything as one large source file, so that the compiler can inline this stuff? If you put the calling procedure in one file, and the called procedure in a separate file, and compile independently, then no inlining and there could be any degree of performance penalty...
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Special code for black and white

Post by bob »

Kempelen wrote:
Harald Johnsen wrote: Now, look again the assembler output, no index.

HJ.
ajaja.....
I see the point now. The trick is the 'inline' keyword!
You generally don't even need to worry about that as the compiler will do it automagically, so long as you compile everything together so that it can see the caller and callee when compiling. Otherwise you have to tell it (Intel at least) that you want inter-file optimizations...
User avatar
Lasse Hansen
Posts: 27
Joined: Wed May 28, 2008 1:07 pm
Location: Porsgrunn, Norway

Re: Special code for black and white

Post by Lasse Hansen »

Hi!

I use wtm as an index and have arranged most data sets to fit this,
so that [white pieces] are addressed as the [black pieces + 1], (wtm 0 or 1).
Here is an example of making both white and black pawn captures with same code.

Code: Select all

// Pawn captures left (square mapping H8=bit 0, H7=bit 1,... A1=bit 63)
Atk  = ((Pieces[BPAWNS + wtm]&~FILE_A1A8)<<(9-(wtm<<1)));
Atk &= Pieces[ALLBPIECES + !wtm]; // may use !wtm == wtm^1
It might seem dirty to use logical not in indices, but it's readable
to me (and I did not see any difference when trying wtm^1).

Regards, Lasse
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: Special code for black and white

Post by jwes »

Lasse Hansen wrote:Hi!

I use wtm as an index and have arranged most data sets to fit this,
so that [white pieces] are addressed as the [black pieces + 1], (wtm 0 or 1).
Here is an example of making both white and black pawn captures with same code.

Code: Select all

// Pawn captures left (square mapping H8=bit 0, H7=bit 1,... A1=bit 63)
Atk  = ((Pieces[BPAWNS + wtm]&~FILE_A1A8)<<(9-(wtm<<1)));
Atk &= Pieces[ALLBPIECES + !wtm]; // may use !wtm == wtm^1
It might seem dirty to use logical not in indices, but it's readable
to me (and I did not see any difference when trying wtm^1).

Regards, Lasse
This works neatly for captures because your board is sidewise to what I'm used to, but how do you do it for non-captures, as you need to shift in different directions?
User avatar
Lasse Hansen
Posts: 27
Joined: Wed May 28, 2008 1:07 pm
Location: Porsgrunn, Norway

Re: Special code for black and white

Post by Lasse Hansen »

Normal pawn pushes I do like this.

Code: Select all

	// White + Black : Double pawn step
	B = Pieces[BPAWNS + wtm] & (RANK_A7H7 << 5*wtm);
	B = ((B>>1)<<(2-(wtm<<1))) & ~(Pieces[ALLBPIECES] | Pieces[ALLWPIECES]);
	Atk = ((B>>1)<<(2-(wtm<<1))) & ~(Pieces[ALLBPIECES] | Pieces[ALLWPIECES]);

	// White + Black : Normal 1-step moves
	Atk = ((Pieces[BPAWNS + wtm]>>1)<<(2-(wtm<<1))) & ~(Pieces[ALLBPIECES] | Pieces[ALLWPIECES]);
Regards, Lasse