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

Fix Segmentation fault on foreach_datapar_zipiter #5281

Merged
merged 10 commits into from Apr 16, 2021
Expand Up @@ -33,7 +33,7 @@ namespace hpx { namespace parallel { namespace util { namespace detail {
typedef typename std::iterator_traits<Iter>::value_type value_type;
return (reinterpret_cast<std::uintptr_t>(std::addressof(*it)) &
(traits::vector_pack_alignment<value_type>::value -
1)) != 0;
1)) == 0;
msimberg marked this conversation as resolved.
Show resolved Hide resolved
}
};

Expand Down Expand Up @@ -304,7 +304,7 @@ namespace hpx { namespace parallel { namespace util { namespace detail {
typename hpx::util::invoke_result<F, V1*, V2*>::type
callv(F&& f, Iter1& it1, Iter2& it2)
{
if (is_data_aligned(it1) || is_data_aligned(it2))
if (!is_data_aligned(it1) || !is_data_aligned(it2))
{
return invoke_vectorized_in2<V1, V2>::call_unaligned(
std::forward<F>(f), it1, it2);
Expand Down Expand Up @@ -452,7 +452,7 @@ namespace hpx { namespace parallel { namespace util { namespace detail {

typedef typename traits::vector_pack_type<value_type>::type V;

if (is_data_aligned(it) || is_data_aligned(dest))
if (!is_data_aligned(it) || !is_data_aligned(dest))
{
invoke_vectorized_inout1<V>::call_unaligned(
std::forward<F>(f), it, dest);
Expand All @@ -477,8 +477,8 @@ namespace hpx { namespace parallel { namespace util { namespace detail {
typedef typename traits::vector_pack_type<value1_type>::type V1;
typedef typename traits::vector_pack_type<value2_type>::type V2;

if (is_data_aligned(it1) || is_data_aligned(it2) ||
is_data_aligned(dest))
if (!is_data_aligned(it1) || !is_data_aligned(it2) ||
!is_data_aligned(dest))
{
invoke_vectorized_inout2<V1, V2>::call_unaligned(
std::forward<F>(f), it1, it2, dest);
Expand Down
Expand Up @@ -124,7 +124,7 @@ namespace hpx { namespace parallel { namespace util {
iterator_datapar_compatible<Begin>::value, Begin>::type
call(Begin first, End last, F&& f)
{
while (is_data_aligned(first) && first != last)
while (!is_data_aligned(first) && first != last)
{
datapar_loop_step<Begin>::call1(f, first);
}
Expand Down Expand Up @@ -182,8 +182,8 @@ namespace hpx { namespace parallel { namespace util {

typedef typename traits::vector_pack_type<value_type>::type V;

if (detail::is_data_aligned(it1) ||
detail::is_data_aligned(it2))
if (!detail::is_data_aligned(it1) ||
!detail::is_data_aligned(it2))
{
return std::make_pair(std::move(it1), std::move(it2));
}
Expand Down Expand Up @@ -244,16 +244,16 @@ namespace hpx { namespace parallel { namespace util {
{
std::size_t len = count;

for (/* */; detail::is_data_aligned(first) && len != 0; --len)
for (/* */; !detail::is_data_aligned(first) && len != 0; --len)
{
datapar_loop_step<InIter>::call1(f, first);
}

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

for (std::int64_t lenV = std::int64_t(count - (size + 1));
lenV > 0; lenV -= size, len -= size)
for (std::int64_t len_v = std::int64_t(len - (size + 1));
len_v > 0; len_v -= size, len -= size)
{
datapar_loop_step<InIter>::callv(f, first);
}
Expand Down
Expand Up @@ -47,16 +47,16 @@ namespace hpx { namespace parallel { namespace util {
{
std::size_t len = count;

for (/* */; is_data_aligned(first) && len != 0; --len)
for (/* */; !is_data_aligned(first) && len != 0; --len)
{
datapar_transform_loop_step::call1(f, first, dest);
}

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

for (std::int64_t lenV = std::int64_t(count - (size + 1));
lenV > 0; lenV -= size, len -= size)
for (std::int64_t len_v = std::int64_t(len - (size + 1));
len_v > 0; len_v -= size, len -= size)
{
datapar_transform_loop_step::callv(f, first, dest);
}
Expand Down Expand Up @@ -174,16 +174,16 @@ namespace hpx { namespace parallel { namespace util {
{
std::size_t len = count;

for (/* */; is_data_aligned(first1) && len != 0; --len)
for (/* */; !is_data_aligned(first1) && len != 0; --len)
{
datapar_transform_loop_step::call1(f, first1, first2, dest);
}

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

for (std::int64_t lenV = std::int64_t(count - (size + 1));
lenV > 0; lenV -= size, len -= size)
for (std::int64_t len_v = std::int64_t(len - (size + 1));
len_v > 0; len_v -= size, len -= size)
{
datapar_transform_loop_step::callv(f, first1, first2, dest);
}
Expand Down
Expand Up @@ -8,6 +8,7 @@ set(tests
count_3646
fill_executor_5016
for_each_annotated_function
for_each_datapar
for_loop_2281
minimal_findend
reduce_3641
Expand Down
54 changes: 54 additions & 0 deletions libs/parallelism/algorithms/tests/regressions/for_each_datapar.cpp
@@ -0,0 +1,54 @@
#include <hpx/algorithm.hpp>
msimberg marked this conversation as resolved.
Show resolved Hide resolved
#include <hpx/hpx.hpp>
#include <hpx/hpx_init.hpp>
#include <hpx/modules/testing.hpp>

#include <algorithm>
#include <iterator>
#include <numeric>
#include <string>
#include <vector>

template <typename ExPolicy>
void test_for_each(ExPolicy&& policy)
{
std::vector<int> c(1027);
// this test ensures that aligned is working properly for various inputs
for (size_t first = 0; first < c.size(); ++first)
hpx::for_each(policy, std::begin(c) + first, std::end(c),
[](auto& val) { ++val; });

std::size_t count = 0;
int ans = 0;
std::for_each(std::begin(c), std::end(c), [&count, &ans](int v) -> void {
HPX_TEST_EQ(v, ++ans);
++count;
});
HPX_TEST_EQ(count, c.size());
}

void for_each_test()
{
using namespace hpx::execution;
test_for_each(dataseq);
test_for_each(datapar);
}

int hpx_main()
{
for_each_test();
return hpx::finalize();
}

int main(int argc, char* argv[])
{
std::vector<std::string> const cfg = {"hpx.os_threads=all"};

hpx::init_params init_args;
init_args.cfg = cfg;

HPX_TEST_EQ_MSG(hpx::init(argc, argv, init_args), 0,
"HPX main exited with non-zero status");

return hpx::util::report_errors();
}