Skip to content

Commit

Permalink
Add for_each_n algorithm to shp and mhp (oneapi-src#786)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xewar313 authored Jul 9, 2024
1 parent 927be4f commit e305efe
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
9 changes: 9 additions & 0 deletions include/dr/mhp/algorithms/for_each.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,13 @@ void for_each(DI first, DI last, auto op) {
mhp::for_each(rng::subrange(first, last), op);
}

/// Collective for_each on iterator/sentinel for a distributed range
template <dr::distributed_iterator DI, std::integral I>
DI for_each_n(DI first, I n, auto op) {
auto last = first;
rng::advance(last, n);
mhp::for_each(first, last, op);
return last;
}

} // namespace dr::mhp
15 changes: 15 additions & 0 deletions include/dr/shp/algorithms/for_each.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,19 @@ void for_each(Iter begin, Iter end, Fn &&fn) {
for_each(dr::shp::par_unseq, begin, end, std::forward<Fn>(fn));
}

template <typename ExecutionPolicy, dr::distributed_iterator Iter,
std::integral I, typename Fn>
Iter for_each_n(ExecutionPolicy &&policy, Iter begin, I n, Fn fn) {
auto end = begin;
rng::advance(end, n);
for_each(std::forward<ExecutionPolicy>(policy), begin, end,
std::forward<Fn>(fn));
return end;
}

template <dr::distributed_iterator Iter, std::integral I, typename Fn>
Iter for_each_n(Iter &&r, I n, Fn fn) {
return for_each_n(dr::shp::par_unseq, std::forward<Iter>(r), n, fn);
}

} // namespace dr::shp
43 changes: 43 additions & 0 deletions test/gtest/common/for_each.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ template <typename T> class ForEach : public testing::Test {
public:
};

template <typename T>
void test_foreach_n(std::vector<T> v, int n, int initial_skip, auto func) {
auto size = v.size();
xhp::distributed_vector<T> d_v(size);

for (std::size_t idx = 0; idx < size; idx++) {
d_v[idx] = v[idx];
}
barrier();

xhp::for_each_n(d_v.begin() + initial_skip, n, func);
rng::for_each_n(v.begin() + initial_skip, n, func);

EXPECT_TRUE(equal(v, d_v));
}

TYPED_TEST_SUITE(ForEach, AllTypes);

TYPED_TEST(ForEach, Range) {
Expand Down Expand Up @@ -45,6 +61,33 @@ TYPED_TEST(ForEach, RangeAlignedZip) {
EXPECT_EQ(local, dist);
}

TYPED_TEST(ForEach, ForEachN) {
auto negate = [](auto &&v) { v = -v; };
test_foreach_n<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 5, 0, negate);
}

TYPED_TEST(ForEach, ForEachNLongerThanSize) {
auto negate = [](auto &&v) { v = -v; };
test_foreach_n<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 10, 0, negate);
}

TYPED_TEST(ForEach, ForEachNPartial) {
auto negate = [](auto &&v) { v = -v; };
test_foreach_n<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 5, 2, negate);
}

TYPED_TEST(ForEach, ForEachNWholeLength) {
Ops1<TypeParam> ops(10);

auto negate = [](auto &&v) { v = -v; };
auto input = ops.vec;

xhp::for_each_n(ops.dist_vec.begin(), 10, negate);
rng::for_each(ops.vec.begin(), ops.vec.end(), negate);

EXPECT_TRUE(check_unary_op(input, ops.vec, ops.dist_vec));
}

// Disabled. Not sure how to support this properly for MHP. We need to
// copy the values local so we can operate on them. Read-only data
// seems doable but writing misaligned data is harder. We should
Expand Down

0 comments on commit e305efe

Please sign in to comment.