Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends
Kokkos_DualView.hpp
Go to the documentation of this file.
00001 /*
00002 //@HEADER
00003 // ************************************************************************
00004 //
00005 //                             Kokkos
00006 //         Manycore Performance-Portable Multidimensional Arrays
00007 //
00008 //              Copyright (2012) Sandia Corporation
00009 //
00010 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00011 // the U.S. Government retains certain rights in this software.
00012 //
00013 // Redistribution and use in source and binary forms, with or without
00014 // modification, are permitted provided that the following conditions are
00015 // met:
00016 //
00017 // 1. Redistributions of source code must retain the above copyright
00018 // notice, this list of conditions and the following disclaimer.
00019 //
00020 // 2. Redistributions in binary form must reproduce the above copyright
00021 // notice, this list of conditions and the following disclaimer in the
00022 // documentation and/or other materials provided with the distribution.
00023 //
00024 // 3. Neither the name of the Corporation nor the names of the
00025 // contributors may be used to endorse or promote products derived from
00026 // this software without specific prior written permission.
00027 //
00028 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00029 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00030 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00031 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00032 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00033 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00034 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00035 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00036 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00037 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00038 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00039 //
00040 // Questions?  Contact  H. Carter Edwards (hcedwar@sandia.gov)
00041 //
00042 // ************************************************************************
00043 //@HEADER
00044 */
00045 
00051 
00052 #ifndef KOKKOS_DUALVIEW_HPP
00053 #define KOKKOS_DUALVIEW_HPP
00054 
00055 #include <Kokkos_Core.hpp>
00056 #include <impl/Kokkos_Error.hpp>
00057 
00058 namespace Kokkos {
00059 
00060 /* \class DualView
00061  * \brief Container to manage mirroring a Kokkos::View that lives
00062  *   in device memory with a Kokkos::View that lives in host memory.
00063  *
00064  * This class provides capabilities to manage data which exists in two
00065  * memory spaces at the same time.  It keeps views of the same layout
00066  * on two memory spaces as well as modified flags for both
00067  * allocations.  Users are responsible for setting the modified flags
00068  * manually if they change the data in either memory space, by calling
00069  * the sync() method templated on the device where they modified the
00070  * data.  Users may synchronize data by calling the modify() function,
00071  * templated on the device towards which they want to synchronize
00072  * (i.e., the target of the one-way copy operation).
00073  *
00074  * The DualView class also provides convenience methods such as
00075  * realloc, resize and capacity which call the appropriate methods of
00076  * the underlying Kokkos::View objects.
00077  *
00078  * The four template arguments are the same as those of Kokkos::View.
00079  * (Please refer to that class' documentation for a detailed
00080  * description.)
00081  *
00082  *   \tparam DataType The type of the entries stored in the container.
00083  *
00084  *   \tparam Layout The array's layout in memory.
00085  *
00086  *   \tparam Device The Kokkos Device type.  If its memory space is
00087  *     not the same as the host's memory space, then DualView will
00088  *     contain two separate Views: one in device memory, and one in
00089  *     host memory.  Otherwise, DualView will only store one View.
00090  *
00091  *   \tparam MemoryTraits (optional) The user's intended memory access
00092  *     behavior.  Please see the documentation of Kokkos::View for
00093  *     examples.  The default suffices for most users.
00094  */
00095 template< class DataType ,
00096           class Arg1Type = void ,
00097           class Arg2Type = void ,
00098           class Arg3Type = void>
00099 class DualView : public ViewTraits< DataType , Arg1Type , Arg2Type, Arg3Type >
00100 {
00101 public:
00103 
00104   typedef ViewTraits< DataType , Arg1Type , Arg2Type, Arg3Type > traits ;
00105 
00107   typedef typename traits::device_type::host_mirror_device_type host_mirror_device_type;
00108 
00110   typedef View< typename traits::data_type ,
00111                 typename traits::array_layout ,
00112                 typename traits::device_type ,
00113                 typename traits::memory_traits > t_dev ;
00114 
00117 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_USE_CUDA_UVM)
00118   typedef t_dev t_host;
00119 #else
00120   typedef typename t_dev::HostMirror t_host ;
00121 #endif
00122 
00125   typedef View< typename traits::const_data_type ,
00126                 typename traits::array_layout ,
00127                 typename traits::device_type ,
00128                 typename traits::memory_traits > t_dev_const ;
00129 
00132 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_USE_CUDA_UVM)
00133   typedef t_dev_const t_host_const;
00134 #else
00135   typedef typename t_dev_const::HostMirror t_host_const;
00136 #endif
00137 
00139   typedef View< typename traits::const_data_type ,
00140                 typename traits::array_layout ,
00141                 typename traits::device_type ,
00142                 MemoryTraits<RandomAccess> > t_dev_const_randomread ;
00143 
00147 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_USE_CUDA_UVM)
00148   typedef t_dev_const_randomread t_host_const_randomread;
00149 #else
00150   typedef typename t_dev_const_randomread::HostMirror t_host_const_randomread;
00151 #endif
00152 
00154   typedef View< typename traits::data_type ,
00155                 typename traits::array_layout ,
00156                 typename traits::device_type ,
00157                 MemoryUnmanaged> t_dev_um;
00158 
00160   typedef View< typename t_host::data_type ,
00161                 typename t_host::array_layout ,
00162                 typename t_host::device_type ,
00163                 MemoryUnmanaged> t_host_um;
00164 
00166   typedef View< typename traits::const_data_type ,
00167                 typename traits::array_layout ,
00168                 typename traits::device_type ,
00169                 MemoryUnmanaged> t_dev_const_um;
00170 
00172   typedef View<typename t_host::const_data_type,
00173                typename t_host::array_layout,
00174                typename t_host::device_type,
00175                MemoryUnmanaged> t_host_const_um;
00176 
00178 
00179 
00180 
00181   t_dev d_view;
00182   t_host h_view;
00183 
00185 
00186 
00187 
00188   View<unsigned int,LayoutLeft,host_mirror_device_type> modified_device;
00189   View<unsigned int,LayoutLeft,host_mirror_device_type> modified_host;
00190 
00192 
00193 
00194 
00200   DualView () :
00201     modified_device (View<unsigned int,LayoutLeft,host_mirror_device_type> ("DualView::modified_device")),
00202     modified_host (View<unsigned int,LayoutLeft,host_mirror_device_type> ("DualView::modified_host"))
00203   {}
00204 
00214   DualView (const std::string& label,
00215             const size_t n0 = 0,
00216             const size_t n1 = 0,
00217             const size_t n2 = 0,
00218             const size_t n3 = 0,
00219             const size_t n4 = 0,
00220             const size_t n5 = 0,
00221             const size_t n6 = 0,
00222             const size_t n7 = 0)
00223     : d_view (label, n0, n1, n2, n3, n4, n5, n6, n7)
00224 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_USE_CUDA_UVM)
00225     , h_view (d_view) // with UVM, host View is _always_ a shallow copy
00226 #else
00227     , h_view (create_mirror_view (d_view)) // without UVM, host View mirrors
00228 #endif
00229     , modified_device (View<unsigned int,LayoutLeft,host_mirror_device_type> ("DualView::modified_device"))
00230     , modified_host (View<unsigned int,LayoutLeft,host_mirror_device_type> ("DualView::modified_host"))
00231   {}
00232 
00234   template<class SS, class LS, class DS, class MS>
00235   DualView (const DualView<SS,LS,DS,MS>& src) :
00236     d_view (src.d_view),
00237     h_view (src.h_view),
00238     modified_device (src.modified_device),
00239     modified_host (src.modified_host)
00240   {}
00241 
00252   DualView (const t_dev& d_view_, const t_host& h_view_) :
00253     d_view (d_view_),
00254     h_view (h_view_),
00255     modified_device (View<unsigned int,LayoutLeft,host_mirror_device_type> ("DualView::modified_device")),
00256     modified_host (View<unsigned int,LayoutLeft,host_mirror_device_type> ("DualView::modified_host"))
00257   {
00258     Impl::assert_shapes_are_equal (d_view.shape (), h_view.shape ());
00259   }
00260 
00262 
00263 
00264 
00286   template< class Device >
00287   const typename Impl::if_c<
00288     Impl::is_same<typename t_dev::memory_space,
00289                           typename Device::memory_space>::value,
00290     t_dev,
00291     t_host>::type view () const
00292   {
00293     return Impl::if_c<
00294       Impl::is_same<
00295         typename t_dev::memory_space,
00296         typename Device::memory_space>::value,
00297       t_dev,
00298       t_host >::select (d_view , h_view);
00299   }
00300 
00318   template<class Device>
00319   void sync( const typename Impl::enable_if<
00320         ( Impl::is_same< typename traits::data_type , typename traits::non_const_data_type>::value) ||
00321         ( Impl::is_same< Device , int>::value)
00322         , int >::type& = 0)
00323   {
00324     const unsigned int dev =
00325       Impl::if_c<
00326         Impl::is_same<
00327           typename t_dev::memory_space,
00328           typename Device::memory_space>::value ,
00329         unsigned int,
00330         unsigned int>::select (1, 0);
00331 
00332     if (dev) { // if Device is the same as DualView's device type
00333       if ((modified_host () > 0) && (modified_host () >= modified_device ())) {
00334         deep_copy (d_view, h_view);
00335         modified_host() = modified_device() = 0;
00336       }
00337     } else { // hopefully Device is the same as DualView's host type
00338       if ((modified_device () > 0) && (modified_device () >= modified_host ())) {
00339         deep_copy (h_view, d_view);
00340         modified_host() = modified_device() = 0;
00341       }
00342     }
00343   }
00344 
00345   template<class Device>
00346   void sync ( const typename Impl::enable_if<
00347       ( ! Impl::is_same< typename traits::data_type , typename traits::non_const_data_type>::value ) ||
00348       ( Impl::is_same< Device , int>::value)
00349       , int >::type& = 0 )
00350   {
00351     const unsigned int dev =
00352       Impl::if_c<
00353         Impl::is_same<
00354           typename t_dev::memory_space,
00355           typename Device::memory_space>::value,
00356         unsigned int,
00357         unsigned int>::select (1, 0);
00358     if (dev) { // if Device is the same as DualView's device type
00359       if ((modified_host () > 0) && (modified_host () >= modified_device ())) {
00360         Impl::throw_runtime_exception("Calling sync on a DualView with a const datatype.");
00361       }
00362     } else { // hopefully Device is the same as DualView's host type
00363       if ((modified_device () > 0) && (modified_device () >= modified_host ())) {
00364         Impl::throw_runtime_exception("Calling sync on a DualView with a const datatype.");
00365       }
00366     }
00367   }
00373   template<class Device>
00374   void modify () {
00375     const unsigned int dev =
00376       Impl::if_c<
00377         Impl::is_same<
00378           typename t_dev::memory_space,
00379           typename Device::memory_space>::value,
00380         unsigned int,
00381         unsigned int>::select (1, 0);
00382 
00383     if (dev) { // if Device is the same as DualView's device type
00384       // Increment the device's modified count.
00385       modified_device () = (modified_device () > modified_host () ?
00386                             modified_device () : modified_host ()) + 1;
00387     } else { // hopefully Device is the same as DualView's host type
00388       // Increment the host's modified count.
00389       modified_host () = (modified_device () > modified_host () ?
00390                           modified_device () : modified_host ())  + 1;
00391     }
00392   }
00393 
00395 
00396 
00397 
00403   void realloc( const size_t n0 = 0 ,
00404            const size_t n1 = 0 ,
00405            const size_t n2 = 0 ,
00406            const size_t n3 = 0 ,
00407            const size_t n4 = 0 ,
00408            const size_t n5 = 0 ,
00409            const size_t n6 = 0 ,
00410            const size_t n7 = 0 ) {
00411     ::Kokkos::realloc(d_view,n0,n1,n2,n3,n4,n5,n6,n7);
00412 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_USE_CUDA_UVM)
00413      h_view = d_view ;
00414 #else
00415      h_view = create_mirror_view( d_view );
00416 #endif
00417      /* Reset dirty flags */
00418      modified_device() = modified_host() = 0;
00419   }
00420 
00425   void resize( const size_t n0 = 0 ,
00426            const size_t n1 = 0 ,
00427            const size_t n2 = 0 ,
00428            const size_t n3 = 0 ,
00429            const size_t n4 = 0 ,
00430            const size_t n5 = 0 ,
00431            const size_t n6 = 0 ,
00432            const size_t n7 = 0 ) {
00433    if(modified_device() >= modified_host()) {
00434      /* Resize on Device */
00435      ::Kokkos::resize(d_view,n0,n1,n2,n3,n4,n5,n6,n7);
00436 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_USE_CUDA_UVM)
00437      h_view = d_view ;
00438 #else
00439      h_view = create_mirror_view( d_view );
00440 #endif
00441 
00442      /* Mark Device copy as modified */
00443      modified_device() = modified_device()+1;
00444 
00445    } else {
00446      /* Realloc on Device */
00447 
00448      ::Kokkos::realloc(d_view,n0,n1,n2,n3,n4,n5,n6,n7);
00449 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_USE_CUDA_UVM)
00450      t_host temp_view = d_view ;
00451 #else
00452      t_host temp_view = create_mirror_view( d_view );
00453 #endif
00454 
00455      /* Remap on Host */
00456      Impl::ViewRemap< t_host , t_host >( temp_view , h_view );
00457      h_view = temp_view;
00458 
00459      /* Mark Host copy as modified */
00460      modified_host() = modified_host()+1;
00461    }
00462   }
00463 
00465 
00466 
00467 
00469   size_t capacity() const {
00470     return d_view.capacity();
00471   }
00472 
00474   template< typename iType>
00475   void stride(iType* stride_) const {
00476     d_view.stride(stride_);
00477   }
00478 
00479   /* \brief return size of dimension 0 */
00480   size_t dimension_0() const {return d_view.dimension_0();}
00481   /* \brief return size of dimension 1 */
00482   size_t dimension_1() const {return d_view.dimension_1();}
00483   /* \brief return size of dimension 2 */
00484   size_t dimension_2() const {return d_view.dimension_2();}
00485   /* \brief return size of dimension 3 */
00486   size_t dimension_3() const {return d_view.dimension_3();}
00487   /* \brief return size of dimension 4 */
00488   size_t dimension_4() const {return d_view.dimension_4();}
00489   /* \brief return size of dimension 5 */
00490   size_t dimension_5() const {return d_view.dimension_5();}
00491   /* \brief return size of dimension 6 */
00492   size_t dimension_6() const {return d_view.dimension_6();}
00493   /* \brief return size of dimension 7 */
00494   size_t dimension_7() const {return d_view.dimension_7();}
00495 
00497 };
00498 
00499 //
00500 // Partial specializations of Kokkos::subview() for DualView objects.
00501 //
00502 
00503 template< class DstViewType ,
00504           class T , class L , class D , class M ,
00505           class ArgType0 >
00506 DstViewType
00507 subview( const DualView<T,L,D,M> & src ,
00508          const ArgType0 & arg0 )
00509 {
00510   DstViewType sub_view;
00511   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0);
00512   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0);
00513   sub_view.modified_device = src.modified_device;
00514   sub_view.modified_host = src.modified_host;
00515   return sub_view;
00516 }
00517 
00518 
00519 template< class DstViewType ,
00520           class T , class L , class D , class M ,
00521           class ArgType0 , class ArgType1 >
00522 DstViewType
00523 subview( const DualView<T,L,D,M> & src ,
00524          const ArgType0 & arg0 ,
00525          const ArgType1 & arg1 )
00526 {
00527   DstViewType sub_view;
00528   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0,arg1);
00529   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0,arg1);
00530   sub_view.modified_device = src.modified_device;
00531   sub_view.modified_host = src.modified_host;
00532   return sub_view;
00533 }
00534 
00535 template< class DstViewType ,
00536           class T , class L , class D , class M ,
00537           class ArgType0 , class ArgType1 , class ArgType2 >
00538 DstViewType
00539 subview( const DualView<T,L,D,M> & src ,
00540          const ArgType0 & arg0 ,
00541          const ArgType1 & arg1 ,
00542          const ArgType2 & arg2 )
00543 {
00544   DstViewType sub_view;
00545   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0,arg1,arg2);
00546   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0,arg1,arg2);
00547   sub_view.modified_device = src.modified_device;
00548   sub_view.modified_host = src.modified_host;
00549   return sub_view;
00550 }
00551 
00552 template< class DstViewType ,
00553           class T , class L , class D , class M ,
00554           class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 >
00555 DstViewType
00556 subview( const DualView<T,L,D,M> & src ,
00557          const ArgType0 & arg0 ,
00558          const ArgType1 & arg1 ,
00559          const ArgType2 & arg2 ,
00560          const ArgType3 & arg3 )
00561 {
00562   DstViewType sub_view;
00563   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0,arg1,arg2,arg3);
00564   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0,arg1,arg2,arg3);
00565   sub_view.modified_device = src.modified_device;
00566   sub_view.modified_host = src.modified_host;
00567   return sub_view;
00568 }
00569 
00570 template< class DstViewType ,
00571           class T , class L , class D , class M ,
00572           class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
00573           class ArgType4 >
00574 DstViewType
00575 subview( const DualView<T,L,D,M> & src ,
00576          const ArgType0 & arg0 ,
00577          const ArgType1 & arg1 ,
00578          const ArgType2 & arg2 ,
00579          const ArgType3 & arg3 ,
00580          const ArgType4 & arg4 )
00581 {
00582   DstViewType sub_view;
00583   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0,arg1,arg2,arg3,arg4);
00584   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0,arg1,arg2,arg3,arg4);
00585   sub_view.modified_device = src.modified_device;
00586   sub_view.modified_host = src.modified_host;
00587   return sub_view;
00588 }
00589 
00590 template< class DstViewType ,
00591           class T , class L , class D , class M ,
00592           class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
00593           class ArgType4 , class ArgType5 >
00594 DstViewType
00595 subview( const DualView<T,L,D,M> & src ,
00596          const ArgType0 & arg0 ,
00597          const ArgType1 & arg1 ,
00598          const ArgType2 & arg2 ,
00599          const ArgType3 & arg3 ,
00600          const ArgType4 & arg4 ,
00601          const ArgType5 & arg5 )
00602 {
00603   DstViewType sub_view;
00604   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0,arg1,arg2,arg3,arg4,arg5);
00605   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0,arg1,arg2,arg3,arg4,arg5);
00606   sub_view.modified_device = src.modified_device;
00607   sub_view.modified_host = src.modified_host;
00608   return sub_view;
00609 }
00610 
00611 template< class DstViewType ,
00612           class T , class L , class D , class M ,
00613           class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
00614           class ArgType4 , class ArgType5 , class ArgType6 >
00615 DstViewType
00616 subview( const DualView<T,L,D,M> & src ,
00617          const ArgType0 & arg0 ,
00618          const ArgType1 & arg1 ,
00619          const ArgType2 & arg2 ,
00620          const ArgType3 & arg3 ,
00621          const ArgType4 & arg4 ,
00622          const ArgType5 & arg5 ,
00623          const ArgType6 & arg6 )
00624 {
00625   DstViewType sub_view;
00626   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6);
00627   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6);
00628   sub_view.modified_device = src.modified_device;
00629   sub_view.modified_host = src.modified_host;
00630   return sub_view;
00631 }
00632 
00633 template< class DstViewType ,
00634           class T , class L , class D , class M ,
00635           class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
00636           class ArgType4 , class ArgType5 , class ArgType6 , class ArgType7 >
00637 DstViewType
00638 subview( const DualView<T,L,D,M> & src ,
00639          const ArgType0 & arg0 ,
00640          const ArgType1 & arg1 ,
00641          const ArgType2 & arg2 ,
00642          const ArgType3 & arg3 ,
00643          const ArgType4 & arg4 ,
00644          const ArgType5 & arg5 ,
00645          const ArgType6 & arg6 ,
00646          const ArgType7 & arg7 )
00647 {
00648   DstViewType sub_view;
00649   sub_view.d_view = subview<typename DstViewType::t_dev>(src.d_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
00650   sub_view.h_view = subview<typename DstViewType::t_host>(src.h_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
00651   sub_view.modified_device = src.modified_device;
00652   sub_view.modified_host = src.modified_host;
00653   return sub_view;
00654 }
00655 
00656 //
00657 // Partial specialization of Kokkos::deep_copy() for DualView objects.
00658 //
00659 
00660 template< class DT , class DL , class DD , class DM ,
00661           class ST , class SL , class SD , class SM >
00662 void
00663 deep_copy (DualView<DT,DL,DD,DM> dst, // trust me, this must not be a reference
00664            const DualView<ST,SL,SD,SM>& src )
00665 {
00666   if (src.modified_device () >= src.modified_host ()) {
00667     deep_copy (dst.d_view, src.d_view);
00668     dst.template modify<typename DualView<DT,DL,DD,DM>::device_type> ();
00669   } else {
00670     deep_copy (dst.h_view, src.h_view);
00671     dst.template modify<typename DualView<DT,DL,DD,DM>::host_mirror_device_type> ();
00672   }
00673 }
00674 
00675 } // namespace Kokkos
00676 
00677 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends