Sierra Toolkit  Version of the Day
CudaMemoryMgr.hpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010 Sandia Corporation. */
3 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */
4 /* license for use of this work by or on behalf of the U.S. Government. */
5 /* Export of this program may require a license from the */
6 /* United States Government. */
7 /*------------------------------------------------------------------------*/
8 
9 #ifndef stk_algsup_CudaMemoryMgr_hpp
10 #define stk_algsup_CudaMemoryMgr_hpp
11 
12 #include <stdio.h>
13 #include <stdexcept>
14 #include <map>
15 
16 #include <stk_algsup/CudaCall.hpp>
17 
18 namespace stk_classic {
19 
32  public:
35  : host_to_device_map(),
36  device_to_host_map()
37  {}
38 
43  virtual ~CudaMemoryMgr();
44 
45 #ifdef STK_HAVE_CUDA
46 
55  template<class T>
56  T* get_buffer(const T* host_ptr, size_t buf_size);
57 
62  template<class T>
63  T* get_buffer(size_t buf_size);
64 
69  template<class T>
70  void destroy_buffer(T*& device_ptr);
71 
76  template<class T>
77  void copy_to_buffer(const T* host_ptr, size_t buf_size, T* device_ptr);
78 
83  template<class T>
84  void copy_from_buffer(T* host_ptr, size_t buf_size, const T* device_ptr);
85 
86  static CudaMemoryMgr& get_singleton();
87 
88 #endif
89 
90  private:
91  std::map<const void*,void*> host_to_device_map;
92  std::map<const void*,const void*> device_to_host_map;
93 };//class CudaMemoryMgr
94 
95 #ifdef STK_HAVE_CUDA
96 
97 //------------------------------------------------------------------------------
98 template<class T>
99 inline
100 T* CudaMemoryMgr::get_buffer(const T* host_ptr, size_t buf_size)
101 {
102  T* device_ptr = NULL;
103 
104  std::map<const void*,void*>::iterator iter = host_to_device_map.find(host_ptr);
105 
106  if (iter == host_to_device_map.end()) {
107  void* void_device_ptr = NULL;
108  CUDA_CALL( cudaMalloc( &void_device_ptr, sizeof(T)*buf_size) );
109  device_ptr = reinterpret_cast<T*>(void_device_ptr);
110 
111  host_to_device_map.insert( std::make_pair(host_ptr, device_ptr) );
112  device_to_host_map.insert( std::make_pair(device_ptr, host_ptr) );
113  }
114  else {
115  device_ptr = reinterpret_cast<T*>(iter->second);
116  }
117 
118  return device_ptr;
119 }
120 
121 //------------------------------------------------------------------------------
122 template<class T>
123 inline
124 T* CudaMemoryMgr::get_buffer(size_t buf_size)
125 {
126  T* device_ptr = NULL;
127 
128  CUDA_CALL( cudaMalloc( (void**)&device_ptr, sizeof(T)*buf_size) );
129 
130  device_to_host_map.insert( std::make_pair(device_ptr, NULL) );
131 
132  return device_ptr;
133 }
134 
135 //------------------------------------------------------------------------------
136 template<class T>
137 inline
138 void CudaMemoryMgr::destroy_buffer(T*& device_ptr)
139 {
140  std::map<const void*,const void*>::iterator iter = device_to_host_map.find(device_ptr);
141  if (iter != device_to_host_map.end()) {
142  const void* host_ptr = iter->second;
143  if (host_ptr != NULL) {
144  std::map<const void*,void*>::iterator iter2 = host_to_device_map.find(host_ptr);
145  if (iter2 != host_to_device_map.end()) {
146  host_to_device_map.erase(iter2);
147  }
148  }
149  CUDA_CALL( cudaFree(device_ptr) );
150  device_ptr = NULL;
151  device_to_host_map.erase(iter);
152  }
153 }
154 
155 //------------------------------------------------------------------------------
156 template<class T>
157 inline
158 void CudaMemoryMgr::copy_to_buffer(const T* host_ptr, size_t buf_size, T* device_ptr)
159 {
160  std::map<const void*,const void*>::iterator iter = device_to_host_map.find(device_ptr);
161  if (iter == device_to_host_map.end()) {
162  //failed to find device_ptr in device_to_host_map
163  throw std::runtime_error("CudaMemoryMgr::copy_to_buffer ERROR, device_ptr not known.");
164  }
165 
166  CUDA_CALL( cudaMemcpy( device_ptr, host_ptr, sizeof(T)*buf_size, cudaMemcpyHostToDevice) );
167 }
168 
169 //------------------------------------------------------------------------------
170 template<class T>
171 inline
172 void CudaMemoryMgr::copy_from_buffer(T* host_ptr, size_t buf_size, const T* device_ptr)
173 {
174  std::map<const void*,const void*>::iterator iter = device_to_host_map.find(device_ptr);
175  if (iter == device_to_host_map.end()) {
176  //failed to find device_ptr in device_to_host_map
177  throw std::runtime_error("CudaMemoryMgr::copy_from_buffer ERROR, device_ptr not known.");
178  }
179 
180  CUDA_CALL( cudaMemcpy( host_ptr, device_ptr, sizeof(T)*buf_size, cudaMemcpyDeviceToHost) );
181 }
182 
183 #endif
184 
185 }//namespace stk_classic
186 
187 #endif
188 
Sierra Toolkit.