Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt datapar generate #5594

Merged
merged 11 commits into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libs/core/algorithms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ set(algorithms_headers
hpx/parallel/algorithms/detail/distance.hpp
hpx/parallel/algorithms/detail/fill.hpp
hpx/parallel/algorithms/detail/find.hpp
hpx/parallel/algorithms/detail/generate.hpp
hpx/parallel/algorithms/detail/indirect.hpp
hpx/parallel/algorithms/detail/insertion_sort.hpp
hpx/parallel/algorithms/detail/is_sorted.hpp
Expand Down Expand Up @@ -149,6 +150,7 @@ set(algorithms_headers
hpx/parallel/container_numeric.hpp
hpx/parallel/datapar.hpp
hpx/parallel/datapar/fill.hpp
hpx/parallel/datapar/generate.hpp
hpx/parallel/datapar/adjacent_difference.hpp
hpx/parallel/datapar/iterator_helpers.hpp
hpx/parallel/datapar/loop.hpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) 2021 Srinivas Yadav
//
// 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 <hpx/config.hpp>
#include <hpx/executors/execution_policy.hpp>
#include <hpx/functional/detail/tag_fallback_invoke.hpp>
#include <hpx/parallel/util/loop.hpp>

#include <algorithm>
#include <cstddef>
#include <utility>

namespace hpx { namespace parallel { inline namespace v1 { namespace detail {

///////////////////////////////////////////////////////////////////////////
template <typename Iter, typename Sent, typename F>
constexpr Iter sequential_generate_helper(Iter first, Sent last, F&& f)
{
return util::loop_ind(hpx::execution::seq, first, last,
[f = std::forward<F>(f)](auto& v) mutable { v = f(); });
}

struct sequential_generate_t
: hpx::functional::detail::tag_fallback<sequential_generate_t>
{
private:
template <typename ExPolicy, typename Iter, typename Sent, typename F>
friend constexpr Iter tag_fallback_invoke(
sequential_generate_t, ExPolicy&&, Iter first, Sent last, F&& f)
{
return sequential_generate_helper(first, last, std::forward<F>(f));
}
};

#if !defined(HPX_COMPUTE_DEVICE_CODE)
HPX_INLINE_CONSTEXPR_VARIABLE sequential_generate_t sequential_generate =
sequential_generate_t{};
#else
template <typename ExPolicy, typename Iter, typename Sent, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE Iter sequential_generate(
ExPolicy&& policy, Iter first, Sent last, F&& f)
{
return sequential_generate_t{}(
std::forward<ExPolicy>(policy), first, last, std::forward<F>(f));
}
#endif

///////////////////////////////////////////////////////////////////////////
template <typename Iter, typename F>
constexpr Iter sequential_generate_n_helper(
Iter first, std::size_t count, F&& f)
{
return std::generate_n(first, count, f);
}

struct sequential_generate_n_t
: hpx::functional::detail::tag_fallback<sequential_generate_n_t>
{
private:
template <typename ExPolicy, typename Iter, typename F>
friend constexpr Iter tag_fallback_invoke(sequential_generate_n_t,
ExPolicy&&, Iter first, std::size_t count, F&& f)
{
return sequential_generate_n_helper(
first, count, std::forward<F>(f));
}
};

#if !defined(HPX_COMPUTE_DEVICE_CODE)
HPX_INLINE_CONSTEXPR_VARIABLE sequential_generate_n_t
sequential_generate_n = sequential_generate_n_t{};
#else
template <typename ExPolicy, typename Iter, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE Iter sequential_generate_n(
ExPolicy&& policy, Iter first, std::size_t count, F&& f)
{
return sequential_generate_n_t{}(
std::forward<ExPolicy>(policy), first, count, std::forward<F>(f));
}
#endif

}}}} // namespace hpx::parallel::v1::detail
62 changes: 36 additions & 26 deletions libs/core/algorithms/include/hpx/parallel/algorithms/generate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,34 +135,28 @@ namespace hpx {

#include <hpx/execution/algorithms/detail/is_negative.hpp>
#include <hpx/executors/execution_policy.hpp>
#include <hpx/parallel/algorithms/detail/advance_to_sentinel.hpp>
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
#include <hpx/parallel/algorithms/detail/distance.hpp>
#include <hpx/parallel/algorithms/detail/generate.hpp>
#include <hpx/parallel/algorithms/for_each.hpp>
#include <hpx/parallel/util/detail/algorithm_result.hpp>
#include <hpx/parallel/util/partitioner.hpp>
#include <hpx/parallel/util/projection_identity.hpp>

#include <algorithm>
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <utility>
#include <vector>

namespace hpx { namespace parallel { inline namespace v1 {

///////////////////////////////////////////////////////////////////////////
// generate
namespace detail {

template <typename Iter, typename Sent, typename F>
constexpr Iter sequential_generate(Iter first, Sent last, F&& f)
{
while (first != last)
{
*first++ = f();
}
return first;
}

template <typename FwdIter>
struct generate : public detail::algorithm<generate<FwdIter>, FwdIter>
{
Expand All @@ -174,23 +168,31 @@ namespace hpx { namespace parallel { inline namespace v1 {
template <typename ExPolicy, typename Iter, typename Sent,
typename F>
static constexpr Iter sequential(
ExPolicy, Iter first, Sent last, F&& f)
ExPolicy&& policy, Iter first, Sent last, F&& f)
{
return sequential_generate(first, last, std::forward<F>(f));
return sequential_generate(std::forward<ExPolicy>(policy),
first, last, std::forward<F>(f));
}

template <typename ExPolicy, typename Iter, typename Sent,
typename F>
static typename util::detail::algorithm_result<ExPolicy, Iter>::type
parallel(ExPolicy&& policy, Iter first, Sent last, F&& f)
{
using type = typename std::iterator_traits<Iter>::value_type;

return for_each_n<Iter>().call(
auto f1 = [policy = std::forward<ExPolicy>(policy),
f = std::forward<F>(f)](
Iter part_begin, std::size_t part_size) mutable {
auto part_end = part_begin;
std::advance(part_end, part_size);
return sequential_generate(std::forward<ExPolicy>(policy),
part_begin, part_end, std::forward<F>(f));
};
return util::partitioner<ExPolicy, Iter>::call(
std::forward<ExPolicy>(policy), first,
detail::distance(first, last),
[f = std::forward<F>(f)](type& v) mutable { v = f(); },
util::projection_identity());
detail::distance(first, last), std::move(f1),
[first, last](std::vector<hpx::future<Iter>>&&) {
return detail::advance_to_sentinel(first, last);
});
}
};
} // namespace detail
Expand Down Expand Up @@ -236,9 +238,10 @@ namespace hpx { namespace parallel { inline namespace v1 {

template <typename ExPolicy, typename InIter, typename F>
static FwdIter sequential(
ExPolicy, InIter first, std::size_t count, F&& f)
ExPolicy&& policy, InIter first, std::size_t count, F&& f)
{
return std::generate_n(first, count, f);
return sequential_generate_n(
std::forward<ExPolicy>(policy), first, count, f);
}

template <typename ExPolicy, typename F>
Expand All @@ -247,12 +250,19 @@ namespace hpx { namespace parallel { inline namespace v1 {
parallel(
ExPolicy&& policy, FwdIter first, std::size_t count, F&& f)
{
typedef typename std::iterator_traits<FwdIter>::value_type type;

return for_each_n<FwdIter>().call(
std::forward<ExPolicy>(policy), first, count,
[f = std::forward<F>(f)](type& v) mutable { v = f(); },
util::projection_identity());
auto f1 = [policy = std::forward<ExPolicy>(policy),
f = std::forward<F>(f)](FwdIter part_begin,
std::size_t part_size) mutable {
return sequential_generate_n(std::forward<ExPolicy>(policy),
part_begin, part_size, std::forward<F>(f));
};
return util::partitioner<ExPolicy, FwdIter>::call(
std::forward<ExPolicy>(policy), first, count, std::move(f1),
[first, count](
std::vector<hpx::future<FwdIter>>&&) mutable {
std::advance(first, count);
return first;
});
}
};
} // namespace detail
Expand Down
1 change: 1 addition & 0 deletions libs/core/algorithms/include/hpx/parallel/datapar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <hpx/executors/datapar/execution_policy.hpp>
#include <hpx/parallel/datapar/adjacent_difference.hpp>
#include <hpx/parallel/datapar/fill.hpp>
#include <hpx/parallel/datapar/generate.hpp>
#include <hpx/parallel/datapar/iterator_helpers.hpp>
#include <hpx/parallel/datapar/loop.hpp>
#include <hpx/parallel/datapar/transfer.hpp>
Expand Down
127 changes: 127 additions & 0 deletions libs/core/algorithms/include/hpx/parallel/datapar/generate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright (c) 2021 Srinivas Yadav
//
// 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 <hpx/config.hpp>

#if defined(HPX_HAVE_DATAPAR)
#include <hpx/execution/traits/is_execution_policy.hpp>
#include <hpx/execution/traits/vector_pack_alignment_size.hpp>
#include <hpx/execution/traits/vector_pack_type.hpp>
#include <hpx/functional/tag_invoke.hpp>
#include <hpx/parallel/algorithms/detail/generate.hpp>
#include <hpx/parallel/datapar/iterator_helpers.hpp>
#include <hpx/parallel/datapar/loop.hpp>
#include <hpx/parallel/util/result_types.hpp>

#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <utility>

namespace hpx { namespace parallel { inline namespace v1 { namespace detail {

template <typename Iterator>
struct datapar_generate_helper
{
using iterator_type = std::decay_t<Iterator>;
using value_type = std::iterator_traits<iterator_type>::value_type;
using V = hpx::parallel::traits::vector_pack_type<value_type>::type;

static constexpr std::size_t size = traits::vector_pack_size<V>::value;

template <typename Iter, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE static typename std::enable_if_t<
hpx::parallel::util::detail::iterator_datapar_compatible<
Iter>::value,
Iter>
call(Iter first, std::size_t count, F&& f)
{
std::size_t len = count;
for (; !hpx::parallel::util::detail::is_data_aligned(first) &&
len != 0;
--len)
{
*first++ = f.template operator()<value_type>();
}

for (std::int64_t len_v = std::int64_t(len - (size + 1)); len_v > 0;
len_v -= size, len -= size)
{
auto tmp = f.template operator()<V>();
traits::vector_pack_store<V, value_type>::aligned(tmp, first);
std::advance(first, size);
}

for (/* */; len != 0; --len)
{
*first++ = f.template operator()<value_type>();
}
return first;
}

template <typename Iter, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE static typename std::enable_if_t<
!hpx::parallel::util::detail::iterator_datapar_compatible<
Iter>::value,
Iter>
call(Iter first, std::size_t count, F&& f)
{
while (count--)
{
*first++ = f.template operator()<value_type>();
}
return first;
}
};

///////////////////////////////////////////////////////////////////////////
struct datapar_generate
{
template <typename ExPolicy, typename Iter, typename Sent, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE static Iter call(
ExPolicy&&, Iter first, Sent last, F&& f)
{
std::size_t count = std::distance(first, last);
return datapar_generate_helper<Iter>::call(
first, count, std::forward<F>(f));
}
};

template <typename ExPolicy, typename Iter, typename Sent, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE typename std::enable_if<
hpx::is_vectorpack_execution_policy<ExPolicy>::value, Iter>::type
tag_invoke(
sequential_generate_t, ExPolicy&& policy, Iter first, Sent last, F&& f)
{
return datapar_generate::call(
std::forward<ExPolicy>(policy), first, last, std::forward<F>(f));
}

///////////////////////////////////////////////////////////////////////////
struct datapar_generate_n
{
template <typename ExPolicy, typename Iter, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE static Iter call(
ExPolicy&&, Iter first, std::size_t count, F&& f)
{
return datapar_generate_helper<Iter>::call(
first, count, std::forward<F>(f));
}
};

template <typename ExPolicy, typename Iter, typename F>
HPX_HOST_DEVICE HPX_FORCEINLINE typename std::enable_if<
hpx::is_vectorpack_execution_policy<ExPolicy>::value, Iter>::type
tag_invoke(sequential_generate_n_t, ExPolicy&& policy, Iter first,
std::size_t count, F&& f)
{
return datapar_generate_n::call(
std::forward<ExPolicy>(policy), first, count, std::forward<F>(f));
}
}}}} // namespace hpx::parallel::v1::detail
#endif
Loading