Skip to content

Commit

Permalink
improve tests with intra-team result check
Browse files Browse the repository at this point in the history
  • Loading branch information
fnrizzi committed Sep 13, 2023
1 parent 7d9394d commit 541f674
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 49 deletions.
23 changes: 23 additions & 0 deletions algorithms/unit_tests/TestStdAlgorithmsCommon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,29 @@ auto create_deep_copyable_compatible_clone(ViewType view) {
// others
//

template <class TeamHandleType, class ValueType1, class ValueType2>
KOKKOS_FUNCTION bool team_members_have_matching_result(
const TeamHandleType& teamHandle, const ValueType1 memberValueIn,
const ValueType2 targetIn) {
using T = std::common_type_t<ValueType1, ValueType2>;
const T memberValue = memberValueIn;
const T target = targetIn;

// set accum to 1 if a mismach is found
const bool mismatch = memberValue != target;
int accum = static_cast<int>(mismatch);
// FIXME_OPENMPTARGET: team API does not meet the TeamHandle concept and
// ignores the reducer passed
#if defined KOKKOS_ENABLE_OPENMPTARGET
Kokkos::Sum<int> dummyReducer(accum);
const auto result = teamHandle.team_reduce(accum, dummyReducer);
return (result == 0);
#else
teamHandle.team_reduce(Kokkos::Sum<int>(accum));
return (accum == 0);
#endif
}

template <class ValueType1, class ValueType2>
auto make_bounds(const ValueType1& lower, const ValueType2 upper) {
return Kokkos::pair<ValueType1, ValueType2>{lower, upper};
Expand Down
43 changes: 31 additions & 12 deletions algorithms/unit_tests/TestStdAlgorithmsTeamAdjacentFind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,22 @@ struct IsEqualFunctor {
}
};

template <class DataViewType, class DistancesViewType, class BinaryPredType>
template <class DataViewType, class DistancesViewType,
class IntraTeamSentinelView, class BinaryPredType>
struct TestFunctorA {
DataViewType m_dataView;
DistancesViewType m_distancesView;
IntraTeamSentinelView m_intraTeamSentinelView;
int m_apiPick;
BinaryPredType m_binaryPred;

TestFunctorA(const DataViewType dataView,
const DistancesViewType distancesView, int apiPick,
const DistancesViewType distancesView,
const IntraTeamSentinelView intraTeamSentinelView, int apiPick,
BinaryPredType binaryPred)
: m_dataView(dataView),
m_distancesView(distancesView),
m_intraTeamSentinelView(intraTeamSentinelView),
m_apiPick(apiPick),
m_binaryPred(binaryPred) {}

Expand All @@ -50,23 +54,24 @@ struct TestFunctorA {
const auto myRowIndex = member.league_rank();

auto myRowViewFrom = Kokkos::subview(m_dataView, myRowIndex, Kokkos::ALL());
ptrdiff_t resultDist = 0;

switch (m_apiPick) {
case 0: {
const auto it = KE::adjacent_find(member, KE::cbegin(myRowViewFrom),
KE::cend(myRowViewFrom));
resultDist = KE::distance(KE::cbegin(myRowViewFrom), it);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_distancesView(myRowIndex) =
KE::distance(KE::cbegin(myRowViewFrom), it);
m_distancesView(myRowIndex) = resultDist;
});
break;
}

case 1: {
const auto it = KE::adjacent_find(member, myRowViewFrom);
resultDist = KE::distance(KE::begin(myRowViewFrom), it);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_distancesView(myRowIndex) =
KE::distance(KE::begin(myRowViewFrom), it);
m_distancesView(myRowIndex) = resultDist;
});
break;
}
Expand All @@ -75,22 +80,31 @@ struct TestFunctorA {
const auto it =
KE::adjacent_find(member, KE::cbegin(myRowViewFrom),
KE::cend(myRowViewFrom), m_binaryPred);
resultDist = KE::distance(KE::cbegin(myRowViewFrom), it);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_distancesView(myRowIndex) =
KE::distance(KE::cbegin(myRowViewFrom), it);
m_distancesView(myRowIndex) = resultDist;
});
break;
}

case 3: {
const auto it = KE::adjacent_find(member, myRowViewFrom, m_binaryPred);
resultDist = KE::distance(KE::begin(myRowViewFrom), it);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_distancesView(myRowIndex) =
KE::distance(KE::begin(myRowViewFrom), it);
m_distancesView(myRowIndex) = resultDist;
});
break;
}
}

// store result of checking if all members have their local
// values matching the one stored in m_distancesView
member.team_barrier();
const bool intraTeamCheck = team_members_have_matching_result(
member, resultDist, m_distancesView(myRowIndex));
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_intraTeamSentinelView(myRowIndex) = intraTeamCheck;
});
}
};

Expand Down Expand Up @@ -150,23 +164,28 @@ void test_A(const bool ensureAdjacentFindCanFind, std::size_t numTeams,
// of the interval that team operates on and then we check that these
// distances match the std result
Kokkos::View<std::size_t*> distancesView("distancesView", numTeams);
// sentinel to check if all members of the team compute the same result
Kokkos::View<bool*> intraTeamSentinelView("intraTeamSameResult", numTeams);

// use CTAD for functor
IsEqualFunctor<ValueType> binaryPred;
TestFunctorA fnc(dataView, distancesView, apiId, binaryPred);
TestFunctorA fnc(dataView, distancesView, intraTeamSentinelView, apiId,
binaryPred);
Kokkos::parallel_for(policy, fnc);

// -----------------------------------------------
// run cpp-std kernel and check
// -----------------------------------------------
auto distancesView_h = create_host_space_copy(distancesView);
auto distancesView_h = create_host_space_copy(distancesView);
auto intraTeamSentinelView_h = create_host_space_copy(intraTeamSentinelView);

for (std::size_t i = 0; i < dataView.extent(0); ++i) {
auto rowFrom = Kokkos::subview(dataView_dc_h, i, Kokkos::ALL());
const auto rowFromBegin = KE::cbegin(rowFrom);
const auto rowFromEnd = KE::cend(rowFrom);
const std::size_t beginEndDist = KE::distance(rowFromBegin, rowFromEnd);

ASSERT_TRUE(intraTeamSentinelView_h(i));
switch (apiId) {
case 0:
case 1: {
Expand Down
44 changes: 31 additions & 13 deletions algorithms/unit_tests/TestStdAlgorithmsTeamReduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,25 @@ struct PlusFunctor {
};

template <class DataViewType, class ReductionInitValuesViewType,
class ReduceResultsViewType, class BinaryPredType>
class ReduceResultsViewType, class IntraTeamSentinelView,
class BinaryPredType>
struct TestFunctorA {
DataViewType m_dataView;
ReductionInitValuesViewType m_reductionInitValuesView;
ReduceResultsViewType m_reduceResultsView;
IntraTeamSentinelView m_intraTeamSentinelView;
int m_apiPick;
BinaryPredType m_binaryPred;

TestFunctorA(const DataViewType dataView,
const ReductionInitValuesViewType reductionInitValuesView,
const ReduceResultsViewType reduceResultsView, int apiPick,
const ReduceResultsViewType reduceResultsView,
const IntraTeamSentinelView intraTeamSentinelView, int apiPick,
BinaryPredType binaryPred)
: m_dataView(dataView),
m_reductionInitValuesView(reductionInitValuesView),
m_reduceResultsView(reduceResultsView),
m_intraTeamSentinelView(intraTeamSentinelView),
m_apiPick(apiPick),
m_binaryPred(binaryPred) {}

Expand All @@ -60,59 +64,68 @@ struct TestFunctorA {
const auto rowFromBegin = KE::cbegin(myRowViewFrom);
const auto rowFromEnd = KE::cend(myRowViewFrom);
const auto initReductionVal = m_reductionInitValuesView(myRowIndex);
typename ReduceResultsViewType::non_const_value_type result = 0;

switch (m_apiPick) {
case 0: {
const auto result = KE::reduce(member, rowFromBegin, rowFromEnd);
result = KE::reduce(member, rowFromBegin, rowFromEnd);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_reduceResultsView(myRowIndex) = result;
});
break;
}

case 1: {
const auto result = KE::reduce(member, myRowViewFrom);
result = KE::reduce(member, myRowViewFrom);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_reduceResultsView(myRowIndex) = result;
});
break;
}

case 2: {
const auto result =
KE::reduce(member, rowFromBegin, rowFromEnd, initReductionVal);
result = KE::reduce(member, rowFromBegin, rowFromEnd, initReductionVal);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_reduceResultsView(myRowIndex) = result;
});
break;
}

case 3: {
const auto result = KE::reduce(member, myRowViewFrom, initReductionVal);
result = KE::reduce(member, myRowViewFrom, initReductionVal);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_reduceResultsView(myRowIndex) = result;
});
break;
}

case 4: {
const auto result = KE::reduce(member, rowFromBegin, rowFromEnd,
initReductionVal, m_binaryPred);
result = KE::reduce(member, rowFromBegin, rowFromEnd, initReductionVal,
m_binaryPred);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_reduceResultsView(myRowIndex) = result;
});
break;
}

case 5: {
const auto result =
result =
KE::reduce(member, myRowViewFrom, initReductionVal, m_binaryPred);
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_reduceResultsView(myRowIndex) = result;
});
break;
}
}

// store result of checking if all members have their local
// values matching the one stored in m_distancesView
member.team_barrier();
const bool intraTeamCheck = team_members_have_matching_result(
member, result, m_reduceResultsView(myRowIndex));
Kokkos::single(Kokkos::PerTeam(member), [=, *this]() {
m_intraTeamSentinelView(myRowIndex) = intraTeamCheck;
});
}
};

Expand Down Expand Up @@ -153,21 +166,24 @@ void test_A(std::size_t numTeams, std::size_t numCols, int apiId) {
// to verify that things work, each team stores the result of its reduce
// call, and then we check that these match what we expect
Kokkos::View<ValueType*> reduceResultsView("reduceResultsView", numTeams);
// sentinel to check if all members of the team compute the same result
Kokkos::View<bool*> intraTeamSentinelView("intraTeamSameResult", numTeams);

PlusFunctor<ValueType> binaryPred;

// use CTAD for functor
auto reductionInitValuesView =
Kokkos::create_mirror_view_and_copy(space_t(), reductionInitValuesView_h);
TestFunctorA fnc(dataView, reductionInitValuesView, reduceResultsView, apiId,
binaryPred);
TestFunctorA fnc(dataView, reductionInitValuesView, reduceResultsView,
intraTeamSentinelView, apiId, binaryPred);
Kokkos::parallel_for(policy, fnc);

// -----------------------------------------------
// run cpp-std kernel and check
// -----------------------------------------------

auto reduceResultsView_h = create_host_space_copy(reduceResultsView);
auto reduceResultsView_h = create_host_space_copy(reduceResultsView);
auto intraTeamSentinelView_h = create_host_space_copy(intraTeamSentinelView);

for (std::size_t i = 0; i < dataView.extent(0); ++i) {
auto rowFrom = Kokkos::subview(dataViewBeforeOp_h, i, Kokkos::ALL());
Expand All @@ -176,6 +192,8 @@ void test_A(std::size_t numTeams, std::size_t numCols, int apiId) {
const auto rowFromEnd = KE::cend(rowFrom);
const auto initVal = reductionInitValuesView_h(i);

ASSERT_TRUE(intraTeamSentinelView_h(i));

// GCC 8 does not have reduce so guard against this
#if defined(__GNUC__) && __GNUC__ == 8
#define reduce testing_reduce
Expand Down

0 comments on commit 541f674

Please sign in to comment.