10#ifndef TPETRA_DETAILS_EXECUTIONSPACES_HPP
11#define TPETRA_DETAILS_EXECUTIONSPACES_HPP
17#include <Kokkos_Core.hpp>
19#include <Teuchos_RCP.hpp>
40#define TPETRA_DETAILS_SPACES_THROW(x) \
42 std::stringstream ss; \
43 ss << __FILE__ << ":" << __LINE__ << ": " << x; \
44 throw std::runtime_error(ss.str()); \
63#if defined(KOKKOS_ENABLE_CUDA)
70 throw std::runtime_error(
ss.str());
73#define TPETRA_DETAILS_SPACES_CUDA_RUNTIME(x) \
74 Tpetra::Details::Spaces::success_or_throw((x), __FILE__, __LINE__)
85#if defined(KOKKOS_ENABLE_CUDA)
91 cudaEvent_t execSpaceWaitEvent_;
94 ~CudaInfo() =
default;
95 CudaInfo(
const CudaInfo &other) =
delete;
96 CudaInfo(CudaInfo &&other) =
delete;
98extern CudaInfo cudaInfo;
102#if defined(KOKKOS_ENABLE_CUDA)
103template <
typename Space>
104using IsCuda = std::enable_if_t<std::is_same_v<Space, Kokkos::Cuda>,
bool>;
105template <
typename Space>
106using NotCuda = std::enable_if_t<!std::is_same_v<Space, Kokkos::Cuda>,
bool>;
107template <
typename S1,
typename S2>
108using BothCuda = std::enable_if_t<
109 std::is_same_v<S1, Kokkos::Cuda> && std::is_same_v<S2, Kokkos::Cuda>,
bool>;
110template <
typename S1,
typename S2>
111using NotBothCuda = std::enable_if_t<!std::is_same_v<S1, Kokkos::Cuda> ||
112 !std::is_same_v<S2, Kokkos::Cuda>,
116#if defined(KOKKOS_ENABLE_SERIAL)
118template <
typename Space>
119using IsSerial = std::enable_if_t<std::is_same_v<Space, Kokkos::Serial>,
bool>;
122#if defined(KOKKOS_ENABLE_OPENMP)
124template <
typename Space>
125using IsOpenMP = std::enable_if_t<std::is_same_v<Space, Kokkos::OpenMP>,
bool>;
128#if defined(KOKKOS_ENABLE_HIP)
130template <
typename Space>
131using IsHIP = std::enable_if_t<std::is_same_v<Space, Kokkos::HIP>,
bool>;
134#if defined(KOKKOS_ENABLE_SYCL)
136template <
typename Space>
137using IsSYCL = std::enable_if_t<std::is_same_v<Space, Kokkos::Experimental::SYCL>,
bool>;
145template <
typename ExecSpace,
Priority priority = Priority::medium
146#if defined(KOKKOS_ENABLE_CUDA)
148 NotCuda<ExecSpace> =
true
161#if defined(KOKKOS_ENABLE_CUDA)
164Kokkos::Cuda make_instance() {
172 case Priority::medium:
179 throw std::runtime_error(
"unexpected static Tpetra Space priority");
183 return Kokkos::Cuda(
stream,
true );
192template <
typename ExecSpace>
197 case Priority::medium:
202 throw std::runtime_error(
"unexpected dynamic Tpetra Space priority");
217template <
typename ExecSpace>
221 using rcp_type = Teuchos::RCP<const execution_space>;
229 template <Priority priority = Priority::medium>
232 "Tpetra::Details::Spaces::space_instance");
234 constexpr int p =
static_cast<int>(
priority);
235 static_assert(
p <
sizeof(instances) /
sizeof(instances[0]),
236 "Spaces::Priority enum error");
239 TPETRA_DETAILS_SPACES_THROW(
"requested instance id " <<
i <<
" (< 0)");
242 TPETRA_DETAILS_SPACES_THROW(
243 "requested instance id "
245 <<
") set by TPETRA_SPACES_ID_WARN_LIMIT");
250 while (
size_t(
i) >= instances[
p].
size()) {
251 instances[
p].push_back(Teuchos::ENull());
265 rcp_type
r = Teuchos::RCP<const execution_space>(
269 instances[
p][
i] =
r.create_weak();
275 auto r = instances[
p][
i].create_strong();
284 for (
const rcp_type &
rcp : instances[
i]) {
285 if (
rcp.is_valid_ptr() && !
rcp.is_null()) {
288 <<
" execution space instance survived to "
289 "~InstanceLifetimeManager. strong_count() = "
290 <<
rcp.strong_count()
291 <<
". Did a Tpetra object live past Kokkos::finalize()?"
300 std::vector<rcp_type>
301 instances[
static_cast<int>(Spaces::Priority::NUM_LEVELS)];
304#if defined(KOKKOS_ENABLE_CUDA)
307#if defined(KOKKOS_ENABLE_SERIAL)
310#if defined(KOKKOS_ENABLE_OPENMP)
313#if defined(KOKKOS_ENABLE_HIP)
316#if defined(KOKKOS_ENABLE_SYCL)
320#if defined(KOKKOS_ENABLE_CUDA)
327Teuchos::RCP<const ExecSpace> space_instance(
int i = 0) {
332#if defined(KOKKOS_ENABLE_SERIAL)
338Teuchos::RCP<const ExecSpace> space_instance(
int i = 0) {
343#if defined(KOKKOS_ENABLE_OPENMP)
347template <
typename ExecSpace, Priority priority = Priority::medium,
348 IsOpenMP<ExecSpace> =
true>
349Teuchos::RCP<const ExecSpace> space_instance(
int i = 0) {
350 return openMPSpaces.space_instance<priority>(i);
354#if defined(KOKKOS_ENABLE_HIP)
357template <
typename ExecSpace,
Priority priority = Priority::medium,
358 IsHIP<ExecSpace> =
true>
360 return HIPSpaces.space_instance<priority>(i);
363#if defined(KOKKOS_ENABLE_SYCL)
367template <
typename ExecSpace,
Priority priority = Priority::medium,
368 IsSYCL<ExecSpace> =
true>
370 return SYCLSpaces.space_instance<priority>(i);
379template <
typename ExecSpace>
385 case Priority::medium:
390 throw std::runtime_error(
391 "unexpected dynamic Tpetra Space priority in space_instance");
408template <
typename S1,
typename S2
409#if defined(KOKKOS_ENABLE_CUDA)
416 "Tpetra::Details::Spaces::exec_space_wait");
421#if defined(KOKKOS_ENABLE_CUDA)
422template <
typename S1,
typename S2, BothCuda<S1, S2> = true>
425 "Tpetra::Details::Spaces::exec_space_wait");
429 if (
waitee.impl_instance_id() !=
431 .impl_instance_id()) {
444template <
typename S1,
typename S2>
445void exec_space_wait(
const S1 &waitee,
const S2 &waiter) {
447 "Tpetra::Details::Spaces::exec_space_wait");
449 exec_space_wait(
"anonymous", waitee, waiter);
452template <
typename ExecutionSpace>
453constexpr KOKKOS_INLINE_FUNCTION
bool is_gpu_exec_space() {
457#if defined(KOKKOS_ENABLE_CUDA)
459constexpr KOKKOS_INLINE_FUNCTION
bool is_gpu_exec_space<Kokkos::Cuda>() {
464#if defined(KOKKOS_ENABLE_HIP)
466constexpr KOKKOS_INLINE_FUNCTION
bool
467is_gpu_exec_space<Kokkos::HIP>() {
472#if defined(KOKKOS_ENABLE_SYCL)
474constexpr KOKKOS_INLINE_FUNCTION
bool
475is_gpu_exec_space<Kokkos::Experimental::SYCL>() {
484#undef TPETRA_DETAILS_SPACES_THROW
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
void exec_space_wait(const char *msg, const S1 &waitee, const S2 &)
cause future work submitted to waiter to wait for the current work in waitee to finish
ExecSpace make_instance()
Construct a Kokkos execution space instance with the following priority.
Teuchos::RCP< const ExecSpace > space_instance(const Priority &priority, int i=0)
get a strong Teuchos::RCP to Tpetra-managed Kokkos execution space instance i
Priority
Priority interface for Tpetra's managed execution spaces.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Struct that holds views of the contents of a CrsMatrix.
static size_t spacesIdWarnLimit()
Warn if more than this many Kokkos spaces are accessed.
Provides reusable Kokkos execution space instances.
~InstanceLifetimeManager()
Issue a warning if any Tpetra-managed execution space instances survive to the end of static lifetime...
rcp_type space_instance(int i=0)
Retrieve a strong Teuchos::RCP<const ExecSpace> to instance i
Implementation details of Tpetra.
Namespace Tpetra contains the class and methods constituting the Tpetra library.