Skip to content

Commit

Permalink
Merge 2dd79a1 into 3521f71
Browse files Browse the repository at this point in the history
  • Loading branch information
isidorostsa authored May 31, 2024
2 parents 3521f71 + 2dd79a1 commit dceb6c4
Show file tree
Hide file tree
Showing 103 changed files with 5,629 additions and 876 deletions.
29 changes: 28 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) 2020 Mikael Simberg
# Copyright (c) 2007-2024 Hartmut Kaiser
# Copyright (c) 2011-2014 Thomas Heller
# Copyright (c) 2024 Isidoros Tsaousis-Seiras
# Copyright (c) 2007-2008 Chirag Dekate
# Copyright (c) 2011 Bryce Lelbach
# Copyright (c) 2011 Vinay C Amatya
Expand Down Expand Up @@ -577,6 +578,29 @@ if(HPX_WITH_CUDA AND HPX_WITH_HIP)
)
endif()

# ## HPX STDEXEC configuration ##

hpx_option(
HPX_WITH_STDEXEC BOOL
"Use STDEXEC executors instead of native HPX.(default: OFF)" OFF
CATEGORY "Executor"
ADVANCED
)

hpx_option(
HPX_WITH_FETCH_STDEXEC BOOL "Use FetchContent to fetch STDEXEC.(default: OFF)"
OFF
CATEGORY "Executor"
ADVANCED
)

if(HPX_WITH_FETCH_STDEXEC OR HPX_WITH_CXX_STANDARD GREATER_EQUAL 20)
hpx_option(
HPX_WITH_STDEXEC_TAG STRING "STDEXEC repository tag or branch" "main"
CATEGORY "Executor"
)
endif()

# ##############################################################################
# HPX SYCL configuration
# ##############################################################################
Expand Down Expand Up @@ -1345,7 +1369,7 @@ if(HPX_WITH_NETWORKING AND HPX_WITH_PARCELPORT_LCI)
endif()
endif()

# External libraries/frameworks used by sme of the examples and benchmarks
# External libraries/frameworks used by some of the examples and benchmarks
hpx_option(
HPX_WITH_EXAMPLES_OPENMP BOOL
"Enable examples requiring OpenMP support (default: OFF)." OFF
Expand Down Expand Up @@ -2264,6 +2288,9 @@ if(HPX_WITH_CUDA OR HPX_WITH_HIP)
hpx_add_config_define(HPX_HAVE_GPU_SUPPORT)
endif()

# Setup NVIDIA's stdexec if requested
include(HPX_SetupStdexec)

if(HPX_WITH_SANITIZERS)
hpx_add_config_define(HPX_HAVE_SANITIZERS)
endif()
Expand Down
39 changes: 39 additions & 0 deletions cmake/FindStdexec.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) 2024 Isidoros Tsaousis-Seiras
#
# 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 TARGET STDEXEC::stdexec)
if(STDEXEC_ROOT AND NOT Stdexec_ROOT)
set(Stdexec_ROOT
${STDEXEC_ROOT}
CACHE PATH "stdexec base directory"
)
unset(STDEXEC_ROOT CACHE)
endif()

find_path(Stdexec_INCLUDE_DIR stdexec HINTS ${Stdexec_ROOT})
message(STATUS "stdexec include dir: ${Stdexec_INCLUDE_DIR}")
if(Stdexec_INCLUDE_DIR)
file(TO_CMAKE_PATH ${Stdexec_INCLUDE_DIR} Stdexec_INCLUDE_DIR)
else()
message(FATAL_ERROR "stdexec not found")
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
Stdexec
REQUIRED_VARS Stdexec_INCLUDE_DIR
FOUND_VAR Stdexec_FOUND
VERSION_VAR Stdexec_VERSION
FAIL_MESSAGE "stdexec not found"
)

add_library(STDEXEC::stdexec INTERFACE IMPORTED)
target_include_directories(
STDEXEC::stdexec SYSTEM INTERFACE ${Stdexec_INCLUDE_DIR}
)

mark_as_advanced(Stdexec_INCLUDE_DIR Stdexec_ROOT)
endif()
114 changes: 114 additions & 0 deletions cmake/HPX_SetupStdexec.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Copyright (c) 2024 Isidoros Tsaousis-Seiras
#
# 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(STDEXEC_ROOT AND NOT Stdexec_ROOT)
set(Stdexec_ROOT ${STDEXEC_ROOT})
# remove STDEXEC_ROOT from the cache
unset(STDEXEC_ROOT CACHE)
endif()

if(Stdexec_ROOT
OR HPX_WITH_FETCH_STDEXEC
OR HPX_WITH_CXX_STANDARD GREATER_EQUAL 20
)
# explicitly enable HPX_WITH_STDEXEC
set(HPX_WITH_STDEXEC ON)

# prefer Stdexec_ROOT over HPX_WITH_FETCH_STDEXEC by default
if(Stdexec_ROOT AND HPX_WITH_FETCH_STDEXEC)
set(HPX_WITH_FETCH_STDEXEC OFF)
hpx_warn(
"Both Stdexec_ROOT and HPX_WITH_FETCH_STDEXEC are provided. HPX_WITH_FETCH_STDEXEC is set to OFF."
)
elseif(NOT Stdexec_ROOT AND NOT HPX_WITH_FETCH_STDEXEC)
hpx_warn(
"Neither Stdexec_ROOT nor HPX_WITH_FETCH_STDEXEC are provided. HPX_WITH_FETCH_STDEXEC is defaulted to ON."
)
# if (NOT DEFINED HPX_WITH_FETCH_STDEXEC)
set(HPX_WITH_FETCH_STDEXEC ON)
endif()
elseif(HPX_WITH_STDEXEC)
hpx_error(
"HPX_WITH_STDEXEC is set to ON, but Stdexec_ROOT is not provided and HPX_WITH_FETCH_STDEXEC is not enabled. Please provide Stdexec_ROOT or set HPX_WITH_FETCH_STDEXEC to ON."
)
endif()

# STDEXEC requires C++20
if(HPX_WITH_STDEXEC AND HPX_WITH_CXX_STANDARD LESS 20)
hpx_error(
"HPX_WITH_STDEXEC is set to ON, but HPX_WITH_CXX_STANDARD is less than 20. Please set HPX_WITH_CXX_STANDARD to 20 or higher."
)
endif()

if(HPX_WITH_STDEXEC AND NOT TARGET STDEXEC::stdexec)
hpx_add_config_define(HPX_HAVE_STDEXEC)

if(HPX_WITH_FETCH_STDEXEC)
hpx_info(
"HPX_WITH_FETCH_STDEXEC=${HPX_WITH_FETCH_STDEXEC}, Stdexec will be fetched using CMake's FetchContent and installed alongside HPX (HPX_WITH_STDEXEC_TAG=${HPX_WITH_STDEXEC_TAG})"
)
if(UNIX)
include(FetchContent)
fetchcontent_declare(
Stdexec
GIT_REPOSITORY https://github.com/NVIDIA/stdexec.git
GIT_TAG ${HPX_WITH_STDEXEC_TAG}
)

fetchcontent_getproperties(Stdexec)
if(NOT stdexec_POPULATED)
fetchcontent_populate(Stdexec)
endif()
set(Stdexec_ROOT ${stdexec_SOURCE_DIR})

add_library(Stdexec INTERFACE)
target_include_directories(
Stdexec INTERFACE $<BUILD_INTERFACE:${stdexec_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

install(
TARGETS Stdexec
EXPORT HPXStdexecTarget
COMPONENT core
)

install(
DIRECTORY ${Stdexec_ROOT}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT core
FILES_MATCHING
PATTERN "*.hpp"
)

export(
TARGETS Stdexec
NAMESPACE Stdexec::
FILE "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${HPX_PACKAGE_NAME}/HPXStdexecTarget.cmake"
)

install(
EXPORT HPXStdexecTarget
NAMESPACE Stdexec::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${HPX_PACKAGE_NAME}
COMPONENT cmake
)

add_library(STDEXEC::stdexec ALIAS Stdexec)

# fetchcontent_makeavailable(Stdexec)
endif()

else()
find_package(Stdexec REQUIRED)

if(NOT Stdexec_FOUND)
hpx_error(
"Stdexec could not be found, please specify Stdexec_ROOT to point to the correct location"
)
endif()
endif()
endif()
4 changes: 4 additions & 0 deletions libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ if(HPX_WITH_ITTNOTIFY)
target_link_libraries(hpx_core PUBLIC Amplifier::amplifier)
endif()

if(TARGET STDEXEC::stdexec)
target_link_libraries(hpx_core INTERFACE STDEXEC::stdexec)
endif()

if(HPX_WITH_PARCELPORT_GASNET AND GASNET_LIBRARY_DIRS)
target_link_directories(hpx_core PUBLIC ${GASNET_LIBRARY_DIRS})
endif()
Expand Down
76 changes: 53 additions & 23 deletions libs/core/algorithms/include/hpx/parallel/algorithms/rotate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
// 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)

/// \file hpx/parallel/algorithms/rotate.hpp
/// \page hpx::rotate, hpx::rotate_copy
/// \headerfile hpx/algorithm.hpp
/// \file hpx/parallel/algorithms/rotate.hpp

#pragma once

Expand Down Expand Up @@ -266,27 +265,58 @@ namespace hpx::parallel {

detail::reverse<FwdIter> r;

return hpx::dataflow(
hpx::launch::sync,
[=](auto&& f1, auto&& f2) mutable {
// propagate exceptions, if appropriate
constexpr bool handle_futures =
hpx::traits::is_future_v<decltype((f1))> &&
hpx::traits::is_future_v<decltype((f2))>;

if constexpr (handle_futures)
{
f1.get();
f2.get();
}

r.call(p(hpx::execution::non_task), first, last);

std::advance(first, size_right);
return util::in_out_result<FwdIter, Sent>{first, last};
},
r.call(left_policy, first, new_first),
r.call(right_policy, new_first, last));
auto&& process = [=](auto&& f1, auto&& f2) mutable {
// propagate exceptions, if appropriate
constexpr bool handle_futures =
hpx::traits::is_future_v<decltype((f1))> &&
hpx::traits::is_future_v<decltype((f2))>;

if constexpr (handle_futures)
{
f1.get();
f2.get();
}

r.call(p(hpx::execution::non_task), first, last);

std::advance(first, size_right);
return util::in_out_result<FwdIter, Sent>{first, last};
};

using rcall_left_t =
decltype(r.call(left_policy, first, new_first));
using rcall_right_t =
decltype(r.call(right_policy, new_first, last));

// Sanity check
static_assert(std::is_same_v<rcall_left_t, rcall_right_t>);

constexpr bool handle_senders =
hpx::execution::experimental::is_sender_v<rcall_left_t>;
constexpr bool handle_futures =
hpx::traits::is_future_v<rcall_left_t>;
constexpr bool handle_both = handle_senders && handle_futures;

static_assert(handle_senders || handle_futures,
"the reverse operation must return either a sender or a "
"future");

// Futures pass the concept check for senders, so if something is
// both a future and a sender we treat it as a future.
if constexpr (handle_futures || handle_both)
{
return hpx::dataflow(hpx::launch::sync, std::move(process),
r.call(left_policy, first, new_first),
r.call(right_policy, new_first, last));
}
else if constexpr (handle_senders && !handle_both)
{
return hpx::execution::experimental::then(
hpx::execution::experimental::when_all(
r.call(left_policy, first, new_first),
r.call(right_policy, new_first, last)),
std::move(process));
}
}

template <typename IterPair>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <hpx/algorithm.hpp>
#include <hpx/execution.hpp>
#include <hpx/modules/testing.hpp>
#include <hpx/parallel/algorithms/adjacent_difference.hpp>

#include <cstddef>
#include <iostream>
Expand Down Expand Up @@ -83,8 +84,14 @@ void test_adjacent_difference_sender(Policy l, ExPolicy&& policy)
using scheduler_t = ex::thread_pool_policy_scheduler<Policy>;

auto exec = ex::explicit_scheduler_executor(scheduler_t(l));
#ifdef HPX_HAVE_STDEXEC
auto result =
tt::sync_wait(ex::just(std::begin(c), std::end(c), std::begin(d)) |
hpx::adjacent_difference(policy.on(exec)));
#else
auto result = ex::just(std::begin(c), std::end(c), std::begin(d)) |
hpx::adjacent_difference(policy.on(exec)) | tt::sync_wait();
#endif

std::adjacent_difference(std::begin(c), std::end(c), std::begin(d_ans));

Expand Down Expand Up @@ -131,9 +138,14 @@ void test_adjacent_difference_async_direct(Policy l, ExPolicy&& p)
using scheduler_t = ex::thread_pool_policy_scheduler<Policy>;

auto exec = ex::explicit_scheduler_executor(scheduler_t(l));
#ifdef HPX_HAVE_STDEXEC
auto result = tt::sync_wait(hpx::adjacent_difference(
p.on(exec), std::begin(c), std::end(c), std::begin(d)));
#else
auto result = hpx::adjacent_difference(
p.on(exec), std::begin(c), std::end(c), std::begin(d)) |
tt::sync_wait();
#endif
std::adjacent_difference(std::begin(c), std::end(c), std::begin(d_ans));

HPX_TEST(std::equal(std::begin(d), std::end(d), std::begin(d_ans),
Expand Down
12 changes: 11 additions & 1 deletion libs/core/algorithms/tests/unit/algorithms/find_tests.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,15 @@ void test_find_explicit_sender(Policy l, ExPolicy&& policy, IteratorTag)
using scheduler_t = ex::thread_pool_policy_scheduler<Policy>;

auto exec = ex::explicit_scheduler_executor(scheduler_t(l));
#ifdef HPX_HAVE_STDEXEC
auto result = tt::sync_wait(
ex::just(iterator(std::begin(c)), iterator(std::end(c)), int(1)) |
hpx::find(policy.on(exec)));
#else
auto result =
ex::just(iterator(std::begin(c)), iterator(std::end(c)), int(1)) |
hpx::find(policy.on(exec)) | tt::sync_wait();
#endif

base_iterator test_index = std::begin(c) + c.size() / 2;

Expand Down Expand Up @@ -170,10 +176,14 @@ void test_find_explicit_sender_direct_async(Policy l, ExPolicy&& p, IteratorTag)
using scheduler_t = ex::thread_pool_policy_scheduler<Policy>;

auto exec = ex::explicit_scheduler_executor(scheduler_t(l));
#ifdef HPX_HAVE_STDEXEC
auto result = tt::sync_wait(hpx::find(
p.on(exec), iterator(std::begin(c)), iterator(std::end(c)), int(1)));
#else
auto result = hpx::find(p.on(exec), iterator(std::begin(c)),
iterator(std::end(c)), int(1)) |
tt::sync_wait();

#endif
// create iterator at position of value to be found
base_iterator test_index = std::begin(c) + c.size() / 2;

Expand Down
Loading

0 comments on commit dceb6c4

Please sign in to comment.