Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends
Kokkos_Parallel.hpp
Go to the documentation of this file.
00001 /*
00002 //@HEADER
00003 // ************************************************************************
00004 //
00005 //   Kokkos: Manycore Performance-Portable Multidimensional Arrays
00006 //              Copyright (2012) Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
00039 //
00040 // ************************************************************************
00041 //@HEADER
00042 */
00043 
00046 
00047 #ifndef KOKKOS_PARALLEL_HPP
00048 #define KOKKOS_PARALLEL_HPP
00049 
00050 #include <cstddef>
00051 #include <Kokkos_Core_fwd.hpp>
00052 #include <Kokkos_View.hpp>
00053 #include <Kokkos_ExecPolicy.hpp>
00054 #include <impl/Kokkos_Traits.hpp>
00055 #include <impl/Kokkos_Tags.hpp>
00056 
00057 //----------------------------------------------------------------------------
00058 //----------------------------------------------------------------------------
00059 
00060 namespace Kokkos {
00061 namespace Impl {
00062 
00063 //----------------------------------------------------------------------------
00070 template< class Functor
00071         , class Policy
00072         , class EnableFunctor = void
00073         , class EnablePolicy  = void
00074         >
00075 struct FunctorPolicyExecutionSpace {
00076   typedef Kokkos::DefaultExecutionSpace execution_space ;
00077 };
00078 
00079 template< class Functor , class Policy >
00080 struct FunctorPolicyExecutionSpace
00081   < Functor , Policy
00082   , typename enable_if_type< typename Functor::device_type     >::type
00083   , typename enable_if_type< typename Policy ::execution_space >::type
00084   >
00085 {
00086   typedef typename Policy ::execution_space execution_space ;
00087 };
00088 
00089 template< class Functor , class Policy , class EnableFunctor >
00090 struct FunctorPolicyExecutionSpace
00091   < Functor , Policy
00092   , EnableFunctor
00093   , typename enable_if_type< typename Policy::execution_space >::type
00094   >
00095 {
00096   typedef typename Policy ::execution_space execution_space ;
00097 };
00098 
00099 template< class Functor , class Policy , class EnablePolicy >
00100 struct FunctorPolicyExecutionSpace
00101   < Functor , Policy
00102   , typename enable_if_type< typename Functor::device_type >::type
00103   , EnablePolicy
00104   >
00105 {
00106   typedef typename Functor::device_type execution_space ;
00107 };
00108 
00109 //----------------------------------------------------------------------------
00110 
00111 template< class FunctorType , class Enable = void >
00112 struct ReduceAdapterValueType ;
00113 
00114 template< class FunctorType >
00115 struct ReduceAdapterValueType< FunctorType , typename enable_if_type< typename FunctorType::value_type >::type >
00116 {
00117   typedef typename FunctorType::value_type type ;
00118 };
00119 
00125 template< class FunctorType ,
00126           class ValueType = typename ReduceAdapterValueType< FunctorType >::type >
00127 struct ReduceAdapter ;
00128 
00129 //----------------------------------------------------------------------------
00136 template< class FunctorType , class ExecPolicy > class ParallelFor ;
00137 
00143 template< class FunctorType , class ExecPolicy > class ParallelReduce ;
00144 
00151 template< class FunctorType , class ExecPolicy > class ParallelScan ;
00152 
00153 } // namespace Impl
00154 } // namespace Kokkos
00155 
00156 //----------------------------------------------------------------------------
00157 //----------------------------------------------------------------------------
00158 
00159 namespace Kokkos {
00160 
00182 template< class ExecPolicy , class FunctorType >
00183 inline
00184 void parallel_for( const ExecPolicy  & policy
00185                  , const FunctorType & functor
00186                  , typename Impl::enable_if< ! Impl::is_integral< ExecPolicy >::value >::type * = 0
00187                  )
00188 {
00189   (void) Impl::ParallelFor< FunctorType , ExecPolicy >( functor , policy );
00190 }
00191 
00192 template< class FunctorType >
00193 inline
00194 void parallel_for( const size_t        work_count ,
00195                    const FunctorType & functor )
00196 {
00197   typedef typename
00198     Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
00199       execution_space ;
00200   typedef RangePolicy< execution_space > policy ;
00201   (void) Impl::ParallelFor< FunctorType , policy >( functor , policy(0,work_count) );
00202 }
00203 
00204 } // namespace Kokkos
00205 
00206 //----------------------------------------------------------------------------
00207 //----------------------------------------------------------------------------
00208 
00209 namespace Kokkos {
00210 
00245 template< class ExecPolicy , class FunctorType >
00246 inline
00247 void parallel_reduce( const ExecPolicy  & policy 
00248                     , const FunctorType & functor
00249                     , typename Impl::enable_if< ! Impl::is_integral< ExecPolicy >::value >::type * = 0
00250                     )
00251 {
00252   (void) Impl::ParallelReduce< FunctorType , ExecPolicy >( functor , policy );
00253 }
00254 
00255 // integral range policy
00256 template< class FunctorType >
00257 inline
00258 void parallel_reduce( const size_t        work_count
00259                     , const FunctorType & functor
00260                     )
00261 {
00262   typedef typename
00263     Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
00264       execution_space ;
00265 
00266   typedef RangePolicy< execution_space > policy ;
00267 
00268   typedef Kokkos::Impl::ReduceAdapter< FunctorType >  Reduce ;
00269 
00270   typedef typename Kokkos::Impl::if_c< Reduce::StaticValueSize
00271                                      , typename Reduce::scalar_type
00272                                      , typename Reduce::pointer_type
00273                                      >::type value_type ;
00274 
00275   Kokkos::View< value_type
00276               , typename execution_space::host_mirror_device_type
00277               , Kokkos::MemoryUnmanaged
00278               >
00279     result_view ;
00280 
00281   (void) Impl::ParallelReduce< FunctorType , policy >( functor , policy(0,work_count) , result_view );
00282 }
00283 
00284 // general policy and view ouput
00285 template< class ExecPolicy , class FunctorType , class ViewType >
00286 inline
00287 void parallel_reduce( const ExecPolicy  & policy 
00288                     , const FunctorType & functor 
00289                     , const ViewType    & result_view
00290                     , typename Impl::enable_if<
00291                       ( Impl::is_view<ViewType>::value && ! Impl::is_integral< ExecPolicy >::value
00292                       )>::type * = 0 )
00293 {
00294   (void) Impl::ParallelReduce< FunctorType, ExecPolicy >( functor , policy , result_view );
00295 }
00296 
00297 // general policy and pod or array of pod output
00298 template< class ExecPolicy , class FunctorType >
00299 inline
00300 void parallel_reduce( const ExecPolicy  & policy 
00301                     , const FunctorType & functor 
00302                     , typename Impl::enable_if<
00303                       ( ! Impl::is_integral< ExecPolicy >::value )
00304                       , typename Kokkos::Impl::ReduceAdapter< FunctorType >::reference_type
00305                       >::type result_ref )
00306 {
00307   typedef typename
00308     Kokkos::Impl::FunctorPolicyExecutionSpace< FunctorType , ExecPolicy >::execution_space
00309       execution_space ;
00310 
00311   typedef Kokkos::Impl::ReduceAdapter< FunctorType >  Reduce ;
00312 
00313   // Wrap the result output request in a view to inform the implementation
00314   // of the type and memory space.
00315 
00316   typedef typename Kokkos::Impl::if_c< Reduce::StaticValueSize
00317                                      , typename Reduce::scalar_type
00318                                      , typename Reduce::pointer_type
00319                                      >::type value_type ;
00320 
00321   Kokkos::View< value_type
00322               , typename execution_space::host_mirror_device_type
00323               , Kokkos::MemoryUnmanaged
00324               >
00325     result_view( Reduce::pointer( result_ref )
00326                , Reduce::value_count( functor )
00327                );
00328 
00329   (void) Impl::ParallelReduce< FunctorType, ExecPolicy >( functor , policy , result_view );
00330 }
00331 
00332 // integral range policy and view ouput
00333 template< class FunctorType , class ViewType >
00334 inline
00335 void parallel_reduce( const size_t        work_count
00336                     , const FunctorType & functor 
00337                     , const ViewType    & result_view
00338                     , typename Impl::enable_if<( Impl::is_view<ViewType>::value )>::type * = 0 )
00339 {
00340   typedef typename
00341     Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
00342       execution_space ;
00343 
00344   typedef RangePolicy< execution_space > ExecPolicy ;
00345 
00346   (void) Impl::ParallelReduce< FunctorType, ExecPolicy >( functor , ExecPolicy(0,work_count) , result_view );
00347 }
00348 
00349 // integral range policy and pod or array of pod output
00350 template< class FunctorType >
00351 inline
00352 void parallel_reduce( const size_t        work_count ,
00353                       const FunctorType & functor ,
00354                       typename Kokkos::Impl::ReduceAdapter< FunctorType >::reference_type result )
00355 {
00356   typedef typename
00357     Kokkos::Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
00358       execution_space ;
00359 
00360   typedef Kokkos::RangePolicy< execution_space > policy ;
00361 
00362   typedef Kokkos::Impl::ReduceAdapter< FunctorType >  Reduce ;
00363 
00364   // Wrap the result output request in a view to inform the implementation
00365   // of the type and memory space.
00366 
00367   typedef typename Kokkos::Impl::if_c< Reduce::StaticValueSize
00368                                      , typename Reduce::scalar_type
00369                                      , typename Reduce::pointer_type
00370                                      >::type value_type ;
00371 
00372   Kokkos::View< value_type
00373               , typename execution_space::host_mirror_device_type
00374               , Kokkos::MemoryUnmanaged
00375               >
00376     result_view( Reduce::pointer( result )
00377                , Reduce::value_count( functor )
00378                );
00379   
00380   (void) Impl::ParallelReduce< FunctorType , policy >( functor , policy(0,work_count) , result_view );
00381 }
00382 
00383 } // namespace Kokkos
00384 
00385 //----------------------------------------------------------------------------
00386 //----------------------------------------------------------------------------
00387 
00388 namespace Kokkos {
00389 
00541 template< class ExecutionPolicy , class FunctorType >
00542 inline
00543 void parallel_scan( const ExecutionPolicy & policy 
00544                   , const FunctorType     & functor 
00545                   , typename Impl::enable_if< ! Impl::is_integral< ExecutionPolicy >::value >::type * = 0
00546                   )
00547 {
00548   Impl::ParallelScan< FunctorType , ExecutionPolicy > scan( functor , policy );
00549 }
00550 
00551 template< class FunctorType >
00552 inline
00553 void parallel_scan( const size_t        work_count ,
00554                     const FunctorType & functor )
00555 {
00556   typedef typename
00557     Kokkos::Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
00558       execution_space ;
00559 
00560   typedef Kokkos::RangePolicy< execution_space > policy ;
00561 
00562   (void) Impl::ParallelScan< FunctorType , policy >( functor , policy(0,work_count) );
00563 }
00564 
00565 } // namespace Kokkos
00566 
00567 //----------------------------------------------------------------------------
00568 //----------------------------------------------------------------------------
00569 
00570 namespace Kokkos {
00571 namespace Impl {
00572 
00573 template< class FunctorType , class Enable = void >
00574 struct FunctorHasInit : public false_type {};
00575 
00576 template< class FunctorType >
00577 struct FunctorHasInit< FunctorType , typename enable_if< 0 < sizeof( & FunctorType::init ) >::type >
00578   : public true_type {};
00579 
00580 template< class FunctorType , class Enable = void >
00581 struct FunctorHasJoin : public false_type {};
00582 
00583 template< class FunctorType >
00584 struct FunctorHasJoin< FunctorType , typename enable_if< 0 < sizeof( & FunctorType::join ) >::type >
00585   : public true_type {};
00586 
00587 template< class FunctorType , class Enable = void >
00588 struct FunctorHasFinal : public false_type {};
00589 
00590 template< class FunctorType >
00591 struct FunctorHasFinal< FunctorType , typename enable_if< 0 < sizeof( & FunctorType::final ) >::type >
00592   : public true_type {};
00593 
00594 template< class FunctorType , class Enable = void >
00595 struct FunctorTeamShmemSize
00596 {
00597   static inline size_t value( const FunctorType & , int ) { return 0 ; }
00598 };
00599 
00600 template< class FunctorType >
00601 struct FunctorTeamShmemSize< FunctorType , typename enable_if< sizeof( & FunctorType::team_shmem_size ) >::type >
00602 {
00603   static inline size_t value( const FunctorType & f , int team_size ) { return f.team_shmem_size( team_size ) ; }
00604 };
00605 
00606 template< class FunctorType >
00607 struct FunctorTeamShmemSize< FunctorType , typename enable_if< sizeof( & FunctorType::shmem_size ) >::type >
00608 {
00609   static inline size_t value( const FunctorType & f , int team_size ) { return f.shmem_size( team_size ) ; }
00610 };
00611 
00612 } // namespace Impl
00613 } // namespace Kokkos
00614 
00615 //----------------------------------------------------------------------------
00616 //----------------------------------------------------------------------------
00617 
00618 namespace Kokkos {
00619 namespace Impl {
00620 
00621 #if defined( KOKKOS_HAVE_CXX11 )
00622 
00623 template< class FunctionPtr >
00624 struct ReduceAdapterFunctorOperatorArgType ;
00625 
00626 template< class Functor , class Arg0 , class Arg1 >
00627 struct ReduceAdapterFunctorOperatorArgType< void ( Functor::*)( Arg0 , Arg1 & ) const > {
00628   typedef Arg1 type ;
00629 };
00630 
00631 // Functor does not have a 'typedef ... value_type' and C++11 is enabled.
00632 // Deduce the value type from the functor's argument list.
00633 template< class FunctorType , class Enable >
00634 struct ReduceAdapterValueType {
00635 private:
00636   typedef decltype( & FunctorType::operator() ) function_pointer_type ;
00637 public:
00638   typedef typename ReduceAdapterFunctorOperatorArgType< function_pointer_type >::type type ;
00639 };
00640 
00641 #endif /* #if defined( KOKKOS_HAVE_CXX11 ) */
00642 
00643 template< class FunctorType , class ScalarType >
00644 struct ReduceAdapter
00645 {
00646   enum { StaticValueSize = sizeof(ScalarType) };
00647 
00648   typedef ScalarType & reference_type  ;
00649   typedef ScalarType * pointer_type  ;
00650   typedef ScalarType   scalar_type  ;
00651 
00652   KOKKOS_INLINE_FUNCTION static
00653   reference_type reference( void * p ) { return *((ScalarType*) p); }
00654 
00655   KOKKOS_INLINE_FUNCTION static
00656   reference_type reference( void * p , unsigned i ) { return ((ScalarType*) p)[i]; }
00657 
00658   KOKKOS_INLINE_FUNCTION static
00659   pointer_type pointer( reference_type p ) { return & p ; }
00660 
00661   KOKKOS_INLINE_FUNCTION static
00662   unsigned value_count( const FunctorType & ) { return 1 ; }
00663 
00664   KOKKOS_INLINE_FUNCTION static
00665   unsigned value_size( const FunctorType & ) { return sizeof(ScalarType); }
00666 
00667   KOKKOS_INLINE_FUNCTION static
00668   void copy( const FunctorType & , void * const dst , const void * const src )
00669     { *((scalar_type*)dst) = *((const scalar_type*)src); }
00670 
00671   template< class F >
00672   KOKKOS_INLINE_FUNCTION static
00673   void join( const F & f
00674            , volatile void * update
00675            , typename enable_if< is_same<F,FunctorType>::value &&
00676                                  FunctorHasJoin<F>::value
00677                                , volatile const void *
00678                                >::type input )
00679     { f.join( *((volatile ScalarType*)update) , *((volatile const ScalarType*)input) ); }
00680 
00681   template< class F >
00682   KOKKOS_INLINE_FUNCTION static
00683   void join( const F & f
00684            , volatile void * update
00685            , typename enable_if< is_same<F,FunctorType>::value &&
00686                                  ! FunctorHasJoin<F>::value
00687                                , volatile const void *
00688                                >::type input )
00689     { *((volatile ScalarType*)update) += *((volatile const ScalarType*)input); }
00690 
00691   template< class F >
00692   KOKKOS_INLINE_FUNCTION static
00693   reference_type
00694   init( const F & f ,
00695         typename enable_if< ( is_same<F,FunctorType>::value &&
00696                               FunctorHasInit<F>::value )
00697                           >::type * p )
00698     { f.init( *((ScalarType *) p ) );  return *((ScalarType *) p ); }
00699 
00700   template< class F >
00701   KOKKOS_INLINE_FUNCTION static
00702   reference_type
00703   init( const F & ,
00704         typename enable_if< ( is_same<F,FunctorType>::value &&
00705                               ! FunctorHasInit<F>::value )
00706                           >::type * p )
00707     { return *( new(p) ScalarType() ); }
00708 
00709   template< class F >
00710   KOKKOS_INLINE_FUNCTION static
00711   void final( const F & f ,
00712               typename enable_if< ( is_same<F,FunctorType>::value &&
00713                                     FunctorHasFinal<F>::value )
00714                                 >::type * p )
00715     { f.final( *((ScalarType *) p ) ); }
00716 
00717   template< class F >
00718   KOKKOS_INLINE_FUNCTION static
00719   void final( const F & ,
00720               typename enable_if< ( is_same<F,FunctorType>::value &&
00721                                     ! FunctorHasFinal<F>::value )
00722                                 >::type * )
00723     {}
00724 };
00725 
00726 template< class FunctorType , class ScalarType >
00727 struct ReduceAdapter< FunctorType , ScalarType[] >
00728 {
00729   enum { StaticValueSize = 0 };
00730 
00731   typedef ScalarType * reference_type  ;
00732   typedef ScalarType * pointer_type  ;
00733   typedef ScalarType   scalar_type  ;
00734 
00735   KOKKOS_INLINE_FUNCTION static
00736   ScalarType * reference( void * p ) { return (ScalarType*) p ; }
00737 
00738   KOKKOS_INLINE_FUNCTION static
00739   reference_type reference( void * p , unsigned i ) { return ((ScalarType*) p)+i; }
00740 
00741   KOKKOS_INLINE_FUNCTION static
00742   pointer_type pointer( reference_type p ) { return p ; }
00743 
00744   KOKKOS_INLINE_FUNCTION static
00745   unsigned value_count( const FunctorType & f ) { return f.value_count ; }
00746 
00747   KOKKOS_INLINE_FUNCTION static
00748   unsigned value_size( const FunctorType & f ) { return f.value_count * sizeof(ScalarType); }
00749 
00750   KOKKOS_INLINE_FUNCTION static
00751   void copy( const FunctorType & f , void * const dst , const void * const src )
00752     {
00753       for ( int i = 0 ; i < int(f.value_count) ; ++i ) {
00754         ((scalar_type*)dst)[i] = ((const scalar_type*)src)[i];
00755       }
00756     }
00757 
00758   template< class F >
00759   KOKKOS_INLINE_FUNCTION static
00760   void join( const F & f
00761            , volatile void * const update
00762            , typename enable_if< is_same<F,FunctorType>::value &&
00763                                  FunctorHasJoin<F>::value
00764                                , volatile const void * const
00765                                >::type input )
00766     { f.join( ((volatile ScalarType*)update) , ((volatile const ScalarType*)input) ); }
00767 
00768   template< class F >
00769   KOKKOS_INLINE_FUNCTION static
00770   void join( const F & f
00771            , volatile void * const update
00772            , typename enable_if< is_same<F,FunctorType>::value &&
00773                                  ! FunctorHasJoin<F>::value
00774                                , volatile const void * const
00775                                >::type input )
00776     {
00777       for ( int i = 0 ; i < int(f.value_count) ; ++i ) {
00778         ((volatile ScalarType*)update)[i] += ((volatile const ScalarType*)input)[i] ;
00779       }
00780     }
00781 
00782 
00783   template< class F >
00784   KOKKOS_INLINE_FUNCTION static
00785   reference_type
00786   init( const F & f ,
00787         typename enable_if< ( is_same<F,FunctorType>::value &&
00788                               FunctorHasInit<F>::value )
00789                           >::type * p )
00790     { f.init( ((ScalarType *) p ) ); return (ScalarType*) p ; }
00791 
00792   template< class F >
00793   KOKKOS_INLINE_FUNCTION static
00794   reference_type
00795   init( const F & f ,
00796         typename enable_if< ( is_same<F,FunctorType>::value &&
00797                               ! FunctorHasInit<F>::value )
00798                           >::type * p )
00799     {
00800       for ( int i = 0 ; i < int(f.value_count) ; ++i ) {
00801         new(((ScalarType*)p)+i) ScalarType();
00802       }
00803       return (ScalarType*)p ;
00804     }
00805 
00806   template< class F >
00807   KOKKOS_INLINE_FUNCTION static
00808   void final( const F & f ,
00809               typename enable_if< ( is_same<F,FunctorType>::value &&
00810                                     FunctorHasFinal<F>::value )
00811                                 >::type * p )
00812     { f.final( ((ScalarType *) p ) ); }
00813 
00814   template< class F >
00815   KOKKOS_INLINE_FUNCTION static
00816   void final( const F & ,
00817               typename enable_if< ( is_same<F,FunctorType>::value &&
00818                                     ! FunctorHasFinal<F>::value )
00819                                 >::type * )
00820     {}
00821 };
00822 
00823 } // namespace Impl
00824 } // namespace Kokkos
00825 
00826 //----------------------------------------------------------------------------
00827 //----------------------------------------------------------------------------
00828 
00829 #endif /* KOKKOS_PARALLEL_HPP */
00830 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends