Help with multithread

Discussion of chess software programming and technical issues.

Moderator: Ras

MDiaz

Help with multithread

Post by MDiaz »

This is my mt code (its bugy usuaally break at before depth 3) im not mt programer and i like to know the experts opinions that could be help me to solve the bugs.

thanks for yor atention.

singe thread goes fine... an probably alpha-beta goes fine too.

Excuse the spanglis

hijo=son
padre=father
threads_disponibles=threads_availables

Code: Select all

#include "StdAfx.h"
#include "windows.h"
#include "process.h" 
#include "posicion.h"
#include "bitboards.h"
#include "global.h"
#include "mt.h"

#include "Winbase.h"

using namespace std;

//-------------------------------------------------------------------
//INICIO RESULTADOS
//-------------------------------------------------------------------

class result
{
public:
int n;
int eval[256];
int move[256];

 result (void);
~result (void);
};

//-------------------------------------------------------------------

result::result(void)
{
n=0;
for (int i=0;i<256;i++) eval[i]=0;
for (int i=0;i<256;i++) move[i]=0;
}

//-------------------------------------------------------------------

result::~result(void)
{
}

//-------------------------------------------------------------------

class result *resultados;

//-------------------------------------------------------------------

CRITICAL_SECTION CR_result;
CRITICAL_SECTION CR_threads;
CRITICAL_SECTION CR_split;
CRITICAL_SECTION CR_print;
CRITICAL_SECTION CR_familia;

//-------------------------------------------------------------------

void add_result (int padre,int evl,int mov)
{
EnterCriticalSection (&CR_result);
int index=resultados[padre].n;
resultados[padre].n++;
resultados[padre].eval[index]=evl;
resultados[padre].move[index]=mov;
LeaveCriticalSection (&CR_result);
}

//-------------------------------------------------------------------

void get_result (int Id,int &x,int &y)
{
EnterCriticalSection (&CR_result);
resultados[Id].n--;
int index=resultados[Id].n;
x=resultados[Id].eval[index];
y=resultados[Id].move[index];
LeaveCriticalSection (&CR_result);
}

//-------------------------------------------------------------------

int th_resultados_disponibles (int Id)
{
EnterCriticalSection (&CR_result);
int x=resultados[Id].n;
LeaveCriticalSection (&CR_result);
return x;
}

//-------------------------------------------------------------------
//FIN RESULTADOS
//-------------------------------------------------------------------

int MAX_THREADS=0;
int threads_disponibles=0;

HANDLE *HT;

int MT_destino,MT_mov,MT_beta,MT_depth,MT_tipo;

//-------------------------------------------------------------------
//INIT THREAD
//-------------------------------------------------------------------

unsigned __stdcall Init_thread (void* arg)
{
int ID=*((int *) arg);

//Informa de la creación de las threads
cout<<"info iniciando thread "<<ID<<endl;

for(;;) //(Forever)                        
{
setjmp (GLOBAL_TH[ID].Jump); //El salto
ZMT[ID].stop =0;             //Justo despues del salto

EnterCriticalSection  (&CR_threads);
threads_disponibles++;
LeaveCriticalSection  (&CR_threads);

ZMT[ID].usable=1;//usable

WaitForSingleObject(GLOBAL_TH[ID].evento,INFINITE);

EnterCriticalSection  (&CR_threads);
threads_disponibles--;

int mov   =GLOBAL_TH[ID].mov;
int beta  =GLOBAL_TH[ID].beta;
int depth =GLOBAL_TH[ID].depth;
int tipo  =GLOBAL_TH[ID].tipo;
int nmovs =GLOBAL_TH[ID].nmovs;
int padre =GLOBAL_TH[ID].padre;
int eval;

LeaveCriticalSection  (&CR_threads);

eval=ZMT[ID].search_mt(mov,beta,depth,tipo,nmovs);

EnterCriticalSection  (&CR_threads);
add_result    (padre,eval,mov);
ZMT[padre].th_borra_hijo (ID);
LeaveCriticalSection  (&CR_threads);
EnterCriticalSection (&CR_print);
cout<<".";
LeaveCriticalSection  (&CR_print);
};

_endthreadex(0);
return 0;
};

//-------------------------------------------------------------------
//SEARCH MT
//-------------------------------------------------------------------

int posicion::search_mt (int movimiento,int beta,int depth,int tipo,int nmovs)
{
mueve(movimiento);

int ev;

int enjaque=0;
if ((turno==BLANCO)&&(jaqueb(lsb(rb)))) enjaque=1;
if ((turno==NEGRO) &&(jaquen(lsb(rn)))) enjaque=1;

int extension=0;
if (enjaque) extension=PLY;

int nueva_depth=depth-PLY+extension;

if ((enjaque==0)&&(depth>=(3*PLY))&&(nmovs>=4)&&(S->tipo_mov==MOV_MOVE)) nueva_depth=depth-2*PLY;//LMR

if (enjaque) ev=-alfabeta_chk       (1-beta,nueva_depth,tipo^1);
else         ev=-alfabeta           (1-beta,nueva_depth,tipo^1);

if ((nueva_depth<(depth-PLY))&&(ev>=beta)) 
{
if (enjaque) ev=-alfabeta_chk       (1-beta,depth-PLY,tipo^1);
else         ev=-alfabeta           (1-beta,depth-PLY,tipo^1);
}

return ev;
}


//-------------------------------------------------------------------
//SPLIT
//-------------------------------------------------------------------

int posicion::split (int mov,int beta,int depth,int tipo,int nmovs)
{
EnterCriticalSection (&CR_split);

//-------------------------------------------------------------------
//BUSCA THREAD EN ESPERA
//-------------------------------------------------------------------

for (int ID=1;ID<MAX_THREADS;ID++)
if  (ZMT[ID].usable==1)
{
ZMT[ID].usable=0;

//-------------------------------------------------------------------
//COPIA
//-------------------------------------------------------------------

ZMT[ID].S=&ZMT[ID].pS[0];

ZMT[ID].turno        =turno;
ZMT[ID].estado       =estado;
ZMT[ID].np2          =np2;

ZMT[ID].pb           =pb;
ZMT[ID].cb           =cb;
ZMT[ID].ab           =ab;
ZMT[ID].tb           =tb;
ZMT[ID].db           =db;
ZMT[ID].rb           =rb;

ZMT[ID].pn           =pn;
ZMT[ID].cn           =cn;
ZMT[ID].an           =an;
ZMT[ID].tn           =tn;
ZMT[ID].dn           =dn;
ZMT[ID].rn           =rn;

ZMT[ID].hash_key     =hash_key;
ZMT[ID].hash_key_p   =hash_key_p;
ZMT[ID].mov100       =mov100;

//-------------------------------------------------------------------
//TRANSICION
//-------------------------------------------------------------------

GLOBAL_TH[ID].mov    =mov;
GLOBAL_TH[ID].beta   =beta;
GLOBAL_TH[ID].depth  =depth;
GLOBAL_TH[ID].tipo   =tipo;
GLOBAL_TH[ID].nmovs  =nmovs;

//-------------------------------------------------------------------
//FAMILIA
//-------------------------------------------------------------------

GLOBAL_TH[ID].padre =Id;
hijo[n_hijos]       =ID;
n_hijos++;

//-------------------------------------------------------------------
//ARRANQUE
//-------------------------------------------------------------------
//Arranca el multi thread

SetEvent(GLOBAL_TH[ID].evento);

//-------------------------------------------------------------------

LeaveCriticalSection (&CR_split);
return 1;
}
LeaveCriticalSection (&CR_split);
return 0;
}

//-------------------------------------------------------------------
//INICIA MULTITHREAD
//-------------------------------------------------------------------

void init_multithread (int max_threads)
{
//-------------------------------------------------------------------
//Critical section esto es de lo primero que hay que hacer
//-------------------------------------------------------------------

InitializeCriticalSection(&CR_threads);
InitializeCriticalSection(&CR_split);
InitializeCriticalSection(&CR_result);
InitializeCriticalSection(&CR_print);
InitializeCriticalSection(&CR_familia);

//-------------------------------------------------------------------

SYSTEM_INFO sys;
GetSystemInfo (&sys);
N_NUCLEOS=sys.dwNumberOfProcessors;
cout<<"info "<<N_NUCLEOS<<" processors"<<endl;

//-------------------------------------------------------------------

max_threads++;

MAX_THREADS=max_threads;

GLOBAL_TH    =new struct multi_th [max_threads];

HT           =new HANDLE          [max_threads];

VMT          =new int             [max_threads];
ZMT          =new class posicion  [max_threads];
resultados   =new class result    [max_threads];

if (ZMT==NULL) cout<<"info insuficient memory"<<endl;

//-------------------------------------------------------------------

for (int i=0;i<max_threads;i++) ZMT[i].Id     =i;

threads_disponibles                           =0;
for (int i=0;i<max_threads;i++) ZMT[i].stop   =0;
for (int i=0;i<max_threads;i++) ZMT[i].n_hijos=0;
for (int i=0;i<max_threads;i++) ZMT[i].usable =0;

for (int i=0;i<max_threads;i++) GLOBAL_TH[i].evento=INVALID_HANDLE_VALUE;
for (int i=1;i<max_threads;i++) GLOBAL_TH[i].evento=CreateEvent(0,FALSE,FALSE,0);

//-------------------------------------------------------------------

unsigned threadID;
for (int i=1;i<max_threads;i++)
{
threadID;
HT[i]=(HANDLE) _beginthreadex (NULL,0,&Init_thread,&i,0,&threadID);
Sleep(10);//le damos un tiempo para iniciar todo
cout<<"info thread "<<i<<" iniciada Id="<<threadID<<endl;
}

//-------------------------------------------------------------------

cout<<"info "<<threads_disponibles<<" threads"<<endl;
}

//-------------------------------------------------------------------
//stop_thread
//-------------------------------------------------------------------

void posicion::stop_thread (void)
{
for (int i=0;i<n_hijos;i++) ZMT[hijo[i]].stop_thread ();
for (int i=0;i<256    ;i++) hijo[i]=0;
n_hijos=0;
clean_results ();
stop=1;
}

//-------------------------------------------------------------------
//clean results
//-------------------------------------------------------------------

void posicion::clean_results (void)
{
EnterCriticalSection (&CR_result);
resultados[Id].eval[resultados[Id].n]=0;
resultados[Id].move[resultados[Id].n]=0;
resultados[Id].n=0;
LeaveCriticalSection (&CR_result);
}

//-------------------------------------------------------------------
//stop_hijos
//-------------------------------------------------------------------

void posicion::stop_hijos (void)
{
int index;
for (int i=0;i<n_hijos;i++) 
{
index=hijo[i];
ZMT[index].stop_thread   ();
ZMT[index].clean_results ();
}
n_hijos=0;
}

//-------------------------------------------------------------------
//th_esperando_resultado
//-------------------------------------------------------------------

int posicion::th_esperando_resultado (void)
{
return n_hijos;
}

//-------------------------------------------------------------------
//th_borra_hijo
//-------------------------------------------------------------------

void posicion::th_borra_hijo (int Id_hijo)
{
int i,j;
for (i=0;i<n_hijos;i++) 
if (hijo[i]==Id_hijo)
{
j=i;
for (i=j;i<n_hijos;i++) hijo[i]=hijo[i+1];
n_hijos--;
//cout<<"th_borra_hijo";
}
}

//-------------------------------------------------------------------

void posicion::debug_parentesco (void)
{
EnterCriticalSection (&CR_print);
int x=n_hijos;
for (int i=0;i<n_hijos;i++) 
if  (GLOBAL_TH[hijo[i]].padre!=Id) 
{
cout<<endl;
cout<<"ERR: 034  "<<endl;
cout<<"nhijos="<<x<<endl;
cout<<"Id="<<Id<<endl;
cout<<"Padre del hijo de Id="<<GLOBAL_TH[hijo[i]].padre<<endl;
cout<<"nhijos="<<n_hijos<<endl;
for (int k=0;k<n_hijos;k++) cout<<GLOBAL_TH[hijo[i]].padre<<";";
cout<<endl;
getch ();
}
LeaveCriticalSection (&CR_print);
}

//-------------------------------------------------------------------
And alpha-beta

Code: Select all


#include "StdAfx.h"
#include "posicion.h"
#include "bitboards.h"
#include "recognicers.h"
#include "global.h"
#include "mt.h"
#include "hash.h"
#include "global.h"
#include "debug.h"
#include "consolecolors.h"

using namespace std;
//-------------------------------------------------------------------
//ALFABETA
//-------------------------------------------------------------------

int posicion::alfabeta (int beta,int depth,int tipo)
{
//-------------------------------------------------------------------
//TEMPO
//-------------------------------------------------------------------

test_tempo ();

//-------------------------------------------------------------------
//CUTTER
//-------------------------------------------------------------------

if (beta> 31500) return  31500;
if (beta<-31500) return -31500;
if (depth<=7)    return  qsearch (beta,depth,tipo);

//-------------------------------------------------------------------
//NODES
//-------------------------------------------------------------------

NODES++;

//-------------------------------------------------------------------
//REGLA 50 MOVIMIENTOS
//-------------------------------------------------------------------

if (mov100>99) return 0;

//-------------------------------------------------------------------
//REPETICIONES
//-------------------------------------------------------------------

if (repetido()) return 0;

//-------------------------------------------------------------------

int nueva_depth=0;
int enjaque=0;

int bestval  =-32500;
int ev       =-32500;
int ev2      =-32500;
int bestmove =0;

int R;
int aux100;

//-------------------------------------------------------------------
//HASH
//-------------------------------------------------------------------

int  trans_depth=0;
int  ttmove=0;
char dmx,dmi;
int  max,min;

//-------------------------------------------------------------------
//HASH
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//EVALUACION INTERNA
//-------------------------------------------------------------------

int eval_interna=evalua(0);

//-------------------------------------------------------------------
//NULL MOVE PRURING
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//IID
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//NUEVO NIVEL
//-------------------------------------------------------------------

btm=ttmove;

arbol_nuevo_nivel();

S->ttmove=btm;
S->pmov=0;
S->nmov=0;
S->capturas_excluidas=0;
S->underpromo_permited=0;

int nmovs=0;

//-------------------------------------------------------------------
//EXTENSION
//-------------------------------------------------------------------

int singular =0;
int extension=0;

//-------------------------------------------------------------------
//SEARCH
//-------------------------------------------------------------------

S->tipo_search=1;
int movimiento=0;
unsigned __int32 mov2=lista_data[lista_nmov-2].mov;

int org1;
int des1;
int org2;
int des2;

//-------------------------------------------------------------------
//BUCLE SEARCH
//-------------------------------------------------------------------

while ((movimiento=next_move_ab ())||(th_esperando_resultado ())||(th_resultados_disponibles (Id)))
{

//-------------------------------------------------------------------
//RESULTADOS DISPONIBLES
//-------------------------------------------------------------------

while (th_resultados_disponibles (Id))
{
int move_mt=0;
get_result (Id,ev,move_mt);
if (ev>bestval)
{
bestval=ev;
bestmove=move_mt;
if (ev>=beta)
{
stop_hijos    ();
clean_results ();
if   (turno) hash.admov_b (hash_key,bestmove,ev,depth);
else         hash.admov_n (hash_key,bestmove,ev,depth);
if ((bestmove&(CAPTURA|ALPASO|PROMOCION))==0) arbol_add_killer (bestmove,depth);
arbol_borra_nivel();
btm=bestmove;
return ev;
}
}
}

//-------------------------------------------------------------------
//REPETITION PRURING
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//MULTITHREAD
//-------------------------------------------------------------------

if ((movimiento)&&((tipo&1)==0))
if (split(movimiento,beta,depth,tipo,nmovs))
{
nmovs++;
goto BUCLE_MT;
}

//-------------------------------------------------------------------
//NORMAL SEARCH
//-------------------------------------------------------------------

if (movimiento)
{
ev=search_mt(movimiento,beta,depth,tipo,nmovs);
if ((movimiento&PROMOCION)&&(ev==0)) S->underpromo_permited=1;
desmueve();
nmovs++;

if (ev>bestval)
{
bestval=ev;
bestmove=movimiento;
if (ev>=beta) 
{
stop_hijos    ();
clean_results ();
if   (turno) hash.admov_b (hash_key,bestmove,ev,depth);
else         hash.admov_n (hash_key,bestmove,ev,depth);
if ((bestmove&(CAPTURA|ALPASO|PROMOCION))==0) arbol_add_killer (bestmove,depth);
arbol_borra_nivel();
btm=bestmove;
return ev;
}
}
}

//-------------------------------------------------------------------

BUCLE_MT:;
tipo&=6;
}

//-------------------------------------------------------------------
//STALEMATE
//-------------------------------------------------------------------

if (bestval==-32500)
{
btm=0;
arbol_borra_nivel();
return 0;
}

//-------------------------------------------------------------------
//FIN
//-------------------------------------------------------------------

if   (turno) hash.admax_b (hash_key,bestval,depth);
else         hash.admax_n (hash_key,bestval,depth);

arbol_borra_nivel();
return bestval;
}

//-------------------------------------------------------------------