Last active
July 20, 2017 03:53
-
-
Save willkill07/4b46ec5ef8ac89e1e3552e83fa6ce462 to your computer and use it in GitHub Desktop.
OpenMP policy tag dispatching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FORALL_OPENMP_HPP_ | |
#define FORALL_OPENMP_HPP_ | |
#include "openmp.hpp" | |
namespace omp { | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::For> | |
forall_impl(const Exec &) { | |
puts(" #pragma omp for nowait"); | |
puts(" OMP_LOOP()"); | |
} | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::For, tags::Static> | |
forall_impl(const Exec &) { | |
printf(" #pragma omp for schedule(static,%d) nowait\n", Exec::chunk_size); | |
puts(" OMP_LOOP()"); | |
} | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::Parallel> | |
forall_impl(const Exec &) { | |
puts(" #pragma omp parallel"); | |
puts(" {"); | |
forall(typename Exec::inner()); | |
puts(" }"); | |
} | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::BarrierBefore> | |
forall_impl(const Exec &) { | |
puts(" #pragma omp barrier"); | |
forall(typename Exec::inner()); | |
} | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::BarrierAfter> | |
forall_impl(const Exec &) { | |
forall(typename Exec::inner()); | |
puts(" #pragma omp barrier"); | |
} | |
} // end namespace omp | |
// dispatch to omp policy | |
template <typename Exec> | |
typename std::enable_if<Exec::policy == Policy::openmp>::type | |
forall(const Exec &p) { | |
omp::forall_impl<Exec, omp::tag_list>(p); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FORALL_SEQUENTIAL_HPP_ | |
#define FORALL_SEQUENTIAL_HPP_ | |
#include "sequential.hpp" | |
namespace sequential { | |
template <typename Exec> | |
void | |
forall_impl(const Exec &) { | |
puts(" SEQ_LOOP()"); | |
} | |
} | |
// dispatch to sequential policy | |
template <typename Exec> | |
typename std::enable_if<Exec::policy == Policy::seq>::type | |
forall(const Exec &p) { | |
sequential::forall_impl(p); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FORALL_TARGET_OPENMP_HPP_ | |
#define FORALL_TARGET_OPENMP_HPP_ | |
#include "target_openmp.hpp" | |
namespace target_omp { | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::Target, tags::Teams, tags::Distribute> | |
forall_impl(const Exec &) { | |
printf(" #pragma omp target teams distribute num_teams(%d)\n", | |
Exec::num_teams); | |
forall(typename Exec::inner()); | |
} | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::Target, tags::Teams, tags::Distribute, | |
tags::Parallel, tags::For> | |
forall_impl(const Exec &) { | |
printf(" #pragma omp target teams distribute num_teams(%d) parallel for\n", | |
Exec::num_teams); | |
puts(" TARGET_OMP_LOOP();"); | |
} | |
template <typename Exec, typename TagList> | |
exact<Exec, TagList, tags::Target, tags::Teams, tags::Distribute, | |
tags::Parallel, tags::For, tags::Static> | |
forall_impl(const Exec &) { | |
printf( | |
" #pragma omp target teams distribute num_teams(%d) parallel for schedule(static,%d)\n", | |
Exec::num_teams, Exec::chunk_size); | |
puts(" TARGET_OMP_LOOP();"); | |
} | |
} // end namespace target_omp | |
// dispatch to target omp policy | |
template <typename Exec> | |
typename std::enable_if<Exec::policy == Policy::target_openmp>::type | |
forall(const Exec &p) { | |
target_omp::forall_impl<Exec, target_omp::tag_list>(p); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FORALL_HPP_ | |
#define FORALL_HPP_ | |
#include "forall-openmp.hpp" | |
#include "forall-sequential.hpp" | |
#include "forall-target_openmp.hpp" | |
// template type -> value-based | |
template <typename Exec> | |
void | |
forall() { | |
forall(Exec()); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef META_HPP_ | |
#define META_HPP_ | |
#include <type_traits> | |
// metaprogramming utils | |
template <bool...> | |
struct blist; | |
template <typename... Args> | |
struct list {}; | |
template <typename... Args> | |
struct voider { | |
using type = void; | |
}; | |
namespace detail { | |
template <typename Exec, typename T, typename... Ts> | |
struct count { | |
using child = count<Exec, Ts...>; | |
constexpr static bool res = std::is_base_of<T, Exec>::value; | |
constexpr static int true_ = res + child::true_; | |
constexpr static int false_ = !res + child::false_; | |
}; | |
template <typename Exec, typename T> | |
struct count<Exec, T> { | |
constexpr static bool res = std::is_base_of<T, Exec>::value; | |
constexpr static int true_ = res; | |
constexpr static int false_ = !res; | |
}; | |
template <typename Exec, typename TagList, typename... Tags> | |
struct exact; | |
template <typename Exec, typename... AvailableTags, typename... ExpectedTags> | |
struct exact<Exec, list<AvailableTags...>, ExpectedTags...> { | |
using A = count<Exec, AvailableTags...>; | |
using E = count<Exec, ExpectedTags...>; | |
constexpr static bool value = (A::true_ == E::true_) && (E::false_ == 0); | |
}; | |
} // end namespace detail | |
template <typename Exec, typename TagList, typename... Tags> | |
using exact = | |
typename std::enable_if<detail::exact<Exec, TagList, Tags...>::value>::type; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <type_traits> | |
#include "PolicyBase.hpp" | |
#include "sequential.hpp" | |
#include "openmp.hpp" | |
#include "target_openmp.hpp" | |
#include "forall.hpp" | |
int | |
main() { | |
puts("forall<seq_exec>();\n"); | |
forall<seq_exec>(); | |
putchar('\n'); | |
puts("forall<omp_for_exec>();\n"); | |
forall<omp_for_exec>(); | |
putchar('\n'); | |
puts("forall<omp_parallel_for_exec>();\n"); | |
forall<omp_parallel_for_exec>(); | |
putchar('\n'); | |
puts("forall<omp_parallel_static_exec<16>>();\n"); | |
forall<omp_parallel_static_exec<16>>(); | |
putchar('\n'); | |
puts("forall<omp_static_exec<8>>();\n"); | |
forall<omp_static_exec<8>>(); | |
putchar('\n'); | |
puts("forall<omp_for_nowait_exec>();\n"); | |
forall<omp_for_nowait_exec>(); | |
putchar('\n'); | |
puts("forall<omp_static_nowait_exec<8>>();\n"); | |
forall<omp_static_nowait_exec<8>>(); | |
putchar('\n'); | |
puts("forall<omp_target_teams_distribute_parallel_for_exec<256>>();\n"); | |
forall<omp_target_teams_distribute_parallel_for_exec<256>>(); | |
putchar('\n'); | |
puts("forall<omp_target_teams_distribute_parallel_static_exec<128,1>>();\n"); | |
forall<omp_target_teams_distribute_parallel_static_exec<128, 1>>(); | |
putchar('\n'); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef OPENMP_HPP_ | |
#define OPENMP_HPP_ | |
#include "meta.hpp" | |
#include "PolicyBase.hpp" | |
// OpenMP policy tags and types | |
namespace omp { | |
namespace tags { | |
struct Parallel {}; | |
struct Static {}; | |
struct BarrierAfter {}; | |
struct BarrierBefore {}; | |
struct For {}; | |
} // end namespace tags | |
using tag_list = list<tags::Parallel, tags::Static, tags::BarrierAfter, | |
tags::BarrierBefore, tags::For>; | |
template <typename... Args> | |
using policy = PolicyBaseT<Policy::openmp, Platform::undefined, Args...>; | |
template <typename Inner> | |
struct Parallel : policy<tags::Parallel> { | |
using inner = Inner; | |
}; | |
template <typename Loop> | |
struct BarrierAfter : policy<tags::BarrierAfter> { | |
using inner = Loop; | |
}; | |
template <typename Loop> | |
struct BarrierBefore : policy<tags::BarrierBefore> { | |
using inner = Loop; | |
}; | |
template <typename... Options> | |
struct For : policy<Options...>, tags::For {}; | |
template <unsigned int N> | |
struct Static : policy<>, tags::Static { | |
static constexpr unsigned int chunk_size = N; | |
}; | |
} // end namespace omp | |
using omp_for_exec = omp::BarrierAfter<omp::For<>>; | |
template <unsigned int N> | |
using omp_static_exec = omp::BarrierAfter<omp::For<omp::Static<N>>>; | |
using omp_for_nowait_exec = omp::For<>; | |
template <unsigned int N> | |
using omp_static_nowait_exec = omp::For<omp::Static<N>>; | |
template <typename Inner> | |
using omp_parallel_exec = omp::Parallel<Inner>; | |
using omp_parallel_for_exec = omp_parallel_exec<omp_for_exec>; | |
template <unsigned int N> | |
using omp_parallel_static_exec = omp_parallel_exec<omp_static_exec<N>>; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef POLICY_BASE_HPP_ | |
#define POLICY_BASE_HPP_ | |
#include <cstdio> | |
#include "meta.hpp" | |
// Policy base | |
enum class Policy { seq, openmp, target_openmp }; | |
enum class Platform { undefined, cpu }; | |
template <Policy Pol, Platform P, typename... Args> | |
struct PolicyBaseT : public Args... { | |
static constexpr Policy policy = Pol; | |
static constexpr Platform platform = P; | |
}; | |
template <Policy Exec, Policy P, Policy... Rest> | |
struct NoneOf { | |
static constexpr bool value = (Exec != P) && NoneOf<Exec, Rest...>::value; | |
}; | |
template <Policy Exec, Policy P> | |
struct NoneOf<Exec, P> { | |
static constexpr bool value = (Exec != P); | |
}; | |
template <typename Exec> | |
typename std::enable_if<Exec::policy == Policy::seq>::type | |
forall(const Exec &p); | |
template <typename Exec> | |
typename std::enable_if<Exec::policy == Policy::openmp>::type | |
forall(const Exec &p); | |
template <typename Exec> | |
typename std::enable_if<Exec::policy == Policy::target_openmp>::type | |
forall(const Exec &p); | |
template <typename Exec> | |
typename std::enable_if<NoneOf<Exec::policy, Policy::seq, Policy::openmp, | |
Policy::target_openmp>::value>::type | |
forall(const Exec &) { | |
puts("We don't support the passed execution policy with forall"); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SEQUENTIAL_HPP_ | |
#define SEQUENTIAL_HPP_ | |
#include "PolicyBase.hpp" | |
struct seq_exec : PolicyBaseT<Policy::seq, Platform::undefined> {}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef TARGET_OPENMP_HPP_ | |
#define TARGET_OPENMP_HPP_ | |
#include "openmp.hpp" | |
// OpenMP policy tags and types | |
namespace target_omp { | |
namespace tags { | |
using namespace omp::tags; | |
struct Target {}; | |
struct Teams {}; | |
struct Distribute {}; | |
} // end namespace tags | |
using tag_list = | |
list<tags::Target, tags::Teams, tags::Distribute, tags::Parallel, | |
tags::Static, tags::BarrierAfter, tags::BarrierBefore, tags::For>; | |
template <typename... Args> | |
using policy = PolicyBaseT<Policy::target_openmp, Platform::undefined, Args...>; | |
using omp::BarrierAfter; | |
using omp::BarrierBefore; | |
using omp::For; | |
using omp::Parallel; | |
using omp::Static; | |
template <unsigned int N> | |
struct TargetTeamsDistribute | |
: policy<tags::Target, tags::Teams, tags::Distribute> { | |
constexpr static unsigned int num_teams = N; | |
}; | |
template <unsigned int N> | |
struct TargetTeamsDistributeParallelFor | |
: policy<tags::Target, tags::Teams, tags::Distribute, tags::Parallel, | |
tags::For> { | |
constexpr static unsigned int num_teams = N; | |
}; | |
template <unsigned int N, unsigned int M> | |
struct TargetTeamsDistributeParallelStatic | |
: policy<tags::Target, tags::Teams, tags::Distribute, tags::Parallel, | |
tags::For, tags::Static> { | |
constexpr static unsigned int num_teams = N; | |
constexpr static unsigned int chunk_size = M; | |
}; | |
} // end namespace target_omp | |
template <unsigned int N> | |
using omp_target_teams_distribute_exec = target_omp::TargetTeamsDistribute<N>; | |
template <unsigned int N> | |
using omp_target_teams_distribute_parallel_for_exec = | |
target_omp::TargetTeamsDistributeParallelFor<N>; | |
template <unsigned int N, unsigned int M> | |
using omp_target_teams_distribute_parallel_static_exec = | |
target_omp::TargetTeamsDistributeParallelStatic<N, M>; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output: