Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_checkPointer.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 // ************************************************************************
38 // @HEADER
39 
41 #include "Kokkos_Core.hpp"
42 #ifdef HAVE_TPETRACORE_CUDA
43 # include "cuda_runtime_api.h"
44 #endif // HAVE_TPETRACORE_CUDA
45 
46 namespace Tpetra {
47 namespace Details {
48 namespace Impl {
49 
50 enum class EMemoryType {
51  HOST,
52  CUDA_HOST_PINNED,
53  CUDA,
54  CUDA_UVM,
55  ERROR
56 };
57 
58 EMemoryType getCudaMemoryType (const void* ptr)
59 {
60 #ifdef HAVE_TPETRACORE_CUDA
61  cudaPointerAttributes attr;
62  const cudaError_t err = cudaPointerGetAttributes (&attr, ptr);
63  (void) cudaGetLastError (); // reset error state for future CUDA ops
64 
65  if (err == cudaErrorInvalidValue) {
66  // CUDA 11.0 supports passing in an unregistered host pointer. In
67  // that case, attr.type will be cudaMemoryTypeUnregistered. CUDA
68  // 9.2 doesn't yet have the 'type' field in the
69  // cudaPointerAttributes struct, and this function just returns
70  // this error code if given an unregistered host pointer.
71  return EMemoryType::HOST;
72  }
73  else if (err != cudaSuccess) {
74  return EMemoryType::ERROR;
75  }
76 
77 # if 1
78  // cudaPointerAttributes::type doesn't exist yet in CUDA 9.2. We
79  // must use memoryType, which does not distinguish between types of
80  // device memory.
81  if (attr.memoryType == cudaMemoryTypeDevice) {
82  if (attr.isManaged) {
83  return EMemoryType::CUDA_UVM;
84  }
85  else { // if (attr.hostPointer == nullptr) {
86  return EMemoryType::CUDA;
87  }
88  // else {
89  // return EMemoryType::ERROR;
90  // }
91  }
92  else if (attr.memoryType == cudaMemoryTypeHost) {
93  if (attr.devicePointer == nullptr) {
94  return EMemoryType::HOST; // not device accessible
95  }
96  else { // device-accessible host memory is pinned
97  return EMemoryType::CUDA_HOST_PINNED;
98  }
99  }
100  else {
101  return EMemoryType::ERROR;
102  }
103 
104 # else
105 
106  const enum cudaMemoryType theType = attr.type;
107  if (theType == cudaMemoryTypeManaged) {
108  return EMemoryType::CUDA_UVM;
109  }
110  else if (theType == cudaMemoryTypeDevice) {
111  return EMemoryType::CUDA;
112  }
113  else if (theType == cudaMemoryTypeHost) {
114  return EMemoryType::CUDA_HOST_PINNED;
115  }
116  else {
117  return EMemoryType::HOST;
118  }
119 
120 # endif // 1
121 #else // NOT HAVE_TPETRACORE_CUDA
122  return EMemoryType::HOST;
123 #endif // HAVE_TPETRACORE_CUDA
124 }
125 
126 #ifdef HAVE_TPETRACORE_CUDA
127 bool
128 CheckPointerAccessibility<Kokkos::Cuda>::
129 accessible (const void* ptr,
130  const Kokkos::Cuda& /* space */)
131 {
132  const EMemoryType type = getCudaMemoryType (ptr);
133  return type != EMemoryType::HOST && type != EMemoryType::ERROR;
134 }
135 #endif // HAVE_TPETRACORE_CUDA
136 
137 bool isHostAccessible (const void* ptr)
138 {
139 #ifdef HAVE_TPETRACORE_CUDA
140  return getCudaMemoryType (ptr) != EMemoryType::CUDA;
141 #else
142  return true;
143 #endif // HAVE_TPETRACORE_CUDA
144 }
145 
146 } // namespace Impl
147 
148 std::string memorySpaceName (const void* ptr)
149 {
150  using Impl::EMemoryType;
151 
152  const EMemoryType type = Impl::getCudaMemoryType (ptr);
153  if (type == EMemoryType::CUDA_UVM) {
154  return "CudaUVMSpace";
155  }
156  else if (type == EMemoryType::CUDA) {
157  return "CudaSpace";
158  }
159  else if (type == EMemoryType::CUDA_HOST_PINNED) {
160  return "CudaHostPinnedSpace";
161  }
162  else if (type == EMemoryType::HOST) {
163  return "HostSpace";
164  }
165  else { // EMemoryType::ERROR
166  return "ERROR";
167  }
168 }
169 
170 } // namespace Details
171 } // namespace Tpetra
std::string memorySpaceName(const void *ptr)
Return the Kokkos memory space name (without &quot;Kokkos::&quot;) corresponding to the given nonnull pointer...
Declaration of functions for checking whether a given pointer is accessible from a given Kokkos execu...