Help with multithread

Discussion of chess software programming and technical issues.

Moderators: hgm, Dann Corbit, Harvey Williamson

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 &#40;int i=0;i<256;i++) eval&#91;i&#93;=0;
for &#40;int i=0;i<256;i++) move&#91;i&#93;=0;
&#125;

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

result&#58;&#58;~result&#40;void&#41;
&#123;
&#125;

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

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 &#40;int padre,int evl,int mov&#41;
&#123;
EnterCriticalSection (&CR_result&#41;;
int index=resultados&#91;padre&#93;.n;
resultados&#91;padre&#93;.n++;
resultados&#91;padre&#93;.eval&#91;index&#93;=evl;
resultados&#91;padre&#93;.move&#91;index&#93;=mov;
LeaveCriticalSection (&CR_result&#41;;
&#125;

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

void get_result &#40;int Id,int &x,int &y&#41;
&#123;
EnterCriticalSection (&CR_result&#41;;
resultados&#91;Id&#93;.n--;
int index=resultados&#91;Id&#93;.n;
x=resultados&#91;Id&#93;.eval&#91;index&#93;;
y=resultados&#91;Id&#93;.move&#91;index&#93;;
LeaveCriticalSection (&CR_result&#41;;
&#125;

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

int th_resultados_disponibles &#40;int Id&#41;
&#123;
EnterCriticalSection (&CR_result&#41;;
int x=resultados&#91;Id&#93;.n;
LeaveCriticalSection (&CR_result&#41;;
return x;
&#125;

//-------------------------------------------------------------------
//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 &#40;void* arg&#41;
&#123;
int ID=*(&#40;int *) arg&#41;;

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

for&#40;;;) //&#40;Forever&#41;                        
&#123;
setjmp &#40;GLOBAL_TH&#91;ID&#93;.Jump&#41;; //El salto
ZMT&#91;ID&#93;.stop =0;             //Justo despues del salto

EnterCriticalSection  (&CR_threads&#41;;
threads_disponibles++;
LeaveCriticalSection  (&CR_threads&#41;;

ZMT&#91;ID&#93;.usable=1;//usable

WaitForSingleObject&#40;GLOBAL_TH&#91;ID&#93;.evento,INFINITE&#41;;

EnterCriticalSection  (&CR_threads&#41;;
threads_disponibles--;

int mov   =GLOBAL_TH&#91;ID&#93;.mov;
int beta  =GLOBAL_TH&#91;ID&#93;.beta;
int depth =GLOBAL_TH&#91;ID&#93;.depth;
int tipo  =GLOBAL_TH&#91;ID&#93;.tipo;
int nmovs =GLOBAL_TH&#91;ID&#93;.nmovs;
int padre =GLOBAL_TH&#91;ID&#93;.padre;
int eval;

LeaveCriticalSection  (&CR_threads&#41;;

eval=ZMT&#91;ID&#93;.search_mt&#40;mov,beta,depth,tipo,nmovs&#41;;

EnterCriticalSection  (&CR_threads&#41;;
add_result    &#40;padre,eval,mov&#41;;
ZMT&#91;padre&#93;.th_borra_hijo &#40;ID&#41;;
LeaveCriticalSection  (&CR_threads&#41;;
EnterCriticalSection (&CR_print&#41;;
cout<<".";
LeaveCriticalSection  (&CR_print&#41;;
&#125;;

_endthreadex&#40;0&#41;;
return 0;
&#125;;

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

int posicion&#58;&#58;search_mt &#40;int movimiento,int beta,int depth,int tipo,int nmovs&#41;
&#123;
mueve&#40;movimiento&#41;;

int ev;

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

int extension=0;
if &#40;enjaque&#41; extension=PLY;

int nueva_depth=depth-PLY+extension;

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

if &#40;enjaque&#41; ev=-alfabeta_chk       &#40;1-beta,nueva_depth,tipo^1&#41;;
else         ev=-alfabeta           &#40;1-beta,nueva_depth,tipo^1&#41;;

if (&#40;nueva_depth<&#40;depth-PLY&#41;)&&&#40;ev>=beta&#41;) 
&#123;
if &#40;enjaque&#41; ev=-alfabeta_chk       &#40;1-beta,depth-PLY,tipo^1&#41;;
else         ev=-alfabeta           &#40;1-beta,depth-PLY,tipo^1&#41;;
&#125;

return ev;
&#125;


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

int posicion&#58;&#58;split &#40;int mov,int beta,int depth,int tipo,int nmovs&#41;
&#123;
EnterCriticalSection (&CR_split&#41;;

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

for &#40;int ID=1;ID<MAX_THREADS;ID++)
if  &#40;ZMT&#91;ID&#93;.usable==1&#41;
&#123;
ZMT&#91;ID&#93;.usable=0;

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

ZMT&#91;ID&#93;.S=&ZMT&#91;ID&#93;.pS&#91;0&#93;;

ZMT&#91;ID&#93;.turno        =turno;
ZMT&#91;ID&#93;.estado       =estado;
ZMT&#91;ID&#93;.np2          =np2;

ZMT&#91;ID&#93;.pb           =pb;
ZMT&#91;ID&#93;.cb           =cb;
ZMT&#91;ID&#93;.ab           =ab;
ZMT&#91;ID&#93;.tb           =tb;
ZMT&#91;ID&#93;.db           =db;
ZMT&#91;ID&#93;.rb           =rb;

ZMT&#91;ID&#93;.pn           =pn;
ZMT&#91;ID&#93;.cn           =cn;
ZMT&#91;ID&#93;.an           =an;
ZMT&#91;ID&#93;.tn           =tn;
ZMT&#91;ID&#93;.dn           =dn;
ZMT&#91;ID&#93;.rn           =rn;

ZMT&#91;ID&#93;.hash_key     =hash_key;
ZMT&#91;ID&#93;.hash_key_p   =hash_key_p;
ZMT&#91;ID&#93;.mov100       =mov100;

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

GLOBAL_TH&#91;ID&#93;.mov    =mov;
GLOBAL_TH&#91;ID&#93;.beta   =beta;
GLOBAL_TH&#91;ID&#93;.depth  =depth;
GLOBAL_TH&#91;ID&#93;.tipo   =tipo;
GLOBAL_TH&#91;ID&#93;.nmovs  =nmovs;

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

GLOBAL_TH&#91;ID&#93;.padre =Id;
hijo&#91;n_hijos&#93;       =ID;
n_hijos++;

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

SetEvent&#40;GLOBAL_TH&#91;ID&#93;.evento&#41;;

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

LeaveCriticalSection (&CR_split&#41;;
return 1;
&#125;
LeaveCriticalSection (&CR_split&#41;;
return 0;
&#125;

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

void init_multithread &#40;int max_threads&#41;
&#123;
//-------------------------------------------------------------------
//Critical section esto es de lo primero que hay que hacer
//-------------------------------------------------------------------

InitializeCriticalSection&#40;&CR_threads&#41;;
InitializeCriticalSection&#40;&CR_split&#41;;
InitializeCriticalSection&#40;&CR_result&#41;;
InitializeCriticalSection&#40;&CR_print&#41;;
InitializeCriticalSection&#40;&CR_familia&#41;;

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

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

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

max_threads++;

MAX_THREADS=max_threads;

GLOBAL_TH    =new struct multi_th &#91;max_threads&#93;;

HT           =new HANDLE          &#91;max_threads&#93;;

VMT          =new int             &#91;max_threads&#93;;
ZMT          =new class posicion  &#91;max_threads&#93;;
resultados   =new class result    &#91;max_threads&#93;;

if &#40;ZMT==NULL&#41; cout<<"info insuficient memory"<<endl;

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

for &#40;int i=0;i<max_threads;i++) ZMT&#91;i&#93;.Id     =i;

threads_disponibles                           =0;
for &#40;int i=0;i<max_threads;i++) ZMT&#91;i&#93;.stop   =0;
for &#40;int i=0;i<max_threads;i++) ZMT&#91;i&#93;.n_hijos=0;
for &#40;int i=0;i<max_threads;i++) ZMT&#91;i&#93;.usable =0;

for &#40;int i=0;i<max_threads;i++) GLOBAL_TH&#91;i&#93;.evento=INVALID_HANDLE_VALUE;
for &#40;int i=1;i<max_threads;i++) GLOBAL_TH&#91;i&#93;.evento=CreateEvent&#40;0,FALSE,FALSE,0&#41;;

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

unsigned threadID;
for &#40;int i=1;i<max_threads;i++)
&#123;
threadID;
HT&#91;i&#93;=&#40;HANDLE&#41; _beginthreadex &#40;NULL,0,&Init_thread,&i,0,&threadID&#41;;
Sleep&#40;10&#41;;//le damos un tiempo para iniciar todo
cout<<"info thread "<<i<<" iniciada Id="<<threadID<<endl;
&#125;

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

cout<<"info "<<threads_disponibles<<" threads"<<endl;
&#125;

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

void posicion&#58;&#58;stop_thread &#40;void&#41;
&#123;
for &#40;int i=0;i<n_hijos;i++) ZMT&#91;hijo&#91;i&#93;&#93;.stop_thread ();
for &#40;int i=0;i<256    ;i++) hijo&#91;i&#93;=0;
n_hijos=0;
clean_results ();
stop=1;
&#125;

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

void posicion&#58;&#58;clean_results &#40;void&#41;
&#123;
EnterCriticalSection (&CR_result&#41;;
resultados&#91;Id&#93;.eval&#91;resultados&#91;Id&#93;.n&#93;=0;
resultados&#91;Id&#93;.move&#91;resultados&#91;Id&#93;.n&#93;=0;
resultados&#91;Id&#93;.n=0;
LeaveCriticalSection (&CR_result&#41;;
&#125;

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

void posicion&#58;&#58;stop_hijos &#40;void&#41;
&#123;
int index;
for &#40;int i=0;i<n_hijos;i++) 
&#123;
index=hijo&#91;i&#93;;
ZMT&#91;index&#93;.stop_thread   ();
ZMT&#91;index&#93;.clean_results ();
&#125;
n_hijos=0;
&#125;

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

int posicion&#58;&#58;th_esperando_resultado &#40;void&#41;
&#123;
return n_hijos;
&#125;

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

void posicion&#58;&#58;th_borra_hijo &#40;int Id_hijo&#41;
&#123;
int i,j;
for &#40;i=0;i<n_hijos;i++) 
if &#40;hijo&#91;i&#93;==Id_hijo&#41;
&#123;
j=i;
for &#40;i=j;i<n_hijos;i++) hijo&#91;i&#93;=hijo&#91;i+1&#93;;
n_hijos--;
//cout<<"th_borra_hijo";
&#125;
&#125;

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

void posicion&#58;&#58;debug_parentesco &#40;void&#41;
&#123;
EnterCriticalSection (&CR_print&#41;;
int x=n_hijos;
for &#40;int i=0;i<n_hijos;i++) 
if  &#40;GLOBAL_TH&#91;hijo&#91;i&#93;&#93;.padre!=Id&#41; 
&#123;
cout<<endl;
cout<<"ERR&#58; 034  "<<endl;
cout<<"nhijos="<<x<<endl;
cout<<"Id="<<Id<<endl;
cout<<"Padre del hijo de Id="<<GLOBAL_TH&#91;hijo&#91;i&#93;&#93;.padre<<endl;
cout<<"nhijos="<<n_hijos<<endl;
for &#40;int k=0;k<n_hijos;k++) cout<<GLOBAL_TH&#91;hijo&#91;i&#93;&#93;.padre<<";";
cout<<endl;
getch ();
&#125;
LeaveCriticalSection (&CR_print&#41;;
&#125;

//-------------------------------------------------------------------
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&#58;&#58;alfabeta &#40;int beta,int depth,int tipo&#41;
&#123;
//-------------------------------------------------------------------
//TEMPO
//-------------------------------------------------------------------

test_tempo ();

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

if &#40;beta> 31500&#41; return  31500;
if &#40;beta<-31500&#41; return -31500;
if &#40;depth<=7&#41;    return  qsearch &#40;beta,depth,tipo&#41;;

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

NODES++;

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

if &#40;mov100>99&#41; return 0;

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

if &#40;repetido&#40;)) 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&#40;0&#41;;

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

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

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

btm=ttmove;

arbol_nuevo_nivel&#40;);

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&#91;lista_nmov-2&#93;.mov;

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

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

while (&#40;movimiento=next_move_ab ())||&#40;th_esperando_resultado ())||&#40;th_resultados_disponibles &#40;Id&#41;))
&#123;

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

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

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

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

if (&#40;movimiento&#41;&&(&#40;tipo&1&#41;==0&#41;)
if &#40;split&#40;movimiento,beta,depth,tipo,nmovs&#41;)
&#123;
nmovs++;
goto BUCLE_MT;
&#125;

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

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

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

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

BUCLE_MT&#58;;
tipo&=6;
&#125;

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

if &#40;bestval==-32500&#41;
&#123;
btm=0;
arbol_borra_nivel&#40;);
return 0;
&#125;

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

if   &#40;turno&#41; hash.admax_b &#40;hash_key,bestval,depth&#41;;
else         hash.admax_n &#40;hash_key,bestval,depth&#41;;

arbol_borra_nivel&#40;);
return bestval;
&#125;

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