Advertisement
Guest User

Untitled

a guest
Jun 9th, 2023
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.01 KB | None | 0 0
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <vector>
  4. #include <chrono>
  5. #include <boost/compute/core.hpp>
  6. #include <boost/compute/types/struct.hpp>
  7. #include <boost/compute/algorithm/transform.hpp>
  8. #include <boost/compute/container/vector.hpp>
  9.  
  10.  
  11. namespace compute = boost::compute;
  12.  
  13. // printing of the device's info:
  14. std::ostream &operator<<(std::ostream &os, const compute::device & device)
  15. {
  16.     return os << device.name() << " (platform: " << device.platform().name() << ")";
  17. }
  18.  
  19. // struct for maze storing:
  20. struct Field
  21. {
  22.     unsigned nVis[21 * 31];
  23. };
  24.  
  25. // set up the field:
  26. #define pos2int(r, c) ((r) * 31 + (c))
  27. #define WALL (UINT_MAX)
  28. #define EMPTY (0)
  29. Field setField(const std::vector<std::vector<bool>> & f)
  30. {
  31.     Field a;
  32.     for (int r = 0; r < 21; r++)
  33.         for (int c = 0; c < 31; c++)
  34.             a.nVis[pos2int(r,c)] = (f[r][c] ? WALL : EMPTY);
  35.     return a;
  36. }
  37.  
  38. // accumulate the answer for calculated maze (sum of number of visits for each cell)
  39. long long accumulateTheAnswer(const Field &f)
  40. {
  41.     long long res = 0;
  42.     for (int i = 0; i < 21 * 31; i++)
  43.         if (f.nVis[i] != WALL)
  44.             res += f.nVis[i];
  45.     return res;
  46. }
  47.  
  48. // implement bug's moving on CPU:
  49. __attribute__((noinline))
  50. void bugMovingCPU(Field &a)
  51. {
  52.     int pos = 1 * 31 + 1, dir = +31;
  53.     while (pos != 618)
  54.     {
  55.         ++a.nVis[pos];
  56.         unsigned val = a.nVis[pos + dir];
  57.         { unsigned next = a.nVis[pos + 31]; if (next < val) dir = +31, val = next; }
  58.         { unsigned next = a.nVis[pos +  1]; if (next < val) dir =  +1, val = next; }
  59.         { unsigned next = a.nVis[pos - 31]; if (next < val) dir = -31, val = next; }
  60.         { unsigned next = a.nVis[pos -  1]; if (next < val) dir =  -1, val = next; }
  61.         pos += dir;
  62.     }
  63. }
  64.  
  65. // register our structure on GPU:
  66. BOOST_COMPUTE_ADAPT_STRUCT(Field, Field, (nVis))
  67.  
  68. // function to emulate bug's moving on GPU:
  69. BOOST_COMPUTE_FUNCTION(Field, bugMovingGPU, (Field a),
  70. {
  71.     int pos = 1 * 31 + 1, dir = +31;
  72.     while (pos != 618)
  73.     {
  74.         ++a.nVis[pos];
  75.         unsigned val = a.nVis[pos + dir];
  76.         { unsigned next = a.nVis[pos + 31]; if (next < val) dir = +31, val = next; }
  77.         { unsigned next = a.nVis[pos +  1]; if (next < val) dir =  +1, val = next; }
  78.         { unsigned next = a.nVis[pos - 31]; if (next < val) dir = -31, val = next; }
  79.         { unsigned next = a.nVis[pos -  1]; if (next < val) dir =  -1, val = next; }
  80.         pos += dir;
  81.     }
  82.     return a;
  83. });
  84.  
  85. // current time in nanoseconds:
  86. long long currTimeInNanos()
  87. {
  88.     return std::chrono::high_resolution_clock::now().time_since_epoch().count();
  89. }
  90.  
  91. // function for printing numbers like 1234567890 as 1.234.567.890
  92. template<typename T> std::string printWithDots(T x)
  93. {
  94.     std::string s = std::to_string(x);
  95.     std::string t;
  96.     while (s.size())
  97.     {
  98.         for (int cnt = 3; cnt-- && s.size(); )
  99.         {
  100.             t += s.back();
  101.             s.pop_back();
  102.         }
  103.         if (s.size())
  104.             t += '.';
  105.     }
  106.     std::reverse(t.begin(), t.end());
  107.     return t;
  108. }
  109.  
  110. int main(int argc, const char *argv[])
  111. {
  112.     if (argc != 3)
  113.     {
  114.         std::cout << "Usage: ./main <num copies> <input file>" << std::endl;
  115.         return 0;
  116.     }
  117.     const int nFields = std::atoi(argv[1]);
  118.     std::cout << "   nFields: " << nFields << std::endl;
  119.     const char *inputFileName = argv[2];
  120.     std::cout << "input file: '" << inputFileName << "'" << std::endl;
  121.     // reading of the maze from the input file:
  122.     std::ifstream fin(inputFileName);
  123.     if (!fin)
  124.     {
  125.         std::cout << "Can't open the file '" << inputFileName << "'" << std::endl;
  126.         return 0;
  127.     }
  128.     std::vector<std::vector<bool>> f(21, std::vector<bool>(31, 1));
  129.     for (int i = 0; i < 21; i++)
  130.         for (int j = 0; j < 31; j++)
  131.         {
  132.             char ch; fin >> ch;
  133.             f[i][j] = (ch == '#');
  134.         }
  135.    
  136.     // cycle over all of the devices:
  137.     std::cout << "List of available devices:\n";
  138.     for (int i = 0; auto device : compute::system::devices())
  139.         std::cout << std::setw(4) << i++ << ":\t" << device << std::endl;
  140.    
  141.     // get the default device
  142.     compute::device device = compute::system::default_device();
  143.     std::cout << "\nDefault device will be used:\n\t" << device << std::endl;
  144.     compute::context context(device);
  145.     compute::command_queue queue(context, device);    
  146.    
  147.     // start the measuring of runtime:
  148.     long long start = currTimeInNanos();
  149.    
  150.     // create vector of `nFields` copies of input field:
  151.     std::vector<Field> host_vector(nFields, setField(f));
  152.    
  153.     // create a vector on the device
  154.     compute::vector<Field> device_vector(host_vector.size(), context);
  155.    
  156.     // transfer data from the host to the device
  157.     compute::copy(host_vector.begin(), host_vector.end(), device_vector.begin(), queue);
  158.    
  159.     // calculate the answer for each field on GPU:
  160.     compute::transform(
  161.         device_vector.begin(), device_vector.end(), // input range
  162.         device_vector.begin(), // begin of output range
  163.         bugMovingGPU, queue // the lambda function which will be applied to each maze, and device's queue
  164.     );
  165.    
  166.     // copy calculated mazes back to the host
  167.     compute::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
  168.    
  169.     // finish the measuring of runtime:
  170.     long long finish = currTimeInNanos();
  171.     double runtime = (finish - start) * 1e-9;
  172.    
  173.     // calculating number of completed ops:
  174.     long long totalGPU = 0;
  175.     for (const auto &it : host_vector)
  176.         totalGPU += accumulateTheAnswer(it);
  177.     long long speedGPU = totalGPU / runtime;
  178.    
  179.     // print the statistics:
  180.     std::cout << "\nCompleted during " << runtime << " seconds:\n";
  181.     std::cout << "  GPU ops: " << std::setw(18) << printWithDots(totalGPU) << std::endl;
  182.        
  183.     std::cout << "\nProductivity per 1 second:\n";
  184.     std::cout << "GPU Speed: " << std::setw(18) << printWithDots(speedGPU) << "/s" << std::endl;
  185.    
  186.     return 0;
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement