The speed change should be insignificant. You introduced a bug, I think.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.!!!
Special code for black and white
Moderator: Ras
-
- Posts: 12778
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: Special code for black and white
Re: Special code for black and white
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.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...
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?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...
Regards
-
- Posts: 1922
- Joined: Thu Mar 09, 2006 12:51 am
- Location: Earth
Re: Special code for black and white
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.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
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.
Re: Special code for black and white
Your compiler can output the assembler listing of the source.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.
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.
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.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
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.
-
- Posts: 620
- Joined: Fri Feb 08, 2008 10:44 am
- Location: Madrid - Spain
Re: Special code for black and white
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:
Second code:
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....
}
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.....
}
-
- Posts: 620
- Joined: Fri Feb 08, 2008 10:44 am
- Location: Madrid - Spain
Re: Special code for black and white
No Dann, there is no bug, because I get the same result in testing both versions. (evaluating 10 differents positions).Dann Corbit wrote: The speed change should be insignificant. You introduced a bug, I think.
-
- Posts: 620
- Joined: Fri Feb 08, 2008 10:44 am
- Location: Madrid - Spain
Re: Special code for black and white
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?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.
(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.
Re: Special code for black and white
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 :
call the function :
Now, look again the assembler output, no index.
HJ.
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 ) ) );
}
}
Code: Select all
...
switch (pieza) {
...
case ALFIL:
if ( color == BLANCAS ) {
evalBishop(BLANCAS, sq);
} else {
evalBishop(NEGRAS, sq);
}
}
HJ.
Re: Special code for black and white
My apologies for misreading 'data' as 'variable' - hurry is the surest performance killer. Of course local data would be initialised at every call.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?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...
Re: Special code for black and white
Why not: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 :
call the 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 ) ) ); } }
Now, look again the assembler output, no index.Code: Select all
... switch (pieza) { ... case ALFIL: if ( color == BLANCAS ) { evalBishop(BLANCAS, sq); } else { evalBishop(NEGRAS, sq); } }
HJ.
Code: Select all
switch (pieza) {
...
case ALFIL:
evalBishop(color, sq);
}