Advertisement
Guest User

Untitled

a guest
Oct 16th, 2022
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.47 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdint.h>
  5. #include <omp.h>
  6.  
  7.  
  8. size_t get_subtree_size(const size_t array_size) {                                  // calculates subtree size
  9.     size_t subtree_size = 1;
  10.     while (subtree_size < array_size) {
  11.         subtree_size <<= 1u;
  12.     }
  13.     return subtree_size;
  14. }
  15.  
  16.  
  17. uint64_t * initialize_array(const size_t array_size) {                              // initialize array
  18.     uint64_t *a = (uint64_t *) calloc(array_size, sizeof(uint64_t));
  19.  
  20.     for (size_t i = 0; i < array_size; ++i) {
  21.         a[i] = i;
  22.     }
  23.  
  24.     return a;
  25. }
  26.  
  27.  
  28. void build_range_tree(
  29.     const uint64_t *a, const size_t array_size, uint64_t *tree,
  30.     const size_t subtree_size, const size_t threads_count) {
  31.  
  32.     #pragma omp parallel num_threads(threads_count)
  33.     {
  34.         #pragma omp for schedule(static)
  35.         for (size_t i = 0; i < array_size; ++i) {
  36.             tree[i + subtree_size] = a[i];
  37.         }
  38.     }
  39.  
  40.     size_t current_layer_size = (subtree_size >> 1u);
  41.     while (current_layer_size > 0) {
  42.         #pragma opm parallel num_threads(threads_count)
  43.         {
  44.             #pragma omp for schedule(static)
  45.             for (size_t i = current_layer_size; i < (current_layer_size << 1u); ++i) {
  46.                 tree[i] = tree[i << 1u] + tree[(i << 1u) + 1];
  47.             }
  48.         }
  49.         current_layer_size >>= 1u;
  50.     }
  51. }
  52.  
  53.  
  54. uint64_t find_sum_from_subtrees(                                               // right boundaries are not included
  55.     const uint64_t* tree, const size_t left, const size_t right,
  56.     const size_t current_node_index, const size_t current_left,
  57.     const size_t current_right) {
  58.  
  59.     if (left == right || right < current_left || current_right < left) {       // target range not in current observed range
  60.         return 0;
  61.     }
  62.     if (current_left <= left && right <= current_right) {                      // target range is completeley in observed range
  63.         return tree[current_node_index];
  64.     }
  65.  
  66.     const size_t middle = (right + left) >> 1u;                                // getting sums from subtrees
  67.     return
  68.         find_sum_from_subtrees(tree, left, right, current_node_index << 1u, current_left, middle) +
  69.         find_sum_from_subtrees(tree, left, right, (current_node_index << 1u) + 1, middle, current_right);
  70. }
  71.  
  72.  
  73. uint64_t sum_query(                                                            // query wrapper function (for convenient usage)
  74.     const uint64_t *tree, const size_t subtree_size,
  75.     const size_t left, const size_t right) {                                   // right boundary is included
  76.  
  77.     return find_sum_from_subtrees(tree, left, right + 1, 1, 0, subtree_size);  
  78. }
  79.  
  80.  
  81. void perform_queries(                                                          // function for performing queries
  82.     const uint64_t *tree, const size_t queries_count,
  83.     uint64_t *results, const size_t subtree_size, const size_t threads_count) {
  84.  
  85.     #pragma omp parallel num_threads(threads_count)
  86.     {
  87.         #pragma omp for schedule(static)
  88.         for (size_t i = 0; i < queries_count; ++i) {
  89.             size_t left_bound = (subtree_size >> 2u);
  90.             size_t right_bound = left_bound + (subtree_size >> 1u);
  91.             results[i] = sum_query(tree, subtree_size, left_bound, right_bound);
  92.         }
  93.     }
  94. }
  95.  
  96.  
  97. int main(const int argc, const char** argv) {
  98.     if (argc != 5) {                                // check valid launch parameters
  99.         printf(
  100.             "Invalid arguments!\n"
  101.             "argv[1] = threads count\n"
  102.             "argv[2] = input array size\n"
  103.             "argv[3] = queries count\n"
  104.             "argv[4] = launches' count\n"
  105.         );
  106.         return 1;
  107.     }
  108.  
  109.     int32_t threads_count;
  110.     size_t array_size;
  111.     size_t queries_count;
  112.     size_t launches_count;
  113.     size_t subtree_size;
  114.    
  115.     sscanf(argv[1], "%d", &threads_count);         // reading program parameters
  116.     if (threads_count <= 0) {
  117.         printf("threads count must be > 0");
  118.     return 2;
  119.     }
  120.     sscanf(argv[2], "%llu", &array_size);
  121.     sscanf(argv[3], "%llu", &queries_count);
  122.     sscanf(argv[4], "%llu", &launches_count);
  123.     subtree_size = get_subtree_size(array_size);
  124.  
  125.     uint64_t *a = initialize_array(array_size);                                 // array initialization
  126.     uint64_t *results = (uint64_t *) calloc(queries_count, sizeof(uint64_t));   // getting memroy for calculation results holding
  127.     uint64_t *tree = (uint64_t *) calloc(subtree_size << 1u, sizeof(uint64_t)); // getting memory for tree holding
  128.  
  129.     double summary_building_time = 0;
  130.     double summary_queries_time = 0;
  131.  
  132.     for (size_t i = 0; i < launches_count; ++i) {                                   // main launch loop for time measurement
  133.         double building_start = omp_get_wtime();                                    // building time measurement
  134.         build_range_tree(a, array_size, tree, subtree_size, (size_t) threads_count);
  135.     summary_building_time += (omp_get_wtime() - building_start);
  136.  
  137.     double queries_start = omp_get_wtime();                                             // queries execution time measurement
  138.         perform_queries(tree, queries_count, results, subtree_size, (size_t) threads_count);
  139.     summary_queries_time += (omp_get_wtime() - queries_start);
  140.     }
  141.  
  142.     free(a);
  143.     free(results);
  144.     free(tree);
  145.  
  146.     printf("%lf %lf\n", summary_building_time / launches_count, summary_queries_time / launches_count);
  147.     return 0;
  148. }
  149.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement