~ubuntu-branches/debian/sid/lammps/sid

« back to all changes in this revision

Viewing changes to lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.hpp

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2015-04-29 23:44:49 UTC
  • mfrom: (5.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20150429234449-mbhy9utku6hp6oq8
Tags: 0~20150313.gitfa668e1-1
Upload into unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
//@HEADER
 
3
// ************************************************************************
 
4
//
 
5
//   Kokkos: Manycore Performance-Portable Multidimensional Arrays
 
6
//              Copyright (2012) Sandia Corporation
 
7
//
 
8
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 
9
// the U.S. Government retains certain rights in this software.
 
10
//
 
11
// Redistribution and use in source and binary forms, with or without
 
12
// modification, are permitted provided that the following conditions are
 
13
// met:
 
14
//
 
15
// 1. Redistributions of source code must retain the above copyright
 
16
// notice, this list of conditions and the following disclaimer.
 
17
//
 
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.
 
21
//
 
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.
 
25
//
 
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.
 
37
//
 
38
// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
 
39
//
 
40
// ************************************************************************
 
41
//@HEADER
 
42
*/
 
43
 
 
44
// Experimental unified task-data parallel manycore LDRD
 
45
 
 
46
#ifndef KOKKOS_SERIAL_TASKPOLICY_HPP
 
47
#define KOKKOS_SERIAL_TASKPOLICY_HPP
 
48
 
 
49
#include <Kokkos_Macros.hpp>
 
50
#if defined( KOKKOS_HAVE_SERIAL )
 
51
 
 
52
#include <string>
 
53
#include <typeinfo>
 
54
#include <stdexcept>
 
55
 
 
56
#include <Kokkos_Serial.hpp>
 
57
#include <Kokkos_TaskPolicy.hpp>
 
58
#include <Kokkos_View.hpp>
 
59
 
 
60
#include <impl/Kokkos_FunctorAdapter.hpp>
 
61
 
 
62
//----------------------------------------------------------------------------
 
63
/*  Inheritance structure to allow static_cast from the task root type
 
64
 *  and a task's FunctorType.
 
65
 *
 
66
 *    task_root_type == TaskMember< Space , void , void >
 
67
 *
 
68
 *    TaskMember< PolicyType , ResultType , FunctorType >
 
69
 *      : TaskMember< PolicyType::Space , ResultType , FunctorType >
 
70
 *      { ... };
 
71
 *
 
72
 *    TaskMember< Space , ResultType , FunctorType >
 
73
 *      : TaskMember< Space , ResultType , void >
 
74
 *      , FunctorType
 
75
 *      { ... };
 
76
 *
 
77
 *  when ResultType != void
 
78
 *
 
79
 *    TaskMember< Space , ResultType , void >
 
80
 *      : TaskMember< Space , void , void >
 
81
 *      { ... };
 
82
 *
 
83
 */
 
84
//----------------------------------------------------------------------------
 
85
 
 
86
namespace Kokkos {
 
87
namespace Impl {
 
88
 
 
89
/** \brief  Base class for all tasks in the Serial execution space */
 
90
template<>
 
91
class TaskMember< Kokkos::Serial , void , void >
 
92
{
 
93
public:
 
94
 
 
95
  typedef void         (* function_apply_type)  ( TaskMember * );
 
96
  typedef void         (* function_dealloc_type)( TaskMember * );
 
97
  typedef TaskMember * (* function_verify_type) ( TaskMember * );
 
98
 
 
99
private:
 
100
 
 
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
 
111
 
 
112
  // size = 6 Pointers + 4 ints
 
113
 
 
114
  TaskMember() /* = delete */ ;
 
115
  TaskMember( const TaskMember & ) /* = delete */ ;
 
116
  TaskMember & operator = ( const TaskMember & ) /* = delete */ ;
 
117
 
 
118
  static void * allocate( const unsigned arg_sizeof_derived , const unsigned arg_dependence_capacity );
 
119
  static void   deallocate( void * );
 
120
 
 
121
  void throw_error_add_dependence() const ;
 
122
  static void throw_error_verify_type();
 
123
 
 
124
  template < class DerivedTaskType >
 
125
  static
 
126
  void deallocate( TaskMember * t )
 
127
    {
 
128
      DerivedTaskType * ptr = static_cast< DerivedTaskType * >(t);
 
129
      ptr->~DerivedTaskType();
 
130
      deallocate( (void *) ptr );
 
131
    }
 
132
 
 
133
protected :
 
134
 
 
135
  ~TaskMember();
 
136
 
 
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
 
143
            );
 
144
 
 
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
 
150
            );
 
151
 
 
152
public:
 
153
 
 
154
  template< typename ResultType >
 
155
  KOKKOS_FUNCTION static
 
156
  TaskMember * verify_type( TaskMember * t )
 
157
    {
 
158
      enum { check_type = ! Impl::is_same< ResultType , void >::value };
 
159
 
 
160
      if ( check_type && t != 0 ) {
 
161
 
 
162
        // Verify that t->m_verify is this function
 
163
        const function_verify_type self = & TaskMember::template verify_type< ResultType > ;
 
164
 
 
165
        if ( t->m_verify != self ) {
 
166
          t = 0 ;
 
167
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
 
168
          throw_error_verify_type();
 
169
#endif
 
170
        }
 
171
      }
 
172
      return t ;
 
173
    }
 
174
 
 
175
  //----------------------------------------
 
176
  /*  Inheritence Requirements on task types:
 
177
   *    typedef  FunctorType::value_type  value_type ;
 
178
   *    class DerivedTaskType
 
179
   *      : public TaskMember< Serial , value_type , FunctorType >
 
180
   *      { ... };
 
181
   *    class TaskMember< Serial , value_type , FunctorType >
 
182
   *      : public TaskMember< Serial , value_type , void >
 
183
   *      , public Functor
 
184
   *      { ... };
 
185
   *  If value_type != void
 
186
   *    class TaskMember< Serial , value_type , void >
 
187
   *      : public TaskMember< Serial , void , void >
 
188
   *
 
189
   *  Allocate space for DerivedTaskType followed by TaskMember*[ dependence_capacity ]
 
190
   *
 
191
   */
 
192
 
 
193
  /** \brief  Allocate and construct a single-thread task */
 
194
  template< class DerivedTaskType >
 
195
  static
 
196
  TaskMember * create( const typename DerivedTaskType::functor_type &  arg_functor
 
197
                     , const unsigned                                  arg_dependence_capacity )
 
198
    {
 
199
      typedef typename DerivedTaskType::functor_type  functor_type ;
 
200
      typedef typename functor_type::value_type       value_type ;
 
201
 
 
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
 
208
                         , arg_functor );
 
209
 
 
210
      return static_cast< TaskMember * >( task );
 
211
    }
 
212
 
 
213
  /** \brief  Allocate and construct a data parallel task */
 
214
  template< class DerivedTaskType >
 
215
  static
 
216
  TaskMember * create( const typename DerivedTaskType::policy_type &   arg_policy
 
217
                     , const typename DerivedTaskType::functor_type &  arg_functor
 
218
                     , const unsigned                                  arg_dependence_capacity )
 
219
    {
 
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
 
225
                         , arg_policy
 
226
                         , arg_functor
 
227
                         );
 
228
 
 
229
      return static_cast< TaskMember * >( task );
 
230
    }
 
231
 
 
232
  void schedule();
 
233
  static void execute_ready_tasks();
 
234
  static void wait( const Future< void , Kokkos::Serial > & );
 
235
 
 
236
  //----------------------------------------
 
237
 
 
238
  typedef FutureValueTypeIsVoidError get_result_type ;
 
239
 
 
240
  KOKKOS_INLINE_FUNCTION
 
241
  get_result_type get() const { return get_result_type() ; }
 
242
 
 
243
  KOKKOS_INLINE_FUNCTION
 
244
  Kokkos::TaskState get_state() const { return Kokkos::TaskState( m_state ); }
 
245
 
 
246
  //----------------------------------------
 
247
 
 
248
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
 
249
  static
 
250
  void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false );
 
251
#else
 
252
  KOKKOS_INLINE_FUNCTION static
 
253
  void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false ) {}
 
254
#endif
 
255
 
 
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 ; }
 
259
 
 
260
  KOKKOS_INLINE_FUNCTION
 
261
  int get_dependence() const
 
262
    { return m_dep_size ; }
 
263
 
 
264
  KOKKOS_INLINE_FUNCTION
 
265
  void clear_dependence()
 
266
    {
 
267
      for ( int i = 0 ; i < m_dep_size ; ++i ) assign( m_dep + i , 0 );
 
268
      m_dep_size = 0 ;
 
269
    }
 
270
 
 
271
  KOKKOS_INLINE_FUNCTION
 
272
  void add_dependence( TaskMember * before )
 
273
    {
 
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 );
 
278
        ++m_dep_size ;
 
279
      }
 
280
      else {
 
281
        throw_error_add_dependence();
 
282
      }
 
283
    }
 
284
 
 
285
  //----------------------------------------
 
286
 
 
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 )
 
290
    {
 
291
      typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
 
292
 
 
293
      // TaskMember< Kokkos::Serial , ResultType , FunctorType >
 
294
      //   : public TaskMember< Kokkos::Serial , ResultType , void >
 
295
      //   , public FunctorType
 
296
      //   { ... };
 
297
 
 
298
      derived_type & m = * static_cast< derived_type * >( t );
 
299
 
 
300
      Impl::FunctorApply< FunctorType , void , ResultType & >::apply( (FunctorType &) m , & m.m_result );
 
301
    }
 
302
 
 
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 )
 
306
    {
 
307
      typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
 
308
 
 
309
      // TaskMember< Kokkos::Serial , ResultType , FunctorType >
 
310
      //   : public TaskMember< Kokkos::Serial , ResultType , void >
 
311
      //   , public FunctorType
 
312
      //   { ... };
 
313
 
 
314
      derived_type & m = * static_cast< derived_type * >( t );
 
315
 
 
316
      Impl::FunctorApply< FunctorType , void , void >::apply( (FunctorType &) m );
 
317
    }
 
318
};
 
319
 
 
320
//----------------------------------------------------------------------------
 
321
/** \brief  Base class for tasks with a result value in the Serial execution space.
 
322
 *
 
323
 *  The FunctorType must be void because this class is accessed by the
 
324
 *  Future class for the task and result value.
 
325
 *
 
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.
 
328
 */
 
329
template < class ResultType >
 
330
class TaskMember< Kokkos::Serial , ResultType , void >
 
331
  : public TaskMember< Kokkos::Serial , void , void >
 
332
{
 
333
public:
 
334
 
 
335
  ResultType  m_result ;
 
336
 
 
337
  typedef const ResultType & get_result_type ;
 
338
 
 
339
  KOKKOS_INLINE_FUNCTION
 
340
  get_result_type get() const { return m_result ; }
 
341
 
 
342
protected:
 
343
 
 
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 ;
 
347
 
 
348
  inline
 
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
 
353
            )
 
354
    : task_root_type( & task_root_type::template verify_type< ResultType >
 
355
                    , arg_dealloc
 
356
                    , arg_apply
 
357
                    , arg_sizeof_derived
 
358
                    , arg_dependence_capacity )
 
359
    , m_result()
 
360
    {}
 
361
 
 
362
};
 
363
 
 
364
template< class ResultType , class FunctorType >
 
365
class TaskMember< Kokkos::Serial , ResultType , FunctorType >
 
366
  : public TaskMember< Kokkos::Serial , ResultType , void >
 
367
  , public FunctorType
 
368
{
 
369
public:
 
370
 
 
371
  typedef FunctorType  functor_type ;
 
372
 
 
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 ;
 
377
 
 
378
  inline
 
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
 
384
            )
 
385
    : task_base_type( arg_dealloc , arg_apply , arg_sizeof_derived , arg_dependence_capacity )
 
386
    , functor_type( arg_functor )
 
387
    {}
 
388
};
 
389
 
 
390
//----------------------------------------------------------------------------
 
391
/** \brief  ForEach task in the Serial execution space
 
392
 *
 
393
 *  Derived from TaskMember< Kokkos::Serial , ResultType , FunctorType >
 
394
 *  so that Functor can be cast to task root type without knowing policy.
 
395
 */
 
396
template< class Arg0 , class Arg1 , class Arg2 , class ResultType , class FunctorType >
 
397
class TaskForEach< Kokkos::RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial >
 
398
                 , ResultType
 
399
                 , FunctorType >
 
400
  : TaskMember< Kokkos::Serial , ResultType , FunctorType >
 
401
{
 
402
public:
 
403
 
 
404
  typedef FunctorType                                              functor_type ;
 
405
  typedef RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial >       policy_type ;
 
406
 
 
407
private:
 
408
 
 
409
  friend class Kokkos::TaskPolicy< Kokkos::Serial > ;
 
410
  friend class Kokkos::Impl::TaskMember< Kokkos::Serial , void , void > ;
 
411
 
 
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 ;
 
415
 
 
416
  policy_type  m_policy ;
 
417
 
 
418
  template< class Tag >
 
419
  inline
 
420
  typename Impl::enable_if< Impl::is_same<Tag,void>::value >::type
 
421
    apply_policy() const
 
422
    {
 
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);
 
426
      }
 
427
    }
 
428
 
 
429
  template< class Tag >
 
430
  inline
 
431
  typename Impl::enable_if< ! Impl::is_same<Tag,void>::value >::type
 
432
    apply_policy() const
 
433
    {
 
434
      const Tag tag ;
 
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);
 
438
      }
 
439
    }
 
440
 
 
441
  static
 
442
  void apply_parallel( task_root_type * t )
 
443
    {
 
444
      static_cast<TaskForEach*>(t)->template apply_policy< typename policy_type::work_tag >();
 
445
 
 
446
      task_root_type::template apply_single< functor_type , ResultType >( t );
 
447
    }
 
448
 
 
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
 
454
             )
 
455
    : task_base_type( arg_dealloc
 
456
                    , & apply_parallel
 
457
                    , arg_sizeof_derived
 
458
                    , arg_dependence_capacity
 
459
                    , arg_functor )
 
460
    , m_policy( arg_policy )
 
461
    {}
 
462
 
 
463
  TaskForEach() /* = delete */ ;
 
464
  TaskForEach( const TaskForEach & ) /* = delete */ ;
 
465
  TaskForEach & operator = ( const TaskForEach & ) /* = delete */ ;
 
466
};
 
467
 
 
468
//----------------------------------------------------------------------------
 
469
/** \brief  Reduce task in the Serial execution space
 
470
 *
 
471
 *  Derived from TaskMember< Kokkos::Serial , ResultType , FunctorType >
 
472
 *  so that Functor can be cast to task root type without knowing policy.
 
473
 */
 
474
template< class Arg0 , class Arg1 , class Arg2 , class ResultType , class FunctorType >
 
475
class TaskReduce< Kokkos::RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial >
 
476
                , ResultType
 
477
                , FunctorType >
 
478
  : TaskMember< Kokkos::Serial , ResultType , FunctorType >
 
479
{
 
480
public:
 
481
 
 
482
  typedef FunctorType                                              functor_type ;
 
483
  typedef RangePolicy< Arg0 , Arg1 , Arg2 , Kokkos::Serial >       policy_type ;
 
484
 
 
485
private:
 
486
 
 
487
  friend class Kokkos::TaskPolicy< Kokkos::Serial > ;
 
488
  friend class Kokkos::Impl::TaskMember< Kokkos::Serial , void , void > ;
 
489
 
 
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 ;
 
493
 
 
494
  policy_type  m_policy ;
 
495
 
 
496
  template< class Tag >
 
497
  inline
 
498
  void apply_policy( typename Impl::enable_if< Impl::is_same<Tag,void>::value , ResultType & >::type result ) const
 
499
    {
 
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 );
 
504
      }
 
505
    }
 
506
 
 
507
  template< class Tag >
 
508
  inline
 
509
  void apply_policy( typename Impl::enable_if< ! Impl::is_same<Tag,void>::value , ResultType & >::type result ) const
 
510
    {
 
511
      Impl::FunctorValueInit< functor_type , Tag >::init( *this , & result );
 
512
      const Tag tag ;
 
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 );
 
516
      }
 
517
    }
 
518
 
 
519
  static
 
520
  void apply_parallel( task_root_type * t )
 
521
    {
 
522
      TaskReduce * const task = static_cast<TaskReduce*>(t);
 
523
 
 
524
      task->template apply_policy< typename policy_type::work_tag >( task->task_base_type::m_result );
 
525
 
 
526
      task_root_type::template apply_single< functor_type , ResultType >( t );
 
527
    }
 
528
 
 
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
 
534
            )
 
535
    : task_base_type( arg_dealloc
 
536
                    , & apply_parallel
 
537
                    , arg_sizeof_derived
 
538
                    , arg_dependence_capacity
 
539
                    , arg_functor )
 
540
    , m_policy( arg_policy )
 
541
    {}
 
542
 
 
543
  TaskReduce() /* = delete */ ;
 
544
  TaskReduce( const TaskReduce & ) /* = delete */ ;
 
545
  TaskReduce & operator = ( const TaskReduce & ) /* = delete */ ;
 
546
};
 
547
 
 
548
} /* namespace Impl */
 
549
} /* namespace Kokkos */
 
550
 
 
551
//----------------------------------------------------------------------------
 
552
//----------------------------------------------------------------------------
 
553
 
 
554
namespace Kokkos {
 
555
 
 
556
template<>
 
557
class TaskPolicy< Kokkos::Serial >
 
558
{
 
559
public:
 
560
 
 
561
  typedef Kokkos::Serial execution_space ;
 
562
 
 
563
private:
 
564
 
 
565
  typedef Impl::TaskMember< execution_space , void , void > task_root_type ;
 
566
 
 
567
  TaskPolicy & operator = ( const TaskPolicy & ) /* = delete */ ;
 
568
 
 
569
  template< class FunctorType >
 
570
  static inline
 
571
  const task_root_type * get_task_root( const FunctorType * f )
 
572
    {
 
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) );
 
575
    }
 
576
 
 
577
  template< class FunctorType >
 
578
  static inline
 
579
  task_root_type * get_task_root( FunctorType * f )
 
580
    {
 
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) );
 
583
    }
 
584
 
 
585
  const unsigned m_default_dependence_capacity ;
 
586
 
 
587
public:
 
588
 
 
589
  KOKKOS_INLINE_FUNCTION
 
590
  TaskPolicy() : m_default_dependence_capacity(4) {}
 
591
 
 
592
  KOKKOS_INLINE_FUNCTION
 
593
  TaskPolicy( const TaskPolicy & rhs ) : m_default_dependence_capacity( rhs.m_default_dependence_capacity ) {}
 
594
 
 
595
  KOKKOS_INLINE_FUNCTION
 
596
  explicit
 
597
  TaskPolicy( const unsigned arg_default_dependence_capacity )
 
598
    : m_default_dependence_capacity( arg_default_dependence_capacity ) {}
 
599
 
 
600
  KOKKOS_INLINE_FUNCTION
 
601
  TaskPolicy( const TaskPolicy &
 
602
            , const unsigned arg_default_dependence_capacity )
 
603
    : m_default_dependence_capacity( arg_default_dependence_capacity ) {}
 
604
 
 
605
  //----------------------------------------
 
606
 
 
607
  template< class ValueType >
 
608
  KOKKOS_INLINE_FUNCTION
 
609
  const Future< ValueType , execution_space > &
 
610
    spawn( const Future< ValueType , execution_space > & f ) const
 
611
      {
 
612
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
 
613
        f.m_task->schedule();
 
614
#endif
 
615
        return f ;
 
616
      }
 
617
 
 
618
  // Create single-thread task
 
619
 
 
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
 
625
    {
 
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 ) )
 
632
#endif
 
633
        );
 
634
    }
 
635
 
 
636
  // Create parallel foreach task
 
637
 
 
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
 
644
    {
 
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 ) )
 
651
#endif
 
652
       );
 
653
    }
 
654
 
 
655
  // Create parallel reduce task
 
656
 
 
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
 
663
    {
 
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 ) )
 
670
#endif
 
671
        );
 
672
    }
 
673
 
 
674
  // Add dependence
 
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
 
681
                          &&
 
682
                          Impl::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
 
683
                        >::type * = 0
 
684
                      ) const
 
685
    {
 
686
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
 
687
      after.m_task->add_dependence( before.m_task );
 
688
#endif
 
689
    }
 
690
 
 
691
  //----------------------------------------
 
692
  // Functions for an executing task functor to query dependences,
 
693
  // set new dependences, and respawn itself.
 
694
 
 
695
  template< class FunctorType >
 
696
  KOKKOS_INLINE_FUNCTION
 
697
  Future< void , execution_space >
 
698
  get_dependence( const FunctorType * task_functor , int i ) const
 
699
    {
 
700
      return Future<void,execution_space>(
 
701
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
 
702
        get_task_root(task_functor)->get_dependence(i)
 
703
#endif
 
704
        );
 
705
    }
 
706
 
 
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(); }
 
712
#else
 
713
    { return 0 ; }
 
714
#endif
 
715
 
 
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(); }
 
721
#else
 
722
    {}
 
723
#endif
 
724
 
 
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
 
731
                        >::type * = 0
 
732
                      ) const
 
733
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
 
734
    { get_task_root(task_functor)->add_dependence( before.m_task ); }
 
735
#else
 
736
    {}
 
737
#endif
 
738
 
 
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(); }
 
744
#else
 
745
    {}
 
746
#endif
 
747
};
 
748
 
 
749
inline
 
750
void wait( TaskPolicy< Kokkos::Serial > & )
 
751
{ Impl::TaskMember< Kokkos::Serial , void , void >::execute_ready_tasks(); }
 
752
 
 
753
inline
 
754
void wait( const Future< void , Kokkos::Serial > & future )
 
755
{ Impl::TaskMember< Kokkos::Serial , void , void >::wait( future ); }
 
756
 
 
757
} // namespace Kokkos
 
758
 
 
759
//----------------------------------------------------------------------------
 
760
 
 
761
#endif /* defined( KOKKOS_HAVE_SERIAL ) */
 
762
#endif /* #define KOKKOS_SERIAL_TASK_HPP */
 
763