Commit f3488225 authored by Ciarán Ó Rourke's avatar Ciarán Ó Rourke
Browse files

* Initial Commit

parents
cmake_minimum_required(VERSION 3.10)
project(
pi_monte_carlo
VERSION 0.0.1
LANGUAGES CXX
)
# Find needed libraries #########################################
find_package(MPI REQUIRED)
# Setup the pi_monte_carlo library #####################################
add_executable(
pi_monte_carlo
src/pi.cc
)
target_compile_features(pi_monte_carlo PUBLIC cxx_std_14)
target_link_libraries(pi_monte_carlo PRIVATE ${MPI_CXX_LIBRARIES})
target_include_directories(pi_monte_carlo PRIVATE ${MPI_CXX_INCLUDE_PATH})
message(STATUS "MPI_CXX_LIBRARIES = ${MPI_CXX_LIBRARIES}")
message(STATUS "MPI_CXX_INCLUDE_PATH = ${MPI_CXX_INCLUDE_PATH}")
# Pi Monte Carlo
## Build
Execute `./build.sh`
## Run
Execute `mpirun ./build/pi_monte_carlo
#!/bin/bash
script="${BASH_SOURCE[0]:-${(%):-%x}}"
script_dir="$( cd "$( dirname "${script}" )" >/dev/null 2>&1 && pwd )"
build_dir="${script_dir}/build"
mkdir -p ${build_dir}
pushd ${build_dir}
cmake \
"${script_dir}"
make -j 4
popd # build_dir
#include <algorithm>
#include <array>
#include <chrono>
#include <cmath>
#include <iostream>
#include <limits>
#include <mpi.h>
#include <random>
#include <vector>
const unsigned long long BATCH_SIZE = 100000;
const unsigned long long NUM_BATCHES = 10000000;
std::vector<std::array<double, 2>> generate_random_pairs(
const unsigned long long& n, std::default_random_engine& rng)
{
std::uniform_real_distribution<double> distribution(0, 1);
std::vector<std::array<double, 2>> batch(n);
std::for_each(batch.begin(), batch.end(), [&](std::array<double, 2>& pair) {
pair[0] = distribution(rng);
pair[1] = distribution(rng);
});
return batch;
}
bool is_hit(const std::array<double, 2>& pair)
{
if (std::pow(pair[0], 2) + std::pow(pair[1], 2) <= 1) {
return true;
}
return false;
}
/* returns number of hits */
unsigned long long run_batch(
const std::vector<std::array<double, 2>> coordinate_pairs)
{
unsigned long long hits = 0;
std::for_each(
coordinate_pairs.begin(), coordinate_pairs.end(),
[&](std::array<double, 2> pair) {
if (is_hit(pair)) {
hits++;
}
});
return hits;
}
void print_pi(const double& hit_ratio)
{
std::cout << "\r"
<< "Pi = " << 4.0 * hit_ratio << std::flush;
}
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
std::default_random_engine rng(
std::chrono::system_clock::now().time_since_epoch().count());
std::cout.precision(std::numeric_limits<double>::max_digits10);
unsigned long long hits = 0;
for (unsigned long long i = 0; i < NUM_BATCHES; i++) {
std::vector<std::array<double, 2>> coordinate_pairs =
generate_random_pairs(BATCH_SIZE, rng);
hits += run_batch(coordinate_pairs);
unsigned long long global_hits = 0;
MPI_Reduce(
&hits, &global_hits, 1, MPI_UNSIGNED_LONG_LONG, MPI_SUM, 0,
MPI_COMM_WORLD);
if (rank == 0) {
unsigned long long attempts = (1 + i) * BATCH_SIZE * size;
print_pi(
static_cast<double>(global_hits)
/ static_cast<double>(attempts));
}
}
MPI_Finalize();
return 0;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment