void nqueens_rec(int column, list_node* head) { cilk_for (int i=0; i<SIZE; i++) { if (addok(head, i, column)) { // add the node list_node new_node; new_node.next = head; new_node.row = i; if (column+1<SIZE) { #ifdef CUTOFF if (column+1>=CUTOFF_LEVEL) ser_nqueens_rec(column+1, &new_node); else nqueens_rec(column+1, &new_node); #else nqueens_rec(column+1, &new_node); #endif } else { // found a solution //solution_count += 1; } } // else do nothing -- dead computation branch } }
void operator () (const tbb::blocked_range<int> &range) const { for(int i=range.begin(); i<range.end(); i++) { list_node *node; if (addok(head, i, column)) { // add the node #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found if (node!=NULL && solution == NULL) { #endif list_node new_node; new_node.next = head; new_node.row = i; if (column+1<SIZE) { #ifdef CUTOFF if (column+1>=CUTOFF_LEVEL) ser_nqueens_rec(column+1, &new_node); else nqueens_rec(column+1, &new_node); #else nqueens_rec(column+1, &new_node); #endif } else { // found a solution //solution = &new_node; solution_count++; //atomic //abort() } #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found } #endif } // end if addok // else do nothing -- dead computation branch } }
int nqueens() { solution_count = 0; #ifdef CUTOFF if (0>=CUTOFF_LEVEL) ser_nqueens_rec(0, NULL); else nqueens_rec(0, NULL); #else nqueens_rec(0, NULL); #endif return solution_count; }
void operator () (tbb::blocked_range<int> &range, tbb::task* parent_task) const { tbb::blocked_range<int> subrange = range.get_some_safe(); long savedcnt = 0; //while ( subrange.empty() == false && parent_task->bflws_pushed == false) { while ( subrange.empty() == false ) { for(int i=subrange.begin(); i<subrange.end(); i++) { list_node *node; if (addok(head, i, column)) { // add the node #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found if (node!=NULL && solution == NULL) { #endif list_node new_node; new_node.next = head; new_node.row = i; if (column+1<SIZE) { #ifdef CUTOFF if (column+1>=CUTOFF_LEVEL) ser_nqueens_rec(column+1, &new_node); else nqueens_rec(column+1, &new_node, parent_task); #else nqueens_rec(column+1, &new_node, parent_task); #endif } else { // found a solution //solution = &new_node; solution_count++; //atomic //abort() } #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found } #endif } // end if addok // else do nothing -- dead computation branch } // end for-loop over range #ifdef DEQUE_THRESH if ( parent_task->task_pool_size() < DEQUE_THRESH) break; #else if ( parent_task->is_task_pool_empty() ) break; #endif subrange = range.get_some_safe(); //printf("Saved one ping-pong!\n"); //std::cout << "Saved one\n" ; //savedcnt ++; } // end while //printf("Saved %d ping-pongs\n", savedcnt); //std::cout << "Saved " << savedcnt << "\n" ; }
void operator () (tbb::blocked_range<int> &range, tbb::task* parent_task) const { //int cnt = 0; for(int i = range.begin(); i < range.end() /*&& parent_task->bflws_pushed == false*/; i++) { range.remove_some_safe(); list_node *node; if (addok(head, i, column)) { // add the node #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found if (node!=NULL && solution == NULL) { #endif list_node new_node; new_node.next = head; new_node.row = i; if (column+1<SIZE) { #ifdef CUTOFF if (column+1>=CUTOFF_LEVEL) ser_nqueens_rec(column+1, &new_node); else nqueens_rec(column+1, &new_node, parent_task); #else nqueens_rec(column+1, &new_node, parent_task); #endif } else { // found a solution //solution = &new_node; solution_count++; //atomic //abort() } #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found } #endif } // end if addok // else do nothing -- dead computation branch //cnt++; //if (cnt == GRAINSIZE)) { //cnt = 0; //subrange = range.remove_some_safe(); DEQUE_CHECK_CODE (parent_task); //else end = range.end(); //} //printf("Saved one ping-pong!\n"); //std::cout << "Saved one\n" ; //savedcnt ++; //i++; } // end for-loop over range //printf("Saved %d ping-pongs\n", savedcnt); //std::cout << "Saved " << savedcnt << "\n" ; }
void nqueens() { //solution_count.set_value(0); nqueens_rec(0, NULL); }
int nqueens() { solution_count = 0; nqueens_rec(0, NULL, NULL); return solution_count; }
void nqueens_rec(int column, list_node* head, tbb::task* parent_task) { PARTITIONER partitioner; tbb::blocked_range<int> range(0,SIZE,GRAINSIZE); #ifdef _TBB_MELD_ALLOW_CODE_DUPLICATION for(int i = range.begin(); i < range.end() /*&& parent_task->bflws_pushed == false*/; i++) { // DEQUE CHECK if ( parent_task==NULL || parent_task->is_task_pool_empty() ) { tbb::parallel_for (range, nqueensMeldFlatBody(column,head), partitioner); break; } // else range.remove_some_safe(); list_node *node; if (addok(head, i, column)) { // add the node #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found if (node!=NULL && solution == NULL) { #endif list_node new_node; new_node.next = head; new_node.row = i; if (column+1<SIZE) { #ifdef CUTOFF if (column+1>=CUTOFF_LEVEL) ser_nqueens_rec(column+1, &new_node); else nqueens_rec(column+1, &new_node, parent_task); #else nqueens_rec(column+1, &new_node, parent_task); #endif } else { // found a solution //solution = &new_node; solution_count++; //atomic //abort() } #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found } #endif } // end if addok } // end for-loop over range #else // TBB_MELD_DONT_ALLOW_CODE_DUPLICATION nqueensMeldFlatBody body(column,head); // create task //start_for<tbb::blocked_range<int>, nqueensMeldFlatBody, PARTITIONER> *self = NULL; //self = new(task::allocate_root()) start_for(range,body,const_cast<PARTITIONER&>(partitioner)); start_for<tbb::blocked_range<int>, nqueensMeldFlatBody, PARTITIONER>& a = *new(task::allocate_root()) start_for(range,body,const_cast<Partitioner&>(partitioner)); // add to postponed deque self->next_postponed = NULL; // enqueue postponed task tbb::task* saved_tail = self->push_postponed_task(); do { //if ( parent_task==NULL || parent_task->is_task_pool_empty() ) { if ( self->is_task_pool_empty() ) { // TODO: optim if possible split ancestor postponed and continue: // note: this will always be possible since we already added it to // the postponed deque. parallel_for (range, body, partitioner); break; } // else body(range,parent_task); } while(range.empty()==false); // TODO detect if a split has occurred, in which case some synchronization is needed #endif }
void ser_nqueens_rec(int column, list_node* head) { int i; for (i=0; i<SIZE; i++) { list_node *node; if (addok(head, i, column)) { // add the node node = (list_node*)scalable_malloc(sizeof(list_node)); #ifdef DEBUG if(node==NULL) out_of_memory = 1; #endif #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found if (node!=NULL && solution == NULL) { #else // Don't quit. Instead keep scanning the whole search space. if (node!=NULL) { #endif node->next = head; node->row = i; if (column+1<SIZE) { ser_nqueens_rec(column+1, node); } else { // found a solution //solution = node; solution_count++; // atomic } } } // else do nothing -- dead computation branch } } void nqueens_rec(int column, list_node* head); class nqueensBody { public: int column; list_node* head; void operator () (const tbb::blocked_range<int> &range) const { for(int i=range.begin(); i<range.end(); i++) { list_node *node; if (addok(head, i, column)) { // add the node node = (list_node*)scalable_malloc(sizeof(list_node)); #ifdef DEBUG if(node==NULL) out_of_memory = 1; #endif #ifdef QUIT_ON_SOLUTION // QUIT as soon as a solution is found if (node!=NULL && solution == NULL) { #else // Don't quit. Instead keep scanning the whole search space. if (node!=NULL) { #endif node->next = head; node->row = i; if (column+1<SIZE) { #ifdef CUTOFF if (column+1>=CUTOFF_LEVEL) ser_nqueens_rec(column+1, node); else nqueens_rec(column+1, node); #else nqueens_rec(column+1, node); #endif } else { // found a solution //solution = node; solution_count++; //atomic //abort() } } } // end if addok // else do nothing -- dead computation branch } } // Constructor nqueensBody(int col, list_node* hd) : column(col), head(hd) { } }; void nqueens_rec(int column, list_node* head) { #ifdef TWOLVL_SCHED tbb::auto_partitioner firstLevelPartitioner; PARTITIONER partitioner; // tbb::parallel_for (tbb::blocked_range<int>(0,SIZE,GRAINSIZE), nqueensBody(column,head), ((column==0)?firstLevelPartitioner:partitioner) ); if (column==0) tbb::parallel_for (tbb::blocked_range<int>(0,SIZE,GRAINSIZE), nqueensBody(column,head), firstLevelPartitioner ); else tbb::parallel_for (tbb::blocked_range<int>(0,SIZE,GRAINSIZE), nqueensBody(column,head), partitioner ); #else PARTITIONER partitioner; tbb::parallel_for (tbb::blocked_range<int>(0,SIZE,GRAINSIZE), nqueensBody(column,head), partitioner); #endif }