Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends
Kokkos_TaskPolicy.hpp
00001 
00002 /*
00003 //@HEADER
00004 // ************************************************************************
00005 // 
00006 //   Kokkos: Manycore Performance-Portable Multidimensional Arrays
00007 //              Copyright (2012) Sandia Corporation
00008 // 
00009 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00010 // the U.S. Government retains certain rights in this software.
00011 // 
00012 // Redistribution and use in source and binary forms, with or without
00013 // modification, are permitted provided that the following conditions are
00014 // met:
00015 //
00016 // 1. Redistributions of source code must retain the above copyright
00017 // notice, this list of conditions and the following disclaimer.
00018 //
00019 // 2. Redistributions in binary form must reproduce the above copyright
00020 // notice, this list of conditions and the following disclaimer in the
00021 // documentation and/or other materials provided with the distribution.
00022 //
00023 // 3. Neither the name of the Corporation nor the names of the
00024 // contributors may be used to endorse or promote products derived from
00025 // this software without specific prior written permission.
00026 //
00027 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00028 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00030 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00031 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00032 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00033 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00034 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00035 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00036 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00037 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00038 //
00039 // Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov) 
00040 // 
00041 // ************************************************************************
00042 //@HEADER
00043 */
00044 
00045 // Experimental unified task-data parallel manycore LDRD
00046 
00047 #ifndef KOKKOS_TASKPOLICY_HPP
00048 #define KOKKOS_TASKPOLICY_HPP
00049 
00050 #include <Kokkos_Core_fwd.hpp>
00051 #include <impl/Kokkos_Traits.hpp>
00052 #include <impl/Kokkos_Tags.hpp>
00053 #include <impl/Kokkos_StaticAssert.hpp>
00054 
00055 //----------------------------------------------------------------------------
00056 
00057 namespace Kokkos {
00058 namespace Impl {
00059 
00060 struct FutureValueTypeIsVoidError {};
00061 
00062 template< class ExecSpace >
00063 class TaskManager ;
00064 
00065 template < class Policy , class ResultType = void , class Functor = void >
00066 class TaskMember ;
00067 
00068 template< class ExecPolicy >
00069 struct TaskDepends { typedef typename ExecPolicy::execution_space  execution_space ; };
00070 
00071 template< class ExecPolicy >
00072 struct TaskForEach { typedef typename ExecPolicy::execution_space  execution_space ; };
00073 
00074 template< class ExecPolicy >
00075 struct TaskReduce { typedef typename ExecPolicy::execution_space  execution_space ; };
00076 
00077 template< class ExecPolicy >
00078 struct TaskScan { typedef typename ExecPolicy::execution_space  execution_space ; };
00079 
00080 } /* namespace Impl */
00081 } /* namespace Kokkos */
00082 
00083 //----------------------------------------------------------------------------
00084 
00085 namespace Kokkos {
00086 
00094 template< class Arg1 = void , class Arg2 = void >
00095 class Future {
00096 private:
00097 
00098   template< class > friend class Impl::TaskManager ;
00099   template< class , class > friend class Future ;
00100 
00101   // Argument #2, if not void, must be the space.
00102   enum { Arg1_is_space  = Impl::is_execution_space< Arg1 >::value };
00103   enum { Arg2_is_space  = Impl::is_execution_space< Arg2 >::value };
00104   enum { Arg2_is_void   = Impl::is_same< Arg2 , void >::value };
00105 
00106   struct ErrorNoExecutionSpace {};
00107 
00108   enum { Opt1  =   Arg1_is_space && Arg2_is_void
00109        , Opt2  = ! Arg1_is_space && Arg2_is_void
00110        , Opt3  = ! Arg1_is_space && Arg2_is_space 
00111        , OptOK = Impl::StaticAssert< Opt1 || Opt2 || Opt3 , ErrorNoExecutionSpace >::value
00112        };
00113 
00114   typedef typename
00115     Impl::if_c< Opt2 || Opt3 , Arg1 , void >::type
00116       ValueType ;
00117 
00118   typedef typename
00119     Impl::if_c< Opt1 , Arg1 , typename
00120     Impl::if_c< Opt2 , Kokkos::DefaultExecutionSpace , typename
00121     Impl::if_c< Opt3 , Arg2 , void
00122     >::type >::type >::type
00123       ExecutionSpace ;
00124 
00125   typedef Impl::TaskManager< ExecutionSpace >              TaskManager ;
00126   typedef Impl::TaskMember<  ExecutionSpace >              TaskRoot ;
00127   typedef Impl::TaskMember<  ExecutionSpace , ValueType >  TaskValue ;
00128 
00129   TaskRoot * m_task ;
00130 
00131 public:
00132 
00133   typedef ValueType       value_type;
00134   typedef ExecutionSpace  execution_space ;
00135 
00136   //----------------------------------------
00137 
00138   explicit
00139   Future( TaskRoot * task )
00140     : m_task(0)
00141     { TaskManager::assign( & m_task , TaskValue::verify_type( task ) ); }
00142 
00143   //----------------------------------------
00144 
00145   KOKKOS_INLINE_FUNCTION
00146   ~Future() { TaskManager::assign( & m_task , 0 ); }
00147 
00148   //----------------------------------------
00149 
00150   KOKKOS_INLINE_FUNCTION
00151   Future() : m_task(0) {}
00152 
00153   KOKKOS_INLINE_FUNCTION
00154   Future( const Future & rhs )
00155     : m_task(0)
00156     { TaskManager::assign( & m_task , rhs.m_task ); }
00157 
00158   KOKKOS_INLINE_FUNCTION
00159   Future & operator = ( const Future & rhs )
00160     { TaskManager::assign( & m_task , rhs.m_task ); return *this ; }
00161 
00162   //----------------------------------------
00163 
00164   template< class A1 , class A2 >
00165   KOKKOS_INLINE_FUNCTION
00166   Future( const Future<A1,A2> & rhs )
00167     : m_task(0)
00168     { TaskManager::assign( & m_task , TaskValue::verify_type( rhs.m_task ) ); }
00169 
00170   template< class A1 , class A2 >
00171   KOKKOS_INLINE_FUNCTION
00172   Future & operator = ( const Future<A1,A2> & rhs )
00173     { TaskManager::assign( & m_task , TaskValue::verify_type( rhs.m_task ) ); return *this ; }
00174 
00175   //----------------------------------------
00176 
00177   typedef typename TaskValue::get_result_type get_result_type ;
00178 
00179   KOKKOS_INLINE_FUNCTION
00180   typename TaskValue::get_result_type get() const
00181     { return static_cast<TaskValue*>( m_task )->get(); }
00182 };
00183 
00184 } /* namespace Kokkos */
00185 
00186 //----------------------------------------------------------------------------
00187 
00188 namespace Kokkos {
00189 
00191 template< class Arg0 = Kokkos::DefaultExecutionSpace >
00192 class TaskPolicy {
00193 public:
00194 
00195   typedef typename Arg0::execution_space  execution_space ;
00196 
00197   template< class A1 , class A2 >
00198   void wait( const Future<A1,A2> & ) const ;
00199 
00200   template< class FunctorType >
00201   Future< typename FunctorType::value_type , execution_space >
00202   spawn( const FunctorType & ) const ;
00203 
00204   template< class FunctorType >
00205   void respawn( FunctorType * ) const ;
00206 
00207   template< class FunctorType >
00208   Future< void , execution_space >
00209   get_dependence( FunctorType * ) const ;
00210 
00211   template< class ValueType >
00212   TaskPolicy< void /* ... */ >
00213   depends( const Future< ValueType , execution_space > * const , const int );
00214 
00215   template< class ExecPolicy >
00216   TaskPolicy< void /* ... */ > foreach( const ExecPolicy & );
00217 
00218   template< class ExecPolicy >
00219   TaskPolicy< void /* ... */ > reduce( const ExecPolicy & );
00220 
00221   template< class ExecPolicy >
00222   TaskPolicy< void /* ... */ > scan( const ExecPolicy & );
00223 };
00224 
00225 // spawn( M.depends(n,d).foreach(K) , functor );
00226 // M.depends(n,d).foreach(K).spawn( functor );
00227 
00228 template< class Arg0 , class FunctorType >
00229 Future< typename FunctorType::value_type
00230       , typename Arg0::execution_space >
00231 inline
00232 spawn( const TaskPolicy< Arg0 > & policy
00233      , const FunctorType        & functor )
00234 { return policy.spawn( functor ); }
00235 
00236 template< class Arg0 , class A1 , class A2 >
00237 void wait( const TaskPolicy< Arg0 > & policy 
00238          , const Future<A1,A2>      & future
00239          , typename Impl::enable_if<
00240              Impl::is_same< typename Arg0::execution_space
00241                           , typename Future<A1,A2>::execution_space >::value
00242           >::type * = 0 )
00243 { policy.wait( future ); }
00244 
00245 } /* namespace Kokkos */
00246 
00247 //----------------------------------------------------------------------------
00248 
00249 #endif /* #define KOKKOS_TASKPOLICY_HPP */
00250 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends