Advertisement
sepi0l

hpc_reduction

Apr 25th, 2024
707
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.14 KB | None | 0 0
  1. #include <limits.h>
  2. #include <omp.h>
  3. #include <stdlib.h>
  4. #include <array>
  5. #include <chrono>
  6. #include <functional>
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. using std::chrono::duration_cast;
  11. using std::chrono::high_resolution_clock;
  12. using std::chrono::milliseconds;
  13. using namespace std;
  14.  
  15. void s_avg(int arr[], int n)
  16. {
  17.     long sum = 0L;
  18.     int i;
  19.     for (i = 0; i < n; i++)
  20.     {
  21.         sum = sum + arr[i];
  22.     }
  23.     cout <<"sequential average: "<<sum / long(n);
  24. }
  25. void p_avg(int arr[], int n)
  26. {
  27.     long sum = 0L;
  28.     int i;
  29.     #pragma omp parallel for reduction(+ : sum) num_threads(16)
  30.     for (i = 0; i < n; i++)
  31.     {
  32.         sum = sum + arr[i];
  33.     }
  34.     cout <<"parallel average: "<<sum / long(n);
  35. }
  36. void s_sum(int arr[], int n)
  37. {
  38.     long sum = 0L;
  39.     int i;
  40.     for (i = 0; i < n; i++)
  41.     {
  42.         sum = sum + arr[i];
  43.     }
  44.     cout <<"sequential sum: "<<sum;
  45. }
  46.  
  47. void p_sum(int arr[], int n)
  48. {
  49.     long sum = 0L;
  50.     int i;
  51.     #pragma omp parallel for reduction(+ : sum) num_threads(16)
  52.     for (i = 0; i < n; i++)
  53.     {
  54.         sum = sum + arr[i];
  55.     }
  56.     cout <<"parallel sum: "<<sum;
  57. }
  58. void s_max(int arr[], int n)
  59. {
  60.     int max_val = INT_MIN;
  61.     int i;
  62.     for (i = 0; i < n; i++)
  63.     {
  64.         if (arr[i] > max_val)
  65.         {
  66.             max_val = arr[i];
  67.         }
  68.     }
  69.     cout <<"sequential max: "<<max_val;
  70. }
  71.  
  72. void p_max(int arr[], int n)
  73. {
  74.     int max_val = INT_MIN;
  75.     int i;
  76.     #pragma omp parallel for reduction(max : max_val) num_threads(16)
  77.     for (i = 0; i < n; i++)
  78.     {
  79.         if (arr[i] > max_val)
  80.         {
  81.             max_val = arr[i];
  82.         }
  83.     }
  84.     cout <<"parallel max: "<<max_val;
  85. }
  86. void s_min(int arr[], int n)
  87. {
  88.     int min_val = INT_MAX;
  89.     int i;
  90.     for (i = 0; i < n; i++)
  91.     {
  92.         if (arr[i] < min_val)
  93.         {
  94.             min_val = arr[i];
  95.         }
  96.     }
  97.     cout <<"sequential min: "<<min_val;
  98. }
  99.  
  100. void p_min(int arr[], int n)
  101. {
  102.     int min_val = INT_MAX;
  103.     int i;
  104.     #pragma omp parallel for reduction(min : min_val) num_threads(16)
  105.     for (i = 0; i < n; i++) {
  106.         if (arr[i] < min_val)
  107.         {
  108.             min_val = arr[i];
  109.         }
  110.     }
  111.     cout <<"parallel min: "<<min_val;
  112. }
  113. std::string bench_traverse(std::function<void()> traverse_fn)
  114. {
  115.     auto start = high_resolution_clock::now();
  116.     traverse_fn();
  117.     cout << " (";
  118.     auto stop = high_resolution_clock::now();
  119.     // Subtract stop and start timepoints and cast it to required unit.
  120.     // Predefined units are nanoseconds, microseconds, milliseconds, seconds, // minutes, hours. Use duration_cast() function.
  121.     auto duration = duration_cast<milliseconds>(stop - start);
  122.     // To get the value of duration use the count() member function on the
  123.     // duration object
  124.     return std::to_string(duration.count());
  125. }
  126.  
  127. int main(int argc, const char **argv)
  128. {
  129.    
  130.     long sum = 0L;
  131.     int *a, n, rand_max;
  132.    
  133.     cout << "length of the array ";
  134.     cin >> n;
  135.     cout << "max element ";
  136.     cin >> rand_max;
  137.    
  138.     a = new int[n];
  139.     for (int i = 0; i < n; i++)
  140.     {
  141.         a[i] = rand() % rand_max;
  142.     }
  143.     cout << "Generated random array of length " << n << " with elements between 0 to " << rand_max << "\n\n";
  144.     cout << "Given array is \n";
  145.     for (int i = 0; i < n; i++)
  146.     {
  147.         cout << a[i] << ", ";
  148.     }
  149.     cout << "\n\n";
  150.     omp_set_num_threads(16);
  151.  
  152.     std::cout << "Sequential Min: " << bench_traverse([&] { s_min(a, n); }) << "ms)\n";
  153.     std::cout << "Parallel (16) Min: " << bench_traverse([&] { p_min(a, n); }) << "ms)\n\n";
  154.     std::cout << "Sequential Max: " << bench_traverse([&] { s_max(a, n); }) << "ms)\n";
  155.     std::cout << "Parallel (16) Max:" << bench_traverse([&] { p_max(a, n); }) << "ms)\n\n";
  156.     std::cout << "Sequential Sum: " << bench_traverse([&] { s_sum(a, n); }) << "ms)\n";
  157.     std::cout << "Parallel (16) Sum: " << bench_traverse([&] { p_sum(a, n); }) << "ms)\n\n";
  158.     std::cout << "Sequential Average: " << bench_traverse([&] { s_avg(a, n); }) << "ms)\n";
  159.     std::cout << "Parallel (16) Average: " << bench_traverse([&] { p_avg(a, n); }) << "ms)\n\n";
  160.     return 0;
  161. }
  162.  
  163. /*
  164. This code measures the performance of various array operations such as finding the minimum,
  165. maximum, sum, and average in both sequential and parallel implementations using OpenMP. Let's break it down:
  166.  
  167. **Array Operations Functions:**
  168. 1. **Sequential Functions (`s_avg`, `s_sum`, `s_max`, `s_min`):** These functions perform the
  169. array operations sequentially without any parallelization. They calculate the average, sum,
  170. maximum, and minimum values respectively.
  171.  
  172. 2. **Parallel Functions (`p_avg`, `p_sum`, `p_max`, `p_min`):** These functions use OpenMP to
  173. parallelize the array operations. OpenMP directives (`#pragma omp parallel for reduction`) are
  174. used to distribute the work among threads and compute the result concurrently.
  175.  
  176. **Benchmarking Function (`bench_traverse`):**
  177. - This function takes a lambda function as an argument and measures the time taken to execute that function.
  178. - It records the start time, executes the function, records the stop time, calculates the duration, and returns it as milliseconds.
  179.  
  180. **Main Function:**
  181. - It dynamically generates an array of random integers with a specified length and maximum value.
  182. - Each array operation is benchmarked for both sequential and parallel implementations.
  183. - The number of threads for parallel execution is set to 16 using `omp_set_num_threads(16)`.
  184.  
  185. **Output:**
  186. - For each array operation (min, max, sum, average), the code prints the time taken for both sequential
  187. and parallel implementations in milliseconds.
  188.  
  189. **Parallelism in Array Operations:**
  190. - Parallelism is introduced using OpenMP directives such as `#pragma omp parallel for reduction`. This
  191. ensures that the work is distributed among multiple threads, and the results are combined correctly.
  192.  
  193. **Note:**
  194. - The array operations are independent of each other, allowing them to be executed concurrently in
  195. parallel implementations.
  196.  
  197. This code demonstrates how to parallelize array operations using OpenMP to improve performance by
  198. leveraging multiple threads.
  199. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement