17 #include <Kokkos_Macros.hpp> 
   19 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE 
   21               "Including non-public Kokkos header files is not allowed.");
 
   24 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE_4 
   25 #error "The tasking framework is deprecated" 
   28 #ifndef KOKKOS_TASKSCHEDULER_HPP 
   29 #define KOKKOS_TASKSCHEDULER_HPP 
   33 #include <Kokkos_Macros.hpp> 
   34 #if defined(KOKKOS_ENABLE_TASKDAG) 
   36 #include <Kokkos_Core_fwd.hpp> 
   37 #include <Kokkos_TaskScheduler_fwd.hpp> 
   40 #include <Kokkos_MemoryPool.hpp> 
   42 #include <Kokkos_Future.hpp> 
   43 #include <impl/Kokkos_TaskQueue.hpp> 
   44 #include <impl/Kokkos_SingleTaskQueue.hpp> 
   45 #include <impl/Kokkos_TaskQueueMultiple.hpp> 
   46 #include <impl/Kokkos_TaskPolicyData.hpp> 
   47 #include <impl/Kokkos_TaskTeamMember.hpp> 
   48 #include <impl/Kokkos_SimpleTaskScheduler.hpp> 
   53 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS 
   55 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_PUSH()
 
   62 template <
class, 
class>
 
   67 template <
class ExecSpace, 
class QueueType>
 
   68 class KOKKOS_DEPRECATED BasicTaskScheduler : 
public Impl::TaskSchedulerBase {
 
   70   using scheduler_type      = BasicTaskScheduler;
 
   71   using execution_space     = ExecSpace;
 
   72   using queue_type          = QueueType;
 
   73   using memory_space        = 
typename queue_type::memory_space;
 
   74   using memory_pool         = 
typename queue_type::memory_pool;
 
   75   using specialization      = Impl::TaskQueueSpecialization<BasicTaskScheduler>;
 
   76   using member_type         = 
typename specialization::member_type;
 
   77   using team_scheduler_type = BasicTaskScheduler;
 
   78   template <
class Functor>
 
   79   using runnable_task_type =
 
   80       Impl::Task<scheduler_type, typename Functor::value_type, Functor>;
 
   81   template <
class ValueType>
 
   82   using future_type = Kokkos::BasicFuture<ValueType, BasicTaskScheduler>;
 
   83   template <
class FunctorType>
 
   84   using future_type_for_functor = future_type<typename FunctorType::value_type>;
 
   87   using track_type = Kokkos::Impl::SharedAllocationTracker;
 
   88   using task_base  = Impl::TaskBase;
 
   95   template <
typename, 
typename>
 
   96   friend class Impl::TaskQueue;
 
   98   friend struct Impl::TaskQueueSpecialization;
 
   99   template <
typename, 
typename>
 
  100   friend class Impl::TaskQueueSpecializationConstrained;
 
  101   template <
typename, 
typename>
 
  102   friend class Impl::TaskTeamMemberAdapter;
 
  103   template <
typename, 
typename>
 
  104   friend class Impl::TaskExec;
 
  108   KOKKOS_INLINE_FUNCTION
 
  109   BasicTaskScheduler(track_type arg_track, queue_type* arg_queue)
 
  110       : m_track(std::move(arg_track)), m_queue(std::move(arg_queue)) {}
 
  112   KOKKOS_INLINE_FUNCTION
 
  113   team_scheduler_type get_team_scheduler(
int team_rank)
 const {
 
  114     return {m_track, &m_queue->get_team_queue(team_rank)};
 
  119   KOKKOS_INLINE_FUNCTION
 
  120   static constexpr task_base* _get_task_ptr(std::nullptr_t) { 
return nullptr; }
 
  122   template <
class ValueType>
 
  123   KOKKOS_INLINE_FUNCTION 
static constexpr task_base* _get_task_ptr(
 
  124       future_type<ValueType>&& f) {
 
  128   template <
int TaskEnum, 
typename DepTaskType, 
typename FunctorType>
 
  130       Kokkos::BasicFuture<typename FunctorType::value_type, scheduler_type>
 
  131       _spawn_impl(DepTaskType* arg_predecessor_task, TaskPriority arg_priority,
 
  132                   typename task_base::function_type arg_function,
 
  133                   typename task_base::destroy_type ,
 
  134                   FunctorType&& arg_functor) {
 
  135     using functor_future_type =
 
  136         future_type_for_functor<std::decay_t<FunctorType>>;
 
  138         Impl::Task<BasicTaskScheduler, 
typename functor_future_type::value_type,
 
  150     functor_future_type f;
 
  154     const size_t alloc_size =
 
  155         m_queue->template spawn_allocation_size<FunctorType>();
 
  157     void* task_storage = m_queue->allocate(alloc_size);
 
  165           new (task_storage) task_type(std::forward<FunctorType>(arg_functor));
 
  167       f.m_task->m_apply = arg_function;
 
  169       f.m_task->m_queue      = m_queue;
 
  170       f.m_task->m_next       = arg_predecessor_task;
 
  171       f.m_task->m_ref_count  = 2;
 
  172       f.m_task->m_alloc_size = alloc_size;
 
  173       f.m_task->m_task_type  = TaskEnum;
 
  174       f.m_task->m_priority   = (int16_t)arg_priority;
 
  176       Kokkos::memory_fence();
 
  183       m_queue->schedule_runnable(f.m_task);
 
  192   KOKKOS_INLINE_FUNCTION
 
  193   BasicTaskScheduler() : m_track(), m_queue(nullptr) {}
 
  195   KOKKOS_INLINE_FUNCTION
 
  196   BasicTaskScheduler(BasicTaskScheduler&& rhs) noexcept
 
  197       : m_track(rhs.m_track),  
 
  199         m_queue(std::move(rhs.m_queue)) {}
 
  201   KOKKOS_INLINE_FUNCTION
 
  202   BasicTaskScheduler(BasicTaskScheduler 
const& rhs)
 
  203       : m_track(rhs.m_track), m_queue(rhs.m_queue) {}
 
  205   KOKKOS_INLINE_FUNCTION
 
  206   BasicTaskScheduler& operator=(BasicTaskScheduler&& rhs) noexcept {
 
  207     m_track = rhs.m_track;  
 
  209     m_queue = std::move(rhs.m_queue);
 
  213   KOKKOS_INLINE_FUNCTION
 
  214   BasicTaskScheduler& operator=(BasicTaskScheduler 
const& rhs) {
 
  215     if (&rhs == 
this) 
return *
this;
 
  216     m_track = rhs.m_track;
 
  217     m_queue = rhs.m_queue;
 
  221   explicit BasicTaskScheduler(memory_pool 
const& arg_memory_pool) noexcept
 
  222       : m_track(), m_queue(
nullptr) {
 
  224         Kokkos::Impl::SharedAllocationRecord<memory_space,
 
  225                                              typename queue_type::Destroy>;
 
  227     record_type* record = record_type::allocate(
 
  228         memory_space(), 
"Kokkos::TaskQueue", 
sizeof(queue_type));
 
  230     m_queue = 
new (record->data()) queue_type(arg_memory_pool);
 
  232     record->m_destroy.m_queue = m_queue;
 
  234     m_track.assign_allocated_record_to_uninitialized(record);
 
  237   BasicTaskScheduler(memory_space 
const& arg_memory_space,
 
  238                      size_t const mempool_capacity,
 
  239                      unsigned const mempool_min_block_size  
 
  241                      unsigned const mempool_max_block_size  
 
  243                      unsigned const mempool_superblock_size  
 
  245       : BasicTaskScheduler(memory_pool(
 
  246             arg_memory_space, mempool_capacity, mempool_min_block_size,
 
  247             mempool_max_block_size, mempool_superblock_size)) {}
 
  251   KOKKOS_INLINE_FUNCTION
 
  252   queue_type& queue() const noexcept {
 
  253     KOKKOS_EXPECTS(m_queue != 
nullptr);
 
  257   KOKKOS_INLINE_FUNCTION
 
  258   memory_pool* memory() const noexcept {
 
  259     return m_queue ? &(m_queue->m_memory) : (memory_pool*)0;
 
  264   template <
typename FunctorType>
 
  265   KOKKOS_FUNCTION 
size_t spawn_allocation_size()
 const {
 
  266     return m_queue->template spawn_allocation_size<FunctorType>();
 
  271   size_t when_all_allocation_size(
int narg)
 const {
 
  272     return m_queue->when_all_allocation_size(narg);
 
  277   template <
int TaskEnum, 
typename DepFutureType, 
typename FunctorType>
 
  278   KOKKOS_FUNCTION 
static Kokkos::BasicFuture<
typename FunctorType::value_type,
 
  280   spawn(Impl::TaskPolicyWithScheduler<TaskEnum, scheduler_type, DepFutureType>&&
 
  282         typename task_base::function_type arg_function,
 
  283         typename task_base::destroy_type arg_destroy,
 
  284         FunctorType&& arg_functor) {
 
  285     return std::move(arg_policy.scheduler())
 
  286         .
template _spawn_impl<TaskEnum>(
 
  287             _get_task_ptr(std::move(arg_policy.predecessor())),
 
  288             arg_policy.priority(), arg_function, arg_destroy,
 
  289             std::forward<FunctorType>(arg_functor));
 
  292   template <
int TaskEnum, 
typename DepFutureType, 
typename FunctorType>
 
  293   KOKKOS_FUNCTION future_type_for_functor<std::decay_t<FunctorType>> spawn(
 
  294       Impl::TaskPolicyWithPredecessor<TaskEnum, DepFutureType>&& arg_policy,
 
  295       FunctorType&& arg_functor) {
 
  296     using task_type = runnable_task_type<FunctorType>;
 
  297     typename task_type::function_type 
const ptr = task_type::apply;
 
  298     typename task_type::destroy_type 
const dtor = task_type::destroy;
 
  300     auto const priority = arg_policy.priority();
 
  301     return _spawn_impl<TaskEnum>(
 
  302         _get_task_ptr(std::move(arg_policy).predecessor()), priority, ptr, dtor,
 
  303         std::forward<FunctorType>(arg_functor));
 
  306   template <
typename FunctorType, 
typename ValueType, 
typename Scheduler>
 
  307   KOKKOS_FUNCTION 
static void respawn(
 
  308       FunctorType* arg_self,
 
  309       BasicFuture<ValueType, Scheduler> 
const& arg_dependence,
 
  310       TaskPriority 
const& arg_priority) {
 
  313     using value_type = 
typename FunctorType::value_type;
 
  314     using task_type  = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
 
  316     task_type* 
const task = 
static_cast<task_type*
>(arg_self);
 
  318     task->m_priority = 
static_cast<int>(arg_priority);
 
  320     task->add_dependence(arg_dependence.m_task);
 
  325   template <
typename FunctorType>
 
  326   KOKKOS_FUNCTION 
static void respawn(FunctorType* arg_self,
 
  327                                       BasicTaskScheduler 
const&,
 
  328                                       TaskPriority 
const& arg_priority) {
 
  331     using value_type = 
typename FunctorType::value_type;
 
  332     using task_type  = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
 
  334     task_type* 
const task = 
static_cast<task_type*
>(arg_self);
 
  336     task->m_priority = 
static_cast<int>(arg_priority);
 
  338     task->add_dependence(
nullptr);
 
  347   template <
typename ValueType>
 
  348   KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(
 
  349       BasicFuture<ValueType, BasicTaskScheduler> 
const arg[], 
int narg) {
 
  353       queue_type* q = m_queue;
 
  357       for (
int i = 0; i < narg; ++i) {
 
  358         task_base* 
const t = arg[i].m_task;
 
  362           desul::atomic_inc(&(t->m_ref_count), desul::MemoryOrderSeqCst(),
 
  363                             desul::MemoryScopeDevice());
 
  364           if (q != static_cast<queue_type const*>(t->m_queue)) {
 
  366                 "Kokkos when_all Futures must be in the same scheduler");
 
  374         size_t const alloc_size = q->when_all_allocation_size(narg);
 
  376         f.m_task = 
reinterpret_cast<task_base*
>(q->allocate(alloc_size));
 
  384           new (f.m_task) task_base();
 
  386           f.m_task->m_queue      = q;
 
  387           f.m_task->m_ref_count  = 2;
 
  388           f.m_task->m_alloc_size = 
static_cast<int32_t
>(alloc_size);
 
  389           f.m_task->m_dep_count  = narg;
 
  390           f.m_task->m_task_type  = task_base::Aggregate;
 
  394           task_base* 
volatile* 
const dep = f.m_task->aggregate_dependences();
 
  396           for (
int i = 0; i < narg; ++i) {
 
  397             dep[i] = arg[i].m_task;
 
  400           Kokkos::memory_fence();
 
  402           q->schedule_aggregate(f.m_task);
 
  412   KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(
int narg,
 
  414     using input_type = decltype(func(0));
 
  416     static_assert(is_future<input_type>::value,
 
  417                   "Functor must return a Kokkos::Future");
 
  421     if (0 == narg) 
return f;
 
  423     size_t const alloc_size = m_queue->when_all_allocation_size(narg);
 
  425     f.m_task = 
reinterpret_cast<task_base*
>(m_queue->allocate(alloc_size));
 
  432       new (f.m_task) task_base();
 
  436       f.m_task->m_queue      = m_queue;
 
  437       f.m_task->m_ref_count  = 2;
 
  438       f.m_task->m_alloc_size = 
static_cast<int32_t
>(alloc_size);
 
  439       f.m_task->m_dep_count  = narg;
 
  440       f.m_task->m_task_type  = task_base::Aggregate;
 
  446       task_base* 
volatile* 
const dep = f.m_task->aggregate_dependences();
 
  448       for (
int i = 0; i < narg; ++i) {
 
  449         const input_type arg_f = func(i);
 
  450         if (
nullptr != arg_f.m_task) {
 
  459           desul::atomic_inc(&(arg_f.m_task->m_ref_count),
 
  460                             desul::MemoryOrderSeqCst(),
 
  461                             desul::MemoryScopeDevice());
 
  462           dep[i] = arg_f.m_task;
 
  466       Kokkos::memory_fence();
 
  468       m_queue->schedule_aggregate(f.m_task);
 
  476   KOKKOS_INLINE_FUNCTION
 
  477   int allocation_capacity() const noexcept {
 
  478     return m_queue->m_memory.capacity();
 
  481   KOKKOS_INLINE_FUNCTION
 
  482   int allocated_task_count() const noexcept { 
return m_queue->m_count_alloc; }
 
  484   KOKKOS_INLINE_FUNCTION
 
  485   int allocated_task_count_max() const noexcept { 
return m_queue->m_max_alloc; }
 
  487   KOKKOS_INLINE_FUNCTION
 
  488   long allocated_task_count_accum() const noexcept {
 
  489     return m_queue->m_accum_alloc;
 
  494   template <
class S, 
class Q>
 
  495   friend void wait(Kokkos::BasicTaskScheduler<S, Q> 
const&);
 
  508 template <
class T, 
class Scheduler>
 
  509 KOKKOS_DEPRECATED Impl::TaskPolicyWithPredecessor<
 
  510     Impl::TaskType::TaskTeam, Kokkos::BasicFuture<T, Scheduler>>
 
  511     KOKKOS_INLINE_FUNCTION
 
  512     TaskTeam(Kokkos::BasicFuture<T, Scheduler> arg_future,
 
  513              TaskPriority arg_priority = TaskPriority::Regular) {
 
  514   return {std::move(arg_future), arg_priority};
 
  517 template <
class Scheduler>
 
  518 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskTeam,
 
  520     KOKKOS_INLINE_FUNCTION TaskTeam(
 
  521         Scheduler arg_scheduler,
 
  522         std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value, TaskPriority>
 
  523             arg_priority = TaskPriority::Regular) {
 
  524   return {std::move(arg_scheduler), arg_priority};
 
  527 template <
class Scheduler, 
class PredecessorFuture>
 
  528 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<
 
  529     Kokkos::Impl::TaskType::TaskTeam, Scheduler, PredecessorFuture>
 
  530     KOKKOS_INLINE_FUNCTION
 
  531     TaskTeam(Scheduler arg_scheduler, PredecessorFuture arg_future,
 
  532              std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value &&
 
  533                                   Kokkos::is_future<PredecessorFuture>::value,
 
  535                  arg_priority = TaskPriority::Regular) {
 
  537       std::is_same_v<typename PredecessorFuture::scheduler_type, Scheduler>,
 
  538       "Can't create a task policy from a scheduler and a future from " 
  539       "a different scheduler");
 
  541   return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
 
  546 template <
class T, 
class Scheduler>
 
  547 KOKKOS_DEPRECATED Impl::TaskPolicyWithPredecessor<
 
  548     Impl::TaskType::TaskSingle, Kokkos::BasicFuture<T, Scheduler>>
 
  549     KOKKOS_INLINE_FUNCTION
 
  550     TaskSingle(Kokkos::BasicFuture<T, Scheduler> arg_future,
 
  551                TaskPriority arg_priority = TaskPriority::Regular) {
 
  552   return {std::move(arg_future), arg_priority};
 
  555 template <
class Scheduler>
 
  556 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskSingle,
 
  558     KOKKOS_INLINE_FUNCTION TaskSingle(
 
  559         Scheduler arg_scheduler,
 
  560         std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value, TaskPriority>
 
  561             arg_priority = TaskPriority::Regular) {
 
  562   return {std::move(arg_scheduler), arg_priority};
 
  565 template <
class Scheduler, 
class PredecessorFuture>
 
  566 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<
 
  567     Kokkos::Impl::TaskType::TaskSingle, Scheduler, PredecessorFuture>
 
  568     KOKKOS_INLINE_FUNCTION
 
  569     TaskSingle(Scheduler arg_scheduler, PredecessorFuture arg_future,
 
  570                std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value &&
 
  571                                     Kokkos::is_future<PredecessorFuture>::value,
 
  573                    arg_priority = TaskPriority::Regular) {
 
  575       std::is_same_v<typename PredecessorFuture::scheduler_type, Scheduler>,
 
  576       "Can't create a task policy from a scheduler and a future from " 
  577       "a different scheduler");
 
  579   return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
 
  590 template <
int TaskEnum, 
typename Scheduler, 
typename DepFutureType,
 
  591           typename FunctorType>
 
  592 KOKKOS_DEPRECATED 
typename Scheduler::template future_type_for_functor<
 
  593     std::decay_t<FunctorType>>
 
  594 host_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
 
  596            FunctorType&& arg_functor) {
 
  597   using scheduler_type = Scheduler;
 
  599       typename scheduler_type::template runnable_task_type<FunctorType>;
 
  601   static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
 
  602                     TaskEnum == Impl::TaskType::TaskSingle,
 
  603                 "Kokkos host_spawn requires TaskTeam or TaskSingle");
 
  607   typename task_type::function_type ptr;
 
  608   typename task_type::destroy_type dtor;
 
  609   Kokkos::Impl::TaskQueueSpecialization<
 
  610       scheduler_type>::template get_function_pointer<task_type>(ptr, dtor);
 
  612   return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
 
  613                                std::forward<FunctorType>(arg_functor));
 
  622 template <
int TaskEnum, 
typename Scheduler, 
typename DepFutureType,
 
  623           typename FunctorType>
 
  624 KOKKOS_DEPRECATED 
typename Scheduler::template future_type_for_functor<
 
  625     std::decay_t<FunctorType>>
 
  626     KOKKOS_INLINE_FUNCTION
 
  627     task_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
 
  629                FunctorType&& arg_functor) {
 
  630   using scheduler_type = Scheduler;
 
  633       typename scheduler_type::template runnable_task_type<FunctorType>;
 
  635   static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
 
  636                     TaskEnum == Impl::TaskType::TaskSingle,
 
  637                 "Kokkos task_spawn requires TaskTeam or TaskSingle");
 
  639   typename task_type::function_type 
const ptr = task_type::apply;
 
  640   typename task_type::destroy_type 
const dtor = task_type::destroy;
 
  642   return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
 
  643                                std::forward<FunctorType>(arg_functor));
 
  651 template <
typename FunctorType, 
typename T>
 
  652 KOKKOS_DEPRECATED 
void KOKKOS_INLINE_FUNCTION
 
  653 respawn(FunctorType* arg_self, T 
const& arg,
 
  654         TaskPriority 
const& arg_priority = TaskPriority::Regular) {
 
  655   static_assert(Kokkos::is_future<T>::value || Kokkos::is_scheduler<T>::value,
 
  656                 "Kokkos respawn argument must be Future or TaskScheduler");
 
  658   T::scheduler_type::respawn(arg_self, arg, arg_priority);
 
  674 template <
class ExecSpace, 
class QueueType>
 
  675 KOKKOS_DEPRECATED 
inline void wait(
 
  676     BasicTaskScheduler<ExecSpace, QueueType> 
const& scheduler) {
 
  677   using scheduler_type = BasicTaskScheduler<ExecSpace, QueueType>;
 
  678   scheduler_type::specialization::execute(scheduler);
 
  684 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS 
  685 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_POP()