1 | // Copyright David Abrahams 2008. Distributed under the Boost
|
---|
2 | // Software License, Version 1.0. (See accompanying
|
---|
3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
---|
4 | #include "boost/thread.hpp"
|
---|
5 | #include "boost/iterator/counting_iterator.hpp"
|
---|
6 | #include "boost/lambda/lambda.hpp"
|
---|
7 | #include "boost/lambda/bind.hpp"
|
---|
8 | #include "boost/timer.hpp"
|
---|
9 | #include "boost/type_traits/remove_const.hpp"
|
---|
10 | #include "boost/type_traits/remove_reference.hpp"
|
---|
11 | #include "boost/array.hpp"
|
---|
12 | #include "boost/date_time/local_time/local_time.hpp"
|
---|
13 | #include <vector>
|
---|
14 | #include <iterator>
|
---|
15 | #include <numeric>
|
---|
16 | #include <algorithm>
|
---|
17 | #include <cmath>
|
---|
18 | #include <iostream>
|
---|
19 |
|
---|
20 | namespace my
|
---|
21 | {
|
---|
22 | double sqrt(double x)
|
---|
23 | {
|
---|
24 | return std::sqrt(x);
|
---|
25 | }
|
---|
26 | }
|
---|
27 |
|
---|
28 | // sum terms [i-j) of the power series for pi/4
|
---|
29 | double calc(std::size_t i, std::size_t j)
|
---|
30 | {
|
---|
31 | double sum = 0.0;
|
---|
32 |
|
---|
33 | while (i < j)
|
---|
34 | {
|
---|
35 | sum += (i % 2 == 0 ? 1.0 : -1.0) / (2*i + 1);
|
---|
36 | ++i;
|
---|
37 | }
|
---|
38 | return sum;
|
---|
39 | }
|
---|
40 |
|
---|
41 | std::size_t const max_parallelism = 20;
|
---|
42 | typedef boost::array<boost::thread, max_parallelism> thread_pool;
|
---|
43 | typedef boost::array<double, max_parallelism> result_pool;
|
---|
44 |
|
---|
45 | double calc_pi(std::size_t nterms, std::size_t parallelism, thread_pool& threads, result_pool& results)
|
---|
46 | {
|
---|
47 | assert(parallelism > 0 && parallelism <= threads.size()); // make sure we've allocated enough space
|
---|
48 | assert(threads.size() == results.size()); // make sure we've allocated enough space
|
---|
49 |
|
---|
50 | using namespace boost::lambda;
|
---|
51 | double const step = nterms * 1.0 / parallelism;
|
---|
52 | for (int i = 1; i < parallelism; ++i)
|
---|
53 | {
|
---|
54 | threads[i] = boost::thread(
|
---|
55 | var(results[i]) = bind(calc, i * step, (i+1) * step)
|
---|
56 | );
|
---|
57 | }
|
---|
58 |
|
---|
59 | // do a calculation in this thread
|
---|
60 | results[0] = calc(0, step);
|
---|
61 |
|
---|
62 | // wait for all threads to finish
|
---|
63 | for (int i = 1; i < parallelism; ++i)
|
---|
64 | threads[i].join();
|
---|
65 |
|
---|
66 | return std::accumulate( results.begin(), results.begin() + parallelism, 0.0 );
|
---|
67 | }
|
---|
68 |
|
---|
69 |
|
---|
70 |
|
---|
71 | int main()
|
---|
72 | {
|
---|
73 | std::size_t const n = 200000000;
|
---|
74 |
|
---|
75 |
|
---|
76 | thread_pool threads;
|
---|
77 | result_pool results;
|
---|
78 |
|
---|
79 | std::cout << "warming up the cache..." << std::endl;
|
---|
80 | double pi = 4*calc_pi(n, 4, threads, results);
|
---|
81 | std::cout << "start" << std::endl;
|
---|
82 |
|
---|
83 | for (std::size_t p = 1; p < max_parallelism; ++p)
|
---|
84 | {
|
---|
85 | using namespace boost::gregorian;
|
---|
86 | using namespace boost::posix_time;
|
---|
87 | using namespace boost::local_time;
|
---|
88 |
|
---|
89 | ptime start = microsec_clock::local_time();
|
---|
90 | boost::timer time;
|
---|
91 |
|
---|
92 | pi = 4*calc_pi(n, p, threads, results);
|
---|
93 | microsec_clock::time_duration_type t0 = microsec_clock::local_time() - start;
|
---|
94 | double t1 = time.elapsed();
|
---|
95 |
|
---|
96 | std::cout << "calculating pi = " << pi << " using " << p << " threads took: " << t0 << " but timer reports: " << t1 << std::endl;
|
---|
97 | }
|
---|
98 | }
|
---|