Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Kokkos_View_Copy_Assign.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Amesos2: Templated Direct Sparse Solver Package
4 //
5 // Copyright 2011 NTESS and the Amesos2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
18 #ifndef AMESOS2_KOKKOS_VIEW_COPY_ASSIGN_HPP
19 #define AMESOS2_KOKKOS_VIEW_COPY_ASSIGN_HPP
20 
21 namespace Amesos2 {
22 
23 // allocate dst size if necessary - 2 methods handle 1d and 2d
24 template<class dst_t, class src_t> // version for 1d view
25 typename std::enable_if<static_cast<int>(dst_t::rank) == 1>::type
26 update_dst_size(dst_t & dst, const src_t & src) {
27  if(dst.extent(0) != src.extent(0)) { // templated just for 1D
28  dst = dst_t(Kokkos::ViewAllocateWithoutInitializing("dst"),
29  src.extent(0));
30  }
31 }
32 
33 template<class dst_t, class src_t> // version for 2d view
34 typename std::enable_if<static_cast<int>(dst_t::rank) == 2>::type
35 update_dst_size(dst_t & dst, const src_t & src) { // templated just for 2d
36  if(dst.extent(0) != src.extent(0) || dst.extent(1) != src.extent(1)) {
37  dst = dst_t(Kokkos::ViewAllocateWithoutInitializing("dst"),
38  src.extent(0), src.extent(1));
39  }
40 }
41 
42 // now handle type mismatch for same memory space - here types are same
43 // bInitialize:
44 // If bInitialize is false, then the data needs to be allocated but not initialized.
45 // If we are about to solve into x we don't care about setting the original values.
46 // In this case, we are assigning the view directly so bInitialize does not matter.
47 // bAssigned:
48 // bAssigned tells the caller if the data was simply assigned, so it is set true in this case.
49 template<class dst_t, class src_t> // version for same memory spaces
50 typename std::enable_if<std::is_same<typename dst_t::value_type,
51  typename src_t::value_type>::value>::type
52 implement_copy_or_assign_same_mem_check_types(
53  [[maybe_unused]] bool bInitialize,
54  dst_t & dst,
55  const src_t & src,
56  bool & bAssigned
57 ) {
58  dst = src; // just assign the ptr - no need to copy
59  bAssigned = true;
60 }
61 
62 
63 // deep-copy version (no checking)
64 // bInitialize:
65 // If bInitialize is false, then the data needs to be allocated but not initialized.
66 // If we are about to solve into x we don't care about setting the original values.
67 // In this case, we are allocating so we first make the memory via update_dst_size.
68 // Then we only copy from the source if bInitialize is true.
69 // bAssigned:
70 // bAssigned tells the caller if the data was simply assigned, so it is set false in this case.
71 template<class dst_t, class src_t> // actual implementation
72 void deep_copy_only(bool bInitialize, dst_t & dst, const src_t & src, bool & bAssigned) {
73  update_dst_size(dst, src); // allocates if necessary
74  if(bInitialize) { // bInitialize false would be for solver getting x, where the actual values are not needed
75  Kokkos::deep_copy(dst, src); // full copy
76  }
77  bAssigned = false;
78 }
79 
80 template<class dst_t, class src_t> // actual implementation
81 void deep_copy_only(dst_t & dst, const src_t & src) {
82  bool bAssigned;
83  deep_copy_only(true, dst, src, bAssigned);
84 }
85 
86 // now handle type mismatch for same memory space - now types are different
87 // bInitialize:
88 // If bInitialize is false, then the data needs to be allocated but not initialized.
89 // If we are about to solve into x we don't care about setting the original values.
90 // In this case, we are allocating so we first make the memory via update_dst_size.
91 // Then we only copy from the source if bInitialize is true.
92 // bAssigned:
93 // bAssigned tells the caller if the data was simply assigned, so it is set false in this case.
94 template<class dst_t, class src_t> // version for same memory spaces
95 typename std::enable_if<!std::is_same<typename dst_t::value_type,
96  typename src_t::value_type>::value>::type
97 implement_copy_or_assign_same_mem_check_types(bool bInitialize, dst_t & dst, const src_t & src, bool & bAssigned) {
98  update_dst_size(dst, src); // allocates if necessary
99  if(bInitialize) { // bInitialize false would be for solver getting x, where the actual values are not needed
100  Kokkos::deep_copy(dst, src); // full copy
101  }
102  bAssigned = false;
103 }
104 
105 // implement_copy_or_assign has 2 versions for matched memory and
106 // mismatched memory. Right now we just check the memory space.
107 // a layout mismatch is going to compile fail so probably reflects an error
108 // in the initial setup.
109 template<class dst_t, class src_t> // version for same memory spaces
110 typename std::enable_if<std::is_same<typename dst_t::memory_space,
111  typename src_t::memory_space>::value>::type
112 deep_copy_or_assign_view(bool bInitialize, dst_t & dst, const src_t & src, bool & bAssigned) {
113  implement_copy_or_assign_same_mem_check_types(bInitialize, dst, src, bAssigned);
114 }
115 
116 // for convenience this version does not take bInitialize input and bAssigned ouput
117 // then it's assumed you want bInitialize true and don't need to know bAssigned
118 template<class dst_t, class src_t> // version for same memory spaces
119 typename std::enable_if<std::is_same<typename dst_t::memory_space,
120  typename src_t::memory_space>::value>::type
121 deep_copy_or_assign_view(dst_t & dst, const src_t & src) {
122  bool bAssigned; // output not needed
123  implement_copy_or_assign_same_mem_check_types(true, dst, src, bAssigned);
124 }
125 
126 template<class dst_t, class src_t> // version for different memory spaces
127 typename std::enable_if<std::is_same<typename dst_t::value_type,
128  typename src_t::value_type>::value>::type
129 implement_copy_or_assign_diff_mem_check_types(bool bInitialize, dst_t & dst, const src_t & src, bool & bAssigned) {
130  update_dst_size(dst, src); // allocates if necessary
131  if(bInitialize) { // bInitialize false would be for solver getting x, where the actual values are not needed
132  Kokkos::deep_copy(dst, src); // full copy
133  }
134  bAssigned = false;
135 }
136 
137 template<class dst_t, class src_t> // version for different memory spaces
138 typename std::enable_if<static_cast<int>(dst_t::rank) == 1>::type
139 implement_copy_or_assign_diff_mem_diff_types_check_dim(dst_t & dst, const src_t & src) {
140  Kokkos::View<typename dst_t::value_type*, typename src_t::execution_space>
141  intermediate(Kokkos::ViewAllocateWithoutInitializing("intermediate"), src.extent(0));
142  Kokkos::deep_copy(intermediate, src); // to dst type
143  Kokkos::deep_copy(dst, intermediate); // to dst mem
144 }
145 
146 template<class dst_t, class src_t> // version for different memory spaces
147 typename std::enable_if<static_cast<int>(dst_t::rank) == 2>::type
148 implement_copy_or_assign_diff_mem_diff_types_check_dim(dst_t & dst, const src_t & src) {
149  Kokkos::View<typename dst_t::value_type**, Kokkos::LayoutLeft, typename src_t::execution_space>
150  intermediate(Kokkos::ViewAllocateWithoutInitializing("intermediate"), src.extent(0), src.extent(1));
151  Kokkos::deep_copy(intermediate, src); // to dst type
152  Kokkos::deep_copy(dst, intermediate); // to dst mem
153 }
154 
155 template<class dst_t, class src_t> // version for different memory spaces
156 typename std::enable_if<!std::is_same<typename dst_t::value_type,
157  typename src_t::value_type>::value>::type
158 implement_copy_or_assign_diff_mem_check_types(bool bInitialize, dst_t & dst, const src_t & src, bool & bAssigned) {
159  update_dst_size(dst, src); // allocates if necessary
160  bAssigned = false;
161  if(bInitialize) { // bInitialize false would be for solver getting x, where the actual values are not needed
162  // since mem space and types are different, we specify the order of operations
163  // Kokkos::deep_copy won't do both since it would be a hidden deep_copy
164  implement_copy_or_assign_diff_mem_diff_types_check_dim(dst, src);
165  }
166 }
167 
168 template<class dst_t, class src_t> // version for different memory spaces
169 typename std::enable_if<!std::is_same<typename dst_t::memory_space,
170  typename src_t::memory_space>::value>::type
171 deep_copy_or_assign_view(bool bInitialize, dst_t & dst, const src_t & src, bool & bAssigned) {
172  implement_copy_or_assign_diff_mem_check_types(bInitialize, dst, src, bAssigned); // full copy
173 }
174 
175 // for convenience this version does not take bInitialize input and bAssigned ouput
176 // then it's assumed you want bInitialize true and don't need to know bAssigned
177 template<class dst_t, class src_t> // version for different memory spaces
178 typename std::enable_if<!std::is_same<typename dst_t::memory_space,
179  typename src_t::memory_space>::value>::type
180 deep_copy_or_assign_view(dst_t & dst, const src_t & src) {
181  bool bAssigned; // output not needed
182  implement_copy_or_assign_diff_mem_check_types(true, dst, src, bAssigned); // full copy
183 }
184 
185 } // end namespace Amesos2
186 
187 #endif // AMESOS2_KOKKOS_VIEW_COPY_ASSIGN_HPP