diff --git a/examples/03_stencil/CMakeLists.txt b/examples/03_stencil/CMakeLists.txt index f50be77..d3ffc2e 100644 --- a/examples/03_stencil/CMakeLists.txt +++ b/examples/03_stencil/CMakeLists.txt @@ -3,11 +3,11 @@ # Distributed under the Boost Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.14) project(stencil CXX) -find_package(HPX 1.7.0 REQUIRED) +find_package(HPX 1.9.0 REQUIRED) add_executable(stencil_serial stencil_serial.cpp) target_link_libraries(stencil_serial PRIVATE HPX::hpx HPX::wrap_main) diff --git a/examples/03_stencil/communicator.hpp b/examples/03_stencil/communicator.hpp index 28aa740..bdf9c4d 100644 --- a/examples/03_stencil/communicator.hpp +++ b/examples/03_stencil/communicator.hpp @@ -3,8 +3,7 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef STENCIL_COMMUNICATOR_HPP -#define STENCIL_COMMUNICATOR_HPP +#pragma once #include @@ -13,45 +12,56 @@ template struct communicator { - enum neighbor { + enum neighbor + { up = 0, down = 1, }; - typedef hpx::lcos::channel channel_type; + using channel_type = hpx::distributed::channel; // rank: our rank in the system // num: number of participating partners communicator(std::size_t rank, std::size_t num) { - static const char* up_name = "/stencil/up/"; - static const char* down_name = "/stencil/down/"; - // Only set up channels if we have more than one partner if (num > 1) { + constexpr char const* down_name = "/stencil/down/"; + constexpr char const* up_name = "/stencil/up/"; + // We have an upper neighbor if our rank is greater than zero. if (rank > 0) { - // Retrieve the channel from our upper neighbor from which we receive - // the row we need to update the first row in our partition. - recv[up] = hpx::find_from_basename(down_name, rank - 1); + // Retrieve the channel from our upper neighbor from which we + // receive the row we need to update the first row in our + // partition. + recv[up] = + hpx::find_from_basename(down_name, rank - 1); // Create the channel we use to send our first row to our upper // neighbor send[up] = channel_type(hpx::find_here()); - // Register the channel with a name such that our neighbor can find it. + + // Register the channel with a name such that our neighbor can + // find it. hpx::register_with_basename(up_name, send[up], rank); } + if (rank < num - 1) { - // Retrieve the channel from our neighbor below from which we receive - // the row we need to update the last row in our partition. - recv[down] = hpx::find_from_basename(up_name, rank + 1); - // Create the channel we use to send our last row to our neighbor - // below + // Retrieve the channel from our neighbor below from which we + // receive the row we need to update the last row in our + // partition. + recv[down] = + hpx::find_from_basename(up_name, rank + 1); + + // Create the channel we use to send our last row to our + // neighbor below send[down] = channel_type(hpx::find_here()); - // Register the channel with a name such that our neighbor can find it. + + // Register the channel with a name such that our neighbor can + // find it. hpx::register_with_basename(down_name, send[down], rank); } } @@ -76,8 +86,6 @@ struct communicator return recv[n].get(hpx::launch::async, step); } - std::array, 2> recv; - std::array, 2> send; + std::array, 2> recv; + std::array, 2> send; }; - -#endif diff --git a/examples/03_stencil/line_iterator.hpp b/examples/03_stencil/line_iterator.hpp index 5ef2618..d25999e 100644 --- a/examples/03_stencil/line_iterator.hpp +++ b/examples/03_stencil/line_iterator.hpp @@ -3,43 +3,40 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef STENCIL_LINE_ITERATOR_HPP -#define STENCIL_LINE_ITERATOR_HPP +#pragma once #include -template +template struct line_iterator - // iterator_facade is a facade class that defines the boilerplate needed for - // a proper standard C++ iterator. As a user, we only have to define basic - // functions + // iterator_facade is a facade class that defines the boilerplate needed for a + // proper standard C++ iterator. As a user, we only have to define basic + // functions : hpx::util::iterator_facade< // Our type: line_iterator, // Value type (When dereferencing the iterator) double, // Our iterator is random access. - std::random_access_iterator_tag - > + std::random_access_iterator_tag> { private: - typedef - hpx::util::iterator_facade< - // Our type: - line_iterator, - // Value type (When dereferencing the iterator) - double, - // Our iterator is random access. - std::random_access_iterator_tag - > - base_type; + using base_type = hpx::util::iterator_facade< + // Our type: + line_iterator, + // Value type (When dereferencing the iterator) + double, + // Our iterator is random access. + std::random_access_iterator_tag>; public: line_iterator(UpIter up_, MiddleIter middle_, DownIter down_) : up(up_) , middle(middle_) , down(down_) - {} + { + } UpIter up; MiddleIter middle; @@ -84,5 +81,3 @@ struct line_iterator return other.middle - middle; } }; - -#endif diff --git a/examples/03_stencil/output.hpp b/examples/03_stencil/output.hpp index 516120f..f94d35d 100644 --- a/examples/03_stencil/output.hpp +++ b/examples/03_stencil/output.hpp @@ -3,24 +3,21 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef STENCIL_OUTPUT_HPP -#define STENCIL_OUTPUT_HPP +#pragma once #include #include template -void output(std::string name, Container const& data, std::size_t Nx, std::size_t Ny) +void output(std::string const& name, Container const& data, std::size_t Nx, + std::size_t Ny) { std::ofstream file(name); - - for(std::size_t y = 0; y != Ny; ++y) + for (std::size_t y = 0; y != Ny; ++y) { - for(std::size_t x = 0; x != Nx; ++x) + for (std::size_t x = 0; x != Nx; ++x) { file << x << " " << y << " " << data[y * Nx + x] << '\n'; } } } - -#endif diff --git a/examples/03_stencil/row_iterator.hpp b/examples/03_stencil/row_iterator.hpp index 136d84b..442fcd9 100644 --- a/examples/03_stencil/row_iterator.hpp +++ b/examples/03_stencil/row_iterator.hpp @@ -3,18 +3,18 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef STENCIL_ROW_ITERATOR_HPP -#define STENCIL_ROW_ITERATOR_HPP +#pragma once #include "line_iterator.hpp" #include -template +template struct row_iterator - // iterator_facade is a facade class that defines the boilerplate needed for - // a proper standard C++ iterator. As a user, we only have to define basic - // functions + // iterator_facade is a facade class that defines the boilerplate needed for a + // proper standard C++ iterator. As a user, we only have to define basic + // functions : hpx::util::iterator_facade< // Our type: row_iterator, @@ -24,17 +24,17 @@ struct row_iterator std::random_access_iterator_tag, // Since dereferencing should return a new line_iterator, we need to // explicitly set the reference type. - line_iterator - > + line_iterator> { - typedef line_iterator line_iterator_type; + using line_iterator_type = line_iterator; row_iterator(std::size_t Nx, MiddleIter middle_) - : up_(middle - Nx) - , middle(middle_) + : middle(middle_) + , up_(middle - Nx) , down_(middle + Nx) , Nx_(Nx) - {} + { + } line_iterator line() const { @@ -45,16 +45,16 @@ struct row_iterator line_iterator top_boundary(Container const& cont) const { - return line_iterator( - cont.begin(), middle, down_); + return line_iterator(cont.begin(), middle, down_); } template line_iterator bottom_boundary(Container const& cont) const { - return line_iterator( - up_, middle, cont.begin()); + return line_iterator(up_, middle, cont.begin()); } MiddleIter middle; @@ -102,5 +102,3 @@ struct row_iterator DownIter down_; std::size_t Nx_; }; - -#endif diff --git a/examples/03_stencil/stencil.hpp b/examples/03_stencil/stencil.hpp index e3f1411..fa46776 100644 --- a/examples/03_stencil/stencil.hpp +++ b/examples/03_stencil/stencil.hpp @@ -3,6 +3,8 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#pragma once + #include "line_iterator.hpp" #include "row_iterator.hpp" @@ -10,8 +12,7 @@ #include template -void init( - std::array& U, std::size_t Nx, std::size_t Ny, +void init(std::array& U, std::size_t Nx, std::size_t Ny, std::size_t rank = 0, std::size_t num_localities = 1) { // Initialize: Boundaries are set to 1, interior is 0 @@ -20,6 +21,7 @@ void init( std::fill(U[0].begin(), U[0].begin() + Nx, 1.0); std::fill(U[1].begin(), U[1].begin() + Nx, 1.0); } + for (std::size_t y = 0; y < Ny; ++y) { U[0][y * Nx + 0] = 1.0; @@ -28,6 +30,7 @@ void init( U[0][y * Nx + (Nx - 1)] = 1.0; U[1][y * Nx + (Nx - 1)] = 1.0; } + if (rank == num_localities - 1) { std::fill(U[0].end() - Nx, U[0].end(), 1.0); @@ -39,12 +42,14 @@ template OutIter line_update(InIter begin, InIter end, OutIter result) { ++result; + // Iterate over the interior: skip the last and first element - for(InIter it = begin + 1; it != end - 1; ++it, ++result) + for (InIter it = begin + 1; it != end - 1; ++it, ++result) { - *result = 0.25 * (it.up[-1] + it.up[+1] + it.down[-1] + it.down[+1]) - - *it.middle; + *result = 0.25 * (it.up[-1] + it.up[+1] + it.down[-1] + it.down[+1]) - + *it.middle; } + ++result; return result; diff --git a/examples/03_stencil/stencil_parallel_0.cpp b/examples/03_stencil/stencil_parallel_0.cpp index eecbd0a..e83e084 100644 --- a/examples/03_stencil/stencil_parallel_0.cpp +++ b/examples/03_stencil/stencil_parallel_0.cpp @@ -3,8 +3,8 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "stencil.hpp" #include "output.hpp" +#include "stencil.hpp" #include #include @@ -12,17 +12,17 @@ #include #include -#include #include +#include int hpx_main(hpx::program_options::variables_map& vm) { - std::size_t Nx = vm["Nx"].as(); - std::size_t Ny = vm["Ny"].as(); - std::size_t steps = vm["steps"].as(); + std::size_t const Nx = vm["Nx"].as(); + std::size_t const Ny = vm["Ny"].as(); + std::size_t const steps = vm["steps"].as(); - typedef std::vector data_type; - typedef row_iterator iterator; + using data_type = std::vector; + using iterator = row_iterator; std::array U; @@ -31,28 +31,30 @@ int hpx_main(hpx::program_options::variables_map& vm) init(U, Nx, Ny); - hpx::chrono::high_resolution_timer t; + hpx::chrono::high_resolution_timer const tim; - // Construct our column iterators. We want to begin with the second - // row to avoid out of bound accesses. + // Construct our column iterators. We want to begin with the second row to + // avoid out of bound accesses. iterator curr(Nx, U[0].begin()); iterator next(Nx, U[1].begin()); auto policy = hpx::execution::par; - for (std::size_t t = 0; t < steps; ++t) + for (std::size_t t = 0; t != steps; ++t) { // We store the result of our update in the next middle line. - hpx::for_loop(policy, curr + 1, curr + Ny - 1, + hpx::experimental::for_loop(policy, curr + 1, curr + Ny - 1, // We need to advance the result by one row each iteration - hpx::parallel::induction(next.middle + Nx, Nx), - [Nx](iterator it, data_type::iterator result) { + hpx::experimental::induction(next.middle + Nx, Nx), + [Nx](iterator const& it, data_type::iterator const& result) { line_update(*it, *it + Nx, result); }); std::swap(curr, next); } - double elapsed = t.elapsed(); - double mlups = (((Nx - 2.) * (Ny - 2.) * steps) / 1e6)/ elapsed; + double const elapsed = tim.elapsed(); + double const mlups = + (static_cast((Nx - 2) * (Ny - 2) * steps) / 1e6) / elapsed; + std::cout << "MLUPS: " << mlups << "\n"; if (vm.count("output")) @@ -65,6 +67,7 @@ int main(int argc, char* argv[]) { using namespace hpx::program_options; + // clang-format off options_description desc_commandline; desc_commandline.add_options() ("Nx", value()->default_value(1024), @@ -76,6 +79,7 @@ int main(int argc, char* argv[]) ("output", value(), "Save output to file") ; + // clang-format on hpx::init_params init_args; init_args.desc_cmdline = desc_commandline; diff --git a/examples/03_stencil/stencil_parallel_1.cpp b/examples/03_stencil/stencil_parallel_1.cpp index b874e50..423f1dd 100644 --- a/examples/03_stencil/stencil_parallel_1.cpp +++ b/examples/03_stencil/stencil_parallel_1.cpp @@ -3,31 +3,30 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "stencil.hpp" #include "output.hpp" +#include "stencil.hpp" #include #include +#include #include -#include -#include #include #include #include -#include #include +#include int hpx_main(hpx::program_options::variables_map& vm) { - std::size_t Nx = vm["Nx"].as(); - std::size_t Ny = vm["Ny"].as(); - std::size_t steps = vm["steps"].as(); + std::size_t const Nx = vm["Nx"].as(); + std::size_t const Ny = vm["Ny"].as(); + std::size_t const steps = vm["steps"].as(); - typedef hpx::compute::host::block_allocator allocator_type; - typedef hpx::compute::host::block_executor<> executor_type; - typedef hpx::compute::vector data_type; - typedef row_iterator iterator; + using allocator_type = hpx::compute::host::block_allocator; + using executor_type = hpx::compute::host::block_executor<>; + using data_type = hpx::compute::vector; + using iterator = row_iterator; std::array U; @@ -40,27 +39,29 @@ int hpx_main(hpx::program_options::variables_map& vm) init(U, Nx, Ny); executor_type executor(numa_domains); - hpx::chrono::high_resolution_timer t; + hpx::chrono::high_resolution_timer tim; - // Construct our column iterators. We want to begin with the second - // row to avoid out of bound accesses. + // Construct our column iterators. We want to begin with the second row to + // avoid out of bound accesses. iterator curr(Nx, U[0].begin()); iterator next(Nx, U[1].begin()); auto policy = hpx::execution::par.on(executor); for (std::size_t t = 0; t < steps; ++t) { - hpx::for_loop(policy, curr + 1, curr + Ny - 1, + hpx::experimental::for_loop(policy, curr + 1, curr + Ny - 1, // We need to advance the result by one row each iteration - hpx::parallel::induction(next.middle + Nx, Nx), - [Nx](iterator it, data_type::iterator result) { + hpx::experimental::induction(next.middle + Nx, Nx), + [Nx](iterator const& it, data_type::iterator const& result) { line_update(*it, *it + Nx, result); }); std::swap(curr, next); } - double elapsed = t.elapsed(); - double mlups = (((Nx - 2.) * (Ny - 2.) * steps) / 1e6)/ elapsed; + double const elapsed = tim.elapsed(); + double const mlups = + (static_cast((Nx - 2) * (Ny - 2) * steps) / 1e6) / elapsed; + std::cout << "MLUPS: " << mlups << "\n"; if (vm.count("output")) @@ -73,6 +74,7 @@ int main(int argc, char* argv[]) { using namespace hpx::program_options; + // clang-format off options_description desc_commandline; desc_commandline.add_options() ("Nx", value()->default_value(1024), @@ -84,12 +86,10 @@ int main(int argc, char* argv[]) ("output", value(), "Save output to file") ; + // clang-format on - // Initialize and run HPX, this example requires to run hpx_main on all - // localities - std::vector const cfg = { - "hpx.numa_sensitive=2" - }; + // Initialize and run HPX + std::vector const cfg = {"hpx.numa_sensitive=2"}; hpx::init_params init_args; init_args.desc_cmdline = desc_commandline; diff --git a/examples/03_stencil/stencil_parallel_2.cpp b/examples/03_stencil/stencil_parallel_2.cpp index 28783bd..fe21a2f 100644 --- a/examples/03_stencil/stencil_parallel_2.cpp +++ b/examples/03_stencil/stencil_parallel_2.cpp @@ -3,42 +3,41 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "stencil.hpp" -#include "output.hpp" #include "communicator.hpp" +#include "output.hpp" +#include "stencil.hpp" #include #include +#include #include #include #include -#include #include #include #include -#include #include -#include +#include #include #include +#include - -typedef std::vector communication_type; +using communication_type = std::vector; HPX_REGISTER_CHANNEL_DECLARATION(communication_type); HPX_REGISTER_CHANNEL(communication_type, stencil_communication); int hpx_main(hpx::program_options::variables_map& vm) { - std::size_t Nx = vm["Nx"].as(); - std::size_t Ny_global = vm["Ny"].as(); - std::size_t steps = vm["steps"].as(); + std::size_t const Nx = vm["Nx"].as(); + std::size_t const Ny_global = vm["Ny"].as(); + std::size_t const steps = vm["steps"].as(); - typedef hpx::compute::host::block_allocator allocator_type; - typedef hpx::compute::host::block_executor<> executor_type; - typedef hpx::compute::vector data_type; - typedef row_iterator iterator; + using allocator_type = hpx::compute::host::block_allocator; + using executor_type = hpx::compute::host::block_executor<>; + using data_type = hpx::compute::vector; + using iterator = row_iterator; std::array U; @@ -49,7 +48,7 @@ int hpx_main(hpx::program_options::variables_map& vm) std::size_t rank = hpx::get_locality_id(); // We divide our grid in stripes along the y axis. - std::size_t Ny = Ny_global / num_localities; + std::size_t const Ny = Ny_global / num_localities; U[0] = data_type(Nx * Ny, 0.0, alloc); U[1] = data_type(Nx * Ny, 0.0, alloc); @@ -57,12 +56,13 @@ int hpx_main(hpx::program_options::variables_map& vm) init(U, Nx, Ny, rank, num_localities); // Setup our communicator - typedef communicator> communicator_type; + using communicator_type = communicator>; communicator_type comm(rank, num_localities); if (rank == 0) { - std::cout << "Running example using " << num_localities << " Partitions\n"; + std::cout << "Running example using " << num_localities + << " partitions\n"; } if (comm.has_neighbor(communicator_type::up)) @@ -71,6 +71,7 @@ int hpx_main(hpx::program_options::variables_map& vm) comm.set(communicator_type::up, std::vector(U[0].begin(), U[0].begin() + Nx), 0); } + if (comm.has_neighbor(communicator_type::down)) { // send initial value to our neighbor below @@ -79,10 +80,10 @@ int hpx_main(hpx::program_options::variables_map& vm) } executor_type executor(numa_domains); - hpx::chrono::high_resolution_timer t; + hpx::chrono::high_resolution_timer tim; - // Construct our column iterators. We want to begin with the second - // row to avoid out of bound accesses. + // Construct our column iterators. We want to begin with the second row to + // avoid out of bound accesses. iterator curr(Nx, U[0].begin()); iterator next(Nx, U[1].begin()); @@ -95,8 +96,10 @@ int hpx_main(hpx::program_options::variables_map& vm) { // Get the first row. auto result = next.middle; + // retrieve the row which is 'up' from our first row. std::vector up = comm.get(communicator_type::up, t).get(); + // Create a row iterator with that top boundary auto it = curr.top_boundary(up); @@ -111,12 +114,11 @@ int hpx_main(hpx::program_options::variables_map& vm) } // Update our interior spatial domain - hpx::for_loop(policy, curr + 1, curr + Ny - 1, + hpx::experimental::for_loop(policy, curr + 1, curr + Ny - 1, // We need to advance the result by one row each iteration - hpx::parallel::induction(next.middle + Nx, Nx), - [Nx](iterator it, data_type::iterator result) { - hpx::util::annotate_function apex_profiler("line_update"); - + hpx::experimental::induction(next.middle + Nx, Nx), + [Nx](iterator const& it, data_type::iterator const& result) { + hpx::scoped_annotation apex_profiler("line_update"); line_update(*it, *it + Nx, result); }); @@ -126,18 +128,22 @@ int hpx_main(hpx::program_options::variables_map& vm) { // Get the last row. auto result = next.middle + (Ny - 2) * Nx; + // retrieve the row which is 'down' from our last row. - std::vector down = comm.get(communicator_type::down, t).get(); + std::vector down = + comm.get(communicator_type::down, t).get(); + // Create a row iterator with that bottom boundary auto it = (curr + Ny - 2).bottom_boundary(down); + // After getting our missing row, we can update our last row line_update(it, it + Nx, result); - // Finally, we can send the updated last row for our neighbor - // to consume in the next timestep. Don't send if we are on - // the last timestep - comm.set(communicator_type::down, - std::vector(result, result + Nx), t + 1); + // Finally, we can send the updated last row for our neighbor to + // consume in the next timestep. Don't send if we are on the last + // timestep + comm.set(communicator_type::down, std::vector(result, result + Nx), + t + 1); } if (rank == 0) @@ -145,19 +151,23 @@ int hpx_main(hpx::program_options::variables_map& vm) std::swap(curr, next); } - double elapsed = t.elapsed(); - if (rank == 0) - std::cout << "\n"; + double elapsed = tim.elapsed(); if (rank == 0) { - double mlups = (((Nx - 2.) * (Ny_global - 2.) * steps) / 1e6)/ elapsed; + std::cout << "\n"; + double mlups = + (static_cast((Nx - 2) * (Ny_global - 2) * steps) / 1e6) / + elapsed; std::cout << "MLUPS: " << mlups << "\n"; } if (vm.count("output")) - output(vm["output"].as() + std::to_string(rank), U[0], Nx, Ny); + { + output(vm["output"].as() + std::to_string(rank), U[0], Nx, + Ny); + } return hpx::finalize(); } @@ -166,6 +176,7 @@ int main(int argc, char* argv[]) { using namespace hpx::program_options; + // clang-format off options_description desc_commandline; desc_commandline.add_options() ("Nx", value()->default_value(1024), @@ -177,13 +188,12 @@ int main(int argc, char* argv[]) ("output", value(), "Save output to file") ; + // clang-format on // Initialize and run HPX, this example requires to run hpx_main on all // localities std::vector const cfg = { - "hpx.run_hpx_main!=1", - "hpx.numa_sensitive=2" - }; + "hpx.run_hpx_main!=1", "hpx.numa_sensitive=2"}; hpx::init_params init_args; init_args.desc_cmdline = desc_commandline; diff --git a/examples/03_stencil/stencil_parallel_3.cpp b/examples/03_stencil/stencil_parallel_3.cpp index 264d819..a1bfffd 100644 --- a/examples/03_stencil/stencil_parallel_3.cpp +++ b/examples/03_stencil/stencil_parallel_3.cpp @@ -3,39 +3,37 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "stencil.hpp" -#include "output.hpp" #include "communicator.hpp" +#include "output.hpp" +#include "stencil.hpp" #include #include +#include #include #include #include -#include #include #include -#include #include -#include +#include #include #include +#include - -typedef std::vector communication_type; +using communication_type = std::vector; HPX_REGISTER_CHANNEL_DECLARATION(communication_type); HPX_REGISTER_CHANNEL(communication_type, stencil_communication); -void worker( - std::size_t rank, std::size_t num, std::size_t Nx, std::size_t Ny, std::size_t steps, - std::string const& output_name) +void worker(std::size_t rank, std::size_t num, std::size_t Nx, std::size_t Ny, + std::size_t steps, std::string const& output_name) { - typedef hpx::compute::host::block_allocator allocator_type; - typedef hpx::compute::host::block_executor<> executor_type; - typedef hpx::compute::vector data_type; - typedef row_iterator iterator; + using allocator_type = hpx::compute::host::block_allocator; + using executor_type = hpx::compute::host::block_executor<>; + using data_type = hpx::compute::vector; + using iterator = row_iterator; std::array U; @@ -48,29 +46,30 @@ void worker( init(U, Nx, Ny, rank, num); // Setup our communicator - typedef communicator> communicator_type; + using communicator_type = communicator>; communicator_type comm(rank, num); if (comm.has_neighbor(communicator_type::up)) { // send initial value to our upper neighbor comm.set(communicator_type::up, - std::vector(U[0].begin(), U[0].begin() + Nx), 0); + std::vector(U[0].begin(), U[0].begin() + Nx), 0); } + if (comm.has_neighbor(communicator_type::down)) { - // send initial value to our neighbor below + // send initial value to our neighbor below comm.set(communicator_type::down, - std::vector(U[0].end() - Nx, U[0].end()), 0); + std::vector(U[0].end() - Nx, U[0].end()), 0); } if (rank == 0) { - std::cout << "Running example using " << num << " Partitions\n"; + std::cout << "Running example using " << num << " partitions\n"; } executor_type executor(numa_domains); - hpx::chrono::high_resolution_timer t; + hpx::chrono::high_resolution_timer tim; // Construct our column iterators. We want to begin with the second // row to avoid out of bound accesses. @@ -102,10 +101,10 @@ void worker( } // Update our interior spatial domain - hpx::for_loop(policy, curr + 1, curr + Ny - 1, + hpx::experimental::for_loop(policy, curr + 1, curr + Ny - 1, // We need to advance the result by one row each iteration - hpx::parallel::induction(next.middle + Nx, Nx), - [Nx](iterator it, data_type::iterator result) { + hpx::experimental::induction(next.middle + Nx, Nx), + [Nx](iterator const& it, data_type::iterator const& result) { line_update(*it, *it + Nx, result); }); @@ -115,18 +114,22 @@ void worker( { // Get the last row. auto result = next.middle + (Ny - 2) * Nx; + // retrieve the row which is 'down' from our last row. - std::vector down = comm.get(communicator_type::down, t).get(); + std::vector down = + comm.get(communicator_type::down, t).get(); + // Create a row iterator with that bottom boundary auto it = (curr + Ny - 2).bottom_boundary(down); + // After getting our missing row, we can update our last row line_update(it, it + Nx, result); - // Finally, we can send the updated last row for our neighbor - // to consume in the next timestep. Don't send if we are on - // the last timestep - comm.set(communicator_type::down, - std::vector(result, result + Nx), t + 1); + // Finally, we can send the updated last row for our neighbor to + // consume in the next timestep. Don't send if we are on the last + // timestep + comm.set(communicator_type::down, std::vector(result, result + Nx), + t + 1); } if (rank == 0) @@ -134,14 +137,15 @@ void worker( std::swap(curr, next); } - double elapsed = t.elapsed(); - if (rank == 0) - std::cout << "\n"; + double elapsed = tim.elapsed(); if (rank == 0) { - double mlups = (((Nx - 2.) * (Ny * num - 2.) * steps) / 1e6)/ elapsed; + std::cout << "\n"; + double const mlups = + (static_cast((Nx - 2) * (Ny * num - 2) * steps) / 1e6) / + elapsed; std::cout << "MLUPS: " << mlups << "\n"; } @@ -151,13 +155,15 @@ void worker( int hpx_main(hpx::program_options::variables_map& vm) { - std::size_t Nx = vm["Nx"].as(); - std::size_t Ny_global = vm["Ny"].as(); - std::size_t steps = vm["steps"].as(); + std::size_t const Nx = vm["Nx"].as(); + std::size_t const Ny_global = vm["Ny"].as(); + std::size_t const steps = vm["steps"].as(); - std::size_t rank = hpx::get_locality_id(); - std::size_t num_localities = hpx::get_num_localities(hpx::launch::sync); - std::size_t num_local_partitions = vm["local-partitions"].as(); + std::size_t const rank = hpx::get_locality_id(); + std::size_t const num_localities = + hpx::get_num_localities(hpx::launch::sync); + std::size_t const num_local_partitions = + vm["local-partitions"].as(); std::size_t num_partitions = num_localities * num_local_partitions; @@ -172,11 +178,9 @@ int hpx_main(hpx::program_options::variables_map& vm) if (vm.count("output")) output_name = vm["output"].as(); - workers.push_back(hpx::async(&worker, - (rank * num_local_partitions) + part, num_partitions, - Nx, Ny, steps, - output_name - )); + workers.push_back( + hpx::async(&worker, (rank * num_local_partitions) + part, + num_partitions, Nx, Ny, steps, output_name)); } hpx::when_all(workers).get(); @@ -188,6 +192,7 @@ int main(int argc, char* argv[]) { using namespace hpx::program_options; + // clang-format off options_description desc_commandline; desc_commandline.add_options() ("Nx", value()->default_value(1024), @@ -201,13 +206,12 @@ int main(int argc, char* argv[]) ("output", value(), "Save output to file") ; + // clang-format on // Initialize and run HPX, this example requires to run hpx_main on all // localities std::vector const cfg = { - "hpx.run_hpx_main!=1", - "hpx.numa_sensitive=2" - }; + "hpx.run_hpx_main!=1", "hpx.numa_sensitive=2"}; hpx::init_params init_args; init_args.desc_cmdline = desc_commandline; diff --git a/examples/03_stencil/stencil_parallel_4.cpp b/examples/03_stencil/stencil_parallel_4.cpp index 9eddeec..8b79c67 100644 --- a/examples/03_stencil/stencil_parallel_4.cpp +++ b/examples/03_stencil/stencil_parallel_4.cpp @@ -3,40 +3,38 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "stencil.hpp" -#include "output.hpp" #include "communicator.hpp" +#include "output.hpp" +#include "stencil.hpp" #include #include +#include #include #include #include -#include #include #include #include -#include #include -#include +#include #include #include +#include - -typedef std::vector communication_type; +using communication_type = std::vector; HPX_REGISTER_CHANNEL_DECLARATION(communication_type); HPX_REGISTER_CHANNEL(communication_type, stencil_communication); -void worker( - std::size_t rank, std::size_t num, std::size_t Nx, std::size_t Ny, std::size_t steps, - std::string const& output_name) +void worker(std::size_t rank, std::size_t num, std::size_t Nx, std::size_t Ny, + std::size_t steps, std::string const& output_name) { - typedef hpx::compute::host::block_allocator allocator_type; - typedef hpx::compute::host::block_executor<> executor_type; - typedef hpx::compute::vector data_type; - typedef row_iterator iterator; + using allocator_type = hpx::compute::host::block_allocator; + using executor_type = hpx::compute::host::block_executor<>; + using data_type = hpx::compute::vector; + using iterator = row_iterator; std::array U; @@ -49,29 +47,30 @@ void worker( init(U, Nx, Ny, rank, num); // Setup our communicator - typedef communicator> communicator_type; + using communicator_type = communicator>; communicator_type comm(rank, num); if (rank == 0) { - std::cout << "Running example using " << num << " Partitions\n"; + std::cout << "Running example using " << num << " partitions\n"; } if (comm.has_neighbor(communicator_type::up)) { // send initial value to our upper neighbor comm.set(communicator_type::up, - std::vector(U[0].begin(), U[0].begin() + Nx), 0); + std::vector(U[0].begin(), U[0].begin() + Nx), 0); } + if (comm.has_neighbor(communicator_type::down)) { - // send initial value to our neighbor below + // send initial value to our neighbor below comm.set(communicator_type::down, - std::vector(U[0].end() - Nx, U[0].end()), 0); + std::vector(U[0].end() - Nx, U[0].end()), 0); } executor_type executor(numa_domains); - hpx::chrono::high_resolution_timer t; + hpx::chrono::high_resolution_timer tim; // Construct our column iterators. We want to begin with the second // row to avoid out of bound accesses. @@ -84,8 +83,8 @@ void worker( hpx::future step_future = hpx::make_ready_future(); for (std::size_t t = 0; t < steps; ++t) { - step_future = step_future.then([&comm, policy, curr, next, Ny, Nx, t](hpx::future&& prev) mutable - { + step_future = step_future.then([&comm, policy, curr, next, Ny, Nx, t]( + hpx::future&& prev) mutable { // Trigger possible errors... prev.get(); @@ -94,30 +93,31 @@ void worker( hpx::future top_boundary_future; if (comm.has_neighbor(communicator_type::up)) { - // retrieve the row which is 'up' from our first row. - top_boundary_future = comm.get(communicator_type::up, t).then( - [&comm, curr, next, Ny, Nx, t](hpx::future>&& up_future) - { - hpx::util::annotate_function apex_profiler("line_update"); + auto f = [&comm, curr, next, Ny, Nx, t]( + hpx::future>&& up_future) { + hpx::scoped_annotation apex_profiler("line_update"); - // Get the first row. - auto result = next.middle; - std::vector up = up_future.get(); + // Get the first row. + auto const result = next.middle; + std::vector const up = up_future.get(); - // Create a row iterator with that top boundary - auto it = curr.top_boundary(up); + // Create a row iterator with that top boundary + auto const it = curr.top_boundary(up); - // After getting our missing row, we can update our first row - line_update(it, it + Nx, result); + // After getting our missing row, we can update our first + // row + line_update(it, it + Nx, result); - // Finally, we can send the updated first row for our neighbor - // to consume in the next timestep. Don't send if we are on - // the last timestep - comm.set(communicator_type::up, - std::vector(result, result + Nx), t + 1); - } - ); + // Finally, we can send the updated first row for our + // neighbor to consume in the next timestep. Don't send if + // we are on the last timestep + comm.set(communicator_type::up, + std::vector(result, result + Nx), t + 1); + }; + // retrieve the row which is 'up' from our first row. + top_boundary_future = + comm.get(communicator_type::up, t).then(std::move(f)); } else { @@ -125,40 +125,45 @@ void worker( } // Update our interior spatial domain - hpx::future interior_future = - hpx::for_loop(policy, curr + 1, curr + Ny - 1, - // We need to advance the result by one row each iteration - hpx::parallel::induction(next.middle + Nx, Nx), - [Nx](iterator it, data_type::iterator result) { - hpx::util::annotate_function apex_profiler("line_update (for)"); - line_update(*it, *it + Nx, result); - }); + hpx::future interior_future = hpx::experimental::for_loop( + policy, curr + 1, curr + Ny - 1, + // We need to advance the result by one row each iteration + hpx::experimental::induction(next.middle + Nx, Nx), + [Nx](iterator const& it, data_type::iterator const& result) { + hpx::scoped_annotation apex_profiler("line_update (for)"); + line_update(*it, *it + Nx, result); + }); // Update our lower boundary if we have an interior partition and a // neighbor below hpx::future bottom_boundary_future; if (comm.has_neighbor(communicator_type::down)) { - bottom_boundary_future = comm.get(communicator_type::down, t).then( - [&comm, curr, next, Ny, Nx, t](hpx::future>&& bottom_future) - { - hpx::util::annotate_function apex_profiler("line_update - for2"); - // Get the last row. - auto result = next.middle + (Ny - 2) * Nx; - // retrieve the row which is 'down' from our last row. - std::vector down = bottom_future.get(); - // Create a row iterator with that bottom boundary - auto it = (curr + Ny - 2).bottom_boundary(down); - // After getting our missing row, we can update our last row - line_update(it, it + Nx, result); - - // Finally, we can send the updated last row for our neighbor - // to consume in the next timestep. Don't send if we are on - // the last timestep - comm.set(communicator_type::down, - std::vector(result, result + Nx), t + 1); - } - ); + auto f = [&comm, curr, next, Ny, Nx, t]( + hpx::future>&& bottom_future) { + hpx::scoped_annotation apex_profiler("line_update - for2"); + + // Get the last row. + auto const result = next.middle + (Ny - 2) * Nx; + + // retrieve the row which is 'down' from our last row. + std::vector const down = bottom_future.get(); + + // Create a row iterator with that bottom boundary + auto const it = (curr + Ny - 2).bottom_boundary(down); + + // After getting our missing row, we can update our last row + line_update(it, it + Nx, result); + + // Finally, we can send the updated last row for our + // neighbor to consume in the next timestep. Don't send if + // we are on the last timestep + comm.set(communicator_type::down, + std::vector(result, result + Nx), t + 1); + }; + + bottom_boundary_future = + comm.get(communicator_type::down, t).then(std::move(f)); } else { @@ -173,11 +178,14 @@ void worker( } // Wait until everything has finished. step_future.get(); - double elapsed = t.elapsed(); + + double elapsed = tim.elapsed(); if (rank == 0) { - double mlups = (((Nx - 2.) * (Ny * num - 2.) * steps) / 1e6)/ elapsed; + double mlups = + (static_cast((Nx - 2) * (Ny * num - 2) * steps) / 1e6) / + elapsed; std::cout << "MLUPS: " << mlups << "\n"; } @@ -187,18 +195,20 @@ void worker( int hpx_main(hpx::program_options::variables_map& vm) { - std::size_t Nx = vm["Nx"].as(); - std::size_t Ny_global = vm["Ny"].as(); - std::size_t steps = vm["steps"].as(); + std::size_t const Nx = vm["Nx"].as(); + std::size_t const Ny_global = vm["Ny"].as(); + std::size_t const steps = vm["steps"].as(); - std::size_t rank = hpx::get_locality_id(); - std::size_t num_localities = hpx::get_num_localities(hpx::launch::sync); - std::size_t num_local_partitions = vm["local-partitions"].as(); + std::size_t const rank = hpx::get_locality_id(); + std::size_t const num_localities = + hpx::get_num_localities(hpx::launch::sync); + std::size_t const num_local_partitions = + vm["local-partitions"].as(); std::size_t num_partitions = num_localities * num_local_partitions; // We divide our grid in stripes along the y axis. - std::size_t Ny = Ny_global / num_partitions; + std::size_t const Ny = Ny_global / num_partitions; std::vector> workers; workers.reserve(num_local_partitions); @@ -208,11 +218,9 @@ int hpx_main(hpx::program_options::variables_map& vm) if (vm.count("output")) output_name = vm["output"].as(); - workers.push_back(hpx::async(&worker, - (rank * num_local_partitions) + part, num_partitions, - Nx, Ny, steps, - output_name - )); + workers.push_back( + hpx::async(&worker, (rank * num_local_partitions) + part, + num_partitions, Nx, Ny, steps, output_name)); } hpx::when_all(workers).get(); @@ -224,6 +232,7 @@ int main(int argc, char* argv[]) { using namespace hpx::program_options; + // clang-format off options_description desc_commandline; desc_commandline.add_options() ("Nx", value()->default_value(1024), @@ -237,13 +246,12 @@ int main(int argc, char* argv[]) ("output", value(), "Save output to file") ; + // clang-format on // Initialize and run HPX, this example requires to run hpx_main on all // localities std::vector const cfg = { - "hpx.run_hpx_main!=1", - "hpx.numa_sensitive=2" - }; + "hpx.run_hpx_main!=1", "hpx.numa_sensitive=2"}; hpx::init_params init_args; init_args.desc_cmdline = desc_commandline; diff --git a/examples/03_stencil/stencil_serial.cpp b/examples/03_stencil/stencil_serial.cpp index a4ecd8e..8a10bcc 100644 --- a/examples/03_stencil/stencil_serial.cpp +++ b/examples/03_stencil/stencil_serial.cpp @@ -3,25 +3,25 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#include "stencil.hpp" #include "output.hpp" +#include "stencil.hpp" #include #include #include #include -#include #include +#include int hpx_main(hpx::program_options::variables_map& vm) { - std::size_t Nx = vm["Nx"].as(); - std::size_t Ny = vm["Ny"].as(); - std::size_t steps = vm["steps"].as(); + std::size_t const Nx = vm["Nx"].as(); + std::size_t const Ny = vm["Ny"].as(); + std::size_t const steps = vm["steps"].as(); - typedef std::vector data_type; - typedef row_iterator::iterator> iterator; + using data_type = std::vector; + using iterator = row_iterator::iterator>; std::array U; @@ -30,30 +30,32 @@ int hpx_main(hpx::program_options::variables_map& vm) init(U, Nx, Ny); - hpx::chrono::high_resolution_timer t; + hpx::chrono::high_resolution_timer const tim; // Construct our column iterators. We want to begin with the second // row to avoid out of bound accesses. iterator curr(Nx, U[0].begin()); iterator next(Nx, U[1].begin()); - for (std::size_t t = 0; t < steps; ++t) + for (std::size_t t = 0; t != steps; ++t) { // We store the result of our update in the next middle line. // We need to skip the first row. auto result = next.middle + Nx; // Iterate over the interior: skip the first and last column - for(auto it = curr + 1; it != curr + Ny - 1; ++it) + for (auto it = curr + 1; it != curr + Ny - 1; ++it) { result = line_update(*it, *it + Nx, result); } std::swap(curr, next); } - double elapsed = t.elapsed(); - double mlups = (((Nx - 2.) * (Ny - 2.) * steps) / 1e6)/ elapsed; + double const elapsed = tim.elapsed(); + double const mlups = + (static_cast((Nx - 2) * (Ny - 2) * steps) / 1e6) / elapsed; + std::cout << "MLUPS: " << mlups << "\n"; if (vm.count("output")) @@ -66,6 +68,7 @@ int main(int argc, char* argv[]) { using namespace hpx::program_options; + // clang-format off options_description desc_commandline; desc_commandline.add_options() ("Nx", value()->default_value(1024), @@ -77,6 +80,7 @@ int main(int argc, char* argv[]) ("output", value(), "Save output to file") ; + // clang-format on hpx::init_params init_args; init_args.desc_cmdline = desc_commandline; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b3699dd..2080d5e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,15 +3,7 @@ # Distributed under the Boost Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -cmake_minimum_required(VERSION 3.5) - -#-------------------------------------------------- -# this policy is used in HPX CMakeLists and causes the -# CMAKE_CXX_COMPILER_ID to change, (on OSX). -# This triggers compiler mismatch error. -# So we use the same policy here. -#-------------------------------------------------- -cmake_policy(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.14) #-------------------------------------------------- # project declaration