I have asked a similar question before ,but I have not obtained enough attention to my problem due to the complexity of it , so let me rephrase the whole problem .
moveT ChooseComputerMove(state)
{
moveT bestMove;
maxMove(state,bestMove);
return bestMove;
}
int maxMove(state, bestMove)
{
int v = -1000;
#pragma omp parallel for
for(int i = 0; i< nMoves; i++)
{
moveT move = validMoves[i];
makemove(state,move);
#pragma omp task
rating = -maxMove(state, move);
if(rating < v)
{v=rating ; bestMove = move;}
#pragma omp taskwait
Retractmove(state,move)
}
return v;
}
Is my code semantically correct ; I already have tested it in my code , and it gives me segmentation fault;
Update : Sorry for the spelling mistakes and I have edited my code .
Consider this a comment. Your explicit task region is incorrectly written and besides that it is also redundant. You spawn only one explicit task in each iteration and then wait for it to finish with the
taskwait. But since task execution may be deferred, the task itself might execute after the line with the comparison operator. E.g.The body of the task is the next block that follows the
taskpragma.The actual execution flow might be:
if(rating < v) ....statement is executed.taskwaitconstruct is hit which blocks execution until all tasks are processed. This initiates the execution of the task.vis never updated since theifstatement was already executed.You would rather want to put both statements in a
taskconstruct and also remove thetaskwaitsince it is implied at the end of the parallel region. Sincemakemovemodifies thestatevector, you might want to employ the single task producer pattern:The task producer loop is run in serial in one thread only (because of the
singledirective). Then at the end of the parallel region there is an implicit task scheduling point, hence the other threads start executing the queued tasks. Thestateis shared by default and has to be madefirstprivatein order for the task to inherit a private version, otherwise all tasks would modify the same globalstatevariable at the same time which would lead to problems. The privatisation ofstatewould result in much higher memory usage, hence it is not a good idea to allow tasking up to the bottom of the recursion tree. Rather you should stop generating tasks at a certain level and continue with serial execution. This would also reduce the overhead induced by the explicit tasking.Another thing to notice – unless special measures are taken, only the top-level call would run in parallel. All other recursive calls would result in nested parallel regions and nested parallelism is disabled by default, which means that deeper recursion levels would automatically execute serially. To enable nested parallelism, either set the environment value
OMP_NESTEDtotrueor put the following call somewhere in the beginning of the program:Beware that this might result in a huge number of concurrent threads.