1 /* 2 Copyright (c) 2023 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #include "oneapi/tbb/tick_count.h" 18 19 #include "common/utility/get_default_num_threads.hpp" 20 #include "common/utility/utility.hpp" 21 22 #include "common.h" 23 24 const number_t chunk_size = 4096; // Multiple of 16, to fit float datatype to a vector register. 25 26 // number of intervals 27 number_t num_intervals = 1000000000; 28 pi_t step = pi_t(0.0); 29 30 bool silent = false; 31 32 double compute_pi_serial() { 33 double ret = 0; 34 35 step = pi_t(1.0) / num_intervals; 36 37 number_t tail = num_intervals % chunk_size; 38 number_t last = num_intervals - tail; 39 40 for (number_t slice = 0; slice < last; slice += chunk_size) { 41 ret += pi_slice_kernel(slice); 42 } 43 ret += pi_slice_kernel(last, tail); 44 ret *= step; 45 46 return ret; 47 } 48 49 int main(int argc, char* argv[]) { 50 try { 51 tbb::tick_count main_start_time = tbb::tick_count::now(); 52 // zero number of threads means to run serial version 53 utility::thread_number_range threads(utility::get_default_num_threads, 0); 54 55 utility::parse_cli_arguments( 56 argc, 57 argv, 58 utility::cli_argument_pack() 59 //"-h" option for for displaying help is present implicitly 60 .positional_arg(threads, "n-of-threads", utility::thread_number_range_desc) 61 .positional_arg(num_intervals, "n-of-intervals", "number of intervals") 62 .arg(silent, "silent", "no output except time elapsed")); 63 64 for (int p = threads.first; p <= threads.last; p = threads.step(p)) { 65 pi_t pi; 66 double compute_time; 67 if (p == 0) { 68 //run a serial version 69 tbb::tick_count compute_start_time = tbb::tick_count::now(); 70 pi = compute_pi_serial(); 71 compute_time = (tbb::tick_count::now() - compute_start_time).seconds(); 72 } 73 else { 74 //run a parallel version 75 threading tp(p); 76 tbb::tick_count compute_start_time = tbb::tick_count::now(); 77 pi = compute_pi_parallel(); 78 compute_time = (tbb::tick_count::now() - compute_start_time).seconds(); 79 } 80 81 if (!silent) { 82 if (p == 0) { 83 std::cout << "Serial run:\tpi = " << pi << "\tcompute time = " << compute_time 84 << " sec\n"; 85 } 86 else { 87 std::cout << "Parallel run:\tpi = " << pi << "\tcompute time = " << compute_time 88 << " sec\t on " << p << " threads\n"; 89 } 90 } 91 } 92 93 utility::report_elapsed_time((tbb::tick_count::now() - main_start_time).seconds()); 94 return 0; 95 } 96 catch (std::exception& e) { 97 std::cerr << "error occurred. error text is :\"" << e.what() << "\"\n"; 98 return 1; 99 } 100 } 101