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