|
Kokkos Core Kernels Package
Version of the Day
|
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
1.7.6.1