From 8a2bf8c48f40dc5531fb67b21650a7792e5e93a6 Mon Sep 17 00:00:00 2001 From: Nikunj Gupta Date: Thu, 18 Jun 2020 23:20:39 +0530 Subject: [PATCH 01/29] Adds distributed scalable 1d stencil --- examples/distributed_stencil/1d_stencil.cpp | 169 ++++++++++++++++++ examples/distributed_stencil/CMakeLists.txt | 32 ++++ examples/distributed_stencil/communicator.hpp | 84 +++++++++ examples/distributed_stencil/stencil.hpp | 54 ++++++ 4 files changed, 339 insertions(+) create mode 100644 examples/distributed_stencil/1d_stencil.cpp create mode 100644 examples/distributed_stencil/CMakeLists.txt create mode 100644 examples/distributed_stencil/communicator.hpp create mode 100644 examples/distributed_stencil/stencil.hpp diff --git a/examples/distributed_stencil/1d_stencil.cpp b/examples/distributed_stencil/1d_stencil.cpp new file mode 100644 index 000000000000..8174fbe199cc --- /dev/null +++ b/examples/distributed_stencil/1d_stencil.cpp @@ -0,0 +1,169 @@ +// Copyright (c) 2020 Nikunj Gupta +// +// 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 "communicator.hpp" +#include "stencil.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using communication_type = double; + +HPX_REGISTER_CHANNEL_DECLARATION(communication_type); +HPX_REGISTER_CHANNEL(communication_type, stencil_communication); + +int hpx_main(boost::program_options::variables_map& vm) +{ + std::size_t Nx_global = vm["Nx"].as(); + std::size_t steps = vm["steps"].as(); + std::size_t nlp = vm["Nlp"].as(); + + typedef hpx::compute::host::block_allocator allocator_type; + typedef hpx::compute::host::block_executor<> executor_type; + typedef hpx::compute::vector data_type; + + std::array U; + + auto numa_domains = hpx::compute::host::numa_domains(); + allocator_type alloc(numa_domains); + + std::size_t num_localities = hpx::get_num_localities(hpx::launch::sync); + std::size_t num_worker_threads = hpx::get_num_worker_threads(); + std::size_t rank = hpx::get_locality_id(); + + hpx::util::high_resolution_timer t_main; + + // Keep only partial data + std::size_t Nx = Nx_global / num_localities; + std::size_t local_nx = Nx / nlp; + + U[0] = data_type(Nx, 0.0, alloc); + U[1] = data_type(Nx, 0.0, alloc); + + init(U, Nx, rank, num_localities); + + // setup communicator + using communicator_type = communicator; + communicator_type comm(rank, num_localities); + + if (rank == 0) + { + std::cout << "Starting benchmark with " << num_localities << + " nodes and " << num_worker_threads << + " threads.\n"; + } + + if (comm.has_neighbor(communicator_type::left)) + { + // Send initial value to the left neighbor + comm.set(communicator_type::left, U[0][0], 0); + } + if (comm.has_neighbor(communicator_type::right)) + { + // Send initial value to the right neighbor + comm.set(communicator_type::right, U[0][Nx-1], 0); + } + + auto range = boost::irange(static_cast(0), nlp); + + executor_type executor(numa_domains); + auto policy = hpx::parallel::execution::par.on(executor); + + hpx::util::high_resolution_timer t; + for (std::size_t t = 0; t < steps; ++t) + { + data_type& curr = U[t % 2]; + data_type& next = U[(t + 1) % 2]; + + hpx::parallel::for_each( + policy, + std::begin(range), std::end(range), + [&U, local_nx, nlp, t] (std::size_t i) + { + if (i == 0) stencil_update(U, 1, local_nx, t); + else if (i == nlp-1) stencil_update(U, i * local_nx, (i + 1) * local_nx - 1, t); + else stencil_update(U, i * local_nx, (i + 1) * local_nx, t); + } + ); + + // Left and right neighbor element should be transported + // by now. + + if (comm.has_neighbor(communicator_type::left)) + { + // Synchronization step. Wait for the left neighbor to arrive. + double left = comm.get(communicator_type::left, t).get(); + + // next[0] = (left + curr[1]) * 0.5f; + next[0] = curr[0] + ((k*dt)/(dx*dx)) * (left - 2*curr[0] + curr[1]); + + // Dispatch the updated value to left neighbor for it to get + // consumed in the next timestep + comm.set(communicator_type::left, next[0], t+1); + } + + if (comm.has_neighbor(communicator_type::right)) + { + // Synchronization step. Wait for the right neighbor to arrive. + double right = comm.get(communicator_type::right, t).get(); + + // next[Nx-1] = (right + curr[Nx-2]) * 0.5f; + next[Nx-1] = curr[Nx-1] + ((k*dt)/(dx*dx)) * (curr[Nx-2] - 2*curr[Nx-1] + right); + + // Dispatch the updated value to right neighbor for it to get + // consumed in the next timestep + comm.set(communicator_type::right, next[Nx-1], t+1); + } + } + double elapsed = t.elapsed(); + double telapsed = t_main.elapsed(); + + // for (double elem : U[(steps)%2]) + // std::cout << elem << " "; + // std::cout << std::endl; + + if (rank == 0) + { + std::cout << "Total time: " << telapsed << std::endl; + std::cout << "Kernel execution time: " << elapsed << std::endl; + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + using namespace hpx::program_options; + + options_description desc_commandline; + desc_commandline.add_options() + ("Nx", value()->default_value(1024), + "Total stencil points") + ("Nlp", value()->default_value(16), + "Number of Local Partitions") + ("steps", value()->default_value(100), + "Number of steps to apply the stencil") + ; + + // Initialize and run HPX, this example requires to run hpx_main on all + // localities + std::vector const cfg = { + "hpx.run_hpx_main!=1", + }; + + return hpx::init(desc_commandline, argc, argv, cfg); +} \ No newline at end of file diff --git a/examples/distributed_stencil/CMakeLists.txt b/examples/distributed_stencil/CMakeLists.txt new file mode 100644 index 000000000000..1bbdc34c6030 --- /dev/null +++ b/examples/distributed_stencil/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2020 Nikunj Gupta +# +# SPDX-License-Identifier: BSL-1.0 +# 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) + +if(NOT HPX_WITH_DISTRIBUTED_RUNTIME) + return() +endif() + +set(example_programs 1d_stencil) + +foreach(example_program ${example_programs}) + set(sources ${example_program}.cpp) + + source_group("Source Files" FILES ${sources}) + + # add example executable + add_hpx_executable( + ${example_program} INTERNAL_FLAGS + SOURCES ${sources} ${${example_program}_FLAGS} + FOLDER "Examples/1dStencil" + ) + + add_hpx_example_target_dependencies("1d_stencil" ${example_program}) + + if(HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) + add_hpx_example_test( + "1d_stencil" ${example_program} ${${example_program}_PARAMETERS} + ) + endif() +endforeach() diff --git a/examples/distributed_stencil/communicator.hpp b/examples/distributed_stencil/communicator.hpp new file mode 100644 index 000000000000..1550cbc80c17 --- /dev/null +++ b/examples/distributed_stencil/communicator.hpp @@ -0,0 +1,84 @@ +// Copyright (c) 2016 Thomas Heller +// Copyright (c) 2020 Nikunj Gupta +// +// 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 + +#include + +#include + +template +struct communicator +{ + enum neighbor { + left = 0, + right = 1, + }; + + typedef hpx::lcos::channel channel_type; + + // rank: our rank in the system + // num: number of participating partners + communicator(std::size_t rank, std::size_t num) + { + static const char* left_name = "/stencil/left/"; + static const char* right_name = "/stencil/right/"; + + // Only set left channels if we have more than one partner + if (num > 1) + { + // We have a left neighbor if our rank is greater than zero. + if (rank > 0) + { + // Retrieve the channel from our left neighbor from which we receive + // the point we need to update the first point in our partition. + recv[left] = hpx::find_from_basename(right_name, rank - 1); + + // Create the channel we use to send our first point to our leftper + // neighbor + send[left] = channel_type(hpx::find_here()); + // Register the channel with a name such that our neighbor can find it. + hpx::register_with_basename(left_name, send[left], rank); + } + if (rank < num - 1) + { + // Retrieve the channel from our right neighbor from which we receive + // the point we need to update the last point in our partition. + recv[right] = hpx::find_from_basename(left_name, rank + 1); + // Create the channel we use to send our last point to our neighbor + // below + send[right] = channel_type(hpx::find_here()); + // Register the channel with a name such that our neighbor can find it. + hpx::register_with_basename(right_name, send[right], rank); + } + } + } + + bool has_neighbor(neighbor n) const + { + return recv[n] && send[n]; + } + + void set(neighbor n, T t, std::size_t step) + { + // Send our data to the neighbor n using fire and forget semantics + // Synchronization happens when receiving values. + send[n].set(hpx::launch::apply, std::move(t), step); + } + + hpx::future get(neighbor n, std::size_t step) + { + // Get our data from our neighbor, we return a future to allow the + // algorithm to synchronize. + return recv[n].get(hpx::launch::async, step); + } + + std::array, 2> recv; + std::array, 2> send; +}; + +#endif \ No newline at end of file diff --git a/examples/distributed_stencil/stencil.hpp b/examples/distributed_stencil/stencil.hpp new file mode 100644 index 000000000000..84c910632329 --- /dev/null +++ b/examples/distributed_stencil/stencil.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2020 Nikunj Gupta +// +// 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 +#include +#include +#include +#include +#include + + +#include +#include + +using allocator_type = hpx::compute::host::block_allocator; +using data_type = hpx::compute::vector; + +const double k = 0.5; // heat transfer coefficient +const double dt = 1.; // time step +const double dx = 1.; // grid spacing + +template +void init( + std::array& U, std::size_t Nx, + std::size_t rank = 0, std::size_t num_localities = 1) +{ + // Initialize: Boundaries are set to 1, interior is 0 + if (rank == 0) + { + U[0][0] = 1.0; + U[1][0] = 1.0; + } + if (rank == num_localities - 1) + { + U[0][Nx-1] = 100.0; + U[1][Nx-1] = 100.0; + } +} + +void stencil_update(std::array& U, const std::size_t& begin + , const std::size_t& end, const std::size_t t) +{ + data_type& curr = U[t % 2]; + data_type& next = U[(t + 1) % 2]; + + #pragma unroll + for (std::size_t i = begin; i < end; ++i) + { + // next[i] = (curr[i-1] + curr[i+1]) * 0.5f; + next[i] = curr[i] + ((k*dt)/(dx*dx)) * (curr[i-1] - 2*curr[i] + curr[i+1]); + } +} \ No newline at end of file From e959e9c249da36c4e8d27bc3a976c0e562de0624 Mon Sep 17 00:00:00 2001 From: Nikunj Gupta Date: Thu, 18 Jun 2020 23:27:59 +0530 Subject: [PATCH 02/29] Add folder to example cmake --- examples/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6b67102fe9b2..bf89bfe27adf 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,6 +12,7 @@ set(subdirs async_io balancing cancelable_action + distributed_stencil future_reduce heartbeat jacobi From 39fc6aa0f29e80addb057f83041cc405d62154f1 Mon Sep 17 00:00:00 2001 From: Nikunj Gupta Date: Tue, 23 Jun 2020 15:32:59 +0530 Subject: [PATCH 03/29] Make suggested changes --- .../1d_stencil_channel.cpp} | 14 ++++---- examples/1d_stencil/CMakeLists.txt | 1 + .../communicator.hpp | 2 +- .../stencil.hpp | 3 +- examples/CMakeLists.txt | 1 - examples/distributed_stencil/CMakeLists.txt | 32 ------------------- 6 files changed, 10 insertions(+), 43 deletions(-) rename examples/{distributed_stencil/1d_stencil.cpp => 1d_stencil/1d_stencil_channel.cpp} (96%) rename examples/{distributed_stencil => 1d_stencil}/communicator.hpp (99%) rename examples/{distributed_stencil => 1d_stencil}/stencil.hpp (96%) delete mode 100644 examples/distributed_stencil/CMakeLists.txt diff --git a/examples/distributed_stencil/1d_stencil.cpp b/examples/1d_stencil/1d_stencil_channel.cpp similarity index 96% rename from examples/distributed_stencil/1d_stencil.cpp rename to examples/1d_stencil/1d_stencil_channel.cpp index 8174fbe199cc..11c08f0741f3 100644 --- a/examples/distributed_stencil/1d_stencil.cpp +++ b/examples/1d_stencil/1d_stencil_channel.cpp @@ -3,6 +3,12 @@ // 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) +// This is the a separate examples demonstrating the development +// of a fully distributed solver for a simple 1D heat distribution problem. +// +// This example makes use of LCOS channels to send and receive +// elements. + #include "communicator.hpp" #include "stencil.hpp" @@ -108,7 +114,6 @@ int hpx_main(boost::program_options::variables_map& vm) // Synchronization step. Wait for the left neighbor to arrive. double left = comm.get(communicator_type::left, t).get(); - // next[0] = (left + curr[1]) * 0.5f; next[0] = curr[0] + ((k*dt)/(dx*dx)) * (left - 2*curr[0] + curr[1]); // Dispatch the updated value to left neighbor for it to get @@ -121,7 +126,6 @@ int hpx_main(boost::program_options::variables_map& vm) // Synchronization step. Wait for the right neighbor to arrive. double right = comm.get(communicator_type::right, t).get(); - // next[Nx-1] = (right + curr[Nx-2]) * 0.5f; next[Nx-1] = curr[Nx-1] + ((k*dt)/(dx*dx)) * (curr[Nx-2] - 2*curr[Nx-1] + right); // Dispatch the updated value to right neighbor for it to get @@ -132,10 +136,6 @@ int hpx_main(boost::program_options::variables_map& vm) double elapsed = t.elapsed(); double telapsed = t_main.elapsed(); - // for (double elem : U[(steps)%2]) - // std::cout << elem << " "; - // std::cout << std::endl; - if (rank == 0) { std::cout << "Total time: " << telapsed << std::endl; @@ -166,4 +166,4 @@ int main(int argc, char* argv[]) }; return hpx::init(desc_commandline, argc, argv, cfg); -} \ No newline at end of file +} diff --git a/examples/1d_stencil/CMakeLists.txt b/examples/1d_stencil/CMakeLists.txt index 868f0aab59fc..00625757055e 100644 --- a/examples/1d_stencil/CMakeLists.txt +++ b/examples/1d_stencil/CMakeLists.txt @@ -19,6 +19,7 @@ set(example_programs 1d_stencil_6 1d_stencil_7 1d_stencil_8 + 1d_stencil_channel ) if(HPX_WITH_APEX) diff --git a/examples/distributed_stencil/communicator.hpp b/examples/1d_stencil/communicator.hpp similarity index 99% rename from examples/distributed_stencil/communicator.hpp rename to examples/1d_stencil/communicator.hpp index 1550cbc80c17..62420a726066 100644 --- a/examples/distributed_stencil/communicator.hpp +++ b/examples/1d_stencil/communicator.hpp @@ -81,4 +81,4 @@ struct communicator std::array, 2> send; }; -#endif \ No newline at end of file +#endif diff --git a/examples/distributed_stencil/stencil.hpp b/examples/1d_stencil/stencil.hpp similarity index 96% rename from examples/distributed_stencil/stencil.hpp rename to examples/1d_stencil/stencil.hpp index 84c910632329..e0f8c1886796 100644 --- a/examples/distributed_stencil/stencil.hpp +++ b/examples/1d_stencil/stencil.hpp @@ -48,7 +48,6 @@ void stencil_update(std::array& U, const std::size_t& begin #pragma unroll for (std::size_t i = begin; i < end; ++i) { - // next[i] = (curr[i-1] + curr[i+1]) * 0.5f; next[i] = curr[i] + ((k*dt)/(dx*dx)) * (curr[i-1] - 2*curr[i] + curr[i+1]); } -} \ No newline at end of file +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index bf89bfe27adf..6b67102fe9b2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,7 +12,6 @@ set(subdirs async_io balancing cancelable_action - distributed_stencil future_reduce heartbeat jacobi diff --git a/examples/distributed_stencil/CMakeLists.txt b/examples/distributed_stencil/CMakeLists.txt deleted file mode 100644 index 1bbdc34c6030..000000000000 --- a/examples/distributed_stencil/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2020 Nikunj Gupta -# -# SPDX-License-Identifier: BSL-1.0 -# 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) - -if(NOT HPX_WITH_DISTRIBUTED_RUNTIME) - return() -endif() - -set(example_programs 1d_stencil) - -foreach(example_program ${example_programs}) - set(sources ${example_program}.cpp) - - source_group("Source Files" FILES ${sources}) - - # add example executable - add_hpx_executable( - ${example_program} INTERNAL_FLAGS - SOURCES ${sources} ${${example_program}_FLAGS} - FOLDER "Examples/1dStencil" - ) - - add_hpx_example_target_dependencies("1d_stencil" ${example_program}) - - if(HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) - add_hpx_example_test( - "1d_stencil" ${example_program} ${${example_program}_PARAMETERS} - ) - endif() -endforeach() From fa62c6e4247d3f689df5d9731476482ed29d5aee Mon Sep 17 00:00:00 2001 From: Nikunj Gupta Date: Fri, 26 Jun 2020 21:51:54 +0530 Subject: [PATCH 04/29] Further optimizations --- examples/1d_stencil/1d_stencil_channel.cpp | 73 +++++++++++++--------- examples/1d_stencil/communicator.hpp | 18 +++--- examples/1d_stencil/stencil.hpp | 3 +- 3 files changed, 54 insertions(+), 40 deletions(-) diff --git a/examples/1d_stencil/1d_stencil_channel.cpp b/examples/1d_stencil/1d_stencil_channel.cpp index 11c08f0741f3..b6e43e7a0059 100644 --- a/examples/1d_stencil/1d_stencil_channel.cpp +++ b/examples/1d_stencil/1d_stencil_channel.cpp @@ -95,43 +95,58 @@ int hpx_main(boost::program_options::variables_map& vm) data_type& curr = U[t % 2]; data_type& next = U[(t + 1) % 2]; - hpx::parallel::for_each( - policy, - std::begin(range), std::end(range), - [&U, local_nx, nlp, t] (std::size_t i) - { - if (i == 0) stencil_update(U, 1, local_nx, t); - else if (i == nlp-1) stencil_update(U, i * local_nx, (i + 1) * local_nx - 1, t); - else stencil_update(U, i * local_nx, (i + 1) * local_nx, t); - } - ); - - // Left and right neighbor element should be transported - // by now. + hpx::future l = hpx::make_ready_future(); + hpx::future r = hpx::make_ready_future(); if (comm.has_neighbor(communicator_type::left)) { - // Synchronization step. Wait for the left neighbor to arrive. - double left = comm.get(communicator_type::left, t).get(); - - next[0] = curr[0] + ((k*dt)/(dx*dx)) * (left - 2*curr[0] + curr[1]); - - // Dispatch the updated value to left neighbor for it to get - // consumed in the next timestep - comm.set(communicator_type::left, next[0], t+1); + l = comm.get(communicator_type::left, t) + .then(hpx::launch::sync, + [&U, &next, &curr, &comm, t, local_nx](hpx::future&& gg) + { + double left = gg.get(); + + next[0] = curr[0] + ((k*dt)/(dx*dx)) * (left - 2*curr[0] + curr[1]); + + // Dispatch the updated value to left neighbor for it to get + // consumed in the next timestep + comm.set(communicator_type::left, next[0], t+1); + } + ); } if (comm.has_neighbor(communicator_type::right)) { - // Synchronization step. Wait for the right neighbor to arrive. - double right = comm.get(communicator_type::right, t).get(); + r = comm.get(communicator_type::right, t) + .then(hpx::launch::sync, + [&U, &next, &curr, &comm, t, local_nx, Nx, nlp](hpx::future&& gg) + { + double right = gg.get(); + + next[Nx-1] = curr[Nx-1] + ((k*dt)/(dx*dx)) * (curr[Nx-2] - 2*curr[Nx-1] + right); + + // Dispatch the updated value to right neighbor for it to get + // consumed in the next timestep + comm.set(communicator_type::right, next[Nx-1], t+1); + } + ); + } - next[Nx-1] = curr[Nx-1] + ((k*dt)/(dx*dx)) * (curr[Nx-2] - 2*curr[Nx-1] + right); + hpx::parallel::for_each( + policy, + std::begin(range), std::end(range), + [&U, local_nx, nlp, t, &comm] (std::size_t i) + { + if (i == 0) // && !comm.has_neighbor(communicator_type::left)) + stencil_update(U, 1, local_nx, t); + else if (i == nlp-1) // && !comm.has_neighbor(communicator_type::right)) + stencil_update(U, i * local_nx, (i + 1) * local_nx - 1, t); + else if (i > 0 && i < nlp-1) + stencil_update(U, i * local_nx, (i + 1) * local_nx, t); + } + ); - // Dispatch the updated value to right neighbor for it to get - // consumed in the next timestep - comm.set(communicator_type::right, next[Nx-1], t+1); - } + hpx::wait_all(l, r); } double elapsed = t.elapsed(); double telapsed = t_main.elapsed(); @@ -166,4 +181,4 @@ int main(int argc, char* argv[]) }; return hpx::init(desc_commandline, argc, argv, cfg); -} +} \ No newline at end of file diff --git a/examples/1d_stencil/communicator.hpp b/examples/1d_stencil/communicator.hpp index 62420a726066..2dde76dd0b40 100644 --- a/examples/1d_stencil/communicator.hpp +++ b/examples/1d_stencil/communicator.hpp @@ -31,14 +31,14 @@ struct communicator // Only set left channels if we have more than one partner if (num > 1) { - // We have a left neighbor if our rank is greater than zero. + // We have an leftper neighbor if our rank is greater than zero. if (rank > 0) { - // Retrieve the channel from our left neighbor from which we receive - // the point we need to update the first point in our partition. + // Retrieve the channel from our leftper neighbor from which we receive + // the row we need to leftdate the first row in our partition. recv[left] = hpx::find_from_basename(right_name, rank - 1); - // Create the channel we use to send our first point to our leftper + // Create the channel we use to send our first row to our leftper // neighbor send[left] = channel_type(hpx::find_here()); // Register the channel with a name such that our neighbor can find it. @@ -46,10 +46,10 @@ struct communicator } if (rank < num - 1) { - // Retrieve the channel from our right neighbor from which we receive - // the point we need to update the last point in our partition. + // Retrieve the channel from our neighbor below from which we receive + // the row we need to leftdate the last row in our partition. recv[right] = hpx::find_from_basename(left_name, rank + 1); - // Create the channel we use to send our last point to our neighbor + // Create the channel we use to send our last row to our neighbor // below send[right] = channel_type(hpx::find_here()); // Register the channel with a name such that our neighbor can find it. @@ -67,7 +67,7 @@ struct communicator { // Send our data to the neighbor n using fire and forget semantics // Synchronization happens when receiving values. - send[n].set(hpx::launch::apply, std::move(t), step); + send[n].set(t, step); } hpx::future get(neighbor n, std::size_t step) @@ -81,4 +81,4 @@ struct communicator std::array, 2> send; }; -#endif +#endif \ No newline at end of file diff --git a/examples/1d_stencil/stencil.hpp b/examples/1d_stencil/stencil.hpp index e0f8c1886796..06b6ac13117a 100644 --- a/examples/1d_stencil/stencil.hpp +++ b/examples/1d_stencil/stencil.hpp @@ -44,8 +44,7 @@ void stencil_update(std::array& U, const std::size_t& begin { data_type& curr = U[t % 2]; data_type& next = U[(t + 1) % 2]; - - #pragma unroll + for (std::size_t i = begin; i < end; ++i) { next[i] = curr[i] + ((k*dt)/(dx*dx)) * (curr[i-1] - 2*curr[i] + curr[i+1]); From 06253bde161d92c8b07b0df37b96b8f7df78328d Mon Sep 17 00:00:00 2001 From: Nikunj Gupta Date: Wed, 22 Jul 2020 20:19:55 +0530 Subject: [PATCH 05/29] inspect changes --- examples/1d_stencil/1d_stencil_channel.cpp | 33 +++++++++++--------- examples/1d_stencil/communicator.hpp | 36 ++++++++++++---------- examples/1d_stencil/stencil.hpp | 8 +++-- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/examples/1d_stencil/1d_stencil_channel.cpp b/examples/1d_stencil/1d_stencil_channel.cpp index b6e43e7a0059..272b40535f89 100644 --- a/examples/1d_stencil/1d_stencil_channel.cpp +++ b/examples/1d_stencil/1d_stencil_channel.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using communication_type = double; @@ -41,7 +42,7 @@ int hpx_main(boost::program_options::variables_map& vm) typedef hpx::compute::host::block_allocator allocator_type; typedef hpx::compute::host::block_executor<> executor_type; typedef hpx::compute::vector data_type; - + std::array U; auto numa_domains = hpx::compute::host::numa_domains(); @@ -68,7 +69,7 @@ int hpx_main(boost::program_options::variables_map& vm) if (rank == 0) { - std::cout << "Starting benchmark with " << num_localities << + std::cout << "Starting benchmark with " << num_localities << " nodes and " << num_worker_threads << " threads.\n"; } @@ -83,7 +84,7 @@ int hpx_main(boost::program_options::variables_map& vm) // Send initial value to the right neighbor comm.set(communicator_type::right, U[0][Nx-1], 0); } - + auto range = boost::irange(static_cast(0), nlp); executor_type executor(numa_domains); @@ -102,14 +103,15 @@ int hpx_main(boost::program_options::variables_map& vm) { l = comm.get(communicator_type::left, t) .then(hpx::launch::sync, - [&U, &next, &curr, &comm, t, local_nx](hpx::future&& gg) + [&next, &curr, &comm, t](hpx::future&& gg) { double left = gg.get(); - next[0] = curr[0] + ((k*dt)/(dx*dx)) * (left - 2*curr[0] + curr[1]); + next[0] = curr[0] + + ((k*dt)/(dx*dx)) * (left - 2*curr[0] + curr[1]); - // Dispatch the updated value to left neighbor for it to get - // consumed in the next timestep + // Dispatch the updated value to left neighbor for it + // to get consumed in the next timestep comm.set(communicator_type::left, next[0], t+1); } ); @@ -119,14 +121,15 @@ int hpx_main(boost::program_options::variables_map& vm) { r = comm.get(communicator_type::right, t) .then(hpx::launch::sync, - [&U, &next, &curr, &comm, t, local_nx, Nx, nlp](hpx::future&& gg) + [&next, &curr, &comm, t, Nx](hpx::future&& gg) { double right = gg.get(); - next[Nx-1] = curr[Nx-1] + ((k*dt)/(dx*dx)) * (curr[Nx-2] - 2*curr[Nx-1] + right); + next[Nx-1] = curr[Nx-1] + ((k*dt)/(dx*dx)) * + (curr[Nx-2] - 2*curr[Nx-1] + right); - // Dispatch the updated value to right neighbor for it to get - // consumed in the next timestep + // Dispatch the updated value to right neighbor for it + // to get consumed in the next timestep comm.set(communicator_type::right, next[Nx-1], t+1); } ); @@ -135,11 +138,11 @@ int hpx_main(boost::program_options::variables_map& vm) hpx::parallel::for_each( policy, std::begin(range), std::end(range), - [&U, local_nx, nlp, t, &comm] (std::size_t i) + [&U, local_nx, nlp, t] (std::size_t i) { - if (i == 0) // && !comm.has_neighbor(communicator_type::left)) + if (i == 0) stencil_update(U, 1, local_nx, t); - else if (i == nlp-1) // && !comm.has_neighbor(communicator_type::right)) + else if (i == nlp-1) stencil_update(U, i * local_nx, (i + 1) * local_nx - 1, t); else if (i > 0 && i < nlp-1) stencil_update(U, i * local_nx, (i + 1) * local_nx, t); @@ -181,4 +184,4 @@ int main(int argc, char* argv[]) }; return hpx::init(desc_commandline, argc, argv, cfg); -} \ No newline at end of file +} diff --git a/examples/1d_stencil/communicator.hpp b/examples/1d_stencil/communicator.hpp index 2dde76dd0b40..a06cd17262ad 100644 --- a/examples/1d_stencil/communicator.hpp +++ b/examples/1d_stencil/communicator.hpp @@ -4,12 +4,12 @@ // 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 #include +#include template struct communicator @@ -34,25 +34,31 @@ struct communicator // We have an leftper neighbor if our rank is greater than zero. if (rank > 0) { - // Retrieve the channel from our leftper neighbor from which we receive - // the row we need to leftdate the first row in our partition. - recv[left] = hpx::find_from_basename(right_name, rank - 1); + // Retrieve the channel from our leftper neighbor from which + // we receive the row we need to leftdate the first row in our + // partition. + recv[left] = hpx::find_from_basename< + channel_type>(right_name, rank - 1); - // Create the channel we use to send our first row to our leftper - // neighbor + // Create the channel we use to send our first row to our + // left neighbor send[left] = 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(left_name, send[left], rank); } if (rank < num - 1) { - // Retrieve the channel from our neighbor below from which we receive - // the row we need to leftdate the last row in our partition. - recv[right] = hpx::find_from_basename(left_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 leftdate the last row in our + // partition. + recv[right] = hpx::find_from_basename< + channel_type>(left_name, rank + 1); + // Create the channel we use to send our last row to our + // neighbor below send[right] = 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(right_name, send[right], rank); } } @@ -80,5 +86,3 @@ struct communicator std::array, 2> recv; std::array, 2> send; }; - -#endif \ No newline at end of file diff --git a/examples/1d_stencil/stencil.hpp b/examples/1d_stencil/stencil.hpp index 06b6ac13117a..b155df1302b0 100644 --- a/examples/1d_stencil/stencil.hpp +++ b/examples/1d_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 #include #include @@ -13,6 +15,7 @@ #include #include +#include using allocator_type = hpx::compute::host::block_allocator; using data_type = hpx::compute::vector; @@ -44,9 +47,10 @@ void stencil_update(std::array& U, const std::size_t& begin { data_type& curr = U[t % 2]; data_type& next = U[(t + 1) % 2]; - + for (std::size_t i = begin; i < end; ++i) { - next[i] = curr[i] + ((k*dt)/(dx*dx)) * (curr[i-1] - 2*curr[i] + curr[i+1]); + next[i] = curr[i] + ((k*dt)/(dx*dx)) * + (curr[i-1] - 2*curr[i] + curr[i+1]); } } From 5d97186e5ca4530ed1b7c85efab7f932a966c46b Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Wed, 22 Jul 2020 10:30:34 -0500 Subject: [PATCH 06/29] Converting resiliency APIs to tag_invoke based CPOs - import resiliency APIs to hpx::experimental, convert all code to use the functions through hpx::experimental --- libs/resiliency/CMakeLists.txt | 8 +- libs/resiliency/docs/index.rst | 24 +-- .../examples/1d_stencil_replay_exception.cpp | 2 +- .../examples/1d_stencil_replay_validate.cpp | 2 +- libs/resiliency/examples/async_replay.cpp | 20 +- libs/resiliency/examples/async_replicate.cpp | 14 +- .../examples/async_replicate_vote.cpp | 4 +- .../examples/dataflow_replicate.cpp | 6 +- .../include/hpx/resiliency/async_replay.hpp | 30 +-- .../hpx/resiliency/async_replicate.hpp | 182 ++++++++++-------- .../hpx/resiliency/dataflow_replay.hpp | 30 +-- .../hpx/resiliency/dataflow_replicate.hpp | 61 +++--- .../include/hpx/resiliency/resiliency.hpp | 27 ++- .../hpx/resiliency/resiliency_cpos.hpp | 147 ++++++++++++++ .../replay/1d_stencil_checksum.cpp | 2 +- .../performance/replay/1d_stencil_replay.cpp | 2 +- .../tests/performance/replay/async_replay.cpp | 2 +- .../replay/async_replay_validate.cpp | 2 +- .../performance/replay/dataflow_replay.cpp | 2 +- .../replay/dataflow_replay_validate.cpp | 2 +- .../replicate/1d_stencil_replicate.cpp | 2 +- .../1d_stencil_replicate_checksum.cpp | 2 +- .../replicate/async_replicate_validate.cpp | 2 +- .../replicate/async_replicate_vote.cpp | 2 +- .../async_replicate_vote_validate.cpp | 2 +- 25 files changed, 394 insertions(+), 185 deletions(-) create mode 100644 libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp diff --git a/libs/resiliency/CMakeLists.txt b/libs/resiliency/CMakeLists.txt index 81c00a20bb21..4067a246ac86 100644 --- a/libs/resiliency/CMakeLists.txt +++ b/libs/resiliency/CMakeLists.txt @@ -17,6 +17,7 @@ set(resiliency_headers hpx/resiliency/dataflow_replicate.hpp hpx/resiliency/version.hpp hpx/resiliency/resiliency.hpp + hpx/resiliency/resiliency_cpos.hpp ) # Default location is $HPX_ROOT/libs/resiliency/src @@ -28,6 +29,11 @@ add_hpx_module( GLOBAL_HEADER_GEN OFF SOURCES ${resiliency_sources} HEADERS ${resiliency_headers} - DEPENDENCIES hpx_assertion hpx_config hpx_datastructures hpx_async_local + DEPENDENCIES + hpx_assertion + hpx_async_local + hpx_config + hpx_datastructures + hpx_functional CMAKE_SUBDIRS examples tests ) diff --git a/libs/resiliency/docs/index.rst b/libs/resiliency/docs/index.rst index 75bbd026e21e..887ab5e7b084 100644 --- a/libs/resiliency/docs/index.rst +++ b/libs/resiliency/docs/index.rst @@ -31,27 +31,27 @@ by repeating a task multiple times. The following API functions are exposed: -- :cpp:func:`hpx::resiliency::async_replay`: This version of task replay will +- :cpp:func:`hpx::experimental::async_replay`: This version of task replay will catch user-defined exceptions and automatically reschedule the task N times before throwing an :cpp:func:`hpx::resiliency::abort_replay_exception` if no task is able to complete execution without an exception. -- :cpp:func:`hpx::resiliency::async_replay_validate`: This version of replay +- :cpp:func:`hpx::experimental::async_replay_validate`: This version of replay adds an argument to async replay which receives a user-provided validation function to test the result of the task against. If the task's output is validated, the result is returned. If the output fails the check or an exception is thrown, the task is replayed until no errors are encountered or the number of specified retries has been exceeded. -- :cpp:func:`hpx::resiliency::async_replicate`: This is the most basic +- :cpp:func:`hpx::experimental::async_replicate`: This is the most basic implementation of the task replication. The API returns the first result that runs without detecting any errors. -- :cpp:func:`hpx::resiliency::async_replicate_validate`: This API additionally +- :cpp:func:`hpx::experimental::async_replicate_validate`: This API additionally takes a validation function which evaluates the return values produced by the threads. The first task to compute a valid result is returned. -- :cpp:func:`hpx::resiliency::async_replicate_vote`: This API adds a vote +- :cpp:func:`hpx::experimental::async_replicate_vote`: This API adds a vote function to the basic replicate function. Many hardware or software failures are silent errors which do not interrupt program flow. In order to detect errors of this kind, it is necessary to run the task several times and compare @@ -60,20 +60,20 @@ The following API functions are exposed: consensus function to properly form a consensus. This voting function then returns the "correct"" answer. -- :cpp:func:`hpx::resiliency::async_replicate_vote_validate`: This combines the +- :cpp:func:`hpx::experimental::async_replicate_vote_validate`: This combines the features of the previously discussed replicate set. Replicate vote validate allows a user to provide a validation function to filter results. Additionally, as described in replicate vote, the user can provide a "voting function" which returns the consensus formed by the voting logic. -- :cpp:func:`hpx::resiliency::dataflow_replay`: This version of dataflow replay +- :cpp:func:`hpx::experimental::dataflow_replay`: This version of dataflow replay will catch user-defined exceptions and automatically reschedules the task N times before throwing an :cpp:func:`hpx::resiliency::abort_replay_exception` if no task is able to complete execution without an exception. Any arguments for the executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::resiliency::dataflow_replay_validate` : This version of replay +- :cpp:func:`hpx::experimental::dataflow_replay_validate` : This version of replay adds an argument to dataflow replay which receives a user-provided validation function to test the result of the task against. If the task's output is validated, the result is returned. If the output fails the check or an @@ -82,19 +82,19 @@ The following API functions are exposed: executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::resiliency::dataflow_replicate`: This is the most basic +- :cpp:func:`hpx::experimental::dataflow_replicate`: This is the most basic implementation of the task replication. The API returns the first result that runs without detecting any errors. Any arguments for the executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::resiliency::dataflow_replicate_validate`: This API +- :cpp:func:`hpx::experimental::dataflow_replicate_validate`: This API additionally takes a validation function which evaluates the return values produced by the threads. The first task to compute a valid result is returned. Any arguments for the executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::resiliency::dataflow_replicate_vote`: This API adds a vote +- :cpp:func:`hpx::experimental::dataflow_replicate_vote`: This API adds a vote function to the basic replicate function. Many hardware or software failures are silent errors which do not interrupt program flow. In order to detect errors of this kind, it is necessary to run the task several times and compare @@ -105,7 +105,7 @@ The following API functions are exposed: futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::resiliency::dataflow_replicate_vote_validate`: This combines +- :cpp:func:`hpx::experimental::dataflow_replicate_vote_validate`: This combines the features of the previously discussed replicate set. Replicate vote validate allows a user to provide a validation function to filter results. Additionally, as described in replicate vote, the user can provide a "voting diff --git a/libs/resiliency/examples/1d_stencil_replay_exception.cpp b/libs/resiliency/examples/1d_stencil_replay_exception.cpp index db08f759ad44..8abc5cd6c930 100644 --- a/libs/resiliency/examples/1d_stencil_replay_exception.cpp +++ b/libs/resiliency/examples/1d_stencil_replay_exception.cpp @@ -164,7 +164,7 @@ int hpx_main(hpx::program_options::variables_map& vm) std::vector next_input(subdomains); for (int j = 0; j < subdomains; ++j) { - next_input[j] = hpx::resiliency::dataflow_replay(n, update, + next_input[j] = hpx::experimental::dataflow_replay(n, update, input[(j - 1 + subdomains) % subdomains], input[j], input[(j + 1) % subdomains]); } diff --git a/libs/resiliency/examples/1d_stencil_replay_validate.cpp b/libs/resiliency/examples/1d_stencil_replay_validate.cpp index cf5800c5b9b9..8738c83f668c 100644 --- a/libs/resiliency/examples/1d_stencil_replay_validate.cpp +++ b/libs/resiliency/examples/1d_stencil_replay_validate.cpp @@ -181,7 +181,7 @@ int hpx_main(hpx::program_options::variables_map& vm) std::vector next_input(subdomains); for (int j = 0; j < subdomains; ++j) { - next_input[j] = hpx::resiliency::dataflow_replay_validate(n, + next_input[j] = hpx::experimental::dataflow_replay_validate(n, &validate_result, update, input[(j - 1 + subdomains) % subdomains], input[j], input[(j + 1) % subdomains]); diff --git a/libs/resiliency/examples/async_replay.cpp b/libs/resiliency/examples/async_replay.cpp index e594974708ab..f1368b6db2dc 100644 --- a/libs/resiliency/examples/async_replay.cpp +++ b/libs/resiliency/examples/async_replay.cpp @@ -36,7 +36,7 @@ bool validate(int result) int no_answer() { - throw hpx::resiliency::abort_replay_exception(); + throw hpx::experimental::abort_replay_exception(); } int deep_thought() @@ -60,18 +60,18 @@ int hpx_main(hpx::program_options::variables_map& vm) hpx::util::high_resolution_timer t; // successful replay - hpx::future f = hpx::resiliency::async_replay(sr, &deep_thought); + hpx::future f = hpx::experimental::async_replay(sr, &deep_thought); std::cout << "universal answer: " << f.get() << "\n"; // successful replay validate - f = hpx::resiliency::async_replay_validate( + f = hpx::experimental::async_replay_validate( sr, &validate, &universal_answer); std::cout << "universal answer: " << f.get() << "\n"; // unsuccessful replay - f = hpx::resiliency::async_replay(usr, &deep_thought); + f = hpx::experimental::async_replay(usr, &deep_thought); try { f.get(); @@ -82,35 +82,35 @@ int hpx_main(hpx::program_options::variables_map& vm) } // unsuccessful replay validate - f = hpx::resiliency::async_replay_validate( + f = hpx::experimental::async_replay_validate( usr, &validate, &universal_answer); try { f.get(); } - catch (hpx::resiliency::abort_replay_exception const&) + catch (hpx::experimental::abort_replay_exception const&) { std::cout << "no universal answer!\n"; } // aborted replay - f = hpx::resiliency::async_replay(a, &no_answer); + f = hpx::experimental::async_replay(a, &no_answer); try { f.get(); } - catch (hpx::resiliency::abort_replay_exception const&) + catch (hpx::experimental::abort_replay_exception const&) { std::cout << "aborted universal answer calculation!\n"; } // aborted replay validate - f = hpx::resiliency::async_replay_validate(a, &validate, &no_answer); + f = hpx::experimental::async_replay_validate(a, &validate, &no_answer); try { f.get(); } - catch (hpx::resiliency::abort_replay_exception const&) + catch (hpx::experimental::abort_replay_exception const&) { std::cout << "aborted universal answer calculation!\n"; } diff --git a/libs/resiliency/examples/async_replicate.cpp b/libs/resiliency/examples/async_replicate.cpp index 74da4fe906c4..b72e96943696 100644 --- a/libs/resiliency/examples/async_replicate.cpp +++ b/libs/resiliency/examples/async_replicate.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018 Hartmut Kaiser +// Copyright (c) 2018-2020 Hartmut Kaiser // Copyright (c) 2019 Adrian Serio // Copyright (c) 2019 Nikunj Gupta // @@ -60,18 +60,18 @@ int hpx_main(hpx::program_options::variables_map& vm) // successful replicate hpx::future f = - hpx::resiliency::async_replicate(sr, &deep_thought); + hpx::experimental::async_replicate(sr, &deep_thought); std::cout << "universal answer: " << f.get() << "\n"; // successful replicate_validate - f = hpx::resiliency::async_replicate_validate( + f = hpx::experimental::async_replicate_validate( sr, &validate, &universal_answer); std::cout << "universal answer: " << f.get() << "\n"; // unsuccessful replicate - f = hpx::resiliency::async_replicate(usr, &deep_thought); + f = hpx::experimental::async_replicate(usr, &deep_thought); try { f.get(); @@ -82,7 +82,7 @@ int hpx_main(hpx::program_options::variables_map& vm) } // unsuccessful replicate_validate - f = hpx::resiliency::async_replicate_validate( + f = hpx::experimental::async_replicate_validate( usr, &validate, &universal_answer); try { @@ -94,7 +94,7 @@ int hpx_main(hpx::program_options::variables_map& vm) } // aborted replicate - f = hpx::resiliency::async_replicate(a, &no_answer); + f = hpx::experimental::async_replicate(a, &no_answer); try { f.get(); @@ -105,7 +105,7 @@ int hpx_main(hpx::program_options::variables_map& vm) } // aborted replicate validate - f = hpx::resiliency::async_replicate_validate(a, &validate, &no_answer); + f = hpx::experimental::async_replicate_validate(a, &validate, &no_answer); try { f.get(); diff --git a/libs/resiliency/examples/async_replicate_vote.cpp b/libs/resiliency/examples/async_replicate_vote.cpp index 773c8c7bffb2..3d00f837fc74 100644 --- a/libs/resiliency/examples/async_replicate_vote.cpp +++ b/libs/resiliency/examples/async_replicate_vote.cpp @@ -47,7 +47,7 @@ int hpx_main(hpx::program_options::variables_map& vm) hpx::util::high_resolution_timer t; hpx::future f = - hpx::resiliency::async_replicate_vote(n, &vote, &universal_ans); + hpx::experimental::async_replicate_vote(n, &vote, &universal_ans); std::cout << "Universal ans (maybe true): " << f.get() << std::endl; @@ -59,7 +59,7 @@ int hpx_main(hpx::program_options::variables_map& vm) // Initialize a high resolution timer hpx::util::high_resolution_timer t; - hpx::future f = hpx::resiliency::async_replicate_vote_validate( + hpx::future f = hpx::experimental::async_replicate_vote_validate( n, &vote, &validate, &universal_ans); std::cout << "Universal ans (true ans): " << f.get() << std::endl; diff --git a/libs/resiliency/examples/dataflow_replicate.cpp b/libs/resiliency/examples/dataflow_replicate.cpp index 3bad3730b11d..4a95779f0251 100644 --- a/libs/resiliency/examples/dataflow_replicate.cpp +++ b/libs/resiliency/examples/dataflow_replicate.cpp @@ -58,7 +58,7 @@ int hpx_main(hpx::program_options::variables_map& vm) { // Successful replicate hpx::future f = - hpx::resiliency::dataflow_replicate(sr, moody_add, 5, 5); + hpx::experimental::dataflow_replicate(sr, moody_add, 5, 5); try { std::cout << f.get() << std::endl; @@ -73,7 +73,7 @@ int hpx_main(hpx::program_options::variables_map& vm) } // Unsuccessful replicate - f = hpx::resiliency::dataflow_replay(usr, moody_add, 0, 5); + f = hpx::experimental::dataflow_replay(usr, moody_add, 0, 5); try { std::cout << f.get() << std::endl; @@ -88,7 +88,7 @@ int hpx_main(hpx::program_options::variables_map& vm) } // Aborted replicate - f = hpx::resiliency::dataflow_replay(a, bad_add, 10, 5); + f = hpx::experimental::dataflow_replay(a, bad_add, 10, 5); try { std::cout << f.get() << std::endl; diff --git a/libs/resiliency/include/hpx/resiliency/async_replay.hpp b/libs/resiliency/include/hpx/resiliency/async_replay.hpp index 9643d37ce2f2..d0f4e39a6c6e 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replay.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replay.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2020 Hartmut Kaiser // Copyright (c) 2018-2019 Adrian Serio // Copyright (c) 2019 Nikunj Gupta // @@ -11,6 +11,7 @@ #pragma once #include +#include #include #include @@ -164,13 +165,14 @@ namespace hpx { namespace resiliency { } // namespace detail /////////////////////////////////////////////////////////////////////////// - /// Asynchronously launch given function \a f. Verify the result of - /// those invocations using the given predicate \a pred. Repeat launching - /// on error exactly \a n times (except if abort_replay_exception is thrown). + // Asynchronously launch given function \a f. Verify the result of + // those invocations using the given predicate \a pred. Repeat launching + // on error exactly \a n times (except if abort_replay_exception is thrown). template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - async_replay_validate(std::size_t n, Pred&& pred, F&& f, Ts&&... ts) + tag_invoke( + async_replay_validate_t, std::size_t n, Pred&& pred, F&& f, Ts&&... ts) { using result_type = typename hpx::util::detail::invoke_deferred_result::type; @@ -183,19 +185,25 @@ namespace hpx { namespace resiliency { } /////////////////////////////////////////////////////////////////////////// - /// Asynchronously launch given function \a f. Repeat launching - /// on error exactly \a n times (except if abort_replay_exception is thrown). + // Asynchronously launch given function \a f. Repeat launching + // on error exactly \a n times (except if abort_replay_exception is thrown). template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - async_replay(std::size_t n, F&& f, Ts&&... ts) + tag_invoke(async_replay_t, std::size_t n, F&& f, Ts&&... ts) { - return async_replay_validate(n, detail::replay_validator{}, - std::forward(f), std::forward(ts)...); + using result_type = + typename hpx::util::detail::invoke_deferred_result::type; + + auto helper = detail::make_async_replay_helper( + detail::replay_validator{}, std::forward(f), + std::forward(ts)...); + + return helper->call(n); } /////////////////////////////////////////////////////////////////////////// - /// Functional version of \a hpx::resiliency::async_replay + /// Functional version of \a hpx::experimental::async_replay namespace functional { struct async_replay_validate diff --git a/libs/resiliency/include/hpx/resiliency/async_replicate.hpp b/libs/resiliency/include/hpx/resiliency/async_replicate.hpp index cf013234821c..499976fe6a0b 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replicate.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replicate.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2020 Hartmut Kaiser // Copyright (c) 2018-2019 Adrian Serio // Copyright (c) 2019 Nikunj Gupta // @@ -11,6 +11,7 @@ #pragma once #include +#include #include #include @@ -69,122 +70,139 @@ namespace hpx { namespace resiliency { } return ex; } - } // namespace detail - /////////////////////////////////////////////////////////////////////////// - /// Asynchronously launch given function \a f exactly \a n times. Verify - /// the result of those invocations using the given predicate \a pred. - /// Run all the valid results against a user provided voting function. - /// Return the valid output. - template - hpx::future< - typename hpx::util::detail::invoke_deferred_result::type> - async_replicate_vote_validate( - std::size_t n, Vote&& vote, Pred&& pred, F&& f, Ts&&... ts) - { - using result_type = - typename hpx::util::detail::invoke_deferred_result::type; + /////////////////////////////////////////////////////////////////////// + template + hpx::future< + typename hpx::util::detail::invoke_deferred_result::type> + async_replicate_vote_validate( + std::size_t n, Vote&& vote, Pred&& pred, F&& f, Ts&&... ts) + { + using result_type = + typename hpx::util::detail::invoke_deferred_result::type; - // launch given function n times - std::vector> results; - results.reserve(n); + // launch given function n times + std::vector> results; + results.reserve(n); - for (std::size_t i = 0; i != n; ++i) - { - results.emplace_back(hpx::async(f, ts...)); - } + for (std::size_t i = 0; i != n; ++i) + { + results.emplace_back(hpx::async(f, ts...)); + } - // wait for all threads to finish executing and return the first result - // that passes the predicate, properly handle exceptions - return hpx::dataflow( - hpx::launch::sync, // do not schedule new thread for the lambda - [pred = std::forward(pred), vote = std::forward(vote), - n](std::vector>&& results) mutable - -> result_type { - // Store all valid results - std::vector valid_results; - valid_results.reserve(n); - - std::exception_ptr ex; - - for (auto&& f : std::move(results)) - { - if (f.has_exception()) - { - // rethrow abort_replicate_exception, if caught - ex = detail::rethrow_on_abort_replicate(f); - } - else + // wait for all threads to finish executing and return the first result + // that passes the predicate, properly handle exceptions + return hpx::dataflow( + hpx::launch:: + sync, // do not schedule new thread for the lambda + [pred = std::forward(pred), + vote = std::forward(vote), + n](std::vector>&& results) mutable + -> result_type { + // Store all valid results + std::vector valid_results; + valid_results.reserve(n); + + std::exception_ptr ex; + + for (auto&& f : std::move(results)) { - auto&& result = f.get(); - if (hpx::util::invoke(pred, result)) + if (f.has_exception()) + { + // rethrow abort_replicate_exception, if caught + ex = detail::rethrow_on_abort_replicate(f); + } + else { - valid_results.emplace_back(std::move(result)); + auto&& result = f.get(); + if (hpx::util::invoke(pred, result)) + { + valid_results.emplace_back(std::move(result)); + } } } - } - if (!valid_results.empty()) - { - return hpx::util::invoke( - std::forward(vote), std::move(valid_results)); - } + if (!valid_results.empty()) + { + return hpx::util::invoke( + std::forward(vote), std::move(valid_results)); + } + + if (bool(ex)) + std::rethrow_exception(ex); - if (bool(ex)) - std::rethrow_exception(ex); + // throw aborting exception no correct results ere produced + throw abort_replicate_exception{}; + }, + std::move(results)); + } + } // namespace detail - // throw aborting exception no correct results ere produced - throw abort_replicate_exception{}; - }, - std::move(results)); + /////////////////////////////////////////////////////////////////////////// + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations using the given predicate \a pred. + // Run all the valid results against a user provided voting function. + // Return the valid output. + template + hpx::future< + typename hpx::util::detail::invoke_deferred_result::type> + tag_invoke(async_replicate_vote_validate_t, std::size_t n, Vote&& vote, + Pred&& pred, F&& f, Ts&&... ts) + { + return detail::async_replicate_vote_validate(n, + std::forward(vote), std::forward(pred), + std::forward(f), std::forward(ts)...); } /////////////////////////////////////////////////////////////////////////// - /// Asynchronously launch given function \a f exactly \a n times. Verify - /// the result of those invocations using the given predicate \a pred. Run - /// all the valid results against a user provided voting function. - /// Return the valid output. + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations using the given predicate \a pred. Run + // all the valid results against a user provided voting function. + // Return the valid output. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - async_replicate_vote(std::size_t n, Vote&& vote, F&& f, Ts&&... ts) + tag_invoke( + async_replicate_vote_t, std::size_t n, Vote&& vote, F&& f, Ts&&... ts) { - return async_replicate_vote_validate(n, std::forward(vote), - detail::replicate_validator{}, std::forward(f), - std::forward(ts)...); + return detail::async_replicate_vote_validate(n, + std::forward(vote), detail::replicate_validator{}, + std::forward(f), std::forward(ts)...); } /////////////////////////////////////////////////////////////////////////// - /// Asynchronously launch given function \a f exactly \a n times. Verify - /// the result of those invocations using the given predicate \a pred. - /// Return the first valid result. + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations using the given predicate \a pred. + // Return the first valid result. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - async_replicate_validate(std::size_t n, Pred&& pred, F&& f, Ts&&... ts) + tag_invoke(async_replicate_validate_t, std::size_t n, Pred&& pred, F&& f, + Ts&&... ts) { - return async_replicate_vote_validate(n, detail::replicate_voter{}, - std::forward(pred), std::forward(f), - std::forward(ts)...); + return detail::async_replicate_vote_validate(n, + detail::replicate_voter{}, std::forward(pred), + std::forward(f), std::forward(ts)...); } /////////////////////////////////////////////////////////////////////////// - /// Asynchronously launch given function \a f exactly \a n times. Verify - /// the result of those invocations by checking for exception. - /// Return the first valid result. + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations by checking for exception. + // Return the first valid result. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - async_replicate(std::size_t n, F&& f, Ts&&... ts) + tag_invoke(async_replicate_t, std::size_t n, F&& f, Ts&&... ts) { - return async_replicate_vote_validate(n, detail::replicate_voter{}, - detail::replicate_validator{}, std::forward(f), - std::forward(ts)...); + return detail::async_replicate_vote_validate(n, + detail::replicate_voter{}, detail::replicate_validator{}, + std::forward(f), std::forward(ts)...); } /////////////////////////////////////////////////////////////////////////// - /// Functional version of \a hpx::resiliency::async_replicate_validate and - /// \a hpx::resiliency::async_replicate + /// Functional version of \a hpx::experimental::async_replicate_validate and + /// \a hpx::experimental::async_replicate namespace functional { struct async_replicate_vote_validate diff --git a/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp b/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp index ed0f45238eb8..7d9123f90ef1 100644 --- a/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp +++ b/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2020 Hartmut Kaiser // Copyright (c) 2018-2019 Adrian Serio // // SPDX-License-Identifier: BSL-1.0 @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -20,16 +21,17 @@ namespace hpx { namespace resiliency { - /// Asynchronously launch given function \a f. Verify the result of - /// those invocations using the given predicate \a pred. Repeat launching - /// on error exactly \a n times. - /// - /// Delay the invocation of \a f if any of the arguments to \a f are - /// futures. + // Asynchronously launch given function \a f. Verify the result of + // those invocations using the given predicate \a pred. Repeat launching + // on error exactly \a n times. + // + // Delay the invocation of \a f if any of the arguments to \a f are + // futures. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - dataflow_replay_validate(std::size_t n, Pred&& pred, F&& f, Ts&&... ts) + tag_invoke(dataflow_replay_validate_t, std::size_t n, Pred&& pred, F&& f, + Ts&&... ts) { return hpx::dataflow( hpx::resiliency::functional::async_replay_validate{}, n, @@ -37,15 +39,15 @@ namespace hpx { namespace resiliency { std::forward(ts)...); } - /// Asynchronously launch given function \a f. Repeat launching on error - /// exactly \a n times. - /// - /// Delay the invocation of \a f if any of the arguments to \a f are - /// futures. + // Asynchronously launch given function \a f. Repeat launching on error + // exactly \a n times. + // + // Delay the invocation of \a f if any of the arguments to \a f are + // futures. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - dataflow_replay(std::size_t n, F&& f, Ts&&... ts) + tag_invoke(dataflow_replay_t, std::size_t n, F&& f, Ts&&... ts) { return hpx::dataflow(hpx::resiliency::functional::async_replay{}, n, std::forward(f), std::forward(ts)...); diff --git a/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp b/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp index 1e184faf159a..cd75ee579b76 100644 --- a/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp +++ b/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2020 Hartmut Kaiser // Copyright (c) 2018-2019 Adrian Serio // Copyright (c) 2019 Nikunj Gupta // @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -21,17 +22,17 @@ namespace hpx { namespace resiliency { - /// Launch given function \a f exactly \a n times. Run all the valid - /// results against a user provided voting function. - /// Return the valid output. - /// - /// Delay the invocation of \a f if any of the arguments to \a f are - /// futures. + // Launch given function \a f exactly \a n times. Run all the valid + // results against a user provided voting function. + // Return the valid output. + // + // Delay the invocation of \a f if any of the arguments to \a f are + // futures. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - dataflow_replicate_vote_validate( - std::size_t n, Vote&& vote, Pred&& pred, F&& f, Ts&&... ts) + tag_invoke(dataflow_replicate_vote_validate_t, std::size_t n, Vote&& vote, + Pred&& pred, F&& f, Ts&&... ts) { return hpx::dataflow( hpx::resiliency::functional::async_replicate_vote_validate{}, n, @@ -39,16 +40,17 @@ namespace hpx { namespace resiliency { std::forward(f), std::forward(ts)...); } - /// Launch given function \a f exactly \a n times. Run all the valid - /// results against a user provided voting function. - /// Return the valid output. - /// - /// Delay the invocation of \a f if any of the arguments to \a f are - /// futures. + // Launch given function \a f exactly \a n times. Run all the valid + // results against a user provided voting function. + // Return the valid output. + // + // Delay the invocation of \a f if any of the arguments to \a f are + // futures. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - dataflow_replicate_vote(std::size_t n, Vote&& vote, F&& f, Ts&&... ts) + tag_invoke(dataflow_replicate_vote_t, std::size_t n, Vote&& vote, F&& f, + Ts&&... ts) { return hpx::dataflow( hpx::resiliency::functional::async_replicate_vote{}, n, @@ -56,16 +58,17 @@ namespace hpx { namespace resiliency { std::forward(ts)...); } - /// Launch given function \a f exactly \a n times. Verify the result of - /// those invocations using the given predicate \a pred. Return the first - /// valid result. - /// - /// Delay the invocation of \a f if any of the arguments to \a f are - /// futures. + // Launch given function \a f exactly \a n times. Verify the result of + // those invocations using the given predicate \a pred. Return the first + // valid result. + // + // Delay the invocation of \a f if any of the arguments to \a f are + // futures. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - dataflow_replicate_validate(std::size_t n, Pred&& pred, F&& f, Ts&&... ts) + tag_invoke(dataflow_replicate_validate_t, std::size_t n, Pred&& pred, F&& f, + Ts&&... ts) { return hpx::dataflow( hpx::resiliency::functional::async_replicate_validate{}, n, @@ -73,15 +76,15 @@ namespace hpx { namespace resiliency { std::forward(ts)...); } - /// Launch given function \a f exactly \a n times. Return the first - /// valid result. - /// - /// Delay the invocation of \a f if any of the arguments to \a f are - /// futures. + // Launch given function \a f exactly \a n times. Return the first + // valid result. + // + // Delay the invocation of \a f if any of the arguments to \a f are + // futures. template hpx::future< typename hpx::util::detail::invoke_deferred_result::type> - dataflow_replicate(std::size_t n, F&& f, Ts&&... ts) + tag_invoke(dataflow_replicate_t, std::size_t n, F&& f, Ts&&... ts) { return hpx::dataflow(hpx::resiliency::functional::async_replicate{}, n, std::forward(f), std::forward(ts)...); diff --git a/libs/resiliency/include/hpx/resiliency/resiliency.hpp b/libs/resiliency/include/hpx/resiliency/resiliency.hpp index 6c53a2e4fe90..43e4efe26d07 100644 --- a/libs/resiliency/include/hpx/resiliency/resiliency.hpp +++ b/libs/resiliency/include/hpx/resiliency/resiliency.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2020 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -14,3 +14,28 @@ #include #include #include + +namespace hpx { namespace experimental { + + // Replay APIs + using hpx::resiliency::abort_replay_exception; + + using hpx::resiliency::async_replay_validate; + using hpx::resiliency::async_replay; + + using hpx::resiliency::dataflow_replay_validate; + using hpx::resiliency::dataflow_replay; + + // Replicate APIs + using hpx::resiliency::abort_replicate_exception; + + using hpx::resiliency::async_replicate_vote_validate; + using hpx::resiliency::async_replicate_vote; + using hpx::resiliency::async_replicate_validate; + using hpx::resiliency::async_replicate; + + using hpx::resiliency::dataflow_replicate_vote_validate; + using hpx::resiliency::dataflow_replicate_vote; + using hpx::resiliency::dataflow_replicate_validate; + using hpx::resiliency::dataflow_replicate; +}} // namespace hpx::experimental diff --git a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp new file mode 100644 index 000000000000..bf8fdf884da8 --- /dev/null +++ b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp @@ -0,0 +1,147 @@ +// Copyright (c) 2018-2020 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include + +namespace hpx { namespace resiliency { + + /////////////////////////////////////////////////////////////////////////// + // Replay customization points + + /// Customization point for asynchronously launching the given function \a f. + /// repeatedly. Verify the result of those invocations using the given + /// predicate \a pred. + /// Repeat launching on error exactly \a n times (except if + /// abort_replay_exception is thrown). + HPX_INLINE_CONSTEXPR_VARIABLE struct async_replay_validate_t final + : hpx::functional::tag + { + } async_replay_validate; + + /// Customization point for asynchronously launching given function \a f + /// repeatedly. Repeat launching on error exactly \a n times (except if + /// abort_replay_exception is thrown). + HPX_INLINE_CONSTEXPR_VARIABLE struct async_replay_t final + : hpx::functional::tag + { + } async_replay; + + /// Customization point for asynchronously launching the given function \a f. + /// repeatedly. Verify the result of those invocations using the given + /// predicate \a pred. + /// Repeat launching on error exactly \a n times. + /// + /// Delay the invocation of \a f if any of the arguments to \a f are + /// futures. + HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replay_validate_t final + : hpx::functional::tag + { + } dataflow_replay_validate; + + /// Customization point for asynchronously launching the given function \a f. + /// repeatedly. + /// Repeat launching on error exactly \a n times. + /// + /// Delay the invocation of \a f if any of the arguments to \a f are + /// futures. + HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replay_t final + : hpx::functional::tag + { + } dataflow_replay; + + /////////////////////////////////////////////////////////////////////////// + // Replicate customization points + + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Verify the result of those invocations + /// using the given predicate \a pred. + /// Run all the valid results against a user provided voting function. + /// Return the valid output. + HPX_INLINE_CONSTEXPR_VARIABLE struct async_replicate_vote_validate_t final + : hpx::functional::tag + { + } async_replicate_vote_validate; + + /////////////////////////////////////////////////////////////////////////// + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Verify the result of those invocations + /// using the given predicate \a pred. + /// Run all the valid results against a user provided voting function. + /// Return the valid output. + HPX_INLINE_CONSTEXPR_VARIABLE struct async_replicate_vote_t final + : hpx::functional::tag + { + } // namespace resiliency + async_replicate_vote; + + /////////////////////////////////////////////////////////////////////////// + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Verify the result of those invocations + /// using the given predicate \a pred. + /// Return the first valid result. + HPX_INLINE_CONSTEXPR_VARIABLE struct async_replicate_validate_t final + : hpx::functional::tag + { + } async_replicate_validate; + + /////////////////////////////////////////////////////////////////////////// + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Verify the result of those invocations + /// by checking for exception. + /// Return the first valid result. + HPX_INLINE_CONSTEXPR_VARIABLE struct async_replicate_t final + : hpx::functional::tag + { + } async_replicate; + + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Run all the valid results against a + /// user provided voting function. + /// Return the valid output. + /// + /// Delay the invocation of \a f if any of the arguments to \a f are + /// futures. + HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_vote_validate_t + final : hpx::functional::tag + { + } dataflow_replicate_vote_validate; + + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Run all the valid results against a + /// user provided voting function. + /// Return the valid output. + /// + /// Delay the invocation of \a f if any of the arguments to \a f are + /// futures. + HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_vote_t final + : hpx::functional::tag + { + } dataflow_replicate_vote; + + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Verify the result of those invocations + /// using the given predicate \a pred. Return the first valid result. + /// + /// Delay the invocation of \a f if any of the arguments to \a f are + /// futures. + HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_validate_t final + : hpx::functional::tag + { + } dataflow_replicate_validate; + + /// Customization point for asynchronously launching the given function \a f + /// exactly \a n times concurrently. Return the first valid result. + /// + /// Delay the invocation of \a f if any of the arguments to \a f are + /// futures. + HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_t final + : hpx::functional::tag + { + } dataflow_replicate; +}} // namespace hpx::resiliency diff --git a/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp b/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp index abf3d37c55f1..85324dc6d020 100644 --- a/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp +++ b/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp @@ -237,7 +237,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::resiliency::dataflow_replay_validate; + using hpx::experimental::dataflow_replay_validate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp b/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp index d3b4b48ac128..25f157feaf16 100644 --- a/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp +++ b/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp @@ -194,7 +194,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::resiliency::dataflow_replay; + using hpx::experimental::dataflow_replay; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replay/async_replay.cpp b/libs/resiliency/tests/performance/replay/async_replay.cpp index 5f7d86165caa..e472563464fc 100644 --- a/libs/resiliency/tests/performance/replay/async_replay.cpp +++ b/libs/resiliency/tests/performance/replay/async_replay.cpp @@ -90,7 +90,7 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::resiliency::async_replay( + hpx::future f = hpx::experimental::async_replay( n, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replay/async_replay_validate.cpp b/libs/resiliency/tests/performance/replay/async_replay_validate.cpp index 801e7f292f1a..0f8abc62bf97 100644 --- a/libs/resiliency/tests/performance/replay/async_replay_validate.cpp +++ b/libs/resiliency/tests/performance/replay/async_replay_validate.cpp @@ -93,7 +93,7 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::resiliency::async_replay_validate( + hpx::future f = hpx::experimental::async_replay_validate( n, &validate, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replay/dataflow_replay.cpp b/libs/resiliency/tests/performance/replay/dataflow_replay.cpp index 3352849f39f1..65aef1f8dc0c 100644 --- a/libs/resiliency/tests/performance/replay/dataflow_replay.cpp +++ b/libs/resiliency/tests/performance/replay/dataflow_replay.cpp @@ -239,7 +239,7 @@ struct stepper std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::resiliency::dataflow_replay; + using hpx::experimental::dataflow_replay; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp b/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp index 662804c7b65c..9293e84c8fbe 100644 --- a/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp +++ b/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp @@ -231,7 +231,7 @@ struct stepper std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::resiliency::dataflow_replay_validate; + using hpx::experimental::dataflow_replay_validate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp index fb806ce9c224..c1f45ef3fec3 100644 --- a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp +++ b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp @@ -195,7 +195,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::resiliency::dataflow_replicate; + using hpx::experimental::dataflow_replicate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp index dbdb048226ba..312f0a94fa4f 100644 --- a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp +++ b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp @@ -236,7 +236,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::resiliency::dataflow_replicate_validate; + using hpx::experimental::dataflow_replicate_validate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp b/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp index 200eface3992..4c646c7cf9c0 100644 --- a/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp +++ b/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp @@ -98,7 +98,7 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::resiliency::async_replicate_validate( + hpx::future f = hpx::experimental::async_replicate_validate( n, &validate, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp b/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp index a33f386240e5..667f99d894e7 100644 --- a/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp +++ b/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp @@ -98,7 +98,7 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::resiliency::async_replicate_validate( + hpx::future f = hpx::experimental::async_replicate_validate( n, &validate, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp b/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp index 55a216f0560d..6a634f85f6e3 100644 --- a/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp +++ b/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp @@ -95,7 +95,7 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::resiliency::async_replicate_vote( + hpx::future f = hpx::experimental::async_replicate_vote( n, &vote, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } From 158bfffdca428cc0f9ff89d572edb03ef9b82f0b Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Wed, 22 Jul 2020 14:08:11 -0500 Subject: [PATCH 07/29] Remove functional helpers as those are not needed anymore --- .../include/hpx/resiliency/async_replay.hpp | 33 +--------- .../hpx/resiliency/async_replicate.hpp | 63 +------------------ .../hpx/resiliency/dataflow_replay.hpp | 5 +- .../hpx/resiliency/dataflow_replicate.hpp | 11 ++-- 4 files changed, 8 insertions(+), 104 deletions(-) diff --git a/libs/resiliency/include/hpx/resiliency/async_replay.hpp b/libs/resiliency/include/hpx/resiliency/async_replay.hpp index d0f4e39a6c6e..1937c02fad63 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replay.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replay.hpp @@ -201,35 +201,4 @@ namespace hpx { namespace resiliency { return helper->call(n); } - - /////////////////////////////////////////////////////////////////////////// - /// Functional version of \a hpx::experimental::async_replay - namespace functional { - - struct async_replay_validate - { - template - auto operator()(std::size_t n, Pred&& pred, F&& f, Ts&&... ts) const - -> decltype(hpx::resiliency::async_replay_validate(n, - std::forward(pred), std::forward(f), - std::forward(ts)...)) - { - return hpx::resiliency::async_replay_validate(n, - std::forward(pred), std::forward(f), - std::forward(ts)...); - } - }; - - struct async_replay - { - template - auto operator()(std::size_t n, F&& f, Ts&&... ts) const - -> decltype(hpx::resiliency::async_replay( - n, std::forward(f), std::forward(ts)...)) - { - return hpx::resiliency::async_replay( - n, std::forward(f), std::forward(ts)...); - } - }; - } // namespace functional -}} // namespace hpx::resiliency +}} // namespace hpx::resiliency diff --git a/libs/resiliency/include/hpx/resiliency/async_replicate.hpp b/libs/resiliency/include/hpx/resiliency/async_replicate.hpp index 499976fe6a0b..fea43dec1c32 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replicate.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replicate.hpp @@ -199,65 +199,4 @@ namespace hpx { namespace resiliency { detail::replicate_voter{}, detail::replicate_validator{}, std::forward(f), std::forward(ts)...); } - - /////////////////////////////////////////////////////////////////////////// - /// Functional version of \a hpx::experimental::async_replicate_validate and - /// \a hpx::experimental::async_replicate - namespace functional { - - struct async_replicate_vote_validate - { - template - auto operator()(std::size_t n, Vote&& vote, Pred&& pred, F&& f, - Ts&&... ts) const - -> decltype(hpx::resiliency::async_replicate_vote_validate(n, - std::forward(vote), std::forward(pred), - std::forward(f), std::forward(ts)...)) - { - return hpx::resiliency::async_replicate_vote_validate(n, - std::forward(vote), std::forward(pred), - std::forward(f), std::forward(ts)...); - } - }; - - struct async_replicate_vote - { - template - auto operator()(std::size_t n, Vote&& vote, F&& f, Ts&&... ts) const - -> decltype(hpx::resiliency::async_replicate_vote(n, - std::forward(vote), std::forward(f), - std::forward(ts)...)) - { - return hpx::resiliency::async_replicate_vote(n, - std::forward(vote), std::forward(f), - std::forward(ts)...); - } - }; - - struct async_replicate_validate - { - template - auto operator()(std::size_t n, Pred&& pred, F&& f, Ts&&... ts) const - -> decltype(hpx::resiliency::async_replicate_validate(n, - std::forward(pred), std::forward(f), - std::forward(ts)...)) - { - return hpx::resiliency::async_replicate_validate(n, - std::forward(pred), std::forward(f), - std::forward(ts)...); - } - }; - - struct async_replicate - { - template - auto operator()(std::size_t n, F&& f, Ts&&... ts) const - -> decltype(hpx::resiliency::async_replicate( - n, std::forward(f), std::forward(ts)...)) - { - return hpx::resiliency::async_replicate( - n, std::forward(f), std::forward(ts)...); - } - }; - } // namespace functional -}} // namespace hpx::resiliency +}} // namespace hpx::resiliency diff --git a/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp b/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp index 7d9123f90ef1..d81f225b780d 100644 --- a/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp +++ b/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp @@ -33,8 +33,7 @@ namespace hpx { namespace resiliency { tag_invoke(dataflow_replay_validate_t, std::size_t n, Pred&& pred, F&& f, Ts&&... ts) { - return hpx::dataflow( - hpx::resiliency::functional::async_replay_validate{}, n, + return hpx::dataflow(hpx::resiliency::async_replay_validate, n, std::forward(pred), std::forward(f), std::forward(ts)...); } @@ -49,7 +48,7 @@ namespace hpx { namespace resiliency { typename hpx::util::detail::invoke_deferred_result::type> tag_invoke(dataflow_replay_t, std::size_t n, F&& f, Ts&&... ts) { - return hpx::dataflow(hpx::resiliency::functional::async_replay{}, n, + return hpx::dataflow(hpx::resiliency::async_replay, n, std::forward(f), std::forward(ts)...); } }} // namespace hpx::resiliency diff --git a/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp b/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp index cd75ee579b76..a62b54a6ceb8 100644 --- a/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp +++ b/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp @@ -34,8 +34,7 @@ namespace hpx { namespace resiliency { tag_invoke(dataflow_replicate_vote_validate_t, std::size_t n, Vote&& vote, Pred&& pred, F&& f, Ts&&... ts) { - return hpx::dataflow( - hpx::resiliency::functional::async_replicate_vote_validate{}, n, + return hpx::dataflow(hpx::resiliency::async_replicate_vote_validate, n, std::forward(vote), std::forward(pred), std::forward(f), std::forward(ts)...); } @@ -52,8 +51,7 @@ namespace hpx { namespace resiliency { tag_invoke(dataflow_replicate_vote_t, std::size_t n, Vote&& vote, F&& f, Ts&&... ts) { - return hpx::dataflow( - hpx::resiliency::functional::async_replicate_vote{}, n, + return hpx::dataflow(hpx::resiliency::async_replicate_vote, n, std::forward(vote), std::forward(f), std::forward(ts)...); } @@ -70,8 +68,7 @@ namespace hpx { namespace resiliency { tag_invoke(dataflow_replicate_validate_t, std::size_t n, Pred&& pred, F&& f, Ts&&... ts) { - return hpx::dataflow( - hpx::resiliency::functional::async_replicate_validate{}, n, + return hpx::dataflow(hpx::resiliency::async_replicate_validate, n, std::forward(pred), std::forward(f), std::forward(ts)...); } @@ -86,7 +83,7 @@ namespace hpx { namespace resiliency { typename hpx::util::detail::invoke_deferred_result::type> tag_invoke(dataflow_replicate_t, std::size_t n, F&& f, Ts&&... ts) { - return hpx::dataflow(hpx::resiliency::functional::async_replicate{}, n, + return hpx::dataflow(hpx::resiliency::async_replicate, n, std::forward(f), std::forward(ts)...); } }} // namespace hpx::resiliency From 1e53c02f18aa3867118862ecf46ac823b2abf497 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Wed, 22 Jul 2020 17:13:30 -0500 Subject: [PATCH 08/29] Adding async_replay and async_replicate for executors - adding tests - flyby: enable single integral value as Shape parameter for bulk_async_execute (and friends) --- .../hpx/execution/traits/executor_traits.hpp | 77 +++++++ .../traits/future_then_result_exec.hpp | 59 +----- .../include/hpx/execution_base/execution.hpp | 73 ++++++- .../iterator_support/counting_iterator.hpp | 2 +- libs/resiliency/CMakeLists.txt | 5 +- libs/resiliency/docs/index.rst | 4 +- libs/resiliency/examples/async_replicate.cpp | 8 +- .../hpx/resiliency/async_replay_executor.hpp | 195 ++++++++++++++++++ .../resiliency/async_replicate_executor.hpp | 195 ++++++++++++++++++ .../include/hpx/resiliency/resiliency.hpp | 3 +- .../tests/performance/replay/async_replay.cpp | 2 +- .../replay/async_replay_validate.cpp | 2 +- .../replay/pure_async_for_replay.cpp | 2 +- libs/resiliency/tests/unit/CMakeLists.txt | 23 ++- .../tests/unit/async_replay_executor.cpp | 152 ++++++++++++++ .../tests/unit/async_replicate_executor.cpp | 149 +++++++++++++ .../unit/async_replicate_vote_executor.cpp | 73 +++++++ 17 files changed, 950 insertions(+), 74 deletions(-) create mode 100644 libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp create mode 100644 libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp create mode 100644 libs/resiliency/tests/unit/async_replay_executor.cpp create mode 100644 libs/resiliency/tests/unit/async_replicate_executor.cpp create mode 100644 libs/resiliency/tests/unit/async_replicate_vote_executor.cpp diff --git a/libs/execution/include/hpx/execution/traits/executor_traits.hpp b/libs/execution/include/hpx/execution/traits/executor_traits.hpp index 952cfe7b1833..0a8792b96f69 100644 --- a/libs/execution/include/hpx/execution/traits/executor_traits.hpp +++ b/libs/execution/include/hpx/execution/traits/executor_traits.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,11 @@ #include #include +namespace hpx { namespace lcos { + template + class future; +}} // namespace hpx::lcos + namespace hpx { namespace parallel { namespace execution { /////////////////////////////////////////////////////////////////////////// struct static_chunk_size; @@ -174,6 +180,65 @@ namespace hpx { namespace parallel { namespace execution { hpx::util::detected_or_t; }; + + /////////////////////////////////////////////////////////////////////////// + namespace detail { + template + struct executor_future; + + template + struct exposes_future_type : std::false_type + { + }; + + template + struct exposes_future_type>::type> + : std::true_type + { + }; + + template + struct executor_future, + typename std::enable_if< + hpx::traits::is_two_way_executor::value && + exposes_future_type::value>::type> + { + using type = typename Executor::template future_type; + }; + + template + struct executor_future, + typename std::enable_if< + hpx::traits::is_two_way_executor::value && + !exposes_future_type::value>::type> + { + using type = decltype(std::declval().async_execute( + std::declval(), std::declval()...)); + }; + + template + struct executor_future::value>::type> + { + using type = hpx::lcos::future; + }; + } // namespace detail + + template + struct executor_future + : detail::executor_future::type, T, + hpx::util::pack::type...>> + { + }; + + template + using executor_future_t = + typename executor_future::type; + }}} // namespace hpx::parallel::execution namespace hpx { namespace traits { @@ -266,6 +331,18 @@ namespace hpx { namespace traits { template using executor_index_t = typename executor_index::type; + template + struct executor_future + : parallel::execution::executor_future< + typename std::decay::type, T, + typename std::decay::type...> + { + }; + + template + using executor_future_t = + typename executor_future::type; + /////////////////////////////////////////////////////////////////////////// // extension template diff --git a/libs/execution/include/hpx/execution/traits/future_then_result_exec.hpp b/libs/execution/include/hpx/execution/traits/future_then_result_exec.hpp index e478617f105d..fe32143ff478 100644 --- a/libs/execution/include/hpx/execution/traits/future_then_result_exec.hpp +++ b/libs/execution/include/hpx/execution/traits/future_then_result_exec.hpp @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include #include @@ -22,64 +23,6 @@ #include namespace hpx { namespace traits { - /////////////////////////////////////////////////////////////////////////// - namespace detail { - template - struct executor_future; - - template - struct exposes_future_type : std::false_type - { - }; - - template - struct exposes_future_type>::type> - : std::true_type - { - }; - - template - struct executor_future, - typename std::enable_if< - hpx::traits::is_two_way_executor::value && - exposes_future_type::value>::type> - { - using type = typename Executor::template future_type; - }; - - template - struct executor_future, - typename std::enable_if< - hpx::traits::is_two_way_executor::value && - !exposes_future_type::value>::type> - { - using type = decltype(std::declval().async_execute( - std::declval(), std::declval()...)); - }; - - template - struct executor_future::value>::type> - { - using type = hpx::lcos::future; - }; - } // namespace detail - - template - struct executor_future - : detail::executor_future::type, T, - hpx::util::pack::type...>> - { - }; - - template - using executor_future_t = - typename executor_future::type; - /////////////////////////////////////////////////////////////////////////// namespace detail { /////////////////////////////////////////////////////////////////////// diff --git a/libs/execution_base/include/hpx/execution_base/execution.hpp b/libs/execution_base/include/hpx/execution_base/execution.hpp index 02541715e3f2..206acf65d2b2 100644 --- a/libs/execution_base/include/hpx/execution_base/execution.hpp +++ b/libs/execution_base/include/hpx/execution_base/execution.hpp @@ -10,6 +10,7 @@ #pragma once #include +#include #include #include @@ -309,12 +310,26 @@ namespace hpx { namespace parallel { namespace execution { /////////////////////////////////////////////////////////////////////// // bulk_async_execute customization point + template + using counting_shape_type = hpx::util::iterator_range< + hpx::util::counting_iterator>; + + template + counting_shape_type make_counting_shape(Incrementable n) + { + return hpx::util::make_iterator_range( + hpx::util::make_counting_iterator(Incrementable(0)), + hpx::util::make_counting_iterator(n)); + } + template <> struct customization_point { public: template + typename... Ts, + typename Enable = typename std::enable_if< + !std::is_integral::value>::type> HPX_FORCEINLINE auto operator()( Executor&& exec, F&& f, Shape const& shape, Ts&&... ts) const -> decltype(bulk_async_execute(std::forward(exec), @@ -323,6 +338,22 @@ namespace hpx { namespace parallel { namespace execution { return bulk_async_execute(std::forward(exec), std::forward(f), shape, std::forward(ts)...); } + + template ::value>::type> + HPX_FORCEINLINE auto operator()( + Executor&& exec, F&& f, Shape const& n, Ts&&... ts) const + -> decltype(bulk_async_execute(std::forward(exec), + std::forward(f), + std::declval>(), + std::forward(ts)...)) + { + return bulk_async_execute(std::forward(exec), + std::forward(f), make_counting_shape(n), + std::forward(ts)...); + } }; /////////////////////////////////////////////////////////////////////// @@ -332,7 +363,9 @@ namespace hpx { namespace parallel { namespace execution { { public: template + typename... Ts, + typename Enable = typename std::enable_if< + !std::is_integral::value>::type> HPX_FORCEINLINE auto operator()( Executor&& exec, F&& f, Shape const& shape, Ts&&... ts) const -> decltype(bulk_sync_execute(std::forward(exec), @@ -341,6 +374,22 @@ namespace hpx { namespace parallel { namespace execution { return bulk_sync_execute(std::forward(exec), std::forward(f), shape, std::forward(ts)...); } + + template ::value>::type> + HPX_FORCEINLINE auto operator()( + Executor&& exec, F&& f, Shape const& n, Ts&&... ts) const + -> decltype(bulk_sync_execute(std::forward(exec), + std::forward(f), + std::declval>(), + std::forward(ts)...)) + { + return bulk_sync_execute(std::forward(exec), + std::forward(f), make_counting_shape(n), + std::forward(ts)...); + } }; /////////////////////////////////////////////////////////////////////// @@ -350,7 +399,9 @@ namespace hpx { namespace parallel { namespace execution { { public: template + typename Future, typename... Ts, + typename Enable = typename std::enable_if< + !std::is_integral::value>::type> HPX_FORCEINLINE auto operator()(Executor&& exec, F&& f, Shape const& shape, Future&& predecessor, Ts&&... ts) const -> decltype(bulk_then_execute(std::forward(exec), @@ -361,6 +412,22 @@ namespace hpx { namespace parallel { namespace execution { std::forward(f), shape, std::forward(predecessor), std::forward(ts)...); } + + template ::value>::type> + HPX_FORCEINLINE auto operator()(Executor&& exec, F&& f, + Shape const& n, Future&& predecessor, Ts&&... ts) const + -> decltype(bulk_then_execute(std::forward(exec), + std::forward(f), + std::declval>(), + std::forward(predecessor), std::forward(ts)...)) + { + return bulk_then_execute(std::forward(exec), + std::forward(f), make_counting_shape(n), + std::forward(predecessor), std::forward(ts)...); + } }; /// \endcond } // namespace detail diff --git a/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp b/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp index 3b5b28156077..0b571346a059 100644 --- a/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp +++ b/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp @@ -84,7 +84,7 @@ namespace hpx { namespace util { } // namespace detail //////////////////////////////////////////////////////////////////////////// - // specialization for Iterators (non-itengral types) + // specialization for Iterators (non-intengral types) template class counting_iterator diff --git a/libs/resiliency/CMakeLists.txt b/libs/resiliency/CMakeLists.txt index 4067a246ac86..e49900a01e97 100644 --- a/libs/resiliency/CMakeLists.txt +++ b/libs/resiliency/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019 The STE||AR-Group +# Copyright (c) 2019-2020 The STE||AR-Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -11,7 +11,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Default location is $HPX_ROOT/libs/resiliency/include set(resiliency_headers hpx/resiliency/async_replay.hpp + hpx/resiliency/async_replay_executor.hpp hpx/resiliency/async_replicate.hpp + hpx/resiliency/async_replicate_executor.hpp hpx/resiliency/config.hpp hpx/resiliency/dataflow_replay.hpp hpx/resiliency/dataflow_replicate.hpp @@ -34,6 +36,7 @@ add_hpx_module( hpx_async_local hpx_config hpx_datastructures + hpx_execution hpx_functional CMAKE_SUBDIRS examples tests ) diff --git a/libs/resiliency/docs/index.rst b/libs/resiliency/docs/index.rst index 887ab5e7b084..8e0e2672e5d2 100644 --- a/libs/resiliency/docs/index.rst +++ b/libs/resiliency/docs/index.rst @@ -33,7 +33,7 @@ The following API functions are exposed: - :cpp:func:`hpx::experimental::async_replay`: This version of task replay will catch user-defined exceptions and automatically reschedule the task N times - before throwing an :cpp:func:`hpx::resiliency::abort_replay_exception` if no + before throwing an :cpp:func:`hpx::experimental::abort_replay_exception` if no task is able to complete execution without an exception. - :cpp:func:`hpx::experimental::async_replay_validate`: This version of replay @@ -68,7 +68,7 @@ The following API functions are exposed: - :cpp:func:`hpx::experimental::dataflow_replay`: This version of dataflow replay will catch user-defined exceptions and automatically reschedules the task N - times before throwing an :cpp:func:`hpx::resiliency::abort_replay_exception` + times before throwing an :cpp:func:`hpx::experimental::abort_replay_exception` if no task is able to complete execution without an exception. Any arguments for the executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. diff --git a/libs/resiliency/examples/async_replicate.cpp b/libs/resiliency/examples/async_replicate.cpp index b72e96943696..60a5f34251dd 100644 --- a/libs/resiliency/examples/async_replicate.cpp +++ b/libs/resiliency/examples/async_replicate.cpp @@ -35,7 +35,7 @@ bool validate(int result) int no_answer() { - throw hpx::resiliency::abort_replicate_exception(); + throw hpx::experimental::abort_replicate_exception(); } int deep_thought() @@ -88,7 +88,7 @@ int hpx_main(hpx::program_options::variables_map& vm) { f.get(); } - catch (hpx::resiliency::abort_replicate_exception const&) + catch (hpx::experimental::abort_replicate_exception const&) { std::cout << "no universal answer!\n"; } @@ -99,7 +99,7 @@ int hpx_main(hpx::program_options::variables_map& vm) { f.get(); } - catch (hpx::resiliency::abort_replicate_exception const&) + catch (hpx::experimental::abort_replicate_exception const&) { std::cout << "aborted universal answer calculation!\n"; } @@ -110,7 +110,7 @@ int hpx_main(hpx::program_options::variables_map& vm) { f.get(); } - catch (hpx::resiliency::abort_replicate_exception const&) + catch (hpx::experimental::abort_replicate_exception const&) { std::cout << "aborted universal answer calculation!\n"; } diff --git a/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp b/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp new file mode 100644 index 000000000000..32863d9a486b --- /dev/null +++ b/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp @@ -0,0 +1,195 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2018-2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace hpx { namespace resiliency { + + /////////////////////////////////////////////////////////////////////////// + namespace detail { + + /////////////////////////////////////////////////////////////////////// + template + struct async_replay_executor_helper + : std::enable_shared_from_this< + async_replay_executor_helper> + { + template + async_replay_executor_helper(Pred_&& pred, F_&& f, Tuple_&& tuple) + : pred_(std::forward(pred)) + , f_(std::forward(f)) + , t_(std::forward(tuple)) + { + } + + template + Result invoke(Executor&& exec, hpx::util::index_pack) + { + return hpx::parallel::execution::async_execute( + exec, f_, std::get(t_)...); + } + + template + Result call(Executor&& exec, std::size_t n) + { + // launch given function asynchronously + using pack_type = + hpx::util::make_index_pack::value>; + + Result f = invoke(exec, pack_type{}); + + // attach a continuation that will relaunch the task, if + // necessary + auto this_ = this->shared_from_this(); + return f.then(hpx::launch::sync, + [this_ = std::move(this_), &exec, n](Result&& f) { + if (f.has_exception()) + { + // rethrow abort_replay_exception, if caught + auto ex = rethrow_on_abort_replay(f); + + // execute the task again if an error occurred and + // this was not the last attempt + if (n != 0) + { + return this_->call(exec, n - 1); + } + + // rethrow exception if the number of replays has + // been exhausted + std::rethrow_exception(ex); + } + + auto&& result = f.get(); + + if (!hpx::util::invoke(this_->pred_, result)) + { + // execute the task again if an error occurred and + // this was not the last attempt + if (n != 0) + { + return this_->call(exec, n - 1); + } + + // throw aborting exception as attempts were + // exhausted + throw abort_replay_exception(); + } + + if (n != 0) + { + // return result + return hpx::make_ready_future(std::move(result)); + } + + // throw aborting exception as attempts were + // exhausted + throw abort_replay_exception(); + }); + } + + Pred pred_; + F f_; + Tuple t_; + }; + + template + std::shared_ptr::type, typename std::decay::type, + std::tuple::type...>>> + make_async_replay_executor_helper(Pred&& pred, F&& f, Ts&&... ts) + { + using tuple_type = std::tuple::type...>; + + using return_type = async_replay_executor_helper::type, typename std::decay::type, + std::tuple::type...>>; + + return std::make_shared(std::forward(pred), + std::forward(f), std::make_tuple(std::forward(ts)...)); + } + } // namespace detail + + /////////////////////////////////////////////////////////////////////////// + // Asynchronously launch given function \a f. Verify the result of + // those invocations using the given predicate \a pred. Repeat launching + // on error exactly \a n times (except if abort_replay_exception is thrown). + // clang-format off + template ::value || + hpx::traits::is_two_way_executor::value || + hpx::traits::is_threads_executor::value + )> + // clang-format on + decltype(auto) tag_invoke(async_replay_validate_t, Executor&& exec, + std::size_t n, Pred&& pred, F&& f, Ts&&... ts) + { + using result_type = + typename hpx::util::detail::invoke_deferred_result::type; + + using future_type = + typename hpx::parallel::execution::executor_future::type; + + auto helper = detail::make_async_replay_executor_helper( + std::forward(pred), std::forward(f), + std::forward(ts)...); + + return helper->call(std::forward(exec), n); + } + + /////////////////////////////////////////////////////////////////////////// + // Asynchronously launch given function \a f. Repeat launching + // on error exactly \a n times (except if abort_replay_exception is thrown). + // clang-format off + template ::value || + hpx::traits::is_two_way_executor::value || + hpx::traits::is_threads_executor::value + )> + // clang-format on + decltype(auto) tag_invoke( + async_replay_t, Executor&& exec, std::size_t n, F&& f, Ts&&... ts) + { + using result_type = + typename hpx::util::detail::invoke_deferred_result::type; + + using future_type = + typename hpx::parallel::execution::executor_future::type; + + auto helper = detail::make_async_replay_executor_helper( + detail::replay_validator{}, std::forward(f), + std::forward(ts)...); + + return helper->call(std::forward(exec), n); + } +}} // namespace hpx::resiliency diff --git a/libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp b/libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp new file mode 100644 index 000000000000..7a5a4416d44f --- /dev/null +++ b/libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp @@ -0,0 +1,195 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2018-2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace hpx { namespace resiliency { + namespace detail { + + /////////////////////////////////////////////////////////////////////// + template + typename hpx::traits::executor_future::type>::type + async_replicate_vote_validate_executor(Executor&& exec, std::size_t n, + Vote&& vote, Pred&& pred, F&& f, Ts&&... ts) + { + using result_type = + typename hpx::util::detail::invoke_deferred_result::type; + + using future_type = typename hpx::traits::executor_future::type; + + // launch given function n times + auto func = [f = std::forward(f), + t = hpx::util::make_tuple(std::forward(ts)...)]( + std::size_t) -> result_type { + // ignore argument (invocation count of bulk_execute) + return hpx::util::invoke_fused(f, t); + }; + + std::vector results = + hpx::parallel::execution::bulk_async_execute( + std::forward(exec), std::move(func), n); + + // wait for all threads to finish executing and return the first + // result that passes the predicate, properly handle exceptions + // do not schedule new thread for the lambda + return hpx::dataflow( + hpx::launch::sync, + [pred = std::forward(pred), + vote = std::forward(vote), n]( + std::vector&& results) mutable -> result_type { + // Store all valid results + std::vector valid_results; + valid_results.reserve(n); + + std::exception_ptr ex; + + for (auto&& f : std::move(results)) + { + if (f.has_exception()) + { + // rethrow abort_replicate_exception, if caught + ex = detail::rethrow_on_abort_replicate(f); + } + else + { + auto&& result = f.get(); + if (hpx::util::invoke(pred, result)) + { + valid_results.emplace_back(std::move(result)); + } + } + } + + if (!valid_results.empty()) + { + return hpx::util::invoke( + std::forward(vote), std::move(valid_results)); + } + + if (bool(ex)) + { + std::rethrow_exception(ex); + } + + // throw aborting exception no correct results ere produced + throw abort_replicate_exception{}; + }, + std::move(results)); + } + } // namespace detail + + /////////////////////////////////////////////////////////////////////////// + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations using the given predicate \a pred. + // Run all the valid results against a user provided voting function. + // Return the valid output. + // clang-format off + template ::value || + hpx::traits::is_two_way_executor::value || + hpx::traits::is_threads_executor::value + )> + // clang-format on + decltype(auto) tag_invoke(async_replicate_vote_validate_t, Executor&& exec, + std::size_t n, Vote&& vote, Pred&& pred, F&& f, Ts&&... ts) + { + return detail::async_replicate_vote_validate_executor( + std::forward(exec), n, std::forward(vote), + std::forward(pred), std::forward(f), + std::forward(ts)...); + } + + /////////////////////////////////////////////////////////////////////////// + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations using the given predicate \a pred. Run + // all the valid results against a user provided voting function. + // Return the valid output. + // clang-format off + template ::value || + hpx::traits::is_two_way_executor::value || + hpx::traits::is_threads_executor::value + )> + // clang-format on + decltype(auto) tag_invoke(async_replicate_vote_t, Executor&& exec, + std::size_t n, Vote&& vote, F&& f, Ts&&... ts) + { + return detail::async_replicate_vote_validate_executor( + std::forward(exec), n, std::forward(vote), + detail::replicate_validator{}, std::forward(f), + std::forward(ts)...); + } + + /////////////////////////////////////////////////////////////////////////// + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations using the given predicate \a pred. + // Return the first valid result. + // clang-format off + template ::value || + hpx::traits::is_two_way_executor::value || + hpx::traits::is_threads_executor::value + )> + // clang-format on + decltype(auto) tag_invoke(async_replicate_validate_t, Executor&& exec, + std::size_t n, Pred&& pred, F&& f, Ts&&... ts) + { + return detail::async_replicate_vote_validate_executor( + std::forward(exec), n, detail::replicate_voter{}, + std::forward(pred), std::forward(f), + std::forward(ts)...); + } + + /////////////////////////////////////////////////////////////////////////// + // Asynchronously launch given function \a f exactly \a n times. Verify + // the result of those invocations by checking for exception. + // Return the first valid result. + // clang-format off + template ::value || + hpx::traits::is_two_way_executor::value || + hpx::traits::is_threads_executor::value + )> + // clang-format on + decltype(auto) tag_invoke( + async_replicate_t, Executor&& exec, std::size_t n, F&& f, Ts&&... ts) + { + return detail::async_replicate_vote_validate_executor( + std::forward(exec), n, detail::replicate_voter{}, + detail::replicate_validator{}, std::forward(f), + std::forward(ts)...); + } +}} // namespace hpx::resiliency diff --git a/libs/resiliency/include/hpx/resiliency/resiliency.hpp b/libs/resiliency/include/hpx/resiliency/resiliency.hpp index 43e4efe26d07..2872407956d0 100644 --- a/libs/resiliency/include/hpx/resiliency/resiliency.hpp +++ b/libs/resiliency/include/hpx/resiliency/resiliency.hpp @@ -8,9 +8,10 @@ #pragma once -#include #include +#include #include +#include #include #include #include diff --git a/libs/resiliency/tests/performance/replay/async_replay.cpp b/libs/resiliency/tests/performance/replay/async_replay.cpp index e472563464fc..cdd504874d7d 100644 --- a/libs/resiliency/tests/performance/replay/async_replay.cpp +++ b/libs/resiliency/tests/performance/replay/async_replay.cpp @@ -108,7 +108,7 @@ int hpx_main(hpx::program_options::variables_map& vm) "past the injected error levels" << std::endl; } - catch (hpx::resiliency::abort_replay_exception const&) + catch (hpx::experimental::abort_replay_exception const&) { std::cout << "Number of repeat launches were not enough to get " "past the injected error levels" diff --git a/libs/resiliency/tests/performance/replay/async_replay_validate.cpp b/libs/resiliency/tests/performance/replay/async_replay_validate.cpp index 0f8abc62bf97..d18b7b06aff4 100644 --- a/libs/resiliency/tests/performance/replay/async_replay_validate.cpp +++ b/libs/resiliency/tests/performance/replay/async_replay_validate.cpp @@ -111,7 +111,7 @@ int hpx_main(hpx::program_options::variables_map& vm) "past the injected error levels" << std::endl; } - catch (hpx::resiliency::abort_replay_exception const&) + catch (hpx::experimental::abort_replay_exception const&) { std::cout << "Number of repeat launches were not enough to get " "past the injected error levels" diff --git a/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp b/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp index 8c50f4d1240e..dd51e1e7eb59 100644 --- a/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp +++ b/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp @@ -105,7 +105,7 @@ int hpx_main(hpx::program_options::variables_map& vm) { std::cout << "Exceptions thrown" << std::endl; } - catch (hpx::resiliency::abort_replay_exception const&) + catch (hpx::experimental::abort_replay_exception const&) { std::cout << "Exceptions thrown" << std::endl; } diff --git a/libs/resiliency/tests/unit/CMakeLists.txt b/libs/resiliency/tests/unit/CMakeLists.txt index e050627465c9..de481dc9e1ec 100644 --- a/libs/resiliency/tests/unit/CMakeLists.txt +++ b/libs/resiliency/tests/unit/CMakeLists.txt @@ -1,5 +1,26 @@ -# Copyright (c) 2019 The STE||AR-Group +# Copyright (c) 2020 The STE||AR-Group # # SPDX-License-Identifier: BSL-1.0 # 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) + +set(tests async_replicate_executor async_replicate_vote_executor + async_replay_executor) + +foreach(test ${tests}) + set(sources ${test}.cpp) + + source_group("Source Files" FILES ${sources}) + + set(folder_name "Tests/Unit/Modules/Resiliency") + + # add test executable + add_hpx_executable( + ${test}_test INTERNAL_FLAGS + SOURCES ${sources} ${${test}_FLAGS} + EXCLUDE_FROM_ALL + FOLDER ${folder_name} + ) + + add_hpx_unit_test("modules.resiliency" ${test} ${${test}_PARAMETERS}) +endforeach() diff --git a/libs/resiliency/tests/unit/async_replay_executor.cpp b/libs/resiliency/tests/unit/async_replay_executor.cpp new file mode 100644 index 000000000000..05098fb08ff6 --- /dev/null +++ b/libs/resiliency/tests/unit/async_replay_executor.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2018-2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::experimental::abort_replay_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + hpx::parallel::execution::parallel_executor exec; + + // successful replay + hpx::future f = + hpx::experimental::async_replay(exec, 10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replay validate + f = hpx::experimental::async_replay_validate( + exec, 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replay + f = hpx::experimental::async_replay(exec, 6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replay validate + f = hpx::experimental::async_replay_validate( + exec, 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay + f = hpx::experimental::async_replay(exec, 1, &no_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay validate + f = hpx::experimental::async_replay_validate( + exec, 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/async_replicate_executor.cpp b/libs/resiliency/tests/unit/async_replicate_executor.cpp new file mode 100644 index 000000000000..b6d24a5915ee --- /dev/null +++ b/libs/resiliency/tests/unit/async_replicate_executor.cpp @@ -0,0 +1,149 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); + +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::experimental::abort_replicate_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + hpx::parallel::execution::parallel_executor exec; + + // successful replicate + hpx::future f = + hpx::experimental::async_replicate(exec, 10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replicate_validate + f = hpx::experimental::async_replicate_validate( + exec, 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replicate + f = hpx::experimental::async_replicate(exec, 6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replicate_validate + f = hpx::experimental::async_replicate_validate( + exec, 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate + f = hpx::experimental::async_replicate(exec, 1, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate validate + f = hpx::experimental::async_replicate_validate(exec, 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/async_replicate_vote_executor.cpp b/libs/resiliency/tests/unit/async_replicate_vote_executor.cpp new file mode 100644 index 000000000000..6c4f81ee49df --- /dev/null +++ b/libs/resiliency/tests/unit/async_replicate_vote_executor.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2019 Nikunj Gupta +// Copyright (c) 2018-2020 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +std::random_device rd; +std::mt19937 mt(rd()); +std::uniform_real_distribution dist(1.0, 10.0); + +int vote(std::vector vect) +{ + return vect.at(0); +} + +int universal_ans() +{ + if (dist(mt) > 5) + return 42; + return 84; +} + +bool validate(int ans) +{ + return ans == 42; +} + +int hpx_main() +{ + { + hpx::parallel::execution::parallel_executor exec; + + hpx::future f = hpx::experimental::async_replicate_vote( + exec, 10, &vote, &universal_ans); + + auto result = f.get(); + HPX_TEST(result == 42 || result == 84); + } + + { + hpx::parallel::execution::parallel_executor exec; + + hpx::future f = hpx::experimental::async_replicate_vote_validate( + exec, 10, &vote, &validate, &universal_ans); + + auto result = f.get(); + HPX_TEST(result == 42 || result == 84); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} From 4fb13abaff48af66a0fdd4fed8ab54c51b6354a8 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 23 Jul 2020 10:33:13 +0200 Subject: [PATCH 09/29] Add missing SPDX license tags to channel 1d stencil example --- examples/1d_stencil/1d_stencil_channel.cpp | 1 + examples/1d_stencil/communicator.hpp | 1 + examples/1d_stencil/stencil.hpp | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/1d_stencil/1d_stencil_channel.cpp b/examples/1d_stencil/1d_stencil_channel.cpp index 272b40535f89..0e51e4db454f 100644 --- a/examples/1d_stencil/1d_stencil_channel.cpp +++ b/examples/1d_stencil/1d_stencil_channel.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2020 Nikunj Gupta // +// SPDX-License-Identifier: BSL-1.0 // 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) diff --git a/examples/1d_stencil/communicator.hpp b/examples/1d_stencil/communicator.hpp index a06cd17262ad..70eff8d00a01 100644 --- a/examples/1d_stencil/communicator.hpp +++ b/examples/1d_stencil/communicator.hpp @@ -1,6 +1,7 @@ // Copyright (c) 2016 Thomas Heller // Copyright (c) 2020 Nikunj Gupta // +// SPDX-License-Identifier: BSL-1.0 // 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) diff --git a/examples/1d_stencil/stencil.hpp b/examples/1d_stencil/stencil.hpp index b155df1302b0..69de42097557 100644 --- a/examples/1d_stencil/stencil.hpp +++ b/examples/1d_stencil/stencil.hpp @@ -1,5 +1,6 @@ // Copyright (c) 2020 Nikunj Gupta // +// SPDX-License-Identifier: BSL-1.0 // 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) From 7b52fac50b3847806e6b720cb96f7917b7a29e95 Mon Sep 17 00:00:00 2001 From: John Biddiscombe Date: Mon, 6 Jul 2020 15:07:19 +0200 Subject: [PATCH 10/29] Enable use of future_overhead test when DISTRIBUTED_RUNTIME is OFF --- tests/performance/local/CMakeLists.txt | 4 ++-- tests/performance/local/future_overhead.cpp | 25 +++++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/performance/local/CMakeLists.txt b/tests/performance/local/CMakeLists.txt index 8d468297e961..8a4c88034884 100644 --- a/tests/performance/local/CMakeLists.txt +++ b/tests/performance/local/CMakeLists.txt @@ -13,6 +13,7 @@ set(benchmarks delay_baseline delay_baseline_threaded function_object_wrapper_overhead + future_overhead hpx_tls_overhead native_tls_overhead print_heterogeneous_payloads @@ -111,7 +112,6 @@ if(HPX_WITH_DISTRIBUTED_RUNTIME) ${benchmarks} agas_cache_timings foreach_scaling - future_overhead hpx_homogeneous_timed_task_spawn_executors hpx_heterogeneous_timed_task_spawn parent_vs_child_stealing @@ -149,7 +149,7 @@ set(hpx_heterogeneous_timed_task_spawn_FLAGS DEPENDENCIES iostreams_component set(parent_vs_child_stealing_FLAGS DEPENDENCIES iostreams_component hpx_timing) set(skynet_FLAGS DEPENDENCIES iostreams_component) set(wait_all_timings_FLAGS DEPENDENCIES iostreams_component hpx_timing) -set(future_overhead_FLAGS DEPENDENCIES iostreams_component hpx_timing) +set(future_overhead_FLAGS DEPENDENCIES hpx_timing) set(sizeof_FLAGS DEPENDENCIES iostreams_component) set(foreach_scaling_FLAGS DEPENDENCIES iostreams_component hpx_timing) set(spinlock_overhead1_FLAGS DEPENDENCIES iostreams_component hpx_timing) diff --git a/tests/performance/local/future_overhead.cpp b/tests/performance/local/future_overhead.cpp index eb2d5bf943a8..a3efcbe982e5 100644 --- a/tests/performance/local/future_overhead.cpp +++ b/tests/performance/local/future_overhead.cpp @@ -6,21 +6,24 @@ // 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 +#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME) #include +#include +#endif #include #include #include #include #include -#include #include #include #include #include #include #include -#include #include +#include #include #include @@ -44,9 +47,6 @@ using hpx::program_options::variables_map; using hpx::finalize; using hpx::init; -using hpx::find_here; -using hpx::naming::id_type; - using hpx::apply; using hpx::async; using hpx::future; @@ -54,9 +54,6 @@ using hpx::lcos::wait_each; using hpx::util::high_resolution_timer; -using hpx::cout; -using hpx::flush; - // global vars we stick here to make printouts easy for plotting static std::string queuing = "default"; static std::size_t numa_sensitive = 0; @@ -131,8 +128,6 @@ double null_function() noexcept return 0.0; } -HPX_PLAIN_ACTION(null_function, null_action) - struct scratcher { void operator()(future r) const @@ -141,10 +136,13 @@ struct scratcher } }; +#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME) +HPX_PLAIN_ACTION(null_function, null_action) + // Time async action execution using wait each on futures vector void measure_action_futures_wait_each(std::uint64_t count, bool csv) { - const id_type here = find_here(); + const hpx::naming::id_type here = hpx::find_here(); std::vector> futures; futures.reserve(count); @@ -162,7 +160,7 @@ void measure_action_futures_wait_each(std::uint64_t count, bool csv) // Time async action execution using wait each on futures vector void measure_action_futures_wait_all(std::uint64_t count, bool csv) { - const id_type here = find_here(); + const hpx::naming::id_type here = hpx::find_here(); std::vector> futures; futures.reserve(count); @@ -176,6 +174,7 @@ void measure_action_futures_wait_all(std::uint64_t count, bool csv) const double duration = walltime.elapsed(); print_stats("action", "WaitAll", "no-executor", count, duration, csv); } +#endif // Time async execution using wait each on futures vector template @@ -568,8 +567,10 @@ int hpx_main(variables_map& vm) if (test_all) { measure_function_futures_limiting_executor(count, csv, tpe); +#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME) measure_action_futures_wait_each(count, csv); measure_action_futures_wait_all(count, csv); +#endif measure_function_futures_wait_each(count, csv, par); measure_function_futures_wait_each(count, csv, tpe); measure_function_futures_wait_all(count, csv, par); From 8074316ab3a3c91fed430156ece77ad7b085fdf8 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 23 Jul 2020 16:30:07 +0200 Subject: [PATCH 11/29] Use medusa partition for clang builds on rostam --- .jenkins/lsu/slurm-configuration-clang-7.sh | 2 +- .jenkins/lsu/slurm-configuration-clang-8.sh | 2 +- .jenkins/lsu/slurm-configuration-clang-9.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.jenkins/lsu/slurm-configuration-clang-7.sh b/.jenkins/lsu/slurm-configuration-clang-7.sh index e9ef98e1ea06..0d78dd2220db 100644 --- a/.jenkins/lsu/slurm-configuration-clang-7.sh +++ b/.jenkins/lsu/slurm-configuration-clang-7.sh @@ -4,5 +4,5 @@ # 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) -configuration_slurm_partition="marvin" +configuration_slurm_partition="medusa" configuration_slurm_num_nodes="1" diff --git a/.jenkins/lsu/slurm-configuration-clang-8.sh b/.jenkins/lsu/slurm-configuration-clang-8.sh index e9ef98e1ea06..0d78dd2220db 100644 --- a/.jenkins/lsu/slurm-configuration-clang-8.sh +++ b/.jenkins/lsu/slurm-configuration-clang-8.sh @@ -4,5 +4,5 @@ # 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) -configuration_slurm_partition="marvin" +configuration_slurm_partition="medusa" configuration_slurm_num_nodes="1" diff --git a/.jenkins/lsu/slurm-configuration-clang-9.sh b/.jenkins/lsu/slurm-configuration-clang-9.sh index e9ef98e1ea06..0d78dd2220db 100644 --- a/.jenkins/lsu/slurm-configuration-clang-9.sh +++ b/.jenkins/lsu/slurm-configuration-clang-9.sh @@ -4,5 +4,5 @@ # 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) -configuration_slurm_partition="marvin" +configuration_slurm_partition="medusa" configuration_slurm_num_nodes="1" From 82caa7f2ee62485d54e0cc129522ee173ef02a0f Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 23 Jul 2020 10:29:29 -0500 Subject: [PATCH 12/29] Moving things into hpx::resiliency::experimental - removing explicit dataflow implementations, replaced with tag_deferred<> - adding more tests --- libs/resiliency/CMakeLists.txt | 4 +- libs/resiliency/docs/index.rst | 28 ++-- .../examples/1d_stencil_replay_exception.cpp | 11 +- .../examples/1d_stencil_replay_validate.cpp | 13 +- libs/resiliency/examples/async_replay.cpp | 24 +-- libs/resiliency/examples/async_replicate.cpp | 23 +-- .../examples/async_replicate_vote.cpp | 10 +- .../examples/dataflow_replicate.cpp | 11 +- libs/resiliency/examples/version.cpp | 4 +- .../include/hpx/resiliency/async_replay.hpp | 4 +- .../hpx/resiliency/async_replay_executor.hpp | 4 +- .../hpx/resiliency/async_replicate.hpp | 4 +- .../resiliency/async_replicate_executor.hpp | 4 +- .../hpx/resiliency/dataflow_replay.hpp | 54 ------- .../hpx/resiliency/dataflow_replicate.hpp | 89 ---------- .../include/hpx/resiliency/resiliency.hpp | 33 +--- .../hpx/resiliency/resiliency_cpos.hpp | 40 +++-- .../include/hpx/resiliency/version.hpp | 6 +- libs/resiliency/src/resiliency.cpp | 4 +- .../replay/1d_stencil_checksum.cpp | 4 +- .../performance/replay/1d_stencil_replay.cpp | 4 +- .../tests/performance/replay/async_replay.cpp | 6 +- .../replay/async_replay_validate.cpp | 9 +- .../performance/replay/dataflow_replay.cpp | 4 +- .../replay/dataflow_replay_validate.cpp | 4 +- .../replay/pure_async_for_replay.cpp | 4 +- .../replicate/1d_stencil_replicate.cpp | 4 +- .../1d_stencil_replicate_checksum.cpp | 4 +- .../performance/replicate/async_replicate.cpp | 4 +- .../replicate/async_replicate_validate.cpp | 7 +- .../replicate/async_replicate_vote.cpp | 7 +- .../async_replicate_vote_validate.cpp | 7 +- .../replicate/pure_async_for_replicate.cpp | 2 +- libs/resiliency/tests/unit/CMakeLists.txt | 14 +- .../tests/unit/async_replay_executor.cpp | 24 +-- .../tests/unit/async_replay_plain.cpp | 149 +++++++++++++++++ .../tests/unit/async_replicate_executor.cpp | 26 +-- .../tests/unit/async_replicate_plain.cpp | 147 +++++++++++++++++ .../unit/async_replicate_vote_executor.cpp | 14 +- .../tests/unit/async_replicate_vote_plain.cpp | 70 ++++++++ .../tests/unit/dataflow_replay_executor.cpp | 152 ++++++++++++++++++ .../tests/unit/dataflow_replay_plain.cpp | 149 +++++++++++++++++ .../unit/dataflow_replicate_executor.cpp | 152 ++++++++++++++++++ .../tests/unit/dataflow_replicate_plain.cpp | 147 +++++++++++++++++ 44 files changed, 1160 insertions(+), 324 deletions(-) delete mode 100644 libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp delete mode 100644 libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp create mode 100644 libs/resiliency/tests/unit/async_replay_plain.cpp create mode 100644 libs/resiliency/tests/unit/async_replicate_plain.cpp create mode 100644 libs/resiliency/tests/unit/async_replicate_vote_plain.cpp create mode 100644 libs/resiliency/tests/unit/dataflow_replay_executor.cpp create mode 100644 libs/resiliency/tests/unit/dataflow_replay_plain.cpp create mode 100644 libs/resiliency/tests/unit/dataflow_replicate_executor.cpp create mode 100644 libs/resiliency/tests/unit/dataflow_replicate_plain.cpp diff --git a/libs/resiliency/CMakeLists.txt b/libs/resiliency/CMakeLists.txt index e49900a01e97..0f5352112ba1 100644 --- a/libs/resiliency/CMakeLists.txt +++ b/libs/resiliency/CMakeLists.txt @@ -15,8 +15,6 @@ set(resiliency_headers hpx/resiliency/async_replicate.hpp hpx/resiliency/async_replicate_executor.hpp hpx/resiliency/config.hpp - hpx/resiliency/dataflow_replay.hpp - hpx/resiliency/dataflow_replicate.hpp hpx/resiliency/version.hpp hpx/resiliency/resiliency.hpp hpx/resiliency/resiliency_cpos.hpp @@ -28,7 +26,7 @@ set(resiliency_sources resiliency.cpp) include(HPX_AddModule) add_hpx_module( resiliency - GLOBAL_HEADER_GEN OFF + GLOBAL_HEADER_GEN ON SOURCES ${resiliency_sources} HEADERS ${resiliency_headers} DEPENDENCIES diff --git a/libs/resiliency/docs/index.rst b/libs/resiliency/docs/index.rst index 8e0e2672e5d2..10c47a11e2d9 100644 --- a/libs/resiliency/docs/index.rst +++ b/libs/resiliency/docs/index.rst @@ -31,27 +31,27 @@ by repeating a task multiple times. The following API functions are exposed: -- :cpp:func:`hpx::experimental::async_replay`: This version of task replay will +- :cpp:func:`hpx::resiliency::experimental::async_replay`: This version of task replay will catch user-defined exceptions and automatically reschedule the task N times - before throwing an :cpp:func:`hpx::experimental::abort_replay_exception` if no + before throwing an :cpp:func:`hpx::resiliency::experimental::abort_replay_exception` if no task is able to complete execution without an exception. -- :cpp:func:`hpx::experimental::async_replay_validate`: This version of replay +- :cpp:func:`hpx::resiliency::experimental::async_replay_validate`: This version of replay adds an argument to async replay which receives a user-provided validation function to test the result of the task against. If the task's output is validated, the result is returned. If the output fails the check or an exception is thrown, the task is replayed until no errors are encountered or the number of specified retries has been exceeded. -- :cpp:func:`hpx::experimental::async_replicate`: This is the most basic +- :cpp:func:`hpx::resiliency::experimental::async_replicate`: This is the most basic implementation of the task replication. The API returns the first result that runs without detecting any errors. -- :cpp:func:`hpx::experimental::async_replicate_validate`: This API additionally +- :cpp:func:`hpx::resiliency::experimental::async_replicate_validate`: This API additionally takes a validation function which evaluates the return values produced by the threads. The first task to compute a valid result is returned. -- :cpp:func:`hpx::experimental::async_replicate_vote`: This API adds a vote +- :cpp:func:`hpx::resiliency::experimental::async_replicate_vote`: This API adds a vote function to the basic replicate function. Many hardware or software failures are silent errors which do not interrupt program flow. In order to detect errors of this kind, it is necessary to run the task several times and compare @@ -60,20 +60,20 @@ The following API functions are exposed: consensus function to properly form a consensus. This voting function then returns the "correct"" answer. -- :cpp:func:`hpx::experimental::async_replicate_vote_validate`: This combines the +- :cpp:func:`hpx::resiliency::experimental::async_replicate_vote_validate`: This combines the features of the previously discussed replicate set. Replicate vote validate allows a user to provide a validation function to filter results. Additionally, as described in replicate vote, the user can provide a "voting function" which returns the consensus formed by the voting logic. -- :cpp:func:`hpx::experimental::dataflow_replay`: This version of dataflow replay +- :cpp:func:`hpx::resiliency::experimental::dataflow_replay`: This version of dataflow replay will catch user-defined exceptions and automatically reschedules the task N - times before throwing an :cpp:func:`hpx::experimental::abort_replay_exception` + times before throwing an :cpp:func:`hpx::resiliency::experimental::abort_replay_exception` if no task is able to complete execution without an exception. Any arguments for the executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::experimental::dataflow_replay_validate` : This version of replay +- :cpp:func:`hpx::resiliency::experimental::dataflow_replay_validate` : This version of replay adds an argument to dataflow replay which receives a user-provided validation function to test the result of the task against. If the task's output is validated, the result is returned. If the output fails the check or an @@ -82,19 +82,19 @@ The following API functions are exposed: executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::experimental::dataflow_replicate`: This is the most basic +- :cpp:func:`hpx::resiliency::experimental::dataflow_replicate`: This is the most basic implementation of the task replication. The API returns the first result that runs without detecting any errors. Any arguments for the executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::experimental::dataflow_replicate_validate`: This API +- :cpp:func:`hpx::resiliency::experimental::dataflow_replicate_validate`: This API additionally takes a validation function which evaluates the return values produced by the threads. The first task to compute a valid result is returned. Any arguments for the executed task that are futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::experimental::dataflow_replicate_vote`: This API adds a vote +- :cpp:func:`hpx::resiliency::experimental::dataflow_replicate_vote`: This API adds a vote function to the basic replicate function. Many hardware or software failures are silent errors which do not interrupt program flow. In order to detect errors of this kind, it is necessary to run the task several times and compare @@ -105,7 +105,7 @@ The following API functions are exposed: futures will cause the task invocation to be delayed until all of those futures have become ready. -- :cpp:func:`hpx::experimental::dataflow_replicate_vote_validate`: This combines +- :cpp:func:`hpx::resiliency::experimental::dataflow_replicate_vote_validate`: This combines the features of the previously discussed replicate set. Replicate vote validate allows a user to provide a validation function to filter results. Additionally, as described in replicate vote, the user can provide a "voting diff --git a/libs/resiliency/examples/1d_stencil_replay_exception.cpp b/libs/resiliency/examples/1d_stencil_replay_exception.cpp index 8abc5cd6c930..fd380fe27b24 100644 --- a/libs/resiliency/examples/1d_stencil_replay_exception.cpp +++ b/libs/resiliency/examples/1d_stencil_replay_exception.cpp @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include @@ -164,9 +164,12 @@ int hpx_main(hpx::program_options::variables_map& vm) std::vector next_input(subdomains); for (int j = 0; j < subdomains; ++j) { - next_input[j] = hpx::experimental::dataflow_replay(n, update, - input[(j - 1 + subdomains) % subdomains], input[j], - input[(j + 1) % subdomains]); + // explicitly unwrap future returned by dataflow + hpx::future f = + hpx::resiliency::experimental::dataflow_replay(n, update, + input[(j - 1 + subdomains) % subdomains], input[j], + input[(j + 1) % subdomains]); + next_input[j] = std::move(f); } std::swap(input, next_input); } diff --git a/libs/resiliency/examples/1d_stencil_replay_validate.cpp b/libs/resiliency/examples/1d_stencil_replay_validate.cpp index 8738c83f668c..f871255d708b 100644 --- a/libs/resiliency/examples/1d_stencil_replay_validate.cpp +++ b/libs/resiliency/examples/1d_stencil_replay_validate.cpp @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include @@ -181,10 +181,13 @@ int hpx_main(hpx::program_options::variables_map& vm) std::vector next_input(subdomains); for (int j = 0; j < subdomains; ++j) { - next_input[j] = hpx::experimental::dataflow_replay_validate(n, - &validate_result, update, - input[(j - 1 + subdomains) % subdomains], input[j], - input[(j + 1) % subdomains]); + // explicitly unwrap future returned by dataflow + hpx::future f = + hpx::resiliency::experimental::dataflow_replay_validate(n, + &validate_result, update, + input[(j - 1 + subdomains) % subdomains], input[j], + input[(j + 1) % subdomains]); + next_input[j] = std::move(f); } std::swap(input, next_input); } diff --git a/libs/resiliency/examples/async_replay.cpp b/libs/resiliency/examples/async_replay.cpp index f1368b6db2dc..c53459e50c70 100644 --- a/libs/resiliency/examples/async_replay.cpp +++ b/libs/resiliency/examples/async_replay.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #include @@ -36,7 +36,7 @@ bool validate(int result) int no_answer() { - throw hpx::experimental::abort_replay_exception(); + throw hpx::resiliency::experimental::abort_replay_exception(); } int deep_thought() @@ -60,18 +60,19 @@ int hpx_main(hpx::program_options::variables_map& vm) hpx::util::high_resolution_timer t; // successful replay - hpx::future f = hpx::experimental::async_replay(sr, &deep_thought); + hpx::future f = + hpx::resiliency::experimental::async_replay(sr, &deep_thought); std::cout << "universal answer: " << f.get() << "\n"; // successful replay validate - f = hpx::experimental::async_replay_validate( + f = hpx::resiliency::experimental::async_replay_validate( sr, &validate, &universal_answer); std::cout << "universal answer: " << f.get() << "\n"; // unsuccessful replay - f = hpx::experimental::async_replay(usr, &deep_thought); + f = hpx::resiliency::experimental::async_replay(usr, &deep_thought); try { f.get(); @@ -82,35 +83,36 @@ int hpx_main(hpx::program_options::variables_map& vm) } // unsuccessful replay validate - f = hpx::experimental::async_replay_validate( + f = hpx::resiliency::experimental::async_replay_validate( usr, &validate, &universal_answer); try { f.get(); } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { std::cout << "no universal answer!\n"; } // aborted replay - f = hpx::experimental::async_replay(a, &no_answer); + f = hpx::resiliency::experimental::async_replay(a, &no_answer); try { f.get(); } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { std::cout << "aborted universal answer calculation!\n"; } // aborted replay validate - f = hpx::experimental::async_replay_validate(a, &validate, &no_answer); + f = hpx::resiliency::experimental::async_replay_validate( + a, &validate, &no_answer); try { f.get(); } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { std::cout << "aborted universal answer calculation!\n"; } diff --git a/libs/resiliency/examples/async_replicate.cpp b/libs/resiliency/examples/async_replicate.cpp index 60a5f34251dd..cfebdc10ba34 100644 --- a/libs/resiliency/examples/async_replicate.cpp +++ b/libs/resiliency/examples/async_replicate.cpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include #include @@ -35,7 +35,7 @@ bool validate(int result) int no_answer() { - throw hpx::experimental::abort_replicate_exception(); + throw hpx::resiliency::experimental::abort_replicate_exception(); } int deep_thought() @@ -60,18 +60,18 @@ int hpx_main(hpx::program_options::variables_map& vm) // successful replicate hpx::future f = - hpx::experimental::async_replicate(sr, &deep_thought); + hpx::resiliency::experimental::async_replicate(sr, &deep_thought); std::cout << "universal answer: " << f.get() << "\n"; // successful replicate_validate - f = hpx::experimental::async_replicate_validate( + f = hpx::resiliency::experimental::async_replicate_validate( sr, &validate, &universal_answer); std::cout << "universal answer: " << f.get() << "\n"; // unsuccessful replicate - f = hpx::experimental::async_replicate(usr, &deep_thought); + f = hpx::resiliency::experimental::async_replicate(usr, &deep_thought); try { f.get(); @@ -82,35 +82,36 @@ int hpx_main(hpx::program_options::variables_map& vm) } // unsuccessful replicate_validate - f = hpx::experimental::async_replicate_validate( + f = hpx::resiliency::experimental::async_replicate_validate( usr, &validate, &universal_answer); try { f.get(); } - catch (hpx::experimental::abort_replicate_exception const&) + catch (hpx::resiliency::experimental::abort_replicate_exception const&) { std::cout << "no universal answer!\n"; } // aborted replicate - f = hpx::experimental::async_replicate(a, &no_answer); + f = hpx::resiliency::experimental::async_replicate(a, &no_answer); try { f.get(); } - catch (hpx::experimental::abort_replicate_exception const&) + catch (hpx::resiliency::experimental::abort_replicate_exception const&) { std::cout << "aborted universal answer calculation!\n"; } // aborted replicate validate - f = hpx::experimental::async_replicate_validate(a, &validate, &no_answer); + f = hpx::resiliency::experimental::async_replicate_validate( + a, &validate, &no_answer); try { f.get(); } - catch (hpx::experimental::abort_replicate_exception const&) + catch (hpx::resiliency::experimental::abort_replicate_exception const&) { std::cout << "aborted universal answer calculation!\n"; } diff --git a/libs/resiliency/examples/async_replicate_vote.cpp b/libs/resiliency/examples/async_replicate_vote.cpp index 3d00f837fc74..4df2489ae141 100644 --- a/libs/resiliency/examples/async_replicate_vote.cpp +++ b/libs/resiliency/examples/async_replicate_vote.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -47,7 +47,8 @@ int hpx_main(hpx::program_options::variables_map& vm) hpx::util::high_resolution_timer t; hpx::future f = - hpx::experimental::async_replicate_vote(n, &vote, &universal_ans); + hpx::resiliency::experimental::async_replicate_vote( + n, &vote, &universal_ans); std::cout << "Universal ans (maybe true): " << f.get() << std::endl; @@ -59,8 +60,9 @@ int hpx_main(hpx::program_options::variables_map& vm) // Initialize a high resolution timer hpx::util::high_resolution_timer t; - hpx::future f = hpx::experimental::async_replicate_vote_validate( - n, &vote, &validate, &universal_ans); + hpx::future f = + hpx::resiliency::experimental::async_replicate_vote_validate( + n, &vote, &validate, &universal_ans); std::cout << "Universal ans (true ans): " << f.get() << std::endl; diff --git a/libs/resiliency/examples/dataflow_replicate.cpp b/libs/resiliency/examples/dataflow_replicate.cpp index 4a95779f0251..827212e48c8f 100644 --- a/libs/resiliency/examples/dataflow_replicate.cpp +++ b/libs/resiliency/examples/dataflow_replicate.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -57,8 +57,8 @@ int hpx_main(hpx::program_options::variables_map& vm) { // Successful replicate - hpx::future f = - hpx::experimental::dataflow_replicate(sr, moody_add, 5, 5); + hpx::future f = hpx::resiliency::experimental::dataflow_replicate( + sr, moody_add, 5, 5); try { std::cout << f.get() << std::endl; @@ -73,7 +73,8 @@ int hpx_main(hpx::program_options::variables_map& vm) } // Unsuccessful replicate - f = hpx::experimental::dataflow_replay(usr, moody_add, 0, 5); + f = hpx::resiliency::experimental::dataflow_replay( + usr, moody_add, 0, 5); try { std::cout << f.get() << std::endl; @@ -88,7 +89,7 @@ int hpx_main(hpx::program_options::variables_map& vm) } // Aborted replicate - f = hpx::experimental::dataflow_replay(a, bad_add, 10, 5); + f = hpx::resiliency::experimental::dataflow_replay(a, bad_add, 10, 5); try { std::cout << f.get() << std::endl; diff --git a/libs/resiliency/examples/version.cpp b/libs/resiliency/examples/version.cpp index 0ebc6b201662..54c4c4c0e93c 100644 --- a/libs/resiliency/examples/version.cpp +++ b/libs/resiliency/examples/version.cpp @@ -7,13 +7,13 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include #include int main(int argc, char* argv[]) { std::cout << "HPX Resiliency module version: " - << hpx::resiliency::full_version_str() << "\n"; + << hpx::resiliency::experimental::full_version_str() << "\n"; return 0; } diff --git a/libs/resiliency/include/hpx/resiliency/async_replay.hpp b/libs/resiliency/include/hpx/resiliency/async_replay.hpp index 1937c02fad63..e28084d4ef0b 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replay.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replay.hpp @@ -26,7 +26,7 @@ #include #include -namespace hpx { namespace resiliency { +namespace hpx { namespace resiliency { namespace experimental { /////////////////////////////////////////////////////////////////////////// struct HPX_ALWAYS_EXPORT abort_replay_exception : std::exception @@ -201,4 +201,4 @@ namespace hpx { namespace resiliency { return helper->call(n); } -}} // namespace hpx::resiliency +}}} // namespace hpx::resiliency::experimental diff --git a/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp b/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp index 32863d9a486b..59a8824d5188 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp @@ -29,7 +29,7 @@ #include #include -namespace hpx { namespace resiliency { +namespace hpx { namespace resiliency { namespace experimental { /////////////////////////////////////////////////////////////////////////// namespace detail { @@ -192,4 +192,4 @@ namespace hpx { namespace resiliency { return helper->call(std::forward(exec), n); } -}} // namespace hpx::resiliency +}}} // namespace hpx::resiliency::experimental diff --git a/libs/resiliency/include/hpx/resiliency/async_replicate.hpp b/libs/resiliency/include/hpx/resiliency/async_replicate.hpp index fea43dec1c32..3a4d4615b341 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replicate.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replicate.hpp @@ -22,7 +22,7 @@ #include #include -namespace hpx { namespace resiliency { +namespace hpx { namespace resiliency { namespace experimental { /////////////////////////////////////////////////////////////////////////// struct HPX_ALWAYS_EXPORT abort_replicate_exception : std::exception @@ -199,4 +199,4 @@ namespace hpx { namespace resiliency { detail::replicate_voter{}, detail::replicate_validator{}, std::forward(f), std::forward(ts)...); } -}} // namespace hpx::resiliency +}}} // namespace hpx::resiliency::experimental diff --git a/libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp b/libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp index 7a5a4416d44f..bebbc298ec64 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replicate_executor.hpp @@ -26,7 +26,7 @@ #include #include -namespace hpx { namespace resiliency { +namespace hpx { namespace resiliency { namespace experimental { namespace detail { /////////////////////////////////////////////////////////////////////// @@ -192,4 +192,4 @@ namespace hpx { namespace resiliency { detail::replicate_validator{}, std::forward(f), std::forward(ts)...); } -}} // namespace hpx::resiliency +}}} // namespace hpx::resiliency::experimental diff --git a/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp b/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp deleted file mode 100644 index d81f225b780d..000000000000 --- a/libs/resiliency/include/hpx/resiliency/dataflow_replay.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, -// LLC (NTESS). -// Copyright (c) 2018-2020 Hartmut Kaiser -// Copyright (c) 2018-2019 Adrian Serio -// -// SPDX-License-Identifier: BSL-1.0 -// 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 -#include -#include - -#include -#include - -#include -#include - -namespace hpx { namespace resiliency { - - // Asynchronously launch given function \a f. Verify the result of - // those invocations using the given predicate \a pred. Repeat launching - // on error exactly \a n times. - // - // Delay the invocation of \a f if any of the arguments to \a f are - // futures. - template - hpx::future< - typename hpx::util::detail::invoke_deferred_result::type> - tag_invoke(dataflow_replay_validate_t, std::size_t n, Pred&& pred, F&& f, - Ts&&... ts) - { - return hpx::dataflow(hpx::resiliency::async_replay_validate, n, - std::forward(pred), std::forward(f), - std::forward(ts)...); - } - - // Asynchronously launch given function \a f. Repeat launching on error - // exactly \a n times. - // - // Delay the invocation of \a f if any of the arguments to \a f are - // futures. - template - hpx::future< - typename hpx::util::detail::invoke_deferred_result::type> - tag_invoke(dataflow_replay_t, std::size_t n, F&& f, Ts&&... ts) - { - return hpx::dataflow(hpx::resiliency::async_replay, n, - std::forward(f), std::forward(ts)...); - } -}} // namespace hpx::resiliency diff --git a/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp b/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp deleted file mode 100644 index a62b54a6ceb8..000000000000 --- a/libs/resiliency/include/hpx/resiliency/dataflow_replicate.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, -// LLC (NTESS). -// Copyright (c) 2018-2020 Hartmut Kaiser -// Copyright (c) 2018-2019 Adrian Serio -// Copyright (c) 2019 Nikunj Gupta -// -// SPDX-License-Identifier: BSL-1.0 -// 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 -#include -#include - -#include -#include - -#include -#include - -namespace hpx { namespace resiliency { - - // Launch given function \a f exactly \a n times. Run all the valid - // results against a user provided voting function. - // Return the valid output. - // - // Delay the invocation of \a f if any of the arguments to \a f are - // futures. - template - hpx::future< - typename hpx::util::detail::invoke_deferred_result::type> - tag_invoke(dataflow_replicate_vote_validate_t, std::size_t n, Vote&& vote, - Pred&& pred, F&& f, Ts&&... ts) - { - return hpx::dataflow(hpx::resiliency::async_replicate_vote_validate, n, - std::forward(vote), std::forward(pred), - std::forward(f), std::forward(ts)...); - } - - // Launch given function \a f exactly \a n times. Run all the valid - // results against a user provided voting function. - // Return the valid output. - // - // Delay the invocation of \a f if any of the arguments to \a f are - // futures. - template - hpx::future< - typename hpx::util::detail::invoke_deferred_result::type> - tag_invoke(dataflow_replicate_vote_t, std::size_t n, Vote&& vote, F&& f, - Ts&&... ts) - { - return hpx::dataflow(hpx::resiliency::async_replicate_vote, n, - std::forward(vote), std::forward(f), - std::forward(ts)...); - } - - // Launch given function \a f exactly \a n times. Verify the result of - // those invocations using the given predicate \a pred. Return the first - // valid result. - // - // Delay the invocation of \a f if any of the arguments to \a f are - // futures. - template - hpx::future< - typename hpx::util::detail::invoke_deferred_result::type> - tag_invoke(dataflow_replicate_validate_t, std::size_t n, Pred&& pred, F&& f, - Ts&&... ts) - { - return hpx::dataflow(hpx::resiliency::async_replicate_validate, n, - std::forward(pred), std::forward(f), - std::forward(ts)...); - } - - // Launch given function \a f exactly \a n times. Return the first - // valid result. - // - // Delay the invocation of \a f if any of the arguments to \a f are - // futures. - template - hpx::future< - typename hpx::util::detail::invoke_deferred_result::type> - tag_invoke(dataflow_replicate_t, std::size_t n, F&& f, Ts&&... ts) - { - return hpx::dataflow(hpx::resiliency::async_replicate, n, - std::forward(f), std::forward(ts)...); - } -}} // namespace hpx::resiliency diff --git a/libs/resiliency/include/hpx/resiliency/resiliency.hpp b/libs/resiliency/include/hpx/resiliency/resiliency.hpp index 2872407956d0..9fad9d5d8ecf 100644 --- a/libs/resiliency/include/hpx/resiliency/resiliency.hpp +++ b/libs/resiliency/include/hpx/resiliency/resiliency.hpp @@ -8,35 +8,4 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include - -namespace hpx { namespace experimental { - - // Replay APIs - using hpx::resiliency::abort_replay_exception; - - using hpx::resiliency::async_replay_validate; - using hpx::resiliency::async_replay; - - using hpx::resiliency::dataflow_replay_validate; - using hpx::resiliency::dataflow_replay; - - // Replicate APIs - using hpx::resiliency::abort_replicate_exception; - - using hpx::resiliency::async_replicate_vote_validate; - using hpx::resiliency::async_replicate_vote; - using hpx::resiliency::async_replicate_validate; - using hpx::resiliency::async_replicate; - - using hpx::resiliency::dataflow_replicate_vote_validate; - using hpx::resiliency::dataflow_replicate_vote; - using hpx::resiliency::dataflow_replicate_validate; - using hpx::resiliency::dataflow_replicate; -}} // namespace hpx::experimental +#include diff --git a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp index bf8fdf884da8..a8c84fb86be7 100644 --- a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp +++ b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp @@ -7,9 +7,26 @@ #pragma once #include -#include +#include +#include -namespace hpx { namespace resiliency { +#include + +namespace hpx { namespace resiliency { namespace experimental { + + /////////////////////////////////////////////////////////////////////////// + // helper base class implementing the deferred tag_invoke logic for CPOs + template + struct tag_deferred : hpx::functional::tag + { + static constexpr BaseTag base_tag{}; + + template + friend HPX_FORCEINLINE decltype(auto) tag_invoke(Tag, Args&&... args) + { + return hpx::dataflow(base_tag, std::forward(args)...); + } + }; /////////////////////////////////////////////////////////////////////////// // Replay customization points @@ -40,7 +57,7 @@ namespace hpx { namespace resiliency { /// Delay the invocation of \a f if any of the arguments to \a f are /// futures. HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replay_validate_t final - : hpx::functional::tag + : tag_deferred { } dataflow_replay_validate; @@ -51,7 +68,7 @@ namespace hpx { namespace resiliency { /// Delay the invocation of \a f if any of the arguments to \a f are /// futures. HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replay_t final - : hpx::functional::tag + : tag_deferred { } dataflow_replay; @@ -77,8 +94,7 @@ namespace hpx { namespace resiliency { HPX_INLINE_CONSTEXPR_VARIABLE struct async_replicate_vote_t final : hpx::functional::tag { - } // namespace resiliency - async_replicate_vote; + } async_replicate_vote; /////////////////////////////////////////////////////////////////////////// /// Customization point for asynchronously launching the given function \a f @@ -108,7 +124,9 @@ namespace hpx { namespace resiliency { /// Delay the invocation of \a f if any of the arguments to \a f are /// futures. HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_vote_validate_t - final : hpx::functional::tag + final + : tag_deferred { } dataflow_replicate_vote_validate; @@ -120,7 +138,7 @@ namespace hpx { namespace resiliency { /// Delay the invocation of \a f if any of the arguments to \a f are /// futures. HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_vote_t final - : hpx::functional::tag + : tag_deferred { } dataflow_replicate_vote; @@ -131,7 +149,7 @@ namespace hpx { namespace resiliency { /// Delay the invocation of \a f if any of the arguments to \a f are /// futures. HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_validate_t final - : hpx::functional::tag + : tag_deferred { } dataflow_replicate_validate; @@ -141,7 +159,7 @@ namespace hpx { namespace resiliency { /// Delay the invocation of \a f if any of the arguments to \a f are /// futures. HPX_INLINE_CONSTEXPR_VARIABLE struct dataflow_replicate_t final - : hpx::functional::tag + : tag_deferred { } dataflow_replicate; -}} // namespace hpx::resiliency +}}} // namespace hpx::resiliency::experimental diff --git a/libs/resiliency/include/hpx/resiliency/version.hpp b/libs/resiliency/include/hpx/resiliency/version.hpp index 70cb618b149e..ddc21281ac39 100644 --- a/libs/resiliency/include/hpx/resiliency/version.hpp +++ b/libs/resiliency/include/hpx/resiliency/version.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, // LLC (NTESS). -// Copyright (c) 2018-2019 Hartmut Kaiser +// Copyright (c) 2018-2020 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -30,7 +30,7 @@ #define HPX_RESILIENCY_VERSION_DATE 20190823 -namespace hpx { namespace resiliency { +namespace hpx { namespace resiliency { namespace experimental { // return version of this library HPX_EXPORT unsigned int major_version(); @@ -39,4 +39,4 @@ namespace hpx { namespace resiliency { HPX_EXPORT unsigned long full_version(); HPX_EXPORT std::string full_version_str(); -}} // namespace hpx::resiliency +}}} // namespace hpx::resiliency::experimental diff --git a/libs/resiliency/src/resiliency.cpp b/libs/resiliency/src/resiliency.cpp index 08a66a7a3b80..d449106a70ca 100644 --- a/libs/resiliency/src/resiliency.cpp +++ b/libs/resiliency/src/resiliency.cpp @@ -11,7 +11,7 @@ #include -namespace hpx { namespace resiliency { +namespace hpx { namespace resiliency { namespace experimental { unsigned int major_version() { @@ -39,4 +39,4 @@ namespace hpx { namespace resiliency { std::to_string(HPX_RESILIENCY_VERSION_MINOR) + "." + std::to_string(HPX_RESILIENCY_VERSION_SUBMINOR); } -}} // namespace hpx::resiliency +}}} // namespace hpx::resiliency::experimental diff --git a/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp b/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp index 85324dc6d020..d5af896e6f23 100644 --- a/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp +++ b/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include @@ -237,7 +237,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::experimental::dataflow_replay_validate; + using hpx::resiliency::experimental::dataflow_replay_validate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp b/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp index 25f157feaf16..2632750cf5d9 100644 --- a/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp +++ b/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include @@ -194,7 +194,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::experimental::dataflow_replay; + using hpx::resiliency::experimental::dataflow_replay; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replay/async_replay.cpp b/libs/resiliency/tests/performance/replay/async_replay.cpp index cdd504874d7d..fa3b5da95cde 100644 --- a/libs/resiliency/tests/performance/replay/async_replay.cpp +++ b/libs/resiliency/tests/performance/replay/async_replay.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -90,7 +90,7 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::experimental::async_replay( + hpx::future f = hpx::resiliency::experimental::async_replay( n, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } @@ -108,7 +108,7 @@ int hpx_main(hpx::program_options::variables_map& vm) "past the injected error levels" << std::endl; } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { std::cout << "Number of repeat launches were not enough to get " "past the injected error levels" diff --git a/libs/resiliency/tests/performance/replay/async_replay_validate.cpp b/libs/resiliency/tests/performance/replay/async_replay_validate.cpp index d18b7b06aff4..daf33726c795 100644 --- a/libs/resiliency/tests/performance/replay/async_replay_validate.cpp +++ b/libs/resiliency/tests/performance/replay/async_replay_validate.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -93,8 +93,9 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::experimental::async_replay_validate( - n, &validate, &universal_ans, delay * 1000, error); + hpx::future f = + hpx::resiliency::experimental::async_replay_validate( + n, &validate, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } @@ -111,7 +112,7 @@ int hpx_main(hpx::program_options::variables_map& vm) "past the injected error levels" << std::endl; } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { std::cout << "Number of repeat launches were not enough to get " "past the injected error levels" diff --git a/libs/resiliency/tests/performance/replay/dataflow_replay.cpp b/libs/resiliency/tests/performance/replay/dataflow_replay.cpp index 65aef1f8dc0c..cfadcc233a47 100644 --- a/libs/resiliency/tests/performance/replay/dataflow_replay.cpp +++ b/libs/resiliency/tests/performance/replay/dataflow_replay.cpp @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include @@ -239,7 +239,7 @@ struct stepper std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::experimental::dataflow_replay; + using hpx::resiliency::experimental::dataflow_replay; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp b/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp index 9293e84c8fbe..78dcf6eeb637 100644 --- a/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp +++ b/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include @@ -231,7 +231,7 @@ struct stepper std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::experimental::dataflow_replay_validate; + using hpx::resiliency::experimental::dataflow_replay_validate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp b/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp index dd51e1e7eb59..48959f3150ed 100644 --- a/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp +++ b/libs/resiliency/tests/performance/replay/pure_async_for_replay.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -105,7 +105,7 @@ int hpx_main(hpx::program_options::variables_map& vm) { std::cout << "Exceptions thrown" << std::endl; } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { std::cout << "Exceptions thrown" << std::endl; } diff --git a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp index c1f45ef3fec3..204f4c17f478 100644 --- a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp +++ b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate.cpp @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include @@ -195,7 +195,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::experimental::dataflow_replicate; + using hpx::resiliency::experimental::dataflow_replicate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp index 312f0a94fa4f..bc88b8d4b89f 100644 --- a/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp +++ b/libs/resiliency/tests/performance/replicate/1d_stencil_replicate_checksum.cpp @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include @@ -236,7 +236,7 @@ struct stepper std::uint64_t nd, std::uint64_t n_value, double error, hpx::lcos::local::sliding_semaphore& sem) { - using hpx::experimental::dataflow_replicate_validate; + using hpx::resiliency::experimental::dataflow_replicate_validate; using hpx::util::unwrapping; // U[t][i] is the state of position i at time t. diff --git a/libs/resiliency/tests/performance/replicate/async_replicate.cpp b/libs/resiliency/tests/performance/replicate/async_replicate.cpp index 3c3b6c3c0298..b9f1c64c3b2e 100644 --- a/libs/resiliency/tests/performance/replicate/async_replicate.cpp +++ b/libs/resiliency/tests/performance/replicate/async_replicate.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -90,7 +90,7 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::resiliency::async_replicate( + hpx::future f = hpx::resiliency::experimental::async_replicate( n, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp b/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp index 4c646c7cf9c0..240981ed79d4 100644 --- a/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp +++ b/libs/resiliency/tests/performance/replicate/async_replicate_validate.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -98,8 +98,9 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::experimental::async_replicate_validate( - n, &validate, &universal_ans, delay * 1000, error); + hpx::future f = + hpx::resiliency::experimental::async_replicate_validate( + n, &validate, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp b/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp index 667f99d894e7..bca7e1ea5db2 100644 --- a/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp +++ b/libs/resiliency/tests/performance/replicate/async_replicate_vote.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -98,8 +98,9 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::experimental::async_replicate_validate( - n, &validate, &universal_ans, delay * 1000, error); + hpx::future f = + hpx::resiliency::experimental::async_replicate_validate( + n, &validate, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp b/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp index 6a634f85f6e3..5c6a81410f77 100644 --- a/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp +++ b/libs/resiliency/tests/performance/replicate/async_replicate_vote_validate.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include @@ -95,8 +95,9 @@ int hpx_main(hpx::program_options::variables_map& vm) for (int i = 0; i < num_iterations; ++i) { - hpx::future f = hpx::experimental::async_replicate_vote( - n, &vote, &universal_ans, delay * 1000, error); + hpx::future f = + hpx::resiliency::experimental::async_replicate_vote( + n, &vote, &universal_ans, delay * 1000, error); vect.push_back(std::move(f)); } diff --git a/libs/resiliency/tests/performance/replicate/pure_async_for_replicate.cpp b/libs/resiliency/tests/performance/replicate/pure_async_for_replicate.cpp index 42bde2c5def1..030ea88ebd91 100644 --- a/libs/resiliency/tests/performance/replicate/pure_async_for_replicate.cpp +++ b/libs/resiliency/tests/performance/replicate/pure_async_for_replicate.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include diff --git a/libs/resiliency/tests/unit/CMakeLists.txt b/libs/resiliency/tests/unit/CMakeLists.txt index de481dc9e1ec..238b7284a0aa 100644 --- a/libs/resiliency/tests/unit/CMakeLists.txt +++ b/libs/resiliency/tests/unit/CMakeLists.txt @@ -4,8 +4,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) -set(tests async_replicate_executor async_replicate_vote_executor - async_replay_executor) +set(tests + async_replay_executor + async_replay_plain + async_replicate_executor + async_replicate_plain + async_replicate_vote_executor + async_replicate_vote_plain + dataflow_replay_executor + dataflow_replay_plain + dataflow_replicate_executor + dataflow_replicate_plain +) foreach(test ${tests}) set(sources ${test}.cpp) diff --git a/libs/resiliency/tests/unit/async_replay_executor.cpp b/libs/resiliency/tests/unit/async_replay_executor.cpp index 05098fb08ff6..54f0b1b774b6 100644 --- a/libs/resiliency/tests/unit/async_replay_executor.cpp +++ b/libs/resiliency/tests/unit/async_replay_executor.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #include @@ -35,7 +35,7 @@ bool validate(int result) int no_answer() { - throw hpx::experimental::abort_replay_exception(); + throw hpx::resiliency::experimental::abort_replay_exception(); } int deep_thought() @@ -54,17 +54,17 @@ int hpx_main() hpx::parallel::execution::parallel_executor exec; // successful replay - hpx::future f = - hpx::experimental::async_replay(exec, 10, &deep_thought); + hpx::future f = hpx::resiliency::experimental::async_replay( + exec, 10, &deep_thought); HPX_TEST(f.get() == 42); // successful replay validate - f = hpx::experimental::async_replay_validate( + f = hpx::resiliency::experimental::async_replay_validate( exec, 10, &validate, &universal_answer); HPX_TEST(f.get() == 42); // unsuccessful replay - f = hpx::experimental::async_replay(exec, 6, &deep_thought); + f = hpx::resiliency::experimental::async_replay(exec, 6, &deep_thought); bool exception_caught = false; try @@ -83,7 +83,7 @@ int hpx_main() HPX_TEST(exception_caught); // unsuccessful replay validate - f = hpx::experimental::async_replay_validate( + f = hpx::resiliency::experimental::async_replay_validate( exec, 6, &validate, &universal_answer); exception_caught = false; @@ -92,7 +92,7 @@ int hpx_main() f.get(); HPX_TEST(false); } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { exception_caught = true; } @@ -103,7 +103,7 @@ int hpx_main() HPX_TEST(exception_caught); // aborted replay - f = hpx::experimental::async_replay(exec, 1, &no_answer); + f = hpx::resiliency::experimental::async_replay(exec, 1, &no_answer); exception_caught = false; try @@ -111,7 +111,7 @@ int hpx_main() f.get(); HPX_TEST(false); } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { exception_caught = true; } @@ -122,7 +122,7 @@ int hpx_main() HPX_TEST(exception_caught); // aborted replay validate - f = hpx::experimental::async_replay_validate( + f = hpx::resiliency::experimental::async_replay_validate( exec, 1, &validate, &no_answer); exception_caught = false; @@ -130,7 +130,7 @@ int hpx_main() { f.get(); } - catch (hpx::experimental::abort_replay_exception const&) + catch (hpx::resiliency::experimental::abort_replay_exception const&) { exception_caught = true; } diff --git a/libs/resiliency/tests/unit/async_replay_plain.cpp b/libs/resiliency/tests/unit/async_replay_plain.cpp new file mode 100644 index 000000000000..db5f8657b4e9 --- /dev/null +++ b/libs/resiliency/tests/unit/async_replay_plain.cpp @@ -0,0 +1,149 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2018-2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::resiliency::experimental::abort_replay_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + // successful replay + hpx::future f = + hpx::resiliency::experimental::async_replay(10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replay validate + f = hpx::resiliency::experimental::async_replay_validate( + 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replay + f = hpx::resiliency::experimental::async_replay(6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replay validate + f = hpx::resiliency::experimental::async_replay_validate( + 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay + f = hpx::resiliency::experimental::async_replay(1, &no_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay validate + f = hpx::resiliency::experimental::async_replay_validate( + 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/async_replicate_executor.cpp b/libs/resiliency/tests/unit/async_replicate_executor.cpp index b6d24a5915ee..0f25ae07a73c 100644 --- a/libs/resiliency/tests/unit/async_replicate_executor.cpp +++ b/libs/resiliency/tests/unit/async_replicate_executor.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #include @@ -36,7 +36,7 @@ bool validate(int result) int no_answer() { - throw hpx::experimental::abort_replicate_exception(); + throw hpx::resiliency::experimental::abort_replicate_exception(); } int deep_thought() @@ -55,17 +55,18 @@ int hpx_main() hpx::parallel::execution::parallel_executor exec; // successful replicate - hpx::future f = - hpx::experimental::async_replicate(exec, 10, &deep_thought); + hpx::future f = hpx::resiliency::experimental::async_replicate( + exec, 10, &deep_thought); HPX_TEST(f.get() == 42); // successful replicate_validate - f = hpx::experimental::async_replicate_validate( + f = hpx::resiliency::experimental::async_replicate_validate( exec, 10, &validate, &universal_answer); HPX_TEST(f.get() == 42); // unsuccessful replicate - f = hpx::experimental::async_replicate(exec, 6, &deep_thought); + f = hpx::resiliency::experimental::async_replicate( + exec, 6, &deep_thought); bool exception_caught = false; try @@ -83,7 +84,7 @@ int hpx_main() HPX_TEST(exception_caught); // unsuccessful replicate_validate - f = hpx::experimental::async_replicate_validate( + f = hpx::resiliency::experimental::async_replicate_validate( exec, 6, &validate, &universal_answer); exception_caught = false; @@ -91,7 +92,7 @@ int hpx_main() { f.get(); } - catch (hpx::experimental::abort_replicate_exception const&) + catch (hpx::resiliency::experimental::abort_replicate_exception const&) { exception_caught = true; } @@ -102,14 +103,14 @@ int hpx_main() HPX_TEST(exception_caught); // aborted replicate - f = hpx::experimental::async_replicate(exec, 1, &no_answer); + f = hpx::resiliency::experimental::async_replicate(exec, 1, &no_answer); exception_caught = false; try { f.get(); } - catch (hpx::experimental::abort_replicate_exception const&) + catch (hpx::resiliency::experimental::abort_replicate_exception const&) { exception_caught = true; } @@ -120,14 +121,15 @@ int hpx_main() HPX_TEST(exception_caught); // aborted replicate validate - f = hpx::experimental::async_replicate_validate(exec, 1, &validate, &no_answer); + f = hpx::resiliency::experimental::async_replicate_validate( + exec, 1, &validate, &no_answer); exception_caught = false; try { f.get(); } - catch (hpx::experimental::abort_replicate_exception const&) + catch (hpx::resiliency::experimental::abort_replicate_exception const&) { exception_caught = true; } diff --git a/libs/resiliency/tests/unit/async_replicate_plain.cpp b/libs/resiliency/tests/unit/async_replicate_plain.cpp new file mode 100644 index 000000000000..85b1e09be3b6 --- /dev/null +++ b/libs/resiliency/tests/unit/async_replicate_plain.cpp @@ -0,0 +1,147 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); + +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::resiliency::experimental::abort_replicate_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + // successful replicate + hpx::future f = + hpx::resiliency::experimental::async_replicate(10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replicate_validate + f = hpx::resiliency::experimental::async_replicate_validate( + 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replicate + f = hpx::resiliency::experimental::async_replicate(6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replicate_validate + f = hpx::resiliency::experimental::async_replicate_validate( + 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate + f = hpx::resiliency::experimental::async_replicate(1, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate validate + f = hpx::resiliency::experimental::async_replicate_validate( + 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/async_replicate_vote_executor.cpp b/libs/resiliency/tests/unit/async_replicate_vote_executor.cpp index 6c4f81ee49df..a9ecf662fee0 100644 --- a/libs/resiliency/tests/unit/async_replicate_vote_executor.cpp +++ b/libs/resiliency/tests/unit/async_replicate_vote_executor.cpp @@ -10,13 +10,11 @@ #include #include #include +#include #include -#include #include -#include #include -#include #include std::random_device rd; @@ -45,8 +43,9 @@ int hpx_main() { hpx::parallel::execution::parallel_executor exec; - hpx::future f = hpx::experimental::async_replicate_vote( - exec, 10, &vote, &universal_ans); + hpx::future f = + hpx::resiliency::experimental::async_replicate_vote( + exec, 10, &vote, &universal_ans); auto result = f.get(); HPX_TEST(result == 42 || result == 84); @@ -55,8 +54,9 @@ int hpx_main() { hpx::parallel::execution::parallel_executor exec; - hpx::future f = hpx::experimental::async_replicate_vote_validate( - exec, 10, &vote, &validate, &universal_ans); + hpx::future f = + hpx::resiliency::experimental::async_replicate_vote_validate( + exec, 10, &vote, &validate, &universal_ans); auto result = f.get(); HPX_TEST(result == 42 || result == 84); diff --git a/libs/resiliency/tests/unit/async_replicate_vote_plain.cpp b/libs/resiliency/tests/unit/async_replicate_vote_plain.cpp new file mode 100644 index 000000000000..c48759ba786f --- /dev/null +++ b/libs/resiliency/tests/unit/async_replicate_vote_plain.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2019 Nikunj Gupta +// Copyright (c) 2018-2020 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include + +#include +#include +#include + +std::random_device rd; +std::mt19937 mt(rd()); +std::uniform_real_distribution dist(1.0, 10.0); + +int vote(std::vector vect) +{ + return vect.at(0); +} + +int universal_ans() +{ + if (dist(mt) > 5) + return 42; + return 84; +} + +bool validate(int ans) +{ + return ans == 42; +} + +int hpx_main() +{ + { + hpx::future f = + hpx::resiliency::experimental::async_replicate_vote( + 10, &vote, &universal_ans); + + auto result = f.get(); + HPX_TEST(result == 42 || result == 84); + } + + { + hpx::parallel::execution::parallel_executor exec; + + hpx::future f = + hpx::resiliency::experimental::async_replicate_vote_validate( + 10, &vote, &validate, &universal_ans); + + auto result = f.get(); + HPX_TEST(result == 42 || result == 84); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/dataflow_replay_executor.cpp b/libs/resiliency/tests/unit/dataflow_replay_executor.cpp new file mode 100644 index 000000000000..f16d7da813e7 --- /dev/null +++ b/libs/resiliency/tests/unit/dataflow_replay_executor.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2018-2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::resiliency::experimental::abort_replay_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + hpx::parallel::execution::parallel_executor exec; + + // successful replay + hpx::future f = hpx::resiliency::experimental::dataflow_replay( + exec, 10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replay validate + f = hpx::resiliency::experimental::dataflow_replay_validate( + exec, 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replay + f = hpx::resiliency::experimental::dataflow_replay(exec, 6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replay validate + f = hpx::resiliency::experimental::dataflow_replay_validate( + exec, 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay + f = hpx::resiliency::experimental::dataflow_replay(exec, 1, &no_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay validate + f = hpx::resiliency::experimental::dataflow_replay_validate( + exec, 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/dataflow_replay_plain.cpp b/libs/resiliency/tests/unit/dataflow_replay_plain.cpp new file mode 100644 index 000000000000..ea33eb5636c9 --- /dev/null +++ b/libs/resiliency/tests/unit/dataflow_replay_plain.cpp @@ -0,0 +1,149 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018-2020 Hartmut Kaiser +// Copyright (c) 2018-2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::resiliency::experimental::abort_replay_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + // successful replay + hpx::future f = + hpx::resiliency::experimental::dataflow_replay(10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replay validate + f = hpx::resiliency::experimental::dataflow_replay_validate( + 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replay + f = hpx::resiliency::experimental::dataflow_replay(6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replay validate + f = hpx::resiliency::experimental::dataflow_replay_validate( + 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay + f = hpx::resiliency::experimental::dataflow_replay(1, &no_answer); + + exception_caught = false; + try + { + f.get(); + HPX_TEST(false); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replay validate + f = hpx::resiliency::experimental::dataflow_replay_validate( + 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replay_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/dataflow_replicate_executor.cpp b/libs/resiliency/tests/unit/dataflow_replicate_executor.cpp new file mode 100644 index 000000000000..7da3e499f168 --- /dev/null +++ b/libs/resiliency/tests/unit/dataflow_replicate_executor.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018 Hartmut Kaiser +// Copyright (c) 2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); + +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::resiliency::experimental::abort_replicate_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + hpx::parallel::execution::parallel_executor exec; + + // successful replicate + hpx::future f = hpx::resiliency::experimental::dataflow_replicate( + exec, 10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replicate_validate + f = hpx::resiliency::experimental::dataflow_replicate_validate( + exec, 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replicate + f = hpx::resiliency::experimental::dataflow_replicate( + exec, 6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replicate_validate + f = hpx::resiliency::experimental::dataflow_replicate_validate( + exec, 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate + f = hpx::resiliency::experimental::dataflow_replicate( + exec, 1, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate validate + f = hpx::resiliency::experimental::dataflow_replicate_validate( + exec, 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} diff --git a/libs/resiliency/tests/unit/dataflow_replicate_plain.cpp b/libs/resiliency/tests/unit/dataflow_replicate_plain.cpp new file mode 100644 index 000000000000..71b5fde5237a --- /dev/null +++ b/libs/resiliency/tests/unit/dataflow_replicate_plain.cpp @@ -0,0 +1,147 @@ +// Copyright (c) 2019 National Technology & Engineering Solutions of Sandia, +// LLC (NTESS). +// Copyright (c) 2018 Hartmut Kaiser +// Copyright (c) 2019 Adrian Serio +// Copyright (c) 2019 Nikunj Gupta +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include + +#include +#include + +std::atomic answer(35); + +struct vogon_exception : std::exception +{ +}; + +int universal_answer() +{ + return ++answer; +} + +bool validate(int result) +{ + return result == 42; +} + +int no_answer() +{ + throw hpx::resiliency::experimental::abort_replicate_exception(); +} + +int deep_thought() +{ + static int ans = 35; + ++ans; + if (ans == 42) + return ans; + else + throw vogon_exception(); +} + +int hpx_main() +{ + { + // successful replicate + hpx::future f = hpx::resiliency::experimental::dataflow_replicate( + 10, &deep_thought); + HPX_TEST(f.get() == 42); + + // successful replicate_validate + f = hpx::resiliency::experimental::dataflow_replicate_validate( + 10, &validate, &universal_answer); + HPX_TEST(f.get() == 42); + + // unsuccessful replicate + f = hpx::resiliency::experimental::dataflow_replicate(6, &deep_thought); + + bool exception_caught = false; + try + { + f.get(); + } + catch (vogon_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // unsuccessful replicate_validate + f = hpx::resiliency::experimental::dataflow_replicate_validate( + 6, &validate, &universal_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate + f = hpx::resiliency::experimental::dataflow_replicate(1, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + + // aborted replicate validate + f = hpx::resiliency::experimental::dataflow_replicate_validate( + 1, &validate, &no_answer); + + exception_caught = false; + try + { + f.get(); + } + catch (hpx::resiliency::experimental::abort_replicate_exception const&) + { + exception_caught = true; + } + catch (...) + { + HPX_TEST(false); + } + HPX_TEST(exception_caught); + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + // Initialize and run HPX + HPX_TEST(hpx::init(argc, argv) == 0); + return hpx::util::report_errors(); +} From 8871453ae5d0a6104f25b4bf715d98edf824539b Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 23 Jul 2020 10:50:22 -0500 Subject: [PATCH 13/29] Restore change overwritten before --- .../include/hpx/iterator_support/counting_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp b/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp index 0b571346a059..047d99ba1d9a 100644 --- a/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp +++ b/libs/iterator_support/include/hpx/iterator_support/counting_iterator.hpp @@ -84,7 +84,7 @@ namespace hpx { namespace util { } // namespace detail //////////////////////////////////////////////////////////////////////////// - // specialization for Iterators (non-intengral types) + // specialization for Iterators (non-integral types) template class counting_iterator From 82a488342d583166f39739f31fb66c53dd6df659 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 23 Jul 2020 10:54:49 -0500 Subject: [PATCH 14/29] Fixing clang-tidy problems: 0 --> nullptr --- .../include/hpx/synchronization/lock_types.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/synchronization/include/hpx/synchronization/lock_types.hpp b/libs/synchronization/include/hpx/synchronization/lock_types.hpp index 29da6d02cd9c..c636ce11a42e 100644 --- a/libs/synchronization/include/hpx/synchronization/lock_types.hpp +++ b/libs/synchronization/include/hpx/synchronization/lock_types.hpp @@ -38,7 +38,7 @@ namespace hpx { namespace lcos { namespace local { upgrade_lock& operator=(upgrade_lock const&) = delete; upgrade_lock() noexcept - : m(0) + : m(nullptr) , is_locked(false) { } @@ -71,7 +71,7 @@ namespace hpx { namespace lcos { namespace local { , is_locked(other.is_locked) { other.is_locked = false; - other.m = 0; + other.m = nullptr; } explicit upgrade_lock(std::unique_lock&& other) @@ -105,7 +105,7 @@ namespace hpx { namespace lcos { namespace local { Mutex* release() noexcept { Mutex* const res = m; - m = 0; + m = nullptr; is_locked = false; return res; } @@ -119,7 +119,7 @@ namespace hpx { namespace lcos { namespace local { void lock() { - if (m == 0) + if (m == nullptr) { HPX_THROW_EXCEPTION( lock_error, "mutex::unlock", "upgrade_lock has no mutex"); @@ -134,7 +134,7 @@ namespace hpx { namespace lcos { namespace local { } bool try_lock() { - if (m == 0) + if (m == nullptr) { HPX_THROW_EXCEPTION( lock_error, "mutex::unlock", "upgrade_lock has no mutex"); @@ -149,7 +149,7 @@ namespace hpx { namespace lcos { namespace local { } void unlock() { - if (m == 0) + if (m == nullptr) { HPX_THROW_EXCEPTION( lock_error, "mutex::unlock", "upgrade_lock has no mutex"); @@ -209,7 +209,7 @@ namespace hpx { namespace lcos { namespace local { } ~upgrade_to_unique_lock() { - if (source) + if (source != nullptr) { *source = upgrade_lock(std::move(exclusive)); } @@ -219,7 +219,7 @@ namespace hpx { namespace lcos { namespace local { : source(other.source) , exclusive(std::move(other.exclusive)) { - other.source = 0; + other.source = nullptr; } upgrade_to_unique_lock& operator=( From 95ee6867ffe2aa4c3ec01b99e689303e24a7a089 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 23 Jul 2020 15:02:56 -0500 Subject: [PATCH 15/29] Adding test that derives component from two other components --- tests/unit/component/CMakeLists.txt | 3 + .../inheritance_3_classes_2_concrete.cpp | 320 ++++++++++++++++++ 2 files changed, 323 insertions(+) create mode 100644 tests/unit/component/inheritance_3_classes_2_concrete.cpp diff --git a/tests/unit/component/CMakeLists.txt b/tests/unit/component/CMakeLists.txt index ed7fcf8bc75e..a15df3d0a694 100644 --- a/tests/unit/component/CMakeLists.txt +++ b/tests/unit/component/CMakeLists.txt @@ -20,6 +20,7 @@ if(HPX_WITH_DISTRIBUTED_RUNTIME) inheritance_3_classes_1_abstract inheritance_3_classes_2_abstract inheritance_2_classes_concrete_simple + inheritance_3_classes_2_concrete inheritance_3_classes_concrete local_new migrate_component @@ -59,6 +60,8 @@ if(HPX_WITH_DISTRIBUTED_RUNTIME) set(inheritance_3_classes_concrete_FLAGS DEPENDENCIES iostreams_component) + set(inheritance_3_classes_2_concrete_FLAGS DEPENDENCIES iostreams_component) + set(migrate_component_to_storage_FLAGS DEPENDENCIES unordered_component component_storage_component ) diff --git a/tests/unit/component/inheritance_3_classes_2_concrete.cpp b/tests/unit/component/inheritance_3_classes_2_concrete.cpp new file mode 100644 index 000000000000..1e312a32cdfd --- /dev/null +++ b/tests/unit/component/inheritance_3_classes_2_concrete.cpp @@ -0,0 +1,320 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2012 Bryce Adelstein-Lelbach +// +// SPDX-License-Identifier: BSL-1.0 +// 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 +#include +#include +#include +#include + +#include + +bool a_ctor = false; +bool a_dtor = false; +bool b_ctor = false; +bool b_dtor = false; +bool c_ctor = false; +bool c_dtor = false; + +/////////////////////////////////////////////////////////////////////////////// +// Concrete +struct A : hpx::components::component_base +{ + A() + { + a_ctor = true; + } + virtual ~A() + { + a_dtor = true; + } + + virtual std::string test0() const + { + return "A"; + } + std::string test0_nonvirt() const + { + return test0(); + } + HPX_DEFINE_COMPONENT_ACTION(A, test0_nonvirt, test0_action); +}; + +typedef hpx::components::component serverA_type; +HPX_REGISTER_COMPONENT(serverA_type, A); + +typedef A::test0_action test0_action; +HPX_REGISTER_ACTION_DECLARATION(test0_action); +HPX_REGISTER_ACTION(test0_action); + +/////////////////////////////////////////////////////////////////////////////// +// Concrete +struct B : hpx::components::component_base +{ + B() + { + b_ctor = true; + } + virtual ~B() + { + b_dtor = true; + } + + virtual std::string test1() const + { + return "B"; + } + std::string test1_nonvirt() const + { + return test1(); + } + HPX_DEFINE_COMPONENT_ACTION(B, test1_nonvirt, test1_action); +}; + +typedef hpx::components::component serverB_type; +HPX_REGISTER_COMPONENT(serverB_type, B); + +typedef B::test1_action test1_action; +HPX_REGISTER_ACTION_DECLARATION(test1_action); +HPX_REGISTER_ACTION(test1_action); + +/////////////////////////////////////////////////////////////////////////////// +// Concrete +struct C + : A + , B + , hpx::components::component_base +{ + typedef hpx::components::component_base::wrapping_type wrapping_type; + typedef hpx::components::component_base::wrapped_type wrapped_type; + + using hpx::components::component_base::finalize; + using hpx::components::component_base::get_base_gid; + using hpx::components::component_base::get_current_address; + + typedef C type_holder; + typedef B base_type_holder; + + C() + { + c_ctor = true; + } + ~C() + { + c_dtor = true; + } + + std::string test0() const + { + return "C"; + } + + std::string test1() const + { + return "C"; + } + + std::string test2() const + { + return "C"; + } + HPX_DEFINE_COMPONENT_ACTION(C, test2, test2_action); +}; + +typedef hpx::components::component serverC_type; +HPX_REGISTER_DERIVED_COMPONENT_FACTORY(serverC_type, C, "B"); + +typedef C::test2_action test2_action; +HPX_REGISTER_ACTION_DECLARATION(test2_action); +HPX_REGISTER_ACTION(test2_action); + +/////////////////////////////////////////////////////////////////////////////// +struct clientA : hpx::components::client_base +{ + typedef hpx::components::client_base base_type; + + clientA(hpx::shared_future const& gid) + : base_type(gid) + { + } + + std::string test0() + { + test0_action act; + return act(base_type::get_id()); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +struct clientB : hpx::components::client_base +{ + typedef hpx::components::client_base base_type; + + clientB(hpx::shared_future const& gid) + : base_type(gid) + { + } + + std::string test1() + { + test1_action act; + return act(base_type::get_id()); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +struct clientC : hpx::components::client_base +{ + typedef hpx::components::client_base base_type; + + clientC(hpx::shared_future const& gid) + : base_type(gid) + { + } + + std::string test0() + { + test0_action act; + return act(base_type::get_id()); + } + + std::string test1() + { + test1_action act; + return act(base_type::get_id()); + } + + std::string test2() + { + test2_action act; + return act(base_type::get_id()); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +void reset_globals() +{ + a_ctor = false; + a_dtor = false; + b_ctor = false; + b_dtor = false; + c_ctor = false; + c_dtor = false; +} + +int main() +{ + /////////////////////////////////////////////////////////////////////////// + { + // Client to A, instance of A + clientA obj(hpx::components::new_(hpx::find_here())); + + HPX_TEST_EQ(obj.test0(), "A"); + } + + // Make sure AGAS kicked in... + hpx::agas::garbage_collect(); + hpx::this_thread::yield(); + + HPX_TEST(a_ctor); + HPX_TEST(a_dtor); + HPX_TEST(!b_ctor); + HPX_TEST(!b_dtor); + HPX_TEST(!c_ctor); + HPX_TEST(!c_dtor); + + reset_globals(); + + /////////////////////////////////////////////////////////////////////////// + { + // Client to A, instance of C + clientA obj(hpx::components::new_(hpx::find_here())); + + HPX_TEST_EQ(obj.test0(), "C"); + } + + // Make sure AGAS kicked in... + hpx::agas::garbage_collect(); + hpx::this_thread::yield(); + + HPX_TEST(a_ctor); + HPX_TEST(a_dtor); + HPX_TEST(b_ctor); + HPX_TEST(b_dtor); + HPX_TEST(c_ctor); + HPX_TEST(c_dtor); + + reset_globals(); + + /////////////////////////////////////////////////////////////////////////// + { + // Client to B, instance of B + clientB obj(hpx::components::new_(hpx::find_here())); + + HPX_TEST_EQ(obj.test1(), "B"); + } + + // Make sure AGAS kicked in... + hpx::agas::garbage_collect(); + hpx::this_thread::yield(); + + HPX_TEST(!a_ctor); + HPX_TEST(!a_dtor); + HPX_TEST(b_ctor); + HPX_TEST(b_dtor); + HPX_TEST(!c_ctor); + HPX_TEST(!c_dtor); + + reset_globals(); + + /////////////////////////////////////////////////////////////////////////// + { + // Client to B, instance of C + clientB obj(hpx::components::new_(hpx::find_here())); + + HPX_TEST_EQ(obj.test1(), "C"); + } + + // Make sure AGAS kicked in... + hpx::agas::garbage_collect(); + hpx::this_thread::yield(); + + HPX_TEST(a_ctor); + HPX_TEST(a_dtor); + HPX_TEST(b_ctor); + HPX_TEST(b_dtor); + HPX_TEST(c_ctor); + HPX_TEST(c_dtor); + + reset_globals(); + + /////////////////////////////////////////////////////////////////////////// + { + // Client to C, instance of C + clientC obj(hpx::components::new_(hpx::find_here())); + + HPX_TEST_EQ(obj.test0(), "C"); + HPX_TEST_EQ(obj.test1(), "C"); + HPX_TEST_EQ(obj.test2(), "C"); + } + + // Make sure AGAS kicked in... + hpx::agas::garbage_collect(); + hpx::this_thread::yield(); + + HPX_TEST(a_ctor); + HPX_TEST(a_dtor); + HPX_TEST(b_ctor); + HPX_TEST(b_dtor); + HPX_TEST(c_ctor); + HPX_TEST(c_dtor); + + reset_globals(); + + return 0; +} From 6a7d2ed513a4d5790334c7231c1a35d054f3eb5b Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 23 Jul 2020 17:08:55 -0500 Subject: [PATCH 16/29] Removing obsolete code --- hpx/lcos/detail/promise_base.hpp | 8 -------- hpx/runtime/actions/continuation.hpp | 8 -------- hpx/runtime/components/client_base.hpp | 8 -------- hpx/runtime/components/runtime_support.hpp | 8 -------- hpx/runtime/components/server/component_base.hpp | 7 ------- .../components/server/fixed_component_base.hpp | 8 -------- .../components/server/managed_component_base.hpp | 16 ---------------- 7 files changed, 63 deletions(-) diff --git a/hpx/lcos/detail/promise_base.hpp b/hpx/lcos/detail/promise_base.hpp index f8eea5c44367..01bb1a981179 100644 --- a/hpx/lcos/detail/promise_base.hpp +++ b/hpx/lcos/detail/promise_base.hpp @@ -270,14 +270,6 @@ namespace lcos { return get_id(false, ec); } -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - naming::id_type get_gid(error_code& ec = throws) const - { - return get_id(false, ec); - } -#endif - naming::address resolve(error_code& ec = throws) const { if (!addr_ || !id_) diff --git a/hpx/runtime/actions/continuation.hpp b/hpx/runtime/actions/continuation.hpp index 10b12fd57e88..99a7bde02ff5 100644 --- a/hpx/runtime/actions/continuation.hpp +++ b/hpx/runtime/actions/continuation.hpp @@ -63,14 +63,6 @@ namespace hpx { namespace actions void serialize(hpx::serialization::input_archive& ar, unsigned); void serialize(hpx::serialization::output_archive& ar, unsigned); -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - naming::id_type const& get_gid() const - { - return gid_; - } -#endif - naming::id_type const& get_id() const { return gid_; diff --git a/hpx/runtime/components/client_base.hpp b/hpx/runtime/components/client_base.hpp index c98a90303238..581c28a7a182 100644 --- a/hpx/runtime/components/client_base.hpp +++ b/hpx/runtime/components/client_base.hpp @@ -397,14 +397,6 @@ namespace hpx { namespace components } /////////////////////////////////////////////////////////////////////// -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - id_type const& get_gid() const - { - return get_id(); - } -#endif - id_type const& get_id() const { return get(); diff --git a/hpx/runtime/components/runtime_support.hpp b/hpx/runtime/components/runtime_support.hpp index 2ddf13e56543..f538baeabca8 100644 --- a/hpx/runtime/components/runtime_support.hpp +++ b/hpx/runtime/components/runtime_support.hpp @@ -139,14 +139,6 @@ namespace hpx { namespace components } /////////////////////////////////////////////////////////////////////// -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - naming::id_type const& get_gid() const - { - return gid_; - } -#endif - naming::id_type const& get_id() const { return gid_; diff --git a/hpx/runtime/components/server/component_base.hpp b/hpx/runtime/components/server/component_base.hpp index 1cecc958bfda..26ddc84dd4ee 100644 --- a/hpx/runtime/components/server/component_base.hpp +++ b/hpx/runtime/components/server/component_base.hpp @@ -180,13 +180,6 @@ namespace hpx { namespace components static_cast(*this).get_base_gid()); } -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - naming::id_type get_gid() const - { - return get_id(); - } -#endif protected: naming::gid_type get_base_gid( naming::gid_type const& assign_gid = naming::invalid_gid) const diff --git a/hpx/runtime/components/server/fixed_component_base.hpp b/hpx/runtime/components/server/fixed_component_base.hpp index 94bc45eaa418..2c24d2ed998d 100644 --- a/hpx/runtime/components/server/fixed_component_base.hpp +++ b/hpx/runtime/components/server/fixed_component_base.hpp @@ -142,14 +142,6 @@ class fixed_component_base : public traits::detail::fixed_component_tag naming::id_type::unmanaged); } -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - naming::id_type get_gid() const - { - return get_unmanaged_id(); - } -#endif - void set_locality_id(std::uint32_t locality_id, error_code& ec = throws) { if (gid_) { diff --git a/hpx/runtime/components/server/managed_component_base.hpp b/hpx/runtime/components/server/managed_component_base.hpp index d782110bba48..6e0f6d581ef0 100644 --- a/hpx/runtime/components/server/managed_component_base.hpp +++ b/hpx/runtime/components/server/managed_component_base.hpp @@ -253,14 +253,6 @@ namespace hpx { namespace components naming::id_type get_unmanaged_id() const; naming::id_type get_id() const; -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - naming::id_type get_gid() const - { - return get_unmanaged_id(); - } -#endif - protected: naming::gid_type get_base_gid() const; @@ -453,14 +445,6 @@ namespace hpx { namespace components return naming::id_type(get_base_gid(), naming::id_type::unmanaged); } -#if defined(HPX_HAVE_COMPONENT_GET_GID_COMPATIBILITY) - HPX_DEPRECATED(HPX_DEPRECATED_MSG) - naming::id_type get_gid() const - { - return get_unmanaged_id(); - } -#endif - private: #if !defined(__NVCC__) && !defined(__CUDACC__) // declare friends which are allowed to access get_base_gid() From 410dd55894e563ca1469b52120c6c48d6d6efe07 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 23 Jul 2020 11:19:35 -0500 Subject: [PATCH 17/29] Fixing linker problem and formatting errors --- libs/execution_base/CMakeLists.txt | 2 +- libs/resiliency/CMakeLists.txt | 4 ++++ .../include/hpx/resiliency/resiliency_cpos.hpp | 4 +--- .../tests/performance/replay/1d_stencil_checksum.cpp | 9 ++++++--- .../tests/performance/replay/1d_stencil_replay.cpp | 8 +++++--- .../performance/replay/dataflow_replay_validate.cpp | 9 ++++++--- .../resiliency/tests/unit/async_replicate_vote_plain.cpp | 2 -- libs/resiliency/tests/unit/dataflow_replay_executor.cpp | 3 ++- 8 files changed, 25 insertions(+), 16 deletions(-) diff --git a/libs/execution_base/CMakeLists.txt b/libs/execution_base/CMakeLists.txt index 4881f68c7a10..a4bd82de860a 100644 --- a/libs/execution_base/CMakeLists.txt +++ b/libs/execution_base/CMakeLists.txt @@ -45,6 +45,6 @@ add_hpx_module( HEADERS ${execution_base_headers} COMPAT_HEADERS ${execution_base_compat_headers} DEPENDENCIES hpx_assertion hpx_config hpx_errors hpx_format hpx_functional - hpx_timing + hpx_iterator_support hpx_timing CMAKE_SUBDIRS examples tests ) diff --git a/libs/resiliency/CMakeLists.txt b/libs/resiliency/CMakeLists.txt index 0f5352112ba1..dbf33d39b2fd 100644 --- a/libs/resiliency/CMakeLists.txt +++ b/libs/resiliency/CMakeLists.txt @@ -29,12 +29,16 @@ add_hpx_module( GLOBAL_HEADER_GEN ON SOURCES ${resiliency_sources} HEADERS ${resiliency_headers} + DEPENDENCIES DEPENDENCIES hpx_assertion hpx_async_local hpx_config + hpx_concepts hpx_datastructures hpx_execution hpx_functional + hpx_futures + hpx_type_support CMAKE_SUBDIRS examples tests ) diff --git a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp index a8c84fb86be7..d4db9ba99194 100644 --- a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp +++ b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp @@ -19,12 +19,10 @@ namespace hpx { namespace resiliency { namespace experimental { template struct tag_deferred : hpx::functional::tag { - static constexpr BaseTag base_tag{}; - template friend HPX_FORCEINLINE decltype(auto) tag_invoke(Tag, Args&&... args) { - return hpx::dataflow(base_tag, std::forward(args)...); + return hpx::dataflow(BaseTag{}, std::forward(args)...); } }; diff --git a/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp b/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp index d5af896e6f23..d4a0641ec372 100644 --- a/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp +++ b/libs/resiliency/tests/performance/replay/1d_stencil_checksum.cpp @@ -264,9 +264,12 @@ struct stepper for (std::size_t i = 0; i != subdomains; ++i) { - next[i] = dataflow_replay_validate(n_value, validate_result, Op, - sti, error, current[(i - 1 + subdomains) % subdomains], - current[i], current[(i + 1) % subdomains]); + // explicitly unwrap future + hpx::future f = + dataflow_replay_validate(n_value, validate_result, Op, sti, + error, current[(i - 1 + subdomains) % subdomains], + current[i], current[(i + 1) % subdomains]); + next[i] = std::move(f); } // every nd time steps, attach additional continuation which will diff --git a/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp b/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp index 2632750cf5d9..04a0f5670fb2 100644 --- a/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp +++ b/libs/resiliency/tests/performance/replay/1d_stencil_replay.cpp @@ -221,9 +221,11 @@ struct stepper for (std::size_t i = 0; i != subdomains; ++i) { - next[i] = dataflow_replay(n_value, Op, sti, error, - current[(i - 1 + subdomains) % subdomains], current[i], - current[(i + 1) % subdomains]); + // explicitly unwrap future + hpx::future f = dataflow_replay(n_value, Op, + sti, error, current[(i - 1 + subdomains) % subdomains], + current[i], current[(i + 1) % subdomains]); + next[i] = std::move(f); } // every nd time steps, attach additional continuation which will diff --git a/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp b/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp index 78dcf6eeb637..df2e8c328838 100644 --- a/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp +++ b/libs/resiliency/tests/performance/replay/dataflow_replay_validate.cpp @@ -258,9 +258,12 @@ struct stepper for (std::size_t i = 0; i != subdomains; ++i) { - next[i] = dataflow_replay_validate(n_value, validate_result, Op, - error, current[(i - 1 + subdomains) % subdomains], - current[i], current[(i + 1) % subdomains]); + // explicitly unwrap future + hpx::future f = + dataflow_replay_validate(n_value, validate_result, Op, + error, current[(i - 1 + subdomains) % subdomains], + current[i], current[(i + 1) % subdomains]); + next[i] = std::move(f); } // every nd time steps, attach additional continuation which will diff --git a/libs/resiliency/tests/unit/async_replicate_vote_plain.cpp b/libs/resiliency/tests/unit/async_replicate_vote_plain.cpp index c48759ba786f..9d1c228b880a 100644 --- a/libs/resiliency/tests/unit/async_replicate_vote_plain.cpp +++ b/libs/resiliency/tests/unit/async_replicate_vote_plain.cpp @@ -49,8 +49,6 @@ int hpx_main() } { - hpx::parallel::execution::parallel_executor exec; - hpx::future f = hpx::resiliency::experimental::async_replicate_vote_validate( 10, &vote, &validate, &universal_ans); diff --git a/libs/resiliency/tests/unit/dataflow_replay_executor.cpp b/libs/resiliency/tests/unit/dataflow_replay_executor.cpp index f16d7da813e7..fe27d295e54c 100644 --- a/libs/resiliency/tests/unit/dataflow_replay_executor.cpp +++ b/libs/resiliency/tests/unit/dataflow_replay_executor.cpp @@ -64,7 +64,8 @@ int hpx_main() HPX_TEST(f.get() == 42); // unsuccessful replay - f = hpx::resiliency::experimental::dataflow_replay(exec, 6, &deep_thought); + f = hpx::resiliency::experimental::dataflow_replay( + exec, 6, &deep_thought); bool exception_caught = false; try From 697d1d809729e2851e6e7af1e9d7e2fb068d767f Mon Sep 17 00:00:00 2001 From: John Biddiscombe Date: Thu, 23 Jul 2020 17:59:09 +0200 Subject: [PATCH 18/29] Fix mpi_ring test in distributed mode by ensuring all ranks run hpx_main --- libs/async_mpi/tests/unit/CMakeLists.txt | 3 +-- libs/async_mpi/tests/unit/mpi_ring_async_executor.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libs/async_mpi/tests/unit/CMakeLists.txt b/libs/async_mpi/tests/unit/CMakeLists.txt index 14b28a7266fe..30e6de80fa01 100644 --- a/libs/async_mpi/tests/unit/CMakeLists.txt +++ b/libs/async_mpi/tests/unit/CMakeLists.txt @@ -4,8 +4,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) -set(tests # mpi_ring_async_executor -) +set(tests mpi_ring_async_executor) set(mpi_ring_async_executor_PARAMETERS THREADS_PER_LOCALITY 4 LOCALITIES 2 RUNWRAPPER mpi diff --git a/libs/async_mpi/tests/unit/mpi_ring_async_executor.cpp b/libs/async_mpi/tests/unit/mpi_ring_async_executor.cpp index db58cc50a60c..3744c0542549 100644 --- a/libs/async_mpi/tests/unit/mpi_ring_async_executor.cpp +++ b/libs/async_mpi/tests/unit/mpi_ring_async_executor.cpp @@ -167,10 +167,6 @@ int hpx_main(hpx::program_options::variables_map& vm) } } - // This is needed to make sure that one rank does not shut down - // before others have completed. MPI does not handle that well. - MPI_Barrier(MPI_COMM_WORLD); - if (rank == 0) { std::cout << "time " << t.elapsed() << std::endl; @@ -186,6 +182,10 @@ int hpx_main(hpx::program_options::variables_map& vm) // on an hpx thread int main(int argc, char* argv[]) { + // if this test is run with distributed runtime, we need to make sure + // that all ranks run their main function + std::vector cfg = {"hpx.run_hpx_main!=1"}; + // Init MPI int provided = MPI_THREAD_MULTIPLE; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); @@ -208,7 +208,7 @@ int main(int argc, char* argv[]) // clang-format on // Initialize and run HPX. - auto result = hpx::init(cmdline, argc, argv); + auto result = hpx::init(cmdline, argc, argv, cfg); // Finalize MPI MPI_Finalize(); From 689ce9b586322c90f966ef84aa6eba190f037dd7 Mon Sep 17 00:00:00 2001 From: Joachim K Date: Fri, 24 Jul 2020 16:56:09 +0200 Subject: [PATCH 19/29] Correct typos in the description of the hpx performance counters --- docs/sphinx/manual/optimizing_hpx_applications.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/sphinx/manual/optimizing_hpx_applications.rst b/docs/sphinx/manual/optimizing_hpx_applications.rst index fc0ff5a59251..d40b51f74be5 100644 --- a/docs/sphinx/manual/optimizing_hpx_applications.rst +++ b/docs/sphinx/manual/optimizing_hpx_applications.rst @@ -805,7 +805,7 @@ system and application performance. where: ```` is one of the following: ``primary``, - ``locality``, ``component`` or ``symbol`` + ``locality``, ``component`` or ``symbol`` * ``/total`` @@ -868,7 +868,7 @@ system and application performance. where: ```` is one of the following: ``primary``, - ``locality``, ``component`` or ``symbol``. + ``locality``, ``component`` or ``symbol`` * ``/total`` where: @@ -901,7 +901,7 @@ system and application performance. where: ```` is one of the following: ``cache/evictions``, - ``cache/hits``, ``cache/inserts``, ``cache/misses`` + ``cache/hits``, ``cache/insertions``, ``cache/misses`` * ``locality#*/total`` where: @@ -1143,7 +1143,7 @@ system and application performance. where: ```` is one of the following: ``cache/insertions``, - ``cache/evictions``, ``cache/hits``, ``cache/misses`` ``cache/misses`` + ``cache/evictions``, ``cache/hits``, ``cache/misses`` ` Date: Fri, 24 Jul 2020 11:37:26 -0500 Subject: [PATCH 20/29] Improve libCDS integration - make git repository and tag configurable - place generated projects in 'Core' FOLDER --- CMakeLists.txt | 14 +++++++++++++- cmake/HPX_SetupLibCDS.cmake | 13 ++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b47890ad0d20..6e6b2820ab3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -932,8 +932,20 @@ if(HPX_WITH_APEX) endif() # LibCDS option -hpx_option(HPX_WITH_LIBCDS BOOL "Enable LibCDS support." OFF) +hpx_option( + HPX_WITH_LIBCDS BOOL "Enable LibCDS support (experimental)." OFF + CATEGORY "Thread Manager" ADVANCED +) if(HPX_WITH_LIBCDS) + hpx_option( + HPX_WITH_LIBCDS_GIT_REPOSITORY STRING + "Define the LibCDS git repository to use." + https://github.com/STEllAR-GROUP/libcds CATEGORY "Thread Manager" ADVANCED + ) + hpx_option( + HPX_WITH_LIBCDS_GIT_TAG STRING "Define the LibCDS git tag to use." + hpx-thread CATEGORY "Thread Manager" ADVANCED + ) include(HPX_SetupLibCDS) if(NOT libcds_POPULATED) hpx_error("HPX_WITH_LIBCDS was set to ON, but HPX failed to fetch LibCDS") diff --git a/cmake/HPX_SetupLibCDS.cmake b/cmake/HPX_SetupLibCDS.cmake index 3b41ba088032..db11803ab42c 100644 --- a/cmake/HPX_SetupLibCDS.cmake +++ b/cmake/HPX_SetupLibCDS.cmake @@ -17,6 +17,7 @@ if(HPX_WITH_LIBCDS AND NOT TARGET LibCDS::cds) include(FetchContent) + include(HPX_Message) set(LIBCDS_WITH_HPX ON @@ -27,11 +28,14 @@ if(HPX_WITH_LIBCDS AND NOT TARGET LibCDS::cds) CACHE INTERNAL "" ) + hpx_info( + "Fetching libCDS from repository: ${HPX_WITH_LIBCDS_GIT_REPOSITORY}, " + "tag: ${HPX_WITH_LIBCDS_GIT_TAG}" + ) fetchcontent_declare( libcds - # GIT_REPOSITORY https://github.com/khizmax/libcds - GIT_REPOSITORY https://github.com/weilewei/libcds - GIT_TAG hpx-thread + GIT_REPOSITORY ${HPX_WITH_LIBCDS_GIT_REPOSITORY} + GIT_TAG ${HPX_WITH_LIBCDS_GIT_TAG} GIT_SHALLOW TRUE ) fetchcontent_getproperties(libcds) @@ -40,6 +44,9 @@ if(HPX_WITH_LIBCDS AND NOT TARGET LibCDS::cds) fetchcontent_populate(libcds) set(LIBCDS_CXX_STANDARD ${HPX_CXX_STANDARD}) add_subdirectory(${libcds_SOURCE_DIR} ${libcds_BINARY_DIR}) + + set_target_properties(cds PROPERTIES FOLDER "Core") + set_target_properties(cds-s PROPERTIES FOLDER "Core") endif() endif() From 709c254d16663dd468e30fe11e651d86f30fcd3f Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 24 Jul 2020 12:16:10 -0500 Subject: [PATCH 21/29] Cleaning up libCDS benchmark --- .../local/libcds_hazard_pointer_overhead.cpp | 81 +++++++++++++------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/tests/performance/local/libcds_hazard_pointer_overhead.cpp b/tests/performance/local/libcds_hazard_pointer_overhead.cpp index 3922498d297f..55afbdac63fd 100644 --- a/tests/performance/local/libcds_hazard_pointer_overhead.cpp +++ b/tests/performance/local/libcds_hazard_pointer_overhead.cpp @@ -10,15 +10,13 @@ #include #include #include -#include #include #include #include +#include #include #include #include -#include -#include #include #include @@ -115,10 +113,27 @@ double global_scratch = 0; std::uint64_t num_iterations = 0; /////////////////////////////////////////////////////////////////////////////// +struct libcds_thread_manager_wrapper +{ + libcds_thread_manager_wrapper(bool uselibcds) + : uselibcds_(uselibcds) + { + if (uselibcds_) + cds::threading::Manager::attachThread(); + } + ~libcds_thread_manager_wrapper() + { + if (uselibcds_) + cds::threading::Manager::detachThread(); + } + + bool uselibcds_; +}; + double null_function(bool uselibcds) noexcept { - if (uselibcds) - cds::threading::Manager::attachThread(); + libcds_thread_manager_wrapper wrap(uselibcds); + if (num_iterations > 0) { const int array_size = 4096; @@ -132,8 +147,6 @@ double null_function(bool uselibcds) noexcept } return dummy[0]; } - if (uselibcds) - cds::threading::Manager::detachThread(); return 0.0; } @@ -210,10 +223,10 @@ void measure_function_futures_create_thread_hierarchical_placement( }; auto const thread_func = hpx::threads::detail::thread_function_nullary{func}; - auto const desc = hpx::util::thread_description(); + auto desc = hpx::util::thread_description(); auto prio = hpx::threads::thread_priority_normal; - auto const stack_size = hpx::threads::thread_stacksize_small; - auto const num_threads = hpx::get_num_worker_threads(); + auto stack_size = hpx::threads::thread_stacksize_small; + auto num_threads = hpx::get_num_worker_threads(); hpx::error_code ec; // start the clock @@ -223,7 +236,7 @@ void measure_function_futures_create_thread_hierarchical_placement( auto const hint = hpx::threads::thread_schedule_hint(static_cast(t)); auto spawn_func = [&thread_func, sched, hint, t, count, num_threads, - desc, prio]() { + desc, prio, stack_size]() { std::uint64_t const count_start = t * count / num_threads; std::uint64_t const count_end = (t + 1) * count / num_threads; hpx::error_code ec; @@ -253,10 +266,25 @@ void measure_function_futures_create_thread_hierarchical_placement( } /////////////////////////////////////////////////////////////////////////////// +struct libcds_wrapper +{ + libcds_wrapper() + { + // Initialize libcds + cds::Initialize(); + } + + ~libcds_wrapper() + { + // Terminate libcds + cds::Terminate(); + } +}; + int hpx_main(variables_map& vm) { // Initialize libcds - cds::Initialize(); + libcds_wrapper wrapper; { // Initialize Hazard Pointer singleton @@ -299,15 +327,16 @@ int hpx_main(variables_map& vm) count, csv, bool(cds)); measure_function_futures_thread_count( count, csv, par, bool(cds)); + measure_function_futures_thread_count( + count, csv, par_agg, bool(cds)); measure_function_futures_thread_count( count, csv, tpe, bool(cds)); + measure_function_futures_thread_count( + count, csv, tpe_nostack, bool(cds)); } } } - // Terminate libcds - cds::Terminate(); - return hpx::finalize(); } @@ -318,20 +347,20 @@ int main(int argc, char* argv[]) options_description cmdline("usage: " HPX_APPLICATION_STRING " [options]"); // clang-format off - cmdline.add_options()("futures", - value()->default_value(500000), - "number of futures to invoke") + cmdline.add_options() + ("futures", value()->default_value(500000), + "number of futures to invoke") - ("delay-iterations", value()->default_value(0), - "number of iterations in the delay loop") + ("delay-iterations", value()->default_value(0), + "number of iterations in the delay loop") - ("csv", "output results as csv (format: count,duration)") - ("test-all", "run all benchmarks") - ("repetitions", value()->default_value(1), - "number of repetitions of the full benchmark") + ("csv", "output results as csv (format: count,duration)") + ("test-all", "run all benchmarks") + ("repetitions", value()->default_value(1), + "number of repetitions of the full benchmark") - ("info", value()->default_value("no-info"), - "extra info for plot output (e.g. branch name)"); + ("info", value()->default_value("no-info"), + "extra info for plot output (e.g. branch name)"); // clang-format on // Initialize and run HPX. From ae33624cf456caeeade0179f0f541d1644b2778a Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 24 Jul 2020 13:24:58 -0500 Subject: [PATCH 22/29] Fix codacy warning --- tests/performance/local/libcds_hazard_pointer_overhead.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/local/libcds_hazard_pointer_overhead.cpp b/tests/performance/local/libcds_hazard_pointer_overhead.cpp index 55afbdac63fd..e63c36d9f86f 100644 --- a/tests/performance/local/libcds_hazard_pointer_overhead.cpp +++ b/tests/performance/local/libcds_hazard_pointer_overhead.cpp @@ -115,7 +115,7 @@ std::uint64_t num_iterations = 0; /////////////////////////////////////////////////////////////////////////////// struct libcds_thread_manager_wrapper { - libcds_thread_manager_wrapper(bool uselibcds) + explicit libcds_thread_manager_wrapper(bool uselibcds) : uselibcds_(uselibcds) { if (uselibcds_) From e9a958442a6cba75f479f92c6e5f5eb00a57e358 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 24 Jul 2020 15:30:14 -0500 Subject: [PATCH 23/29] Removing nostack tests --- tests/performance/local/libcds_hazard_pointer_overhead.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/performance/local/libcds_hazard_pointer_overhead.cpp b/tests/performance/local/libcds_hazard_pointer_overhead.cpp index e63c36d9f86f..6f0f6dd2ea24 100644 --- a/tests/performance/local/libcds_hazard_pointer_overhead.cpp +++ b/tests/performance/local/libcds_hazard_pointer_overhead.cpp @@ -315,9 +315,6 @@ int hpx_main(variables_map& vm) hpx::parallel::execution::parallel_executor par; hpx::parallel::execution::parallel_executor_aggregated par_agg; hpx::parallel::execution::thread_pool_executor tpe; - hpx::parallel::execution::thread_pool_executor tpe_nostack( - hpx::threads::thread_priority_default, - hpx::threads::thread_stacksize_nostack); for (int i = 0; i < repetitions; i++) { @@ -331,8 +328,6 @@ int hpx_main(variables_map& vm) count, csv, par_agg, bool(cds)); measure_function_futures_thread_count( count, csv, tpe, bool(cds)); - measure_function_futures_thread_count( - count, csv, tpe_nostack, bool(cds)); } } } From 28e08dd8cb2e09a2e878c2b47f520345bcebc2b2 Mon Sep 17 00:00:00 2001 From: Weile Wei Date: Fri, 24 Jul 2020 15:59:54 -0500 Subject: [PATCH 24/29] explict use hazard pointer threading and constructor --- .../local/libcds_hazard_pointer_overhead.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/performance/local/libcds_hazard_pointer_overhead.cpp b/tests/performance/local/libcds_hazard_pointer_overhead.cpp index 6f0f6dd2ea24..eee2cfe980ac 100644 --- a/tests/performance/local/libcds_hazard_pointer_overhead.cpp +++ b/tests/performance/local/libcds_hazard_pointer_overhead.cpp @@ -119,12 +119,12 @@ struct libcds_thread_manager_wrapper : uselibcds_(uselibcds) { if (uselibcds_) - cds::threading::Manager::attachThread(); + cds::gc::hp::smr::attach_thread(); } ~libcds_thread_manager_wrapper() { if (uselibcds_) - cds::threading::Manager::detachThread(); + cds::gc::hp::smr::detach_thread(); } bool uselibcds_; @@ -287,9 +287,6 @@ int hpx_main(variables_map& vm) libcds_wrapper wrapper; { - // Initialize Hazard Pointer singleton - cds::gc::HP hpGC; - if (vm.count("hpx:queuing")) queuing = vm["hpx:queuing"].as(); @@ -312,6 +309,15 @@ int hpx_main(variables_map& vm) if (HPX_UNLIKELY(0 == count)) throw std::logic_error("error: count of 0 futures specified\n"); + // Hazard pointer count per thread + const std::size_t nHazardPtrCount = 1; + // Max count of simultaneous working thread in your application + const std::size_t nMaxThreadCount = count; + // Capacity of the array of retired objects for the thread + const std::size_t nMaxRetiredPtrCount = 1; + // Initialize Hazard Pointer singleton + cds::gc::HP hpGC(nHazardPtrCount, nMaxThreadCount, nMaxRetiredPtrCount); + hpx::parallel::execution::parallel_executor par; hpx::parallel::execution::parallel_executor_aggregated par_agg; hpx::parallel::execution::thread_pool_executor tpe; From 0c975b43796334fce78ad4be970fcb3786180cff Mon Sep 17 00:00:00 2001 From: Weile Wei Date: Fri, 24 Jul 2020 16:12:07 -0500 Subject: [PATCH 25/29] remove parameters in hp constructor, use default --- .../performance/local/libcds_hazard_pointer_overhead.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/performance/local/libcds_hazard_pointer_overhead.cpp b/tests/performance/local/libcds_hazard_pointer_overhead.cpp index eee2cfe980ac..8b25c9d8af32 100644 --- a/tests/performance/local/libcds_hazard_pointer_overhead.cpp +++ b/tests/performance/local/libcds_hazard_pointer_overhead.cpp @@ -309,14 +309,7 @@ int hpx_main(variables_map& vm) if (HPX_UNLIKELY(0 == count)) throw std::logic_error("error: count of 0 futures specified\n"); - // Hazard pointer count per thread - const std::size_t nHazardPtrCount = 1; - // Max count of simultaneous working thread in your application - const std::size_t nMaxThreadCount = count; - // Capacity of the array of retired objects for the thread - const std::size_t nMaxRetiredPtrCount = 1; - // Initialize Hazard Pointer singleton - cds::gc::HP hpGC(nHazardPtrCount, nMaxThreadCount, nMaxRetiredPtrCount); + cds::gc::HP hpGC; hpx::parallel::execution::parallel_executor par; hpx::parallel::execution::parallel_executor_aggregated par_agg; From 0500516419bb18ce2ec186769d40ba8f169b6897 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 24 Jul 2020 20:26:46 -0500 Subject: [PATCH 26/29] force unwrapping of the inner future on return of dataflow functions --- libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp index d4db9ba99194..59d3d02e81bd 100644 --- a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp +++ b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp @@ -19,8 +19,10 @@ namespace hpx { namespace resiliency { namespace experimental { template struct tag_deferred : hpx::functional::tag { + // force unwrapping of the inner future on return template - friend HPX_FORCEINLINE decltype(auto) tag_invoke(Tag, Args&&... args) + friend HPX_FORCEINLINE auto tag_invoke(Tag, Args&&... args) + -> hpx::functional::tag_invoke_result_t { return hpx::dataflow(BaseTag{}, std::forward(args)...); } From d5f028add746271daa4d7d38708a2fb7445819ba Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Sat, 25 Jul 2020 09:46:29 -0500 Subject: [PATCH 27/29] Fixing async_replay_executor - flyby: fixing cmake-format issues --- libs/execution_base/CMakeLists.txt | 10 ++++++++-- .../include/hpx/resiliency/async_replay_executor.hpp | 10 ++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libs/execution_base/CMakeLists.txt b/libs/execution_base/CMakeLists.txt index a4bd82de860a..347209d7eaa6 100644 --- a/libs/execution_base/CMakeLists.txt +++ b/libs/execution_base/CMakeLists.txt @@ -44,7 +44,13 @@ add_hpx_module( SOURCES ${execution_base_sources} HEADERS ${execution_base_headers} COMPAT_HEADERS ${execution_base_compat_headers} - DEPENDENCIES hpx_assertion hpx_config hpx_errors hpx_format hpx_functional - hpx_iterator_support hpx_timing + DEPENDENCIES + hpx_assertion + hpx_config + hpx_errors + hpx_format + hpx_functional + hpx_iterator_support + hpx_timing CMAKE_SUBDIRS examples tests ) diff --git a/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp b/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp index 59a8824d5188..a74e9d4211b9 100644 --- a/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp +++ b/libs/resiliency/include/hpx/resiliency/async_replay_executor.hpp @@ -52,7 +52,7 @@ namespace hpx { namespace resiliency { namespace experimental { Result invoke(Executor&& exec, hpx::util::index_pack) { return hpx::parallel::execution::async_execute( - exec, f_, std::get(t_)...); + std::forward(exec), f_, std::get(t_)...); } template @@ -68,7 +68,9 @@ namespace hpx { namespace resiliency { namespace experimental { // necessary auto this_ = this->shared_from_this(); return f.then(hpx::launch::sync, - [this_ = std::move(this_), &exec, n](Result&& f) { + [this_ = std::move(this_), + exec = std::forward(exec), + n](Result&& f) mutable { if (f.has_exception()) { // rethrow abort_replay_exception, if caught @@ -78,7 +80,7 @@ namespace hpx { namespace resiliency { namespace experimental { // this was not the last attempt if (n != 0) { - return this_->call(exec, n - 1); + return this_->call(std::move(exec), n - 1); } // rethrow exception if the number of replays has @@ -94,7 +96,7 @@ namespace hpx { namespace resiliency { namespace experimental { // this was not the last attempt if (n != 0) { - return this_->call(exec, n - 1); + return this_->call(std::move(exec), n - 1); } // throw aborting exception as attempts were From 5250f93270750b8911babb781b51a368b5f010b9 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Sat, 25 Jul 2020 10:45:20 -0500 Subject: [PATCH 28/29] Trying to work around MSVC problem --- libs/resiliency/examples/1d_stencil_replay_exception.cpp | 9 +++------ libs/resiliency/examples/1d_stencil_replay_validate.cpp | 4 +--- .../include/hpx/resiliency/resiliency_cpos.hpp | 5 +++-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/libs/resiliency/examples/1d_stencil_replay_exception.cpp b/libs/resiliency/examples/1d_stencil_replay_exception.cpp index fd380fe27b24..c8b4465f2a4d 100644 --- a/libs/resiliency/examples/1d_stencil_replay_exception.cpp +++ b/libs/resiliency/examples/1d_stencil_replay_exception.cpp @@ -164,12 +164,9 @@ int hpx_main(hpx::program_options::variables_map& vm) std::vector next_input(subdomains); for (int j = 0; j < subdomains; ++j) { - // explicitly unwrap future returned by dataflow - hpx::future f = - hpx::resiliency::experimental::dataflow_replay(n, update, - input[(j - 1 + subdomains) % subdomains], input[j], - input[(j + 1) % subdomains]); - next_input[j] = std::move(f); + next_input[j] = hpx::resiliency::experimental::dataflow_replay( + n, update, input[(j - 1 + subdomains) % subdomains], + input[j], input[(j + 1) % subdomains]); } std::swap(input, next_input); } diff --git a/libs/resiliency/examples/1d_stencil_replay_validate.cpp b/libs/resiliency/examples/1d_stencil_replay_validate.cpp index f871255d708b..00c14d456040 100644 --- a/libs/resiliency/examples/1d_stencil_replay_validate.cpp +++ b/libs/resiliency/examples/1d_stencil_replay_validate.cpp @@ -181,13 +181,11 @@ int hpx_main(hpx::program_options::variables_map& vm) std::vector next_input(subdomains); for (int j = 0; j < subdomains; ++j) { - // explicitly unwrap future returned by dataflow - hpx::future f = + next_input[j] = hpx::resiliency::experimental::dataflow_replay_validate(n, &validate_result, update, input[(j - 1 + subdomains) % subdomains], input[j], input[(j + 1) % subdomains]); - next_input[j] = std::move(f); } std::swap(input, next_input); } diff --git a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp index 59d3d02e81bd..90f842126611 100644 --- a/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp +++ b/libs/resiliency/include/hpx/resiliency/resiliency_cpos.hpp @@ -21,8 +21,9 @@ namespace hpx { namespace resiliency { namespace experimental { { // force unwrapping of the inner future on return template - friend HPX_FORCEINLINE auto tag_invoke(Tag, Args&&... args) - -> hpx::functional::tag_invoke_result_t + friend HPX_FORCEINLINE auto tag_invoke(Tag, Args&&... args) -> + typename hpx::functional::tag_invoke_result::type { return hpx::dataflow(BaseTag{}, std::forward(args)...); } From 8943b661093d054f77bcca18aa4d2bc837a1a85c Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Mon, 27 Jul 2020 09:10:33 +0200 Subject: [PATCH 29/29] Increase Jenkins job timeout on rostam --- .jenkins/lsu/entry.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.jenkins/lsu/entry.sh b/.jenkins/lsu/entry.sh index 7c53c8ec944e..7f700763f54e 100755 --- a/.jenkins/lsu/entry.sh +++ b/.jenkins/lsu/entry.sh @@ -27,7 +27,7 @@ sbatch \ --job-name="jenkins-hpx-${configuration_name_with_build_type}" \ --nodes="${configuration_slurm_num_nodes}" \ --partition="${configuration_slurm_partition}" \ - --time="01:30:00" \ + --time="03:00:00" \ --output="jenkins-hpx-${configuration_name_with_build_type}.out" \ --error="jenkins-hpx-${configuration_name_with_build_type}.err" \ --wait .jenkins/lsu/batch.sh