Three Parallel Backtracking Designs | Dr Dobb's
Rather than keeping a 2D array that mimics a physical chessboard, I propose using an integer vector with length equal to the number of rows. The data stored in each element will be the column of a placed queen. This eliminates the chance that two queens will be on the same row, and the test for a legal position can simply search all lower indexed elements to see if those elements correspond to the same column (vertical attack) or are along a diagonal from the newly placed queen. If such a case is found, the newly placed queen attacks an already placed queen and
In parallel, different tasks are going to need a private copy of the board and current partial solution to be examined. Otherwise you have a data race. The smaller data structure saves time and space in the parallel code because each new task generated from a call to
all tasks ultimately do very little work in this implementation. The only thing a non-leaf task does is create new tasks for queens on the next row of the board, if there are any legal positions for a queen on that row. It takes time to create a task and assign that task to a thread. Since there isn't much computation in any task, the task creation time will be a large percentage of the work time. In other words, the overhead of creating the task will be high, let alone assigning it to a thread for execution. Since each task must have a private copy of the state configuration, there can be a large memory usage, too. Thus, any time spent allocating memory for a new current state object and copying relevant values is just more overhead that was not needed in the serial version.
Design 2: One task Created for Each Sub-Tree Rooted at a Particular Depth
Design 3: Create a New Task for Each Child Node, But Only To a Certain Depth
Read full article from Three Parallel Backtracking Designs | Dr Dobb's
Rather than keeping a 2D array that mimics a physical chessboard, I propose using an integer vector with length equal to the number of rows. The data stored in each element will be the column of a placed queen. This eliminates the chance that two queens will be on the same row, and the test for a legal position can simply search all lower indexed elements to see if those elements correspond to the same column (vertical attack) or are along a diagonal from the newly placed queen. If such a case is found, the newly placed queen attacks an already placed queen and
stillLegal() will return FALSE since the position has no hope of leading to a legal solution.BOOL stillLegal(int *board, int r){ BOOL safe = TRUE; int i; // Check vertical for ( i = 0; i < r; ++i) if (board[i] == board[r]) safe = FALSE; // Check diagonals int ld = board[r]; //left diagonal columns int rd = board[r]; // right diagonal columns for ( i = r-1; i >= 0; --i) { --ld; ++rd; if (board[i] == ld || board[i] == rd) safe = FALSE; } return safe;}In parallel, different tasks are going to need a private copy of the board and current partial solution to be examined. Otherwise you have a data race. The smaller data structure saves time and space in the parallel code because each new task generated from a call to
NQueens() will use a copy of the current board to be used as a formal parameter.Design 1: Every New Recursive Call Generates a New Task
void NQueensD1(int *board, int row, int N){ if (row == N) handleSolution(board); else { for (int i = 0; i < N; ++i) { board[row] = i; if (stillLegal(board, row)) { // make copy of current board position int *bnew = new int[N]; for (int j = 0; j <= row; ++j) bnew[j] = board[j];#pragma omp task NQueensD1(bnew, row+1, N); } } } return;}Design 2: One task Created for Each Sub-Tree Rooted at a Particular Depth
void NQueensD2(int *board, int row, int N){ for (int i = 0; i < N; ++i) { board[row] = i; if (stillLegal(board, row)) { if (row < LEVEL) NQueensD2(board, row+1, N); // go deeper in search tree else { int *bnew = new int[N]; for (int j = 0; j <= row; ++j) bnew[j] = board[j];#pragma omp task NQueens(bnew, row+1, N); // generate task of serial function } } } return;}Read full article from Three Parallel Backtracking Designs | Dr Dobb's