Advertisement
nex036ara

nqueens_tbb

Mar 24th, 2012
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.19 KB | None | 0 0
  1. //=======================================================================
  2. //
  3. // SAMPLE SOURCE CODE - SUBJECT TO THE TERMS OF END-USER LICENSE AGREEMENT FOR
  4. // INTEL(R) PARALLEL ADVISOR 2011.
  5. //
  6. // Copyright 2009-2010 Intel Corporation
  7. //
  8. // THIS FILE IS PROVIDED "AS IS" WITH NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT
  9. // NOT LIMITED TO ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  10. // PURPOSE, NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS.
  11. //
  12. // ========================================================================
  13.  
  14. // [DESCRIPTION]
  15. // Solve the nqueens problem  - how many positions of queens can fit on a chess board
  16. // of a given size without attacking each other.
  17. // This is the serial version used to find a candidate hotspot function to parallelize.
  18. //
  19. // [BUILD]
  20. // Use a Release configuration to ensure you find a hotspot representative of a final production build.
  21. //
  22. // [RUN]
  23. // To set the board size in Visual Studio, right click on the project,
  24. // select Properies > Configuration Properties > General > Debugging.  Set
  25. // Command Arguments to the desired value.  13 has been set as the default.
  26. //
  27. // [EXPECTED OUTPUT]
  28. //
  29. // Board Size   Number of Solutions
  30. //     4                2
  31. //     5               10
  32. //     6                4
  33. //     7               40
  34. //     8               92
  35. //     9              352
  36. //    10              724
  37. //    11             2680
  38. //    12            14200
  39. //    13            73712
  40. //    14           365596
  41. //    15          2279184
  42.  
  43. #include <iostream>
  44. #include <windows.h>
  45. #include <mmsystem.h>
  46. #include "tbb/task_scheduler_init.h"
  47. #include "tbb/blocked_range.h"
  48. #include "tbb/parallel_for.h"
  49. #include "tbb/spin_mutex.h"
  50.  
  51. //ADVISOR COMMENT: This is a TBB version of the nqueens application
  52.  
  53. using namespace tbb;
  54. using namespace std;
  55.  
  56. int nrOfSolutions=0;  //keeps track of the number of solutions
  57. int size=0;  // the board-size read from command-line
  58. int correctSolution[16]; //array of the number of correct solutions for each board size
  59.  
  60. // define tbb mutexes
  61. typedef spin_mutex NrOfSolutionsMutexType; 
  62. NrOfSolutionsMutexType NrOfSolutionsMutex;
  63.  
  64. /*
  65. Recursive function to find all solutions on a board
  66. represented by the argument "queens", placing the next queen
  67. at location (row, col)
  68.  
  69. On Return: nrOfSolutions has been increased to add solutions for this board
  70.  
  71. */
  72. void setQueen(int queens[], int row, int col) {
  73.     //check all previously placed rows for attacks
  74.     for(int i=0; i<row; i++) {
  75.         // vertical attacks
  76.         if (queens[i]==col) {
  77.             return;
  78.         }
  79.         // diagonal attacks
  80.         if (abs(queens[i]-col) == (row-i) ) {
  81.             return;
  82.         }
  83.     }
  84.     // column is ok, set the queen
  85.     queens[row]=col;
  86.  
  87.     if(row==size-1) {
  88.         {      
  89.             // increment is not atomic, so setting a lock is required here
  90.             NrOfSolutionsMutexType::scoped_lock mylock(NrOfSolutionsMutex);
  91.             nrOfSolutions++;  //Placed final queen, found a solution!
  92.         } // closing block invokes scoped_lock destructor which releases the lock
  93.  
  94.     }
  95.     else {
  96.         // try to fill next row
  97.         for(int i=0; i<size; i++) {
  98.             setQueen(queens, row+1, i);
  99.         }
  100.     }
  101. }
  102.  
  103.  
  104. class SetQueens {
  105. public:
  106.     void operator()( const blocked_range<size_t>& r ) const {
  107.         for( size_t i=r.begin(); i!=r.end(); ++i ) {
  108.             // try all positions in first row
  109.             // create separate array for each recursion
  110.             // started here
  111.             int * queens = new int[size];
  112.             setQueen(queens, 0, (int)i);
  113.         }
  114.     }
  115. };
  116.  
  117. /*
  118. Function to find all solutions for nQueens problem on size x size chessboard.
  119.  
  120. On Return: nrOfSoultions = number of solutions for size x size chessboard.
  121. */
  122. void solve() {
  123.     // Do a parallel for over the n positions in the first row.
  124.     // Let the scheduler decide how the n tasks are distrubuted
  125.     // on the different threads
  126.     parallel_for(blocked_range<size_t>(0, size, 1), SetQueens() );
  127. }
  128.  
  129. int main(int argc, char*argv[]) {
  130.     if(argc !=2) {
  131.         cerr << "Usage: nqueens_tbb boardSize [default is 13].\n";
  132.         size = 13;
  133.     } else {
  134.         size = atoi(argv[1]);
  135.         if (size < 4 || size > 15) {
  136.             cerr << "Boardsize should be between 4 and 15; setting it to 13. \n" << endl;
  137.             size = 13;
  138.         }
  139.     }
  140.     // Set the expected number of solutions for each board-size for later checking.
  141.     correctSolution[0] = 0;
  142.     correctSolution[1] = 0;
  143.     correctSolution[2] = 0;
  144.     correctSolution[3] = 0;
  145.     correctSolution[4] = 2;
  146.     correctSolution[5] = 10;
  147.     correctSolution[6] = 4;
  148.     correctSolution[7] = 40;
  149.     correctSolution[8] = 92;
  150.     correctSolution[9] = 352;
  151.     correctSolution[10] = 724;
  152.     correctSolution[11] = 2680;
  153.     correctSolution[12] = 14200;
  154.     correctSolution[13] = 73712;
  155.     correctSolution[14] = 365596;
  156.     correctSolution[15] = 2279184;
  157.  
  158.     cout << "Starting 3_nqueens_tbb solver for size " << size << "...\n";
  159.     DWORD startTime=timeGetTime();
  160.     // initialize tbb scheduler
  161.     task_scheduler_init init;
  162.     solve();
  163.     DWORD endTime=timeGetTime();
  164.     cout << "Number of solutions: " << nrOfSolutions << endl;
  165.     if (nrOfSolutions != correctSolution[size])
  166.         cout << "!!Incorrect result!! Number of solutions should be " << correctSolution[size] << endl << endl;
  167.     else
  168.         cout << "Correct result!" << endl;
  169.  
  170.     cout << endl << "Calculations took " << endTime-startTime << "ms.\n";
  171.  
  172.     return 0;
  173. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement