Skip to content

Commit

Permalink
Merge pull request #2202 from Sanac/seg_fill
Browse files Browse the repository at this point in the history
Added segmented fill for hpx::vector
  • Loading branch information
hkaiser committed Jun 15, 2016
2 parents 8e0050c + b19fee6 commit df35195
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 9 deletions.
1 change: 1 addition & 0 deletions hpx/include/parallel_fill.hpp
Expand Up @@ -8,6 +8,7 @@
#define HPX_PARALLEL_FILL_JUL_07_2014_1222PM

#include <hpx/parallel/algorithms/fill.hpp>
#include <hpx/parallel/segmented_algorithms/fill.hpp>

#endif

46 changes: 37 additions & 9 deletions hpx/parallel/algorithms/fill.hpp
Expand Up @@ -13,14 +13,15 @@
#include <hpx/traits/is_value_proxy.hpp>
#include <hpx/util/void_guard.hpp>

#include <hpx/parallel/algorithms/for_each.hpp>
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
#include <hpx/parallel/algorithms/detail/is_negative.hpp>
#include <hpx/parallel/algorithms/for_each.hpp>
#include <hpx/parallel/config/inline_namespace.hpp>
#include <hpx/parallel/execution_policy.hpp>
#include <hpx/parallel/util/detail/algorithm_result.hpp>
#include <hpx/parallel/util/projection_identity.hpp>


#include <algorithm>
#include <iterator>
#include <type_traits>
Expand Down Expand Up @@ -94,9 +95,36 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1)
util::projection_identity());
}
};

template <typename ExPolicy, typename InIter, typename T>
static typename util::detail::algorithm_result<
ExPolicy, void
>::type
fill_(ExPolicy && policy, InIter first, InIter last, T const& value,
std::false_type)
{

typedef std::integral_constant<bool,
parallel::is_sequential_execution_policy<ExPolicy>::value ||
!hpx::traits::is_forward_iterator<InIter>::value
> is_seq;

return detail::fill().call(
std::forward<ExPolicy>(policy), is_seq(),
first, last, value);
}

// forward declare the segmented version of this algorithm
template <typename ExPolicy, typename InIter, typename T>
static typename util::detail::algorithm_result<
ExPolicy, void
>::type
fill_(ExPolicy && policy, InIter first, InIter last, T const& value,
std::true_type);
/// \endcond
}


/// Assigns the given value to the elements in the range [first, last).
///
/// \note Complexity: Performs exactly \a last - \a first assignments.
Expand Down Expand Up @@ -142,16 +170,16 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1)
>::type
fill(ExPolicy && policy, InIter first, InIter last, T value)
{
static_assert(
(hpx::traits::is_forward_iterator<InIter>::value),
"Requires at least forward iterator.");

typedef is_sequential_execution_policy<ExPolicy> is_seq;
typedef hpx::traits::is_segmented_iterator<InIter> is_segmented;

return detail::fill().call(
std::forward<ExPolicy>(policy), is_seq(),
first, last, value);
return detail::fill_(
std::forward<ExPolicy>(policy), first, last, value,
is_segmented()
);
}



///////////////////////////////////////////////////////////////////////////
// fill_n
namespace detail
Expand Down
82 changes: 82 additions & 0 deletions hpx/parallel/segmented_algorithms/fill.hpp
@@ -0,0 +1,82 @@
// Copyright (c) 2016 Minh-Khanh Do
//
// 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 !defined(HPX_PARALLEL_SEGMENTED_ALGORITHM_FILL_MAY_30_2016)
#define HPX_PARALLEL_SEGMENTED_ALGORITHM_FILL_MAY_30_2016

#include <hpx/config.hpp>

#include <hpx/parallel/config/inline_namespace.hpp>
#include <hpx/parallel/execution_policy.hpp>
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
#include <hpx/parallel/util/detail/algorithm_result.hpp>
#include <hpx/parallel/segmented_algorithms/for_each.hpp>

#include <boost/exception_ptr.hpp>

#include <algorithm>
#include <iterator>
#include <list>
#include <type_traits>
#include <vector>


namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1)
{
///////////////////////////////////////////////////////////////////////////
// segmented_fill
namespace detail
{
///////////////////////////////////////////////////////////////////////
/// \cond NOINTERNAL

template<typename T>
struct fill_function
{
fill_function(T val = T()) : value_(val) {}

T value_;

void operator()(T& val) const
{
val = value_;
}

template <typename Archive>
void serialize(Archive& ar, unsigned version)
{
ar & value_;
}
};

///////////////////////////////////////////////////////////////////////
// segmented implementation
template <typename ExPolicy, typename InIter, typename T>
static typename util::detail::algorithm_result<
ExPolicy, void
>::type
fill_(ExPolicy && policy, InIter first, InIter last, T const& value,
std::true_type)
{
typedef typename util::detail::algorithm_result<
ExPolicy, void
>::type result_type;

return hpx::util::void_guard<result_type>(),
hpx::parallel::for_each(std::forward<ExPolicy>(policy),
first, last, fill_function<T>(value));
}

// forward declare the non-segmented version of this algorithm
template <typename ExPolicy, typename InIter, typename T>
static typename util::detail::algorithm_result<
ExPolicy, void>::type
fill_(ExPolicy && policy, InIter first, InIter last, T const& value,
std::false_type);
}
/// \endcond
}}}

#endif
1 change: 1 addition & 0 deletions tests/unit/component/CMakeLists.txt
Expand Up @@ -28,6 +28,7 @@ set(tests
partitioned_vector_iter
partitioned_vector_move
partitioned_vector_transform_reduce
partitioned_vector_fill
)

# add executable needed for launch_process_test
Expand Down
142 changes: 142 additions & 0 deletions tests/unit/component/partitioned_vector_fill.cpp
@@ -0,0 +1,142 @@
// Copyright (c) 2014-2015 Hartmut Kaiser
//
// 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 <hpx/hpx_main.hpp>
#include <hpx/include/partitioned_vector.hpp>
#include <hpx/include/parallel_fill.hpp>

#include <hpx/util/lightweight_test.hpp>

#include <vector>

///////////////////////////////////////////////////////////////////////////////
// Define the vector types to be used.
HPX_REGISTER_PARTITIONED_VECTOR(double);
HPX_REGISTER_PARTITIONED_VECTOR(int);

///////////////////////////////////////////////////////////////////////////////
template <typename T>
void iota_vector(hpx::partitioned_vector<T>& v, T val)
{
typename hpx::partitioned_vector<T>::iterator it = v.begin(), end = v.end();
for(/**/; it != end; ++it)
*it = val++;
}

///////////////////////////////////////////////////////////////////////////////
template <typename T, typename InIter>
void verify_values(InIter first, InIter last, T const& val,
bool must_be_equal = true)
{
for (InIter it = first; it != last; ++it)
{
if(must_be_equal)
{
HPX_TEST_EQ(*it, val);
}
else
{
HPX_TEST_NEQ(*it, val);
}
}
}

///////////////////////////////////////////////////////////////////////////////
template <typename T>
void verify_vector(hpx::partitioned_vector<T> const& v, T const& val,
bool must_be_equal = true)
{
typedef typename hpx::partitioned_vector<T>::const_iterator const_iterator;

std::size_t size = 0;

const_iterator end = v.end();
for (const_iterator it = v.begin(); it != end; ++it, ++size)
{
HPX_TEST_EQ(*it, val);
}

HPX_TEST_EQ(size, v.size());
}

///////////////////////////////////////////////////////////////////////////////
template <typename T, typename DistPolicy, typename ExPolicy>
void fill_algo_tests_with_policy(std::size_t size,
DistPolicy const& policy, ExPolicy const& fill_policy)
{
hpx::partitioned_vector<T> c(size, policy);
iota_vector(c, T(1234));

const T v(42);
hpx::parallel::fill(fill_policy, c.begin(), c.end(), v);
verify_vector(c, v);

const T v1(43);
hpx::parallel::fill(fill_policy, c.begin()+1, c.end()-1, v1);
verify_values(c.begin()+1, c.end()-1, v1);
verify_values(c.begin(), c.begin()+1, v1, false);
verify_values(c.end()-1, c.end(), v1, false);
}

template <typename T, typename DistPolicy, typename ExPolicy>
void fill_algo_tests_with_policy_async(std::size_t size,
DistPolicy const& policy, ExPolicy const& fill_policy)
{
hpx::partitioned_vector<T> c(size, policy);
iota_vector(c, T(1234));

const T v(42);
hpx::future<void> f = hpx::parallel::fill(fill_policy, c.begin(), c.end(), v);
f.wait();

verify_vector(c, v);

const T v1(43);
hpx::future<void> f1 = hpx::parallel::fill(fill_policy, c.begin()+1, c.end()-1, v1);
f1.wait();

verify_values(c.begin()+1, c.end()-1, v1);
verify_values(c.begin(), c.begin()+1, v1, false);
verify_values(c.end()-1, c.end(), v1, false);
}

template <typename T, typename DistPolicy>
void fill_tests_with_policy(std::size_t size, std::size_t localities,
DistPolicy const& policy)
{
using namespace hpx::parallel;
using hpx::parallel::task;

fill_algo_tests_with_policy<T>(size, policy, seq);
fill_algo_tests_with_policy<T>(size, policy, par);

//async
fill_algo_tests_with_policy_async<T>(size, policy, seq(task));
fill_algo_tests_with_policy_async<T>(size, policy, par(task));
}

template <typename T>
void fill_tests()
{
std::size_t const length = 12;
std::vector<hpx::id_type> localities = hpx::find_all_localities();

fill_tests_with_policy<T>(length, 1, hpx::container_layout);
fill_tests_with_policy<T>(length, 3, hpx::container_layout(3));
fill_tests_with_policy<T>(length, 3, hpx::container_layout(3, localities));
fill_tests_with_policy<T>(length, localities.size(),
hpx::container_layout(localities));
}


///////////////////////////////////////////////////////////////////////////////
int main()
{
fill_tests<double>();
fill_tests<int>();

return 0;
}

0 comments on commit df35195

Please sign in to comment.