Image Utilities (IU)
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Groups Pages
lineardevicememory.h
1 #pragma once
2 
3 #include <cuda_runtime_api.h>
4 #include <thrust/device_ptr.h>
5 #include <type_traits>
6 
7 #include "../iucutil.h"
8 #include "linearmemory.h"
9 
10 template<typename, int> class ndarray_ref;
11 
12 namespace iu {
13 
17 template<typename PixelType, unsigned int Ndim>
18 class LinearDeviceMemory: public LinearMemory<Ndim>
19 {
20 public:
22  typedef PixelType pixel_type;
23  static const unsigned int ndim = Ndim;
24 
27  LinearMemory<Ndim>(), data_(0), ext_data_pointer_(false)
28  {
29  }
30 
33  {
34  if ((!ext_data_pointer_) && (data_ != NULL))
35  {
36  IU_CUDA_SAFE_CALL(cudaFree(data_));
37  data_ = 0;
38  }
39  }
40 
45  LinearMemory<Ndim>(size), data_(0), ext_data_pointer_(false)
46  {
47  IU_CUDA_SAFE_CALL(
48  cudaMalloc((void** )&data_, this->numel() * sizeof(PixelType)));
49  if (data_ == 0)
50  throw std::bad_alloc();
51  }
52 
56  LinearDeviceMemory(const unsigned int& numel) :
57  LinearMemory<Ndim>(numel), data_(0), ext_data_pointer_(false)
58  {
59  IU_CUDA_SAFE_CALL(
60  cudaMalloc((void** )&data_, this->numel() * sizeof(PixelType)));
61  if (data_ == 0)
62  throw std::bad_alloc();
63  }
64 
70  LinearDeviceMemory(PixelType* device_data, const Size<Ndim>& size,
71  bool ext_data_pointer = false) :
72  LinearMemory<Ndim>(size), data_(0), ext_data_pointer_(ext_data_pointer)
73  {
74  if (device_data == 0)
75  throw IuException("input data not valid", __FILE__, __FUNCTION__,
76  __LINE__);
77  if (ext_data_pointer_)
78  {
79  // This uses the external data pointer as internal data pointer.
80  data_ = device_data;
81  }
82  else
83  {
84  // allocates an internal data pointer and copies the external data onto it.
85  IU_CUDA_SAFE_CALL(
86  cudaMalloc((void** )&data_, this->numel() * sizeof(PixelType)));
87  if (data_ == 0)
88  throw std::bad_alloc();
89  IU_CUDA_SAFE_CALL(
90  cudaMemcpy(data_, device_data, this->numel() * sizeof(PixelType),
91  cudaMemcpyHostToDevice));
92  }
93  }
94 
100  LinearDeviceMemory(PixelType* device_data, const unsigned int& numel,
101  bool ext_data_pointer = false) :
102  LinearMemory<Ndim>(numel), data_(0), ext_data_pointer_(ext_data_pointer)
103  {
104  if (device_data == 0)
105  throw IuException("input data not valid", __FILE__, __FUNCTION__,
106  __LINE__);
107  if (ext_data_pointer_)
108  {
109  // This uses the external data pointer as internal data pointer.
110  data_ = device_data;
111  }
112  else
113  {
114  // allocates an internal data pointer and copies the external data onto it.
115  IU_CUDA_SAFE_CALL(
116  cudaMalloc((void** )&data_, this->numel() * sizeof(PixelType)));
117  if (data_ == 0)
118  throw std::bad_alloc();
119  IU_CUDA_SAFE_CALL(
120  cudaMemcpy(data_, device_data, this->numel() * sizeof(PixelType),
121  cudaMemcpyHostToDevice));
122  }
123  }
124 
130  PixelType* data(unsigned int offset = 0)
131  {
132  if (offset >= this->numel())
133  {
134  std::stringstream msg;
135  msg << "Offset (" << offset << ") out of range (" << this->numel() << ").";
136  throw IuException(msg.str(), __FILE__, __FUNCTION__, __LINE__);
137  }
138  return &(data_[offset]);
139  }
140 
146  const PixelType* data(unsigned int offset = 0) const
147  {
148  if (offset >= this->numel())
149  {
150  std::stringstream msg;
151  msg << "Offset (" << offset << ") out of range (" << this->numel() << ").";
152  throw IuException(msg.str(), __FILE__, __FUNCTION__, __LINE__);
153  }
154  return reinterpret_cast<const PixelType*>(&(data_[offset]));
155  }
156 
160  thrust::device_ptr<PixelType> begin(void)
161  {
162  return thrust::device_ptr<PixelType>(data());
163  }
164 
168  thrust::device_ptr<PixelType> end(void)
169  {
170  return thrust::device_ptr<PixelType>(data() + this->numel());
171  }
172 
174  virtual size_t bytes() const
175  {
176  return this->numel() * sizeof(PixelType);
177  }
178 
180  virtual unsigned int bitDepth() const
181  {
182  return 8 * sizeof(PixelType);
183  }
184 
186  virtual bool onDevice() const
187  {
188  return true;
189  }
190 
217  struct KernelData
218  {
220  PixelType* data_;
221 
223  int numel_;
224 
226  int* size_;
227 
229  int* stride_;
230 
233  data_(const_cast<PixelType*>(mem.data())), numel_(mem.numel())
234  {
235  IU_CUDA_SAFE_CALL(cudaMalloc((void** )&size_, Ndim * sizeof(unsigned int)));
236  IU_CUDA_SAFE_CALL(
237  cudaMemcpy(size_, mem.size().ptr(), Ndim * sizeof(unsigned int),
238  cudaMemcpyHostToDevice));
239  IU_CUDA_SAFE_CALL(cudaMalloc((void** )&stride_, Ndim * sizeof(unsigned int)));
240  IU_CUDA_SAFE_CALL(
241  cudaMemcpy(stride_, mem.stride().ptr(), Ndim * sizeof(unsigned int),
242  cudaMemcpyHostToDevice));
243  }
244 
246  __host__ ~KernelData()
247  {
248  IU_CUDA_SAFE_CALL(cudaFree(size_));
249  size_ = 0;
250  IU_CUDA_SAFE_CALL(cudaFree(stride_));
251  stride_ = 0;
252  }
253 
259  template<typename ResultType = void>
260  __device__ typename std::enable_if<(Ndim == 2), ResultType>::type getPosition(
261  const unsigned int& linear_idx, unsigned int& idx0, unsigned int& idx1)
262  {
263  idx1 = linear_idx / stride_[1];
264  idx0 = linear_idx % stride_[1];
265  }
266 
273  template<typename ResultType = void>
274  __device__ typename std::enable_if<(Ndim == 3), ResultType>::type getPosition(
275  const unsigned int& linear_idx, unsigned int& idx0, unsigned int& idx1,
276  unsigned int& idx2)
277  {
278  idx2 = linear_idx / stride_[2];
279  idx1 = (linear_idx % stride_[2]) / stride_[1];
280  idx0 = (linear_idx % stride_[2]) % stride_[1];
281  }
282 
290  template<typename ResultType = void>
291  __device__ typename std::enable_if<(Ndim == 4), ResultType>::type getPosition(
292  const unsigned int& linear_idx, unsigned int& idx0, unsigned int& idx1,
293  unsigned int& idx2, unsigned int& idx3)
294  {
295  idx3 = linear_idx / stride_[3];
296  idx2 = (linear_idx % stride_[3]) / stride_[2];
297  idx1 = ((linear_idx % stride_[3]) % stride_[2]) / stride_[1];
298  idx0 = ((linear_idx % stride_[3]) % stride_[2]) % stride_[1];
299  }
300 
309  template<typename ResultType = void>
310  __device__ typename std::enable_if<(Ndim == 5), ResultType>::type getPosition(
311  const unsigned int& linear_idx, unsigned int& idx0, unsigned int& idx1,
312  unsigned int& idx2, unsigned int& idx3, unsigned int& idx4)
313  {
314  idx4 = linear_idx / stride_[4];
315  idx3 = (linear_idx % stride_[4]) / stride_[3];
316  idx2= ((linear_idx % stride_[4]) % stride_[3]) / stride_[2];
317  idx1 = (((linear_idx % stride_[4]) % stride_[3]) % stride_[2]) / stride_[1];
318  idx0 = (((linear_idx % stride_[4]) % stride_[3]) % stride_[2]) % stride_[1];
319  }
320 
326  template<typename ResultType = unsigned int>
327  __device__ typename std::enable_if<(Ndim > 1), ResultType>::type getLinearIndex(
328  const unsigned int& idx0, const unsigned int& idx1)
329  {
330  unsigned int linear_idx = idx0;
331  linear_idx += stride_[1] * idx1;
332  return linear_idx;
333  }
334 
341  template<typename ResultType = unsigned int>
342  __device__ typename std::enable_if<(Ndim > 2), ResultType>::type getLinearIndex(
343  const unsigned int& idx0, const unsigned int& idx1, const unsigned int& idx2)
344  {
345  unsigned int linear_idx = idx0;
346  linear_idx += stride_[1] * idx1;
347  linear_idx += stride_[2] * idx2;
348  return linear_idx;
349  }
350 
358  template<typename ResultType = unsigned int>
359  __device__ typename std::enable_if<(Ndim > 3), ResultType>::type getLinearIndex(
360  const unsigned int& idx0, const unsigned int& idx1, const unsigned int& idx2, const unsigned int& idx3)
361  {
362  unsigned int linear_idx = idx0;
363  linear_idx += stride_[1] * idx1;
364  linear_idx += stride_[2] * idx2;
365  linear_idx += stride_[3] * idx3;
366  return linear_idx;
367  }
368 
377  template<typename ResultType = unsigned int>
378  __device__ typename std::enable_if<(Ndim > 4), ResultType>::type getLinearIndex(
379  const unsigned int& idx0, const unsigned int& idx1, const unsigned int& idx2, const unsigned int& idx3, const unsigned int& idx4)
380  {
381  unsigned int linear_idx = idx0;
382  linear_idx += stride_[1] * idx1;
383  linear_idx += stride_[2] * idx2;
384  linear_idx += stride_[3] * idx3;
385  linear_idx += stride_[4] * idx4;
386  return linear_idx;
387  }
388 
393  __device__ PixelType& operator()(const unsigned int& idx)
394  {
395  return data_[idx];
396  }
397 
403  template<typename ResultType = PixelType>
404  __device__ typename std::enable_if<(Ndim > 1), ResultType&>::type operator()(
405  const unsigned int& idx0, const unsigned int& idx1)
406  {
407  return data_[getLinearIndex(idx0, idx1)];
408  }
409 
416  template<typename ResultType = PixelType>
417  __device__ typename std::enable_if<(Ndim > 2), ResultType&>::type operator()(
418  const unsigned int& idx0, const unsigned int& idx1, const unsigned int& idx2)
419  {
420  return data_[getLinearIndex(idx0, idx1, idx2)];
421  }
422 
430  template<typename ResultType = PixelType>
431  __device__ typename std::enable_if<(Ndim > 3), ResultType&>::type operator()(
432  const unsigned int& idx0, const unsigned int& idx1, const unsigned int& idx2, const unsigned int& idx3)
433  {
434  return data_[getLinearIndex(idx0, idx1, idx2, idx3)];
435  }
436 
445  template<typename ResultType = PixelType>
446  __device__ typename std::enable_if<(Ndim > 4), ResultType&>::type operator()(
447  const unsigned int& idx0, const unsigned int& idx1, const unsigned int& idx2, const unsigned int& idx3, const unsigned int& idx4)
448  {
449  return data_[getLinearIndex(idx0, idx1, idx2, idx3, idx4)];
450  }
451  };
452 
455 
458 
459 private:
461  PixelType* data_;
463  bool ext_data_pointer_;
464 
465 private:
469  LinearDeviceMemory& operator=(const LinearDeviceMemory&);
470 };
471 
474 
475 } // namespace iu
476 
__device__ std::enable_if<(Ndim > 3), ResultType >::type getLinearIndex(const unsigned int &idx0, const unsigned int &idx1, const unsigned int &idx2, const unsigned int &idx3)
Definition: lineardevicememory.h:359
virtual bool onDevice() const
Definition: lineardevicememory.h:186
PixelType * data(unsigned int offset=0)
Definition: lineardevicememory.h:130
virtual size_t bytes() const
Definition: lineardevicememory.h:174
__device__ std::enable_if<(Ndim > 1), ResultType >::type getLinearIndex(const unsigned int &idx0, const unsigned int &idx1)
Definition: lineardevicememory.h:327
__device__ std::enable_if<(Ndim > 2), ResultType >::type getLinearIndex(const unsigned int &idx0, const unsigned int &idx1, const unsigned int &idx2)
Definition: lineardevicememory.h:342
ndarray_ref< PixelType, Ndim > ref() const
unsigned int numel() const
Definition: linearmemory.h:105
int * size_
Definition: lineardevicememory.h:226
__device__ std::enable_if<(Ndim==3), ResultType >::type getPosition(const unsigned int &linear_idx, unsigned int &idx0, unsigned int &idx1, unsigned int &idx2)
Definition: lineardevicememory.h:274
__device__ std::enable_if<(Ndim==2), ResultType >::type getPosition(const unsigned int &linear_idx, unsigned int &idx0, unsigned int &idx1)
Definition: lineardevicememory.h:260
Exceptions with additional error information.
Definition: coredefs.h:32
__device__ std::enable_if<(Ndim > 4), ResultType >::type getLinearIndex(const unsigned int &idx0, const unsigned int &idx1, const unsigned int &idx2, const unsigned int &idx3, const unsigned int &idx4)
Definition: lineardevicememory.h:378
Definition: image_cpu.h:7
int numel_
Definition: lineardevicememory.h:223
virtual unsigned int bitDepth() const
Definition: lineardevicememory.h:180
Base class for linear memory classes.
Definition: linearmemory.h:61
__device__ std::enable_if<(Ndim==5), ResultType >::type getPosition(const unsigned int &linear_idx, unsigned int &idx0, unsigned int &idx1, unsigned int &idx2, unsigned int &idx3, unsigned int &idx4)
Definition: lineardevicememory.h:310
Size< Ndim > size() const
Definition: linearmemory.h:121
Struct pointer KernelData that can be used in CUDA kernels.
Definition: lineardevicememory.h:217
__host__ KernelData(const LinearDeviceMemory< PixelType, Ndim > &mem)
Definition: lineardevicememory.h:232
PixelType pixel_type
Definition: lineardevicememory.h:22
__host__ ~KernelData()
Definition: lineardevicememory.h:246
LinearDeviceMemory(PixelType *device_data, const unsigned int &numel, bool ext_data_pointer=false)
Definition: lineardevicememory.h:100
__device__ PixelType & operator()(const unsigned int &idx)
Definition: lineardevicememory.h:393
LinearDeviceMemory()
Definition: lineardevicememory.h:26
LinearDeviceMemory(const Size< Ndim > &size)
Definition: lineardevicememory.h:44
thrust::device_ptr< PixelType > end(void)
Definition: lineardevicememory.h:168
thrust::device_ptr< PixelType > begin(void)
Definition: lineardevicememory.h:160
int * stride_
Definition: lineardevicememory.h:229
PixelType * data_
Definition: lineardevicememory.h:220
Linear device memory class.
Definition: lineardevicememory.h:18
virtual ~LinearDeviceMemory()
Definition: lineardevicememory.h:32
LinearDeviceMemory(const unsigned int &numel)
Definition: lineardevicememory.h:56
const PixelType * data(unsigned int offset=0) const
Definition: lineardevicememory.h:146
Size< Ndim > stride() const
Definition: linearmemory.h:127
LinearDeviceMemory(PixelType *device_data, const Size< Ndim > &size, bool ext_data_pointer=false)
Definition: lineardevicememory.h:70
Main class for N-dimensional unsigned int vectors (size vectors).
Definition: vector.h:460
__device__ std::enable_if<(Ndim==4), ResultType >::type getPosition(const unsigned int &linear_idx, unsigned int &idx0, unsigned int &idx1, unsigned int &idx2, unsigned int &idx3)
Definition: lineardevicememory.h:291