3
// ************************************************************************
5
// Kokkos: Manycore Performance-Portable Multidimensional Arrays
6
// Copyright (2012) Sandia Corporation
8
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9
// the U.S. Government retains certain rights in this software.
11
// Redistribution and use in source and binary forms, with or without
12
// modification, are permitted provided that the following conditions are
15
// 1. Redistributions of source code must retain the above copyright
16
// notice, this list of conditions and the following disclaimer.
18
// 2. Redistributions in binary form must reproduce the above copyright
19
// notice, this list of conditions and the following disclaimer in the
20
// documentation and/or other materials provided with the distribution.
22
// 3. Neither the name of the Corporation nor the names of the
23
// contributors may be used to endorse or promote products derived from
24
// this software without specific prior written permission.
26
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
// Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
40
// ************************************************************************
44
// Experimental unified task-data parallel manycore LDRD
46
#ifndef KOKKOS_SERIAL_TASKPOLICY_HPP
47
#define KOKKOS_SERIAL_TASKPOLICY_HPP
49
#include <Kokkos_Macros.hpp>
50
#if defined( KOKKOS_HAVE_SERIAL )
56
#include <Kokkos_Serial.hpp>
57
#include <Kokkos_TaskPolicy.hpp>
58
#include <Kokkos_View.hpp>
60
#include <impl/Kokkos_FunctorAdapter.hpp>
62
//----------------------------------------------------------------------------
63
/* Inheritance structure to allow static_cast from the task root type
64
* and a task's FunctorType.
66
* task_root_type == TaskMember< Space , void , void >
68
* TaskMember< PolicyType , ResultType , FunctorType >
69
* : TaskMember< PolicyType::Space , ResultType , FunctorType >
72
* TaskMember< Space , ResultType , FunctorType >
73
* : TaskMember< Space , ResultType , void >
77
* when ResultType != void
79
* TaskMember< Space , ResultType , void >
80
* : TaskMember< Space , void , void >
84
//----------------------------------------------------------------------------
89
/** \brief Base class for all tasks in the Serial execution space */
91
class TaskMember< Kokkos::Serial , void , void >
95
typedef void (* function_apply_type) ( TaskMember * );
96
typedef void (* function_dealloc_type)( TaskMember * );
97
typedef TaskMember * (* function_verify_type) ( TaskMember * );
101
const function_dealloc_type m_dealloc ; ///< Deallocation
102
const function_verify_type m_verify ; ///< Result type verification
103
const function_apply_type m_apply ; ///< Apply function
104
TaskMember ** const m_dep ; ///< Dependences
105
TaskMember * m_wait ; ///< Linked list of tasks waiting on this task
106
TaskMember * m_next ; ///< Linked list of tasks waiting on a different task
107
const int m_dep_capacity ; ///< Capacity of dependences
108
int m_dep_size ; ///< Actual count of dependences
109
int m_ref_count ; ///< Reference count
110
int m_state ; ///< State of the task
112
// size = 6 Pointers + 4 ints
114
TaskMember() /* = delete */ ;
115
TaskMember( const TaskMember & ) /* = delete */ ;
116
TaskMember & operator = ( const TaskMember & ) /* = delete */ ;
118
static void * allocate( const unsigned arg_sizeof_derived , const unsigned arg_dependence_capacity );
119
static void deallocate( void * );
121
void throw_error_add_dependence() const ;
122
static void throw_error_verify_type();
124
template < class DerivedTaskType >
126
void deallocate( TaskMember * t )
128
DerivedTaskType * ptr = static_cast< DerivedTaskType * >(t);
129
ptr->~DerivedTaskType();
130
deallocate( (void *) ptr );
137
// Used by TaskMember< Serial , ResultType , void >
138
TaskMember( const function_verify_type arg_verify
139
, const function_dealloc_type arg_dealloc
140
, const function_apply_type arg_apply
141
, const unsigned arg_sizeof_derived
142
, const unsigned arg_dependence_capacity
145
// Used for TaskMember< Serial , void , void >
146
TaskMember( const function_dealloc_type arg_dealloc
147
, const function_apply_type arg_apply
148
, const unsigned arg_sizeof_derived
149
, const unsigned arg_dependence_capacity
154
template< typename ResultType >
155
KOKKOS_FUNCTION static
156
TaskMember * verify_type( TaskMember * t )
158
enum { check_type = ! Impl::is_same< ResultType , void >::value };
160
if ( check_type && t != 0 ) {
162
// Verify that t->m_verify is this function
163
const function_verify_type self = & TaskMember::template verify_type< ResultType > ;
165
if ( t->m_verify != self ) {
167
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
168
throw_error_verify_type();
175
//----------------------------------------
176
/* Inheritence Requirements on task types:
177
* typedef FunctorType::value_type value_type ;
178
* class DerivedTaskType
179
* : public TaskMember< Serial , value_type , FunctorType >
181
* class TaskMember< Serial , value_type , FunctorType >
182
* : public TaskMember< Serial , value_type , void >
185
* If value_type != void
186
* class TaskMember< Serial , value_type , void >
187
* : public TaskMember< Serial , void , void >
189
* Allocate space for DerivedTaskType followed by TaskMember*[ dependence_capacity ]
193
/** \brief Allocate and construct a single-thread task */
194
template< class DerivedTaskType >
196
TaskMember * create( const typename DerivedTaskType::functor_type & arg_functor
197
, const unsigned arg_dependence_capacity )
199
typedef typename DerivedTaskType::functor_type functor_type ;
200
typedef typename functor_type::value_type value_type ;
202
DerivedTaskType * const task =
203
new( allocate( sizeof(DerivedTaskType) , arg_dependence_capacity ) )
204
DerivedTaskType( & TaskMember::template deallocate< DerivedTaskType >
205
, & TaskMember::template apply_single< functor_type , value_type >
206
, sizeof(DerivedTaskType)
207
, arg_dependence_capacity
210
return static_cast< TaskMember * >( task );
213
/** \brief Allocate and construct a data parallel task */
214
template< class DerivedTaskType >
216
TaskMember * create( const typename DerivedTaskType::policy_type & arg_policy
217
, const typename DerivedTaskType::functor_type & arg_functor
218
, const unsigned arg_dependence_capacity )
220
DerivedTaskType * const task =
221
new( allocate( sizeof(DerivedTaskType) , arg_dependence_capacity ) )
222
DerivedTaskType( & TaskMember::template deallocate< DerivedTaskType >
223
, sizeof(DerivedTaskType)
224
, arg_dependence_capacity
229
return static_cast< TaskMember * >( task );
233
static void execute_ready_tasks();
234
static void wait( const Future< void , Kokkos::Serial > & );
236
//----------------------------------------
238
typedef FutureValueTypeIsVoidError get_result_type ;
240
KOKKOS_INLINE_FUNCTION
241
get_result_type get() const { return get_result_type() ; }
243
KOKKOS_INLINE_FUNCTION
244
Kokkos::TaskState get_state() const { return Kokkos::TaskState( m_state ); }
246
//----------------------------------------
248
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
250
void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false );
252
KOKKOS_INLINE_FUNCTION static
253
void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false ) {}
256
KOKKOS_INLINE_FUNCTION
257
TaskMember * get_dependence( int i ) const
258
{ return ( Kokkos::TASK_STATE_EXECUTING == m_state && 0 <= i && i < m_dep_size ) ? m_dep[i] : (TaskMember*) 0 ; }
260
KOKKOS_INLINE_FUNCTION
261
int get_dependence() const
262
{ return m_dep_size ; }
264
KOKKOS_INLINE_FUNCTION
265
void clear_dependence()
267
for ( int i = 0 ; i < m_dep_size ; ++i ) assign( m_dep + i , 0 );
271
KOKKOS_INLINE_FUNCTION
272
void add_dependence( TaskMember * before )
274
if ( ( Kokkos::TASK_STATE_CONSTRUCTING == m_state ||
275
Kokkos::TASK_STATE_EXECUTING == m_state ) &&
276
m_dep_size < m_dep_capacity ) {
277
assign( m_dep + m_dep_size , before );
281
throw_error_add_dependence();
285
//----------------------------------------
287
template< class FunctorType , class ResultType >
288
KOKKOS_INLINE_FUNCTION static
289
void apply_single( typename Impl::enable_if< ! Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
291
typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
293
// TaskMember< Kokkos::Serial , ResultType , FunctorType >
294
// : public TaskMember< Kokkos::Serial , ResultType , void >
295
// , public FunctorType
298
derived_type & m = * static_cast< derived_type * >( t );
300
Impl::FunctorApply< FunctorType , void , ResultType & >::apply( (FunctorType &) m , & m.m_result );
303
template< class FunctorType , class ResultType >
304
KOKKOS_INLINE_FUNCTION static
305
void apply_single( typename Impl::enable_if< Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
307
typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
309
// TaskMember< Kokkos::Serial , ResultType , FunctorType >
310
// : public TaskMember< Kokkos::Serial , ResultType , void >
311
// , public FunctorType
314
derived_type & m = * static_cast< derived_type * >( t );
316
Impl::FunctorApply< FunctorType , void , void >::apply( (FunctorType &) m );
320
//----------------------------------------------------------------------------
321
/** \brief Base class for tasks with a result value in the Serial execution space.
323
* The FunctorType must be void because this class is accessed by the
324
* Future class for the task and result value.
326
* Must be derived from TaskMember<S,void,void> 'root class' so the Future class
327
* can correctly static_cast from the 'root class' to this class.
329
template < class ResultType >
330
class TaskMember< Kokkos::Serial , ResultType , void >
331
: public TaskMember< Kokkos::Serial , void , void >
335
ResultType m_result ;
337
typedef const ResultType & get_result_type ;
339
KOKKOS_INLINE_FUNCTION
340
get_result_type get() const { return m_result ; }
344
typedef TaskMember< Kokkos::Serial , void , void > task_root_type ;
345
typedef task_root_type::function_dealloc_type function_dealloc_type ;
346
typedef task_root_type::function_apply_type function_apply_type ;
349
TaskMember( const function_dealloc_type arg_dealloc
350
, const function_apply_type arg_apply
351
, const unsigned arg_sizeof_derived
352
, const unsigned arg_dependence_capacity
354
: task_root_type( & task_root_type::template verify_type< ResultType >
358
, arg_dependence_capacity )
364
template< class ResultType , class FunctorType >
365
class TaskMember< Kokkos::Serial , ResultType , FunctorType >
366
: public TaskMember< Kokkos::Serial , ResultType , void >
371
typedef FunctorType functor_type ;
373
typedef TaskMember< Kokkos::Serial , void , void > task_root_type ;
374
typedef TaskMember< Kokkos::Serial , ResultType , void > task_base_type ;
375
typedef task_root_type::function_dealloc_type function_dealloc_type ;
376
typedef task_root_type::function_apply_type function_apply_type ;
379
TaskMember( const function_dealloc_type arg_dealloc
380
, const function_apply_type arg_apply
381
, const unsigned arg_sizeof_derived
382
, const unsigned arg_dependence_capacity
383
, const functor_type & arg_functor
385
: task_base_type( arg_dealloc , arg_apply , arg_sizeof_derived , arg_dependence_capacity )
386
, functor_type( arg_functor )
390
//----------------------------------------------------------------------------
391
/** \brief ForEach task in the Serial execution space
393
* Derived from TaskMember< Kokkos::Serial , ResultType , FunctorType >
394
* so that Functor can be cast to task root type without knowing policy.
396
template< class Arg0 , class Arg1 , class Arg2 , class ResultType , class FunctorType >
397
class TaskForEach< Kokkos::RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial >
400
: TaskMember< Kokkos::Serial , ResultType , FunctorType >
404
typedef FunctorType functor_type ;
405
typedef RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial > policy_type ;
409
friend class Kokkos::TaskPolicy< Kokkos::Serial > ;
410
friend class Kokkos::Impl::TaskMember< Kokkos::Serial , void , void > ;
412
typedef TaskMember< Kokkos::Serial , void , void > task_root_type ;
413
typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > task_base_type ;
414
typedef task_root_type::function_dealloc_type function_dealloc_type ;
416
policy_type m_policy ;
418
template< class Tag >
420
typename Impl::enable_if< Impl::is_same<Tag,void>::value >::type
423
const typename policy_type::member_type e = m_policy.end();
424
for ( typename policy_type::member_type i = m_policy.begin() ; i < e ; ++i ) {
425
functor_type::operator()(i);
429
template< class Tag >
431
typename Impl::enable_if< ! Impl::is_same<Tag,void>::value >::type
435
const typename policy_type::member_type e = m_policy.end();
436
for ( typename policy_type::member_type i = m_policy.begin() ; i < e ; ++i ) {
437
functor_type::operator()(tag,i);
442
void apply_parallel( task_root_type * t )
444
static_cast<TaskForEach*>(t)->template apply_policy< typename policy_type::work_tag >();
446
task_root_type::template apply_single< functor_type , ResultType >( t );
449
TaskForEach( const function_dealloc_type arg_dealloc
450
, const int arg_sizeof_derived
451
, const int arg_dependence_capacity
452
, const policy_type & arg_policy
453
, const functor_type & arg_functor
455
: task_base_type( arg_dealloc
458
, arg_dependence_capacity
460
, m_policy( arg_policy )
463
TaskForEach() /* = delete */ ;
464
TaskForEach( const TaskForEach & ) /* = delete */ ;
465
TaskForEach & operator = ( const TaskForEach & ) /* = delete */ ;
468
//----------------------------------------------------------------------------
469
/** \brief Reduce task in the Serial execution space
471
* Derived from TaskMember< Kokkos::Serial , ResultType , FunctorType >
472
* so that Functor can be cast to task root type without knowing policy.
474
template< class Arg0 , class Arg1 , class Arg2 , class ResultType , class FunctorType >
475
class TaskReduce< Kokkos::RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial >
478
: TaskMember< Kokkos::Serial , ResultType , FunctorType >
482
typedef FunctorType functor_type ;
483
typedef RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial > policy_type ;
487
friend class Kokkos::TaskPolicy< Kokkos::Serial > ;
488
friend class Kokkos::Impl::TaskMember< Kokkos::Serial , void , void > ;
490
typedef TaskMember< Kokkos::Serial , void , void > task_root_type ;
491
typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > task_base_type ;
492
typedef task_root_type::function_dealloc_type function_dealloc_type ;
494
policy_type m_policy ;
496
template< class Tag >
498
void apply_policy( typename Impl::enable_if< Impl::is_same<Tag,void>::value , ResultType & >::type result ) const
500
Impl::FunctorValueInit< functor_type , Tag >::init( *this , & result );
501
const typename policy_type::member_type e = m_policy.end();
502
for ( typename policy_type::member_type i = m_policy.begin() ; i < e ; ++i ) {
503
functor_type::operator()( i, result );
507
template< class Tag >
509
void apply_policy( typename Impl::enable_if< ! Impl::is_same<Tag,void>::value , ResultType & >::type result ) const
511
Impl::FunctorValueInit< functor_type , Tag >::init( *this , & result );
513
const typename policy_type::member_type e = m_policy.end();
514
for ( typename policy_type::member_type i = m_policy.begin() ; i < e ; ++i ) {
515
functor_type::operator()( tag, i, result );
520
void apply_parallel( task_root_type * t )
522
TaskReduce * const task = static_cast<TaskReduce*>(t);
524
task->template apply_policy< typename policy_type::work_tag >( task->task_base_type::m_result );
526
task_root_type::template apply_single< functor_type , ResultType >( t );
529
TaskReduce( const function_dealloc_type arg_dealloc
530
, const int arg_sizeof_derived
531
, const int arg_dependence_capacity
532
, const policy_type & arg_policy
533
, const functor_type & arg_functor
535
: task_base_type( arg_dealloc
538
, arg_dependence_capacity
540
, m_policy( arg_policy )
543
TaskReduce() /* = delete */ ;
544
TaskReduce( const TaskReduce & ) /* = delete */ ;
545
TaskReduce & operator = ( const TaskReduce & ) /* = delete */ ;
548
} /* namespace Impl */
549
} /* namespace Kokkos */
551
//----------------------------------------------------------------------------
552
//----------------------------------------------------------------------------
557
class TaskPolicy< Kokkos::Serial >
561
typedef Kokkos::Serial execution_space ;
565
typedef Impl::TaskMember< execution_space , void , void > task_root_type ;
567
TaskPolicy & operator = ( const TaskPolicy & ) /* = delete */ ;
569
template< class FunctorType >
571
const task_root_type * get_task_root( const FunctorType * f )
573
typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
574
return static_cast< const task_root_type * >( static_cast< const task_type * >(f) );
577
template< class FunctorType >
579
task_root_type * get_task_root( FunctorType * f )
581
typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
582
return static_cast< task_root_type * >( static_cast< task_type * >(f) );
585
const unsigned m_default_dependence_capacity ;
589
KOKKOS_INLINE_FUNCTION
590
TaskPolicy() : m_default_dependence_capacity(4) {}
592
KOKKOS_INLINE_FUNCTION
593
TaskPolicy( const TaskPolicy & rhs ) : m_default_dependence_capacity( rhs.m_default_dependence_capacity ) {}
595
KOKKOS_INLINE_FUNCTION
597
TaskPolicy( const unsigned arg_default_dependence_capacity )
598
: m_default_dependence_capacity( arg_default_dependence_capacity ) {}
600
KOKKOS_INLINE_FUNCTION
601
TaskPolicy( const TaskPolicy &
602
, const unsigned arg_default_dependence_capacity )
603
: m_default_dependence_capacity( arg_default_dependence_capacity ) {}
605
//----------------------------------------
607
template< class ValueType >
608
KOKKOS_INLINE_FUNCTION
609
const Future< ValueType , execution_space > &
610
spawn( const Future< ValueType , execution_space > & f ) const
612
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
613
f.m_task->schedule();
618
// Create single-thread task
620
template< class FunctorType >
621
KOKKOS_INLINE_FUNCTION
622
Future< typename FunctorType::value_type , execution_space >
623
create( const FunctorType & functor
624
, const unsigned dependence_capacity = ~0u ) const
626
typedef typename FunctorType::value_type value_type ;
627
typedef Impl::TaskMember< execution_space , value_type , FunctorType > task_type ;
628
return Future< value_type , execution_space >(
629
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
630
task_root_type::create< task_type >(
631
functor , ( ~0u == dependence_capacity ? m_default_dependence_capacity : dependence_capacity ) )
636
// Create parallel foreach task
638
template< class PolicyType , class FunctorType >
639
KOKKOS_INLINE_FUNCTION
640
Future< typename FunctorType::value_type , execution_space >
641
create_foreach( const PolicyType & policy
642
, const FunctorType & functor
643
, const unsigned dependence_capacity = ~0u ) const
645
typedef typename FunctorType::value_type value_type ;
646
typedef Impl::TaskForEach< PolicyType , value_type , FunctorType > task_type ;
647
return Future< value_type , execution_space >(
648
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
649
task_root_type::create< task_type >( policy , functor ,
650
( ~0u == dependence_capacity ? m_default_dependence_capacity : dependence_capacity ) )
655
// Create parallel reduce task
657
template< class PolicyType , class FunctorType >
658
KOKKOS_INLINE_FUNCTION
659
Future< typename FunctorType::value_type , execution_space >
660
create_reduce( const PolicyType & policy
661
, const FunctorType & functor
662
, const unsigned dependence_capacity = ~0u ) const
664
typedef typename FunctorType::value_type value_type ;
665
typedef Impl::TaskReduce< PolicyType , value_type , FunctorType > task_type ;
666
return Future< value_type , execution_space >(
667
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
668
task_root_type::create< task_type >( policy , functor ,
669
( ~0u == dependence_capacity ? m_default_dependence_capacity : dependence_capacity ) )
675
template< class A1 , class A2 , class A3 , class A4 >
676
KOKKOS_INLINE_FUNCTION
677
void add_dependence( const Future<A1,A2> & after
678
, const Future<A3,A4> & before
679
, typename Impl::enable_if
680
< Impl::is_same< typename Future<A1,A2>::execution_space , execution_space >::value
682
Impl::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
686
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
687
after.m_task->add_dependence( before.m_task );
691
//----------------------------------------
692
// Functions for an executing task functor to query dependences,
693
// set new dependences, and respawn itself.
695
template< class FunctorType >
696
KOKKOS_INLINE_FUNCTION
697
Future< void , execution_space >
698
get_dependence( const FunctorType * task_functor , int i ) const
700
return Future<void,execution_space>(
701
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
702
get_task_root(task_functor)->get_dependence(i)
707
template< class FunctorType >
708
KOKKOS_INLINE_FUNCTION
709
int get_dependence( const FunctorType * task_functor ) const
710
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
711
{ return get_task_root(task_functor)->get_dependence(); }
716
template< class FunctorType >
717
KOKKOS_INLINE_FUNCTION
718
void clear_dependence( FunctorType * task_functor ) const
719
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
720
{ get_task_root(task_functor)->clear_dependence(); }
725
template< class FunctorType , class A3 , class A4 >
726
KOKKOS_INLINE_FUNCTION
727
void add_dependence( FunctorType * task_functor
728
, const Future<A3,A4> & before
729
, typename Impl::enable_if
730
< Impl::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
733
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
734
{ get_task_root(task_functor)->add_dependence( before.m_task ); }
739
template< class FunctorType >
740
KOKKOS_INLINE_FUNCTION
741
void respawn( FunctorType * task_functor ) const
742
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
743
{ get_task_root(task_functor)->schedule(); }
750
void wait( TaskPolicy< Kokkos::Serial > & )
751
{ Impl::TaskMember< Kokkos::Serial , void , void >::execute_ready_tasks(); }
754
void wait( const Future< void , Kokkos::Serial > & future )
755
{ Impl::TaskMember< Kokkos::Serial , void , void >::wait( future ); }
757
} // namespace Kokkos
759
//----------------------------------------------------------------------------
761
#endif /* defined( KOKKOS_HAVE_SERIAL ) */
762
#endif /* #define KOKKOS_SERIAL_TASK_HPP */