Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_StaticView.cpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 // @HEADER
41 
42 #include "Tpetra_Details_StaticView.hpp"
43 
44 namespace Tpetra {
45 namespace Details {
46 namespace Impl {
47 
48 namespace { // (anonymous)
49 
50 // Motivating use cases for the initial size:
51 //
52 // 1. GMRES (need restart length (default 30) number of rows)
53 // 2. Single reduce CG (need 2 x 2)
54 constexpr size_t minimum_initial_size = sizeof (double) * 30 * 2;
55 
56 // Intel 17 seems a bit buggy with respect to initialization of
57 // templated static classes, so let's make the compiler's job really
58 // easy by having nontemplated static raw pointers.
59 
60 #ifdef KOKKOS_ENABLE_CUDA
61 
62 void* cuda_memory_ = nullptr;
63 size_t cuda_memory_size_ = 0;
64 
65 void finalize_cuda_memory ()
66 {
67  if (cuda_memory_ != nullptr) {
68  Kokkos::kokkos_free<Kokkos::CudaSpace> (cuda_memory_);
69  cuda_memory_ = nullptr;
70  cuda_memory_size_ = 0;
71  }
72 }
73 
74 void* cuda_uvm_memory_ = nullptr;
75 size_t cuda_uvm_memory_size_ = 0;
76 
77 void finalize_cuda_uvm_memory ()
78 {
79  if (cuda_uvm_memory_ != nullptr) {
80  Kokkos::kokkos_free<Kokkos::CudaUVMSpace> (cuda_uvm_memory_);
81  cuda_uvm_memory_ = nullptr;
82  cuda_uvm_memory_size_ = 0;
83  }
84 }
85 
86 void* cuda_host_pinned_memory_ = nullptr;
87 size_t cuda_host_pinned_memory_size_ = 0;
88 
89 void finalize_cuda_host_pinned_memory ()
90 {
91  if (cuda_host_pinned_memory_ != nullptr) {
92  Kokkos::kokkos_free<Kokkos::CudaHostPinnedSpace> (cuda_host_pinned_memory_);
93  cuda_host_pinned_memory_ = nullptr;
94  cuda_host_pinned_memory_size_ = 0;
95  }
96 }
97 #endif // KOKKOS_ENABLE_CUDA
98 
99 #ifdef KOKKOS_ENABLE_HIP
100 
101 void* hip_memory_ = nullptr;
102 size_t hip_memory_size_ = 0;
103 
104 void finalize_hip_memory ()
105 {
106  if (hip_memory_ != nullptr) {
107  Kokkos::kokkos_free<Kokkos::HIPSpace> (hip_memory_);
108  hip_memory_ = nullptr;
109  hip_memory_size_ = 0;
110  }
111 }
112 
113 void* hip_host_pinned_memory_ = nullptr;
114 size_t hip_host_pinned_memory_size_ = 0;
115 
116 void finalize_hip_host_pinned_memory ()
117 {
118  if (hip_host_pinned_memory_ != nullptr) {
119  Kokkos::kokkos_free<Kokkos::HIPHostPinnedSpace> (hip_host_pinned_memory_);
120  hip_host_pinned_memory_ = nullptr;
121  hip_host_pinned_memory_size_ = 0;
122  }
123 }
124 #endif // KOKKOS_ENABLE_HIP
125 
126 #ifdef KOKKOS_ENABLE_SYCL
127 
128 void* sycl_memory_ = nullptr;
129 size_t sycl_memory_size_ = 0;
130 
131 void finalize_sycl_memory ()
132 {
133  if (sycl_memory_ != nullptr) {
134  Kokkos::kokkos_free<Kokkos::Experimental::SYCLDeviceUSMSpace> (sycl_memory_);
135  sycl_memory_ = nullptr;
136  sycl_memory_size_ = 0;
137  }
138 }
139 
140 void* sycl_shared_memory_ = nullptr;
141 size_t sycl_shared_memory_size_ = 0;
142 
143 void finalize_sycl_shared_memory ()
144 {
145  if (sycl_shared_memory_ != nullptr) {
146  Kokkos::kokkos_free<Kokkos::Experimental::SYCLSharedUSMSpace> (sycl_shared_memory_);
147  sycl_shared_memory_ = nullptr;
148  sycl_shared_memory_size_ = 0;
149  }
150 }
151 #endif // KOKKOS_ENABLE_SYCL
152 
153 void* host_memory_ = nullptr;
154 size_t host_memory_size_ = 0;
155 
156 void finalize_host_memory ()
157 {
158  if (host_memory_ != nullptr) {
159  Kokkos::kokkos_free<Kokkos::HostSpace> (host_memory_);
160  host_memory_ = nullptr;
161  host_memory_size_ = 0;
162  }
163 }
164 
165 } // namespace (anonymous)
166 
167 #ifdef KOKKOS_ENABLE_CUDA
168 
169 void*
170 StaticKokkosAllocation<Kokkos::CudaSpace>::
171 resize (Kokkos::CudaSpace /* space */,
172  const size_t size)
173 {
174  using memory_space = Kokkos::CudaSpace;
175  static bool created_finalize_hook = false;
176 
177  if (size > cuda_memory_size_) {
178  if (cuda_memory_ != nullptr) {
179  Kokkos::kokkos_free<memory_space> (cuda_memory_);
180  }
181  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
182  cuda_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
183  cuda_memory_size_ = size;
184  }
185  if (! created_finalize_hook) {
186  Kokkos::push_finalize_hook (finalize_cuda_memory);
187  created_finalize_hook = true;
188  }
189 
190  return cuda_memory_;
191 }
192 
193 void*
194 StaticKokkosAllocation<Kokkos::CudaUVMSpace>::
195 resize (Kokkos::CudaUVMSpace /* space */,
196  const size_t size)
197 {
198  using memory_space = Kokkos::CudaUVMSpace;
199  static bool created_finalize_hook = false;
200 
201  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
202  if (req_size > cuda_uvm_memory_size_) {
203  if (cuda_uvm_memory_ != nullptr) {
204  Kokkos::kokkos_free<memory_space> (cuda_uvm_memory_);
205  }
206  cuda_uvm_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
207  cuda_uvm_memory_size_ = req_size;
208  }
209  if (! created_finalize_hook) {
210  Kokkos::push_finalize_hook (finalize_cuda_uvm_memory);
211  created_finalize_hook = true;
212  }
213 
214  return cuda_uvm_memory_;
215 }
216 
217 void*
218 StaticKokkosAllocation<Kokkos::CudaHostPinnedSpace>::
219 resize (Kokkos::CudaHostPinnedSpace /* space */,
220  const size_t size)
221 {
222  using memory_space = Kokkos::CudaHostPinnedSpace;
223  static bool created_finalize_hook = false;
224 
225  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
226  if (req_size > cuda_host_pinned_memory_size_) {
227  if (cuda_host_pinned_memory_ != nullptr) {
228  Kokkos::kokkos_free<memory_space> (cuda_host_pinned_memory_);
229  }
230  cuda_host_pinned_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
231  cuda_host_pinned_memory_size_ = req_size;
232  }
233  if (! created_finalize_hook) {
234  Kokkos::push_finalize_hook (finalize_cuda_host_pinned_memory);
235  created_finalize_hook = true;
236  }
237 
238  return cuda_host_pinned_memory_;
239 }
240 
241 #endif // KOKKOS_ENABLE_CUDA
242 
243 #ifdef KOKKOS_ENABLE_HIP
244 
245 void*
246 StaticKokkosAllocation<Kokkos::HIPSpace>::
247 resize (Kokkos::HIPSpace /* space */,
248  const size_t size)
249 {
250  using memory_space = Kokkos::HIPSpace;
251  static bool created_finalize_hook = false;
252 
253  if (size > hip_memory_size_) {
254  if (hip_memory_ != nullptr) {
255  Kokkos::kokkos_free<memory_space> (hip_memory_);
256  }
257  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
258  hip_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
259  hip_memory_size_ = size;
260  }
261  if (! created_finalize_hook) {
262  Kokkos::push_finalize_hook (finalize_hip_memory);
263  created_finalize_hook = true;
264  }
265 
266  return hip_memory_;
267 }
268 
269 void*
270 StaticKokkosAllocation<Kokkos::HIPHostPinnedSpace>::
271 resize (Kokkos::HIPHostPinnedSpace /* space */,
272  const size_t size)
273 {
274  using memory_space = Kokkos::HIPHostPinnedSpace;
275  static bool created_finalize_hook = false;
276 
277  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
278  if (req_size > hip_host_pinned_memory_size_) {
279  if (hip_host_pinned_memory_ != nullptr) {
280  Kokkos::kokkos_free<memory_space> (hip_host_pinned_memory_);
281  }
282  hip_host_pinned_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
283  hip_host_pinned_memory_size_ = req_size;
284  }
285  if (! created_finalize_hook) {
286  Kokkos::push_finalize_hook (finalize_hip_host_pinned_memory);
287  created_finalize_hook = true;
288  }
289 
290  return hip_host_pinned_memory_;
291 }
292 
293 #endif // KOKKOS_ENABLE_HIP
294 
295 #ifdef KOKKOS_ENABLE_SYCL
296 
297 template <>
298 void*
299 StaticKokkosAllocation<Kokkos::Experimental::SYCLDeviceUSMSpace>::
300 resize (Kokkos::Experimental::SYCLDeviceUSMSpace /* space */,
301  const size_t size)
302 {
303  using memory_space = Kokkos::Experimental::SYCLDeviceUSMSpace;
304  static bool created_finalize_hook = false;
305 
306  if (size > sycl_memory_size_) {
307  if (sycl_memory_ != nullptr) {
308  Kokkos::kokkos_free<memory_space> (sycl_memory_);
309  }
310  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
311  sycl_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
312  sycl_memory_size_ = size;
313  }
314  if (! created_finalize_hook) {
315  Kokkos::push_finalize_hook (finalize_sycl_memory);
316  created_finalize_hook = true;
317  }
318 
319  return sycl_memory_;
320 }
321 
322 template <>
323 void*
324 StaticKokkosAllocation<Kokkos::Experimental::SYCLSharedUSMSpace>::
325 resize (Kokkos::Experimental::SYCLSharedUSMSpace /* space */,
326  const size_t size)
327 {
328  using memory_space = Kokkos::Experimental::SYCLSharedUSMSpace;
329  static bool created_finalize_hook = false;
330 
331  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
332  if (req_size > sycl_shared_memory_size_) {
333  if (sycl_shared_memory_ != nullptr) {
334  Kokkos::kokkos_free<memory_space> (sycl_shared_memory_);
335  }
336  sycl_shared_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
337  sycl_shared_memory_size_ = req_size;
338  }
339  if (! created_finalize_hook) {
340  Kokkos::push_finalize_hook (finalize_sycl_shared_memory);
341  created_finalize_hook = true;
342  }
343 
344  return sycl_shared_memory_;
345 }
346 
347 #endif // KOKKOS_ENABLE_SYCL
348 
349 void*
350 StaticKokkosAllocation<Kokkos::HostSpace>::
351 resize (Kokkos::HostSpace /* space */,
352  const size_t size)
353 {
354  using memory_space = Kokkos::HostSpace;
355  static bool created_finalize_hook = false;
356 
357  const size_t req_size = size > minimum_initial_size ? size : minimum_initial_size;
358  if (req_size > host_memory_size_) {
359  if (host_memory_ != nullptr) {
360  Kokkos::kokkos_free<memory_space> (host_memory_);
361  }
362  host_memory_ = Kokkos::kokkos_malloc<memory_space> (req_size);
363  host_memory_size_ = req_size;
364  }
365  if (! created_finalize_hook) {
366  Kokkos::push_finalize_hook (finalize_host_memory);
367  created_finalize_hook = true;
368  }
369 
370  return host_memory_;
371 }
372 
373 } // namespace Impl
374 } // namespace Details
375 } // namespace Tpetra