Created
February 21, 2017 03:05
-
-
Save dtoma/ee70f0871adaa4a5db77dc795255676f to your computer and use it in GitHub Desktop.
C++ OpenMP Pi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // http://jakascorner.com/blog/2016/05/omp-monte-carlo-pi.html | |
| #include <iostream> | |
| #include <chrono> | |
| #include <random> | |
| #include <vector> | |
| #include <string> | |
| #include <iomanip> | |
| #include <limits> | |
| #include <chrono> | |
| class UniformDistribution | |
| { | |
| public: | |
| UniformDistribution() | |
| : generator(), | |
| distribution(-1.0, 1.0) | |
| { | |
| int seed = std::chrono::system_clock::now().time_since_epoch().count(); | |
| generator.seed(seed); | |
| } | |
| double sample() | |
| { | |
| return distribution(generator); | |
| } | |
| UniformDistribution(const UniformDistribution& ) = delete; | |
| UniformDistribution& operator()(const UniformDistribution& ) = delete; | |
| UniformDistribution(UniformDistribution&& ) = delete; | |
| UniformDistribution& operator()(UniformDistribution&& ) = delete; | |
| private: | |
| std::default_random_engine generator; | |
| std::uniform_real_distribution<double> distribution; | |
| }; | |
| inline double approximatePi(const int numSamples) | |
| { | |
| UniformDistribution distribution; | |
| int counter = 0; | |
| for (int s = 0; s != numSamples; s++) | |
| { | |
| auto x = distribution.sample(); | |
| auto y = distribution.sample(); | |
| if (x * x + y * y < 1) | |
| { | |
| counter++; | |
| } | |
| } | |
| return 4.0 * counter / numSamples; | |
| } | |
| inline int samplesInsideCircle(const int numSamples) | |
| { | |
| UniformDistribution distribution; | |
| int counter = 0; | |
| for (int s = 0; s != numSamples; s++) | |
| { | |
| auto x = distribution.sample(); | |
| auto y = distribution.sample(); | |
| if (x * x + y * y < 1) | |
| { | |
| counter++; | |
| } | |
| } | |
| return counter; | |
| } | |
| inline void sequentialPi() | |
| { | |
| const int numSamples = 1000000000; | |
| const auto approxPi = approximatePi(numSamples); | |
| printf("Sequential version:\nnumber of samples: %d\nreal Pi: 3.141592653589...\napprox.: %.12f\n", numSamples, approxPi); | |
| } | |
| inline void parallelPi() | |
| { | |
| const int numTotalSamples = 1000000000; | |
| int numChunks = 8; | |
| int chunk = numTotalSamples / numChunks; | |
| int counter = 0; | |
| #pragma omp parallel for shared(numChunks, chunk) reduction(+:counter) | |
| for (int i = 0; i < numChunks; i++) | |
| { | |
| counter += samplesInsideCircle(chunk); // maybee change to | |
| } | |
| const double approxPi = 4.0 * counter / numTotalSamples; | |
| printf("Parallel version:\nnumber of samples: %d\nreal Pi: 3.141592653589...\napprox.: %.12f\n", numTotalSamples, approxPi); | |
| } | |
| int main() | |
| { | |
| using millis = std::chrono::milliseconds; | |
| using std::chrono::duration_cast; | |
| using std::chrono::steady_clock; | |
| auto t_seq_1 = steady_clock::now(); | |
| sequentialPi(); | |
| auto t_seq_2 = steady_clock::now(); | |
| auto time1 = duration_cast<millis>( t_seq_2 - t_seq_1 ).count(); | |
| std::cout << "Time: " << time1 << " millisecons.\n" << std::endl; | |
| auto t_par_1 = steady_clock::now(); | |
| parallelPi(); | |
| auto t_par_2 = steady_clock::now(); | |
| auto time2 = duration_cast<millis>( t_par_2 - t_par_1 ).count(); | |
| std::cout << "Time: " << time2 << " millisecons.\n" << std::endl; | |
| return 0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment