Special code for black and white

Discussion of chess software programming and technical issues.

Moderator: Ras

Dann Corbit
Posts: 12778
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Special code for black and white

Post by Dann Corbit »

Kempelen wrote:Hi, Robert,

wooouh..... I modify my code yesterday, as my eval func is not so big, and avoiding code for white and black and making a generic routine for both colors, make the the eval function a 40% less eficcient. I measure the difference with the same 10 positions at the same fixed depth.!!!
The speed change should be insignificant. You introduced a bug, I think.
PK-4

Re: Special code for black and white

Post by PK-4 »

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.
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
User avatar
Zach Wegner
Posts: 1922
Joined: Thu Mar 09, 2006 12:51 am
Location: Earth

Re: Special code for black and white

Post by Zach Wegner »

PK-4 wrote: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
You could also use "const", but I don't think any compiler switch is going to help. Local variables, i.e. auto variables, are put on the stack, so unless a compiler can tell that every one is read-only, it can't do anything.

But really, what's the problem with using static, const, or making them global? I think it's better style to have them be global, you can tell what every evaluation parameter is in one glance, and also be able to access them externally for e.g. tuning.
Harald Johnsen

Re: Special code for black and white

Post by Harald Johnsen »

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.
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 »

Hi,
I don't know exactly if I am doing as you say. I use local variables in both cases.
I post you a sample code of the two version of my engine. The code is for bishop evaluation, but you can try to imagine the complete eval function. In the first one example you will see there are dedicated vars for white and black (like evalBlancas, evalNegras, numeroAlfilesBlancas, numeroAlfilesNegras or peones_blancas, peones_negras....) . In the second one there are dimensional variables of type var[color], in all places, I dont use in this example any dedicated var per color

I think, and the test confirm me, that second one slow a lot as offset calculations has to be done. (also double code lines). The only drawback of the first one is I have to write twice code, for white and black, so executable is double size, and need more carefull for maintenance.

First code:

Code: Select all


int evalBlancas = 0;
int evalNegras = 0;
int numero_alfiles_blancas=0;
int numero_alfiles_negras=0;

for (int sq = 0 ; sq < 64; ++sq) {
	int pieza = piezas[sq]
	int color = color_piezas[sq];

	...code...

	switch (pieza) {
		...
	        case ALFIL:
	
	            if ( color == BLANCAS ) {
	                // La pareja de alfiles
	                ++numero_alfiles_blancas;
	
	                if ( numero_alfiles_blancas >= 2 ) {
	                    evalBlancas += EV_B_PAREJA_DE_ALFILES + ((8 - total_peones) * EV_B_ALFIL_POSICION_ABIERTA);
	                }
	
	                // Situacion
	                evalBlancas += EV_B_SITUACION_ALFIL_BLANCAS[sq];
	
	                if (piezaClava(sq)) {
	                    evalBlancas += EV_B_CLAVADA;
	                }
	
	
	                // Alfil malo
	                if ( bb_sq & st_casillas_blancas ) {
	                    evalBlancas -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_blancas &
	                                     ptrPosicion->peones_blancos & ( st_centro_grande | st_centro_chico ) ) );
	                } else {
	                    evalBlancas -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_negras &
	                                     ptrPosicion->peones_blancos & ( st_centro_grande | st_centro_chico ) ) );
	                }
	
	            } else {
	                // La pareja de alfies
	                ++numero_alfiles_negras;
	
	                if ( numero_alfiles_negras >= 2 ) {
	                    evalNegras += EV_B_PAREJA_DE_ALFILES + ((8 - total_peones) * EV_B_ALFIL_POSICION_ABIERTA);
	                }
	
	                // Situacion
	                evalNegras += EV_B_SITUACION_ALFIL_NEGRAS[sq];
	
	                if (piezaClava(sq)) {
	                    evalNegras += EV_B_CLAVADA;
	                }
	
	                // Alfil malo
	                if ( bb_sq & st_casillas_blancas ) {
	                    evalNegras -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_blancas &
	                                    ptrPosicion->peones_negros & ( st_centro_grande | st_centro_chico ) ) );
	                } else {
	                    evalNegras -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_negras &
	                                    ptrPosicion->peones_negros & ( st_centro_grande | st_centro_chico ) ) );
	                }
	
	            }
	}
	....code....
}
Second code:

Code: Select all

int eval[2] = {0,0};
int numero_alfiles[2]={0,0};
for (int sq = 0; sq<64; ++sq) {
	int pieza = piezas[sq]
	int color = color_piezas[sq];

	....code.....

	switch (pieza):
	        case ALFIL:
	
	            ++numero_alfiles[color];
	
	            if ( numero_alfiles[color] >= 2 ) {
	                eval[color] += EV_B_PAREJA_DE_ALFILES + ((8 - total_peones) * EV_B_ALFIL_POSICION_ABIERTA);
	            }
	
	            // Situacion
	            eval[color] += EV_B_SITUACION_ALFIL[color][sq];
	
	            if (piezaClava(sq)) {
	                eval[color] += EV_B_CLAVADA;
	            }
	
	
	            // Alfil malo
	            if ( bb_sq & st_casillas_blancas ) {
	                eval[color] -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_blancas &
	                                 ptrPosicion->bPeones[color] & ( st_centro_grande | st_centro_chico ) ) );
	            } else {
	                eval[color] -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_negras &
	                                 ptrPosicion->bPeones[color] & ( st_centro_grande | st_centro_chico ) ) );
	            }
	            break;
	}

	....code.....

}
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 »

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).
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: 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.
Harald Johnsen

Re: Special code for black and white

Post by Harald Johnsen »

I see.
You don't even have evaluation *functions* so obviously eveything that was posted above can not work.

Move the code that is inside the switch to a function :

Code: Select all

static void INLINE evalBishop(int color, int sq, ...) {
    
       ++numero_alfiles[color]; 

       if ( numero_alfiles[color] >= 2 ) { 
           eval[color] += EV_B_PAREJA_DE_ALFILES + ((8 - total_peones) * EV_B_ALFIL_POSICION_ABIERTA); 
       } 

       // Situacion 
       eval[color] += EV_B_SITUACION_ALFIL[color][sq]; 

       if (piezaClava(sq)) { 
           eval[color] += EV_B_CLAVADA; 
       } 

       // Alfil malo 
       if ( bb_sq & st_casillas_blancas ) { 
           eval[color] -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_blancas & 
                            ptrPosicion->bPeones[color] & ( st_centro_grande | st_centro_chico ) ) ); 
       } else { 
           eval[color] -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_negras & 
                            ptrPosicion->bPeones[color] & ( st_centro_grande | st_centro_chico ) ) ); 
       } 
}
call the function :

Code: Select all

...
	switch (pieza) { 
      ... 
           case ALFIL: 
    
               if ( color == BLANCAS ) { 
               		evalBishop(BLANCAS, sq);
               } else { 
               		evalBishop(NEGRAS, sq);
               } 
   } 
Now, look again the assembler output, no index.

HJ.
PK-4

Re: Special code for black and white

Post by PK-4 »

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.
Guetti

Re: Special code for black and white

Post by Guetti »

Harald Johnsen wrote:I see.
You don't even have evaluation *functions* so obviously eveything that was posted above can not work.

Move the code that is inside the switch to a function :

Code: Select all

static void INLINE evalBishop(int color, int sq, ...) {
    
       ++numero_alfiles[color]; 

       if ( numero_alfiles[color] >= 2 ) { 
           eval[color] += EV_B_PAREJA_DE_ALFILES + ((8 - total_peones) * EV_B_ALFIL_POSICION_ABIERTA); 
       } 

       // Situacion 
       eval[color] += EV_B_SITUACION_ALFIL[color][sq]; 

       if (piezaClava(sq)) { 
           eval[color] += EV_B_CLAVADA; 
       } 

       // Alfil malo 
       if ( bb_sq & st_casillas_blancas ) { 
           eval[color] -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_blancas & 
                            ptrPosicion->bPeones[color] & ( st_centro_grande | st_centro_chico ) ) ); 
       } else { 
           eval[color] -= ( EV_M_ALFIL_MALO * contarBits ( st_casillas_negras & 
                            ptrPosicion->bPeones[color] & ( st_centro_grande | st_centro_chico ) ) ); 
       } 
}
call the function :

Code: Select all

...
	switch (pieza) { 
      ... 
           case ALFIL: 
    
               if ( color == BLANCAS ) { 
               		evalBishop(BLANCAS, sq);
               } else { 
               		evalBishop(NEGRAS, sq);
               } 
   } 
Now, look again the assembler output, no index.

HJ.
Why not:

Code: Select all

switch (pieza) { 
      ... 
           case ALFIL: 
               evalBishop(color, sq);
                
   }