Xmipp  v3.23.11-Nereus
gpu.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: David Strelak (davidstrelak@gmail.com)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "gpu.h"
27 #include <sstream>
28 #include <cuda_runtime.h>
29 #include "cuda_asserts.h"
30 #include <nvml.h>
31 
33  if (m_isSet) {
34  synch();
35  auto s = (cudaStream_t*)m_stream;
36  gpuErrchk(cudaStreamDestroy(*s));
37  delete (cudaStream_t*)m_stream;
38  m_stream = nullptr;
39  m_uuid = std::string();
40  }
41  m_isSet = false;
42 }
43 
45  int version = 0;
46  gpuErrchk(cudaRuntimeGetVersion(&version));
47  return version;
48 }
49 
50 void GPU::set() {
51  // set device (for current context / thread)
52  setDevice(m_device);
53  if ( ! m_isSet) {
54  // create stream
55  m_stream = new cudaStream_t;
56  gpuErrchk(cudaStreamCreate((cudaStream_t*)m_stream));
57  // remember the state
58  m_isSet = true;
59  // get additional info
60  HW::set();
61  }
62  peekLastError();
63 }
64 
65 void GPU::obtainUUID() {
66  std::stringstream ss;
67  nvmlDevice_t device;
68  // https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceQueries.html#group__nvmlDeviceQueries_1g84dca2d06974131ccec1651428596191
69  if (NVML_SUCCESS == nvmlInit()) {
70  if (NVML_SUCCESS == nvmlDeviceGetHandleByIndex(m_device, &device)) { // FIXME DS this will return ID of the nth device, but not of the 'nth visible device'
71  char uuid[80];
72  if (NVML_SUCCESS == nvmlDeviceGetUUID(device, uuid, 80)) {
73  ss << uuid;
74  }
75  }
76  } else {
77  ss << m_device;
78  }
79  m_uuid = ss.str();
80 }
81 
83  check();
84  gpuErrchk(cudaMemGetInfo(&m_lastFreeBytes, &m_totalBytes));
85 }
86 
87 void GPU::peekLastError() const {
88  check();
89  gpuErrchk(cudaPeekAtLastError());
90 }
91 
92 void GPU::pinMemory(const void *h_mem, size_t bytes,
93  unsigned int flags) {
94  if (isMemoryPinned(h_mem)
95  && (isMemoryPinned((char*)h_mem + bytes - 1))) {
96  return;
97  }
98  assert(0 == cudaHostRegisterDefault); // default value should be 0
99  // check that it's aligned properly to the beginning of the page
100  if (0 != ((size_t)h_mem % 4096)) {
101  // otherwise the cuda-memcheck and cuda-gdb tends to randomly crash (confirmed on cuda 8 - cuda 10)
102  REPORT_ERROR(ERR_PARAM_INCORRECT, "Only pointer aligned to the page size can be registered");
103  }
104  // we remove const, but we don't change the data
105  gpuErrchk(cudaHostRegister(const_cast<void*>(h_mem), bytes, flags));
106 }
107 
108 void GPU::unpinMemory(const void *h_mem) {
109  // we remove const, but we don't change the data
110  auto err = cudaHostUnregister(const_cast<void*>(h_mem));
111  if (cudaErrorHostMemoryNotRegistered == err) {
112  cudaGetLastError(); // clear out the previous API error
113  } else {
114  gpuErrchk(err);
115  }
116 }
117 
119  int deviceCount = 0;
120  gpuErrchk(cudaGetDeviceCount(&deviceCount));
121  return deviceCount;
122 }
123 
124 void GPU::synchAll() const {
125  check();
126  gpuErrchk(cudaDeviceSynchronize());
127 }
128 
129 void GPU::synch() const {
130  check();
131  auto stream = (cudaStream_t*)m_stream;
132  gpuErrchk(cudaStreamSynchronize(*stream));
133 }
134 
136  gpuErrchk(cudaSetDevice(device));
137  gpuErrchk(cudaPeekAtLastError());
138 }
139 
140 bool GPU::isMemoryPinned(const void *h_mem) {
141  cudaPointerAttributes attr;
142  if (cudaPointerGetAttributes(&attr, h_mem) != cudaSuccess) {
143  cudaGetLastError(); // clear out the previous API error
144  return false;
145  }
146  #if defined(CUDART_VERSION) && CUDART_VERSION >= 10000
147  return (cudaMemoryTypeHost == attr.type) || (cudaMemoryTypeManaged == attr.type);
148  #else
149  return cudaMemoryTypeHost == attr.memoryType;
150  #endif
151 }
152 
153 bool GPU::isGpuPointer(const void *p) {
154  cudaPointerAttributes attr;
155  if (cudaPointerGetAttributes(&attr, p) == cudaErrorInvalidValue) {
156  cudaGetLastError(); // clear out the previous API error
157  return false;
158  }
159 #if defined(CUDART_VERSION) && CUDART_VERSION >= 10000
160  return (cudaMemoryTypeDevice == attr.type) || (cudaMemoryTypeManaged == attr.type);
161 #else
162  return cudaMemoryTypeDevice == attr.memoryType;
163 #endif
164 }
#define gpuErrchk(code)
Definition: cuda_asserts.h:31
void * stream() const
Definition: gpu.h:50
Parameter incorrect.
Definition: xmipp_error.h:181
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
static void setDevice(int device)
Definition: gpu.cpp:135
~GPU()
Definition: gpu.cpp:32
static bool isMemoryPinned(const void *h_mem)
Definition: gpu.cpp:140
static void pinMemory(const void *h_mem, size_t bytes, unsigned int flags=0)
Definition: gpu.cpp:92
int device() const
Definition: gpu.h:46
virtual void set()
Definition: hw.h:50
void updateMemoryInfo()
Definition: gpu.cpp:82
void set()
Definition: gpu.cpp:50
size_t m_totalBytes
Definition: hw.h:80
void synch() const
Definition: gpu.cpp:129
int getCudaVersion()
Definition: gpu.cpp:44
size_t m_lastFreeBytes
Definition: hw.h:81
void peekLastError() const
Definition: gpu.cpp:87
static int getDeviceCount()
Definition: gpu.cpp:118
void synchAll() const
Definition: gpu.cpp:124
std::string m_uuid
Definition: hw.h:82
static void unpinMemory(const void *h_mem)
Definition: gpu.cpp:108
bool isGpuPointer(const void *)
Definition: gpu.cpp:153