/* * numerical integration example, as discussed in textbook: * * compute pi by approximating the area under the curve f(x) = 4 / (1 + x*x) * between 0 and 1. * * parallel version using C++11 threads and futures/promises. * * based on example in stack overflow post: * https://stackoverflow.com/questions/7686939/c-simple-return-value-from-stdt hread * * command-line argument gives number of threads. */ #include #include #include /* copied from not-strictly-standard part of math.h */ #define M_PI 3.14159265358979323846 #include #include #include #include #include "timer.h" /* has get_time() */ void thread_fcn(int my_id, int num_threads, long num_steps, double step, std::promise&& p_part_sum); /* ---- main program ---- */ int main(int argc, char *argv[]) { const char* usage_fmt = "usage: %s number_of_steps number_of_threads\n"; /* process command-line arguments */ char* end_ptr_for_strtol; if (argc != 3) { fprintf(stderr, usage_fmt, argv[0]); exit(EXIT_FAILURE); } long num_steps = strtol(argv[1], &end_ptr_for_strtol, 10); if (*end_ptr_for_strtol != '\0') { fprintf(stderr, usage_fmt, argv[0]); exit(EXIT_FAILURE); } int num_threads = strtol(argv[2], &end_ptr_for_strtol, 10); if (*end_ptr_for_strtol != '\0') { fprintf(stderr, usage_fmt, argv[0]); exit(EXIT_FAILURE); } double start_time, end_time; double pi; double sum = 0.0; double step = 1.0/(double) num_steps; std::mutex mutex; /* record start time */ start_time = get_time(); /* * create and start threads, also creating for each a future and a promise * so we can return a value. */ std::vector threads; std::vector> futures; for (int i = 0; i < num_threads; ++i) { std::promise p; futures.push_back(p.get_future()); /* * note use of std::move: * this is adapted from the above-mentioned stack overflow post * and I hope is how you safely "move" p (a local variable) to * the new thread. */ threads.push_back(std::thread( thread_fcn, i, num_threads, num_steps, step, std::move(p))); } /* wait for them to complete */ for (auto& t : threads) { t.join(); } /* get and combine results */ for (auto& f : futures) { sum += f.get(); } /* finish computation */ pi = step * sum; /* record end time */ end_time = get_time(); /* print results */ printf("parallel program results with %d threads and %ld steps:\n", num_threads, num_steps); printf("computed pi = %g (%17.15f)\n",pi, pi); printf("difference between computed pi and math.h M_PI = %17.15f\n", fabs(pi - M_PI)); printf("time to compute = %g seconds\n", end_time - start_time); return EXIT_SUCCESS; } /* ---- code to be executed by each thread ---- */ void thread_fcn(int my_id, int num_threads, long num_steps, double step, std::promise&& p_part_sum) { double x; double part_sum = 0.0; /* do this thread's part of computation */ for (int i=my_id; i < num_steps; i += num_threads) { x = (i+0.5)*step; part_sum += 4.0/(1.0+x*x); } /* set up to return partial sum to caller */ p_part_sum.set_value(part_sum); }