Kokkos Core Kernels Package Version of the Day
Kokkos_TaskScheduler.hpp
1/*
2//@HEADER
3// ************************************************************************
4//
5// Kokkos v. 3.0
6// Copyright (2020) National Technology & Engineering
7// Solutions of Sandia, LLC (NTESS).
8//
9// Under the terms of Contract DE-NA0003525 with NTESS,
10// the U.S. Government retains certain rights in this software.
11//
12// Redistribution and use in source and binary forms, with or without
13// modification, are permitted provided that the following conditions are
14// met:
15//
16// 1. Redistributions of source code must retain the above copyright
17// notice, this list of conditions and the following disclaimer.
18//
19// 2. Redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution.
22//
23// 3. Neither the name of the Corporation nor the names of the
24// contributors may be used to endorse or promote products derived from
25// this software without specific prior written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38//
39// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40//
41// ************************************************************************
42//@HEADER
43*/
44
45#ifndef KOKKOS_TASKSCHEDULER_HPP
46#define KOKKOS_TASKSCHEDULER_HPP
47
48//----------------------------------------------------------------------------
49
50#include <Kokkos_Macros.hpp>
51#if defined(KOKKOS_ENABLE_TASKDAG)
52
53#include <Kokkos_Core_fwd.hpp>
54#include <Kokkos_TaskScheduler_fwd.hpp>
55//----------------------------------------------------------------------------
56
57#include <Kokkos_MemoryPool.hpp>
58#include <impl/Kokkos_Tags.hpp>
59
60#include <Kokkos_Future.hpp>
61#include <impl/Kokkos_TaskQueue.hpp>
62#include <impl/Kokkos_SingleTaskQueue.hpp>
63#include <impl/Kokkos_TaskQueueMultiple.hpp>
64#include <impl/Kokkos_TaskPolicyData.hpp>
65#include <impl/Kokkos_TaskTeamMember.hpp>
66#include <impl/Kokkos_SimpleTaskScheduler.hpp>
67
68//----------------------------------------------------------------------------
69//----------------------------------------------------------------------------
70
71namespace Kokkos {
72
73namespace Impl {
74
75template <class, class>
76class TaskExec;
77
78} // end namespace Impl
79
80template <class ExecSpace, class QueueType>
81class BasicTaskScheduler : public Impl::TaskSchedulerBase {
82 public:
83 using scheduler_type = BasicTaskScheduler;
84 using execution_space = ExecSpace;
85 using queue_type = QueueType;
86 using memory_space = typename queue_type::memory_space;
87 using memory_pool = typename queue_type::memory_pool;
88 using specialization = Impl::TaskQueueSpecialization<BasicTaskScheduler>;
89 using member_type = typename specialization::member_type;
90 using team_scheduler_type = BasicTaskScheduler;
91 template <class Functor>
92 using runnable_task_type =
93 Impl::Task<scheduler_type, typename Functor::value_type, Functor>;
94 template <class ValueType>
95 using future_type = Kokkos::BasicFuture<ValueType, BasicTaskScheduler>;
96 template <class FunctorType>
97 using future_type_for_functor = future_type<typename FunctorType::value_type>;
98
99 private:
100 using track_type = Kokkos::Impl::SharedAllocationTracker;
101 using task_base = Impl::TaskBase;
102
103 track_type m_track;
104 queue_type* m_queue;
105
106 //----------------------------------------
107
108 template <typename, typename>
109 friend class Impl::TaskQueue;
110 template <typename>
111 friend struct Impl::TaskQueueSpecialization;
112 template <typename, typename>
113 friend class Impl::TaskQueueSpecializationConstrained;
114 template <typename, typename>
115 friend class Impl::TaskTeamMemberAdapter;
116 template <typename, typename>
117 friend class Impl::TaskExec;
118
119 //----------------------------------------
120
121 KOKKOS_INLINE_FUNCTION
122 BasicTaskScheduler(track_type arg_track, queue_type* arg_queue)
123 : m_track(std::move(arg_track)), m_queue(std::move(arg_queue)) {}
124
125 KOKKOS_INLINE_FUNCTION
126 team_scheduler_type get_team_scheduler(int team_rank) const {
127 return {m_track, &m_queue->get_team_queue(team_rank)};
128 }
129
130 //----------------------------------------
131
132 KOKKOS_INLINE_FUNCTION
133 static constexpr task_base* _get_task_ptr(std::nullptr_t) { return nullptr; }
134
135 template <class ValueType>
136 KOKKOS_INLINE_FUNCTION static constexpr task_base* _get_task_ptr(
137 future_type<ValueType>&& f) {
138 return f.m_task;
139 }
140
141 template <int TaskEnum, typename DepTaskType, typename FunctorType>
142 KOKKOS_FUNCTION
143 Kokkos::BasicFuture<typename FunctorType::value_type, scheduler_type>
144 _spawn_impl(DepTaskType* arg_predecessor_task, TaskPriority arg_priority,
145 typename task_base::function_type arg_function,
146 typename task_base::destroy_type /*arg_destroy*/,
147 FunctorType&& arg_functor) {
148 using functor_future_type =
149 future_type_for_functor<typename std::decay<FunctorType>::type>;
150 using task_type =
151 Impl::Task<BasicTaskScheduler, typename functor_future_type::value_type,
152 FunctorType>;
153
154 //----------------------------------------
155 // Give single-thread back-ends an opportunity to clear
156 // queue of ready tasks before allocating a new task
157
158 // TODO @tasking @optimization DSH re-enable this, maybe?
159 // specialization::iff_single_thread_recursive_execute(scheduler);
160
161 //----------------------------------------
162
163 functor_future_type f;
164
165 // Allocate task from memory pool
166
167 const size_t alloc_size =
168 m_queue->template spawn_allocation_size<FunctorType>();
169
170 void* task_storage = m_queue->allocate(alloc_size);
171
172 if (task_storage) {
173 // Placement new construction
174 // Reference count starts at two:
175 // +1 for the matching decrement when task is complete
176 // +1 for the future
177 f.m_task =
178 new (task_storage) task_type(std::forward<FunctorType>(arg_functor));
179
180 f.m_task->m_apply = arg_function;
181 // f.m_task->m_destroy = arg_destroy;
182 f.m_task->m_queue = m_queue;
183 f.m_task->m_next = arg_predecessor_task;
184 f.m_task->m_ref_count = 2;
185 f.m_task->m_alloc_size = alloc_size;
186 f.m_task->m_task_type = TaskEnum;
187 f.m_task->m_priority = (int16_t)arg_priority;
188
189 Kokkos::memory_fence();
190
191 // The dependence (if any) is processed immediately
192 // within the schedule function, as such the dependence's
193 // reference count does not need to be incremented for
194 // the assignment.
195
196 m_queue->schedule_runnable(f.m_task);
197 // This task may be updated or executed at any moment,
198 // even during the call to 'schedule'.
199 }
200
201 return f;
202 }
203
204 public:
205 KOKKOS_INLINE_FUNCTION
206 BasicTaskScheduler() : m_track(), m_queue(nullptr) {}
207
208 KOKKOS_INLINE_FUNCTION
209 BasicTaskScheduler(BasicTaskScheduler&& rhs) noexcept
210 : m_track(rhs.m_track), // probably should be a move, but this is
211 // deprecated code anyway
212 m_queue(std::move(rhs.m_queue)) {}
213
214 KOKKOS_INLINE_FUNCTION
215 BasicTaskScheduler(BasicTaskScheduler const& rhs)
216 : m_track(rhs.m_track), m_queue(rhs.m_queue) {}
217
218 KOKKOS_INLINE_FUNCTION
219 BasicTaskScheduler& operator=(BasicTaskScheduler&& rhs) noexcept {
220 m_track = rhs.m_track; // probably should be a move, but this is deprecated
221 // code anyway
222 m_queue = std::move(rhs.m_queue);
223 return *this;
224 }
225
226 KOKKOS_INLINE_FUNCTION
227 BasicTaskScheduler& operator=(BasicTaskScheduler const& rhs) {
228 m_track = rhs.m_track;
229 m_queue = rhs.m_queue;
230 return *this;
231 }
232
233 explicit BasicTaskScheduler(memory_pool const& arg_memory_pool) noexcept
234 : m_track(), m_queue(nullptr) {
235 using record_type =
236 Kokkos::Impl::SharedAllocationRecord<memory_space,
237 typename queue_type::Destroy>;
238
239 record_type* record = record_type::allocate(
240 memory_space(), "Kokkos::TaskQueue", sizeof(queue_type));
241
242 m_queue = new (record->data()) queue_type(arg_memory_pool);
243
244 record->m_destroy.m_queue = m_queue;
245
246 m_track.assign_allocated_record_to_uninitialized(record);
247 }
248
249 BasicTaskScheduler(memory_space const& arg_memory_space,
250 size_t const mempool_capacity,
251 unsigned const mempool_min_block_size // = 1u << 6
252 ,
253 unsigned const mempool_max_block_size // = 1u << 10
254 ,
255 unsigned const mempool_superblock_size // = 1u << 12
256 )
257 : BasicTaskScheduler(memory_pool(
258 arg_memory_space, mempool_capacity, mempool_min_block_size,
259 mempool_max_block_size, mempool_superblock_size)) {}
260
261 //----------------------------------------
262
263 KOKKOS_INLINE_FUNCTION
264 queue_type& queue() const noexcept {
265 KOKKOS_EXPECTS(m_queue != nullptr);
266 return *m_queue;
267 }
268
269 KOKKOS_INLINE_FUNCTION
270 memory_pool* memory() const noexcept {
271 return m_queue ? &(m_queue->m_memory) : (memory_pool*)0;
272 }
273
274 //----------------------------------------
276 template <typename FunctorType>
277 KOKKOS_FUNCTION size_t spawn_allocation_size() const {
278 return m_queue->template spawn_allocation_size<FunctorType>();
279 }
280
282 KOKKOS_FUNCTION
283 size_t when_all_allocation_size(int narg) const {
284 return m_queue->when_all_allocation_size(narg);
285 }
286
287 //----------------------------------------
288
289 template <int TaskEnum, typename DepFutureType, typename FunctorType>
290 KOKKOS_FUNCTION static Kokkos::BasicFuture<typename FunctorType::value_type,
291 scheduler_type>
292 spawn(Impl::TaskPolicyWithScheduler<TaskEnum, scheduler_type, DepFutureType>&&
293 arg_policy,
294 typename task_base::function_type arg_function,
295 typename task_base::destroy_type arg_destroy,
296 FunctorType&& arg_functor) {
297 return std::move(arg_policy.scheduler())
298 .template _spawn_impl<TaskEnum>(
299 _get_task_ptr(std::move(arg_policy.predecessor())),
300 arg_policy.priority(), arg_function, arg_destroy,
301 std::forward<FunctorType>(arg_functor));
302 }
303
304 template <int TaskEnum, typename DepFutureType, typename FunctorType>
305 KOKKOS_FUNCTION
306 future_type_for_functor<typename std::decay<FunctorType>::type>
307 spawn(
308 Impl::TaskPolicyWithPredecessor<TaskEnum, DepFutureType>&& arg_policy,
309 FunctorType&& arg_functor) {
310 using task_type = runnable_task_type<FunctorType>;
311 typename task_type::function_type const ptr = task_type::apply;
312 typename task_type::destroy_type const dtor = task_type::destroy;
313
314 return _spawn_impl<TaskEnum>(
315 _get_task_ptr(std::move(arg_policy).predecessor()),
316 arg_policy.priority(), ptr, dtor,
317 std::forward<FunctorType>(arg_functor));
318 }
319
320 template <typename FunctorType, typename ValueType, typename Scheduler>
321 KOKKOS_FUNCTION static void respawn(
322 FunctorType* arg_self,
323 BasicFuture<ValueType, Scheduler> const& arg_dependence,
324 TaskPriority const& arg_priority) {
325 // Precondition: task is in Executing state
326
327 using value_type = typename FunctorType::value_type;
328 using task_type = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
329
330 task_type* const task = static_cast<task_type*>(arg_self);
331
332 task->m_priority = static_cast<int>(arg_priority);
333
334 task->add_dependence(arg_dependence.m_task);
335
336 // Postcondition: task is in Executing-Respawn state
337 }
338
339 template <typename FunctorType>
340 KOKKOS_FUNCTION static void respawn(FunctorType* arg_self,
341 BasicTaskScheduler const&,
342 TaskPriority const& arg_priority) {
343 // Precondition: task is in Executing state
344
345 using value_type = typename FunctorType::value_type;
346 using task_type = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
347
348 task_type* const task = static_cast<task_type*>(arg_self);
349
350 task->m_priority = static_cast<int>(arg_priority);
351
352 task->add_dependence(nullptr);
353
354 // Postcondition: task is in Executing-Respawn state
355 }
356
357 //----------------------------------------
361 template <typename ValueType>
362 KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(
363 BasicFuture<ValueType, BasicTaskScheduler> const arg[], int narg) {
364 future_type<void> f;
365
366 if (narg) {
367 queue_type* q = m_queue;
368
369 // BasicTaskScheduler const* scheduler_ptr = nullptr;
370
371 for (int i = 0; i < narg; ++i) {
372 task_base* const t = arg[i].m_task;
373 if (nullptr != t) {
374 // Increment reference count to track subsequent assignment.
375 Kokkos::atomic_increment(&(t->m_ref_count));
376 if (q != static_cast<queue_type const*>(t->m_queue)) {
377 Kokkos::abort(
378 "Kokkos when_all Futures must be in the same scheduler");
379 }
380 }
381 }
382
383 if (q != nullptr) { // this should probably handle the queue == 0 case,
384 // but this is deprecated code anyway
385
386 size_t const alloc_size = q->when_all_allocation_size(narg);
387
388 f.m_task = reinterpret_cast<task_base*>(q->allocate(alloc_size));
389 // f.m_scheduler = *scheduler_ptr;
390
391 if (f.m_task) {
392 // Reference count starts at two:
393 // +1 to match decrement when task completes
394 // +1 for the future
395
396 new (f.m_task) task_base();
397
398 f.m_task->m_queue = q;
399 f.m_task->m_ref_count = 2;
400 f.m_task->m_alloc_size = static_cast<int32_t>(alloc_size);
401 f.m_task->m_dep_count = narg;
402 f.m_task->m_task_type = task_base::Aggregate;
403
404 // Assign dependences, reference counts were already incremented
405
406 task_base* volatile* const dep = f.m_task->aggregate_dependences();
407
408 for (int i = 0; i < narg; ++i) {
409 dep[i] = arg[i].m_task;
410 }
411
412 Kokkos::memory_fence();
413
414 q->schedule_aggregate(f.m_task);
415 // this when_all may be processed at any moment
416 }
417 }
418 }
419
420 return f;
421 }
422
423 template <class F>
424 KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(int narg,
425 F const func) {
426 using input_type = decltype(func(0));
427
428 static_assert(is_future<input_type>::value,
429 "Functor must return a Kokkos::Future");
430
431 future_type<void> f;
432
433 if (0 == narg) return f;
434
435 size_t const alloc_size = m_queue->when_all_allocation_size(narg);
436
437 f.m_task = reinterpret_cast<task_base*>(m_queue->allocate(alloc_size));
438
439 if (f.m_task) {
440 // Reference count starts at two:
441 // +1 to match decrement when task completes
442 // +1 for the future
443
444 new (f.m_task) task_base();
445 // f.m_scheduler = *this;
446
447 // f.m_task->m_scheduler = &f.m_scheduler;
448 f.m_task->m_queue = m_queue;
449 f.m_task->m_ref_count = 2;
450 f.m_task->m_alloc_size = static_cast<int32_t>(alloc_size);
451 f.m_task->m_dep_count = narg;
452 f.m_task->m_task_type = task_base::Aggregate;
453 // f.m_task->m_apply = nullptr;
454 // f.m_task->m_destroy = nullptr;
455
456 // Assign dependences, reference counts were already incremented
457
458 task_base* volatile* const dep = f.m_task->aggregate_dependences();
459
460 for (int i = 0; i < narg; ++i) {
461 const input_type arg_f = func(i);
462 if (nullptr != arg_f.m_task) {
463 // Not scheduled, so task scheduler is not yet set
464 // if ( m_queue != static_cast< BasicTaskScheduler const * >(
465 // arg_f.m_task->m_scheduler )->m_queue ) {
466 // Kokkos::abort("Kokkos when_all Futures must be in the same
467 // scheduler" );
468 //}
469 // Increment reference count to track subsequent assignment.
470 Kokkos::atomic_increment(&(arg_f.m_task->m_ref_count));
471 dep[i] = arg_f.m_task;
472 }
473 }
474
475 Kokkos::memory_fence();
476
477 m_queue->schedule_aggregate(f.m_task);
478 // this when_all may be processed at any moment
479 }
480 return f;
481 }
482
483 //----------------------------------------
484
485 KOKKOS_INLINE_FUNCTION
486 int allocation_capacity() const noexcept {
487 return m_queue->m_memory.capacity();
488 }
489
490 KOKKOS_INLINE_FUNCTION
491 int allocated_task_count() const noexcept { return m_queue->m_count_alloc; }
492
493 KOKKOS_INLINE_FUNCTION
494 int allocated_task_count_max() const noexcept { return m_queue->m_max_alloc; }
495
496 KOKKOS_INLINE_FUNCTION
497 long allocated_task_count_accum() const noexcept {
498 return m_queue->m_accum_alloc;
499 }
500
501 //----------------------------------------
502
503 template <class S, class Q>
504 friend void wait(Kokkos::BasicTaskScheduler<S, Q> const&);
505};
506
507} // namespace Kokkos
508
509//----------------------------------------------------------------------------
510//----------------------------------------------------------------------------
511
512namespace Kokkos {
513
514//----------------------------------------------------------------------------
515// Construct a TaskTeam execution policy
516
517template <class T, class Scheduler>
518Impl::TaskPolicyWithPredecessor<Impl::TaskType::TaskTeam,
519 Kokkos::BasicFuture<T, Scheduler> >
520 KOKKOS_INLINE_FUNCTION
521 TaskTeam(Kokkos::BasicFuture<T, Scheduler> arg_future,
522 TaskPriority arg_priority = TaskPriority::Regular) {
523 return {std::move(arg_future), arg_priority};
524}
525
526template <class Scheduler>
527Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskTeam, Scheduler>
528 KOKKOS_INLINE_FUNCTION
529 TaskTeam(Scheduler arg_scheduler,
530 typename std::enable_if<Kokkos::is_scheduler<Scheduler>::value,
531 TaskPriority>::type arg_priority =
532 TaskPriority::Regular) {
533 return {std::move(arg_scheduler), arg_priority};
534}
535
536template <class Scheduler, class PredecessorFuture>
537Impl::TaskPolicyWithScheduler<Kokkos::Impl::TaskType::TaskTeam, Scheduler,
538 PredecessorFuture>
539 KOKKOS_INLINE_FUNCTION TaskTeam(
540 Scheduler arg_scheduler, PredecessorFuture arg_future,
541 typename std::enable_if<Kokkos::is_scheduler<Scheduler>::value &&
542 Kokkos::is_future<PredecessorFuture>::value,
543 TaskPriority>::type arg_priority =
544 TaskPriority::Regular) {
545 static_assert(std::is_same<typename PredecessorFuture::scheduler_type,
546 Scheduler>::value,
547 "Can't create a task policy from a scheduler and a future from "
548 "a different scheduler");
549
550 return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
551}
552
553// Construct a TaskSingle execution policy
554
555template <class T, class Scheduler>
556Impl::TaskPolicyWithPredecessor<Impl::TaskType::TaskSingle,
557 Kokkos::BasicFuture<T, Scheduler> >
558 KOKKOS_INLINE_FUNCTION
559 TaskSingle(Kokkos::BasicFuture<T, Scheduler> arg_future,
560 TaskPriority arg_priority = TaskPriority::Regular) {
561 return {std::move(arg_future), arg_priority};
562}
563
564template <class Scheduler>
565Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskSingle, Scheduler>
566 KOKKOS_INLINE_FUNCTION
567 TaskSingle(Scheduler arg_scheduler,
568 typename std::enable_if<Kokkos::is_scheduler<Scheduler>::value,
569 TaskPriority>::type arg_priority =
570 TaskPriority::Regular) {
571 return {std::move(arg_scheduler), arg_priority};
572}
573
574template <class Scheduler, class PredecessorFuture>
575Impl::TaskPolicyWithScheduler<Kokkos::Impl::TaskType::TaskSingle, Scheduler,
576 PredecessorFuture>
577 KOKKOS_INLINE_FUNCTION TaskSingle(
578 Scheduler arg_scheduler, PredecessorFuture arg_future,
579 typename std::enable_if<Kokkos::is_scheduler<Scheduler>::value &&
580 Kokkos::is_future<PredecessorFuture>::value,
581 TaskPriority>::type arg_priority =
582 TaskPriority::Regular) {
583 static_assert(std::is_same<typename PredecessorFuture::scheduler_type,
584 Scheduler>::value,
585 "Can't create a task policy from a scheduler and a future from "
586 "a different scheduler");
587
588 return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
589}
590
591//----------------------------------------------------------------------------
592
599template <int TaskEnum, typename Scheduler, typename DepFutureType,
600 typename FunctorType>
601typename Scheduler::template future_type_for_functor<
602 typename std::decay<FunctorType>::type>
603host_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
604 arg_policy,
605 FunctorType&& arg_functor) {
606 using scheduler_type = Scheduler;
607 using task_type =
608 typename scheduler_type::template runnable_task_type<FunctorType>;
609
610 static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
611 TaskEnum == Impl::TaskType::TaskSingle,
612 "Kokkos host_spawn requires TaskTeam or TaskSingle");
613
614 // May be spawning a Cuda task, must use the specialization
615 // to query on-device function pointer.
616 typename task_type::function_type ptr;
617 typename task_type::destroy_type dtor;
618 Kokkos::Impl::TaskQueueSpecialization<
619 scheduler_type>::template get_function_pointer<task_type>(ptr, dtor);
620
621 return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
622 std::forward<FunctorType>(arg_functor));
623}
624
631template <int TaskEnum, typename Scheduler, typename DepFutureType,
632 typename FunctorType>
633typename Scheduler::template future_type_for_functor<
634 typename std::decay<FunctorType>::type>
635 KOKKOS_INLINE_FUNCTION
636 task_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
637 arg_policy,
638 FunctorType&& arg_functor) {
639 using scheduler_type = Scheduler;
640
641 using task_type =
642 typename scheduler_type::template runnable_task_type<FunctorType>;
643
644#if defined(KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST) && \
645 defined(KOKKOS_ENABLE_CUDA)
646
647 // This doesn't work with clang cuda
648 // static_assert(
649 // !std::is_same<Kokkos::Cuda, typename Scheduler::execution_space>::value,
650 // "Error calling Kokkos::task_spawn for Cuda space within Host code");
651
652#endif
653
654 static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
655 TaskEnum == Impl::TaskType::TaskSingle,
656 "Kokkos task_spawn requires TaskTeam or TaskSingle");
657
658 typename task_type::function_type const ptr = task_type::apply;
659 typename task_type::destroy_type const dtor = task_type::destroy;
660
661 return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
662 std::forward<FunctorType>(arg_functor));
663}
664
670template <typename FunctorType, typename T>
671void KOKKOS_INLINE_FUNCTION
672respawn(FunctorType* arg_self, T const& arg,
673 TaskPriority const& arg_priority = TaskPriority::Regular) {
674 static_assert(Kokkos::is_future<T>::value || Kokkos::is_scheduler<T>::value,
675 "Kokkos respawn argument must be Future or TaskScheduler");
676
677 T::scheduler_type::respawn(arg_self, arg, arg_priority);
678}
679
680//----------------------------------------------------------------------------
681
682// template<typename ValueType, typename Scheduler>
683// KOKKOS_INLINE_FUNCTION
684// BasicFuture<void, Scheduler>
685// when_all(BasicFuture<ValueType, Scheduler> const arg[], int narg)
686//{
687// return BasicFuture<void, Scheduler>::scheduler_type::when_all(arg, narg);
688//}
689
690//----------------------------------------------------------------------------
691// Wait for all runnable tasks to complete
692
693template <class ExecSpace, class QueueType>
694inline void wait(BasicTaskScheduler<ExecSpace, QueueType> const& scheduler) {
695 using scheduler_type = BasicTaskScheduler<ExecSpace, QueueType>;
696 scheduler_type::specialization::execute(scheduler);
697 // scheduler.m_queue->execute();
698}
699
700} // namespace Kokkos
701
702//----------------------------------------------------------------------------
703//----------------------------------------------------------------------------
704
706// END OLD CODE
708
709#endif /* #if defined( KOKKOS_ENABLE_TASKDAG ) */
710#endif /* #ifndef KOKKOS_TASKSCHEDULER_HPP */