803b75acf16d178619a964ff2c7fc3bfa69e9767
[cuda.git] / libutils / DeviceMemory.cuh
1 /*
2         Copyright (C) 2012  fmaj7b5.info
3
4         This program is free software: you can redistribute it and/or modify
5         it under the terms of the GNU General Public License as published by
6         the Free Software Foundation, either version 2 of the License, or
7         (at your option) any later version.
8
9         This program is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12         GNU General Public License for more details.
13
14         You should have received a copy of the GNU General Public License
15         along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifndef FM7b5_DEVICE_MEMORY_CUH
19 #define FM7b5_DEVICE_MEMORY_CUH
20
21 #include <stdexcept>
22 #include <type_traits>
23 #include <cuda.h>
24
25 #include "MDView.cuh"
26
27 namespace FM7b5
28 {
29         namespace memory
30         {
31                 //! Linear 1-D memory
32                 template <class T>
33                 class Linear
34                 {
35                 public:
36                         typedef T value_type;
37                         typedef typename std::add_pointer<T>::type pointer_type;
38                         typedef typename std::add_const<pointer_type>::type const_pointer_type;
39                         typedef typename std::add_reference<T>::type reference_type;
40
41                         Linear(const size_t count = 0)
42                                 : m_count(count)
43                         {
44                                 m_extent = sizeof(value_type);
45                                 md_data = static_cast<pointer_type>(allocate(m_extent * count));
46                         }
47
48                         ~Linear()
49                         {
50                                 deallocate(md_data);
51                         }
52
53                         void* allocate(const size_t byte)
54                         {
55                                 void* p(nullptr);
56                                 cudaError_t status;
57
58                                 status = cudaMalloc(&p, byte);
59                                 if (status != cudaSuccess) {
60                                         throw std::bad_alloc(cudaGetErrorString(status));
61                                 }
62
63                                 return p;
64                         }
65
66                         void deallocate(void* p)
67                         {
68                                 cudaFree(p);
69                         }
70
71                         void copy_from(const void* const src, const size_t byte)
72                         {
73                                 cudaMemcpy(md_data, src, byte, cudaMemcpyHostToDevice);
74                         }
75
76                         void copy_to(void* const dst, const size_t byte)
77                         {
78                                 cudaMemcpy(dst, md_data, byte, cudaMemcpyDeviceToHost);
79                         }
80
81                         size_t size() const { return m_extent * m_count; }
82                         size_t count() const { return m_count; }
83                         pointer_type data() const { return md_data; }
84
85                         MDView<value_type, 1> ref() const
86                         {
87                                 return MDView<value_type, 1>(md_data, &m_extent);
88                         }
89
90                 protected:
91                         size_t m_extent;
92                         size_t m_count;
93                         pointer_type md_data;
94                 };
95
96                 //! Linear 2-D memory
97                 template <class T>
98                 class LinearPitch
99                 {
100                 public:
101                         typedef T value_type;
102                         typedef typename std::add_pointer<T>::type pointer_type;
103                         typedef typename std::add_const<pointer_type>::type const_pointer_type;
104                         typedef typename std::add_reference<T>::type reference_type;
105
106                         LinearPitch(const size_t width, const size_t height)
107                                 : m_width(width), m_height(height)
108                         {
109                                 md_data = static_cast<pointer_type>(allocate(width, height, &m_extent[0]));
110                                 m_extent[1] = sizeof(value_type);
111                         }
112
113                         ~LinearPitch()
114                         {
115                                 deallocate(md_data);
116                         }
117
118                         void* allocate(const size_t width, const size_t height, size_t* pitch)
119                         {
120                                 void* p(nullptr);
121                                 cudaError_t status;
122
123                                 status = cudaMallocPitch(&p, pitch, sizeof(value_type) * width, height);
124                                 if (status != cudaSuccess) {
125                                         throw std::bad_alloc(cudaGetErrorString(status));
126                                 }
127
128                                 return p;
129                         }
130
131                         void deallocate(void* p)
132                         {
133                                 cudaFree(p);
134                         }
135
136                         void copy_from(const void* const src, const size_t width, const size_t height, size_t spitch = 0)
137                         {
138                                 if (spitch < 1) {
139                                         spitch = width;
140                                 }
141                                 cudaMemcpy2D(md_data, pitch(), src, spitch, width, height, cudaMemcpyHostToDevice);
142                         }
143
144                         void copy_to(void* const dst, const size_t width, const size_t height, size_t dpitch = 0)
145                         {
146                                 if (dpitch < 1) {
147                                         dpitch = width;
148                                 }
149                                 cudaMemcpy2D(dst, dpitch, md_data, pitch(), width, height, cudaMemcpyDeviceToHost);
150                         }
151
152                         size_t size() const { return m_extent[1] * m_height; }
153                         size_t width() const { return m_width; }
154                         size_t height() const { return m_height; }
155                         size_t pitch() const { return m_extent[0]; }
156                         pointer_type data() const { return md_data; }
157
158                         MDView<value_type, 2> ref() const
159                         {
160                                 return MDView<value_type, 2>(md_data, m_extent);
161                         }
162
163                 protected:
164                         size_t m_width;
165                         size_t m_height;
166                         size_t m_extent[2];
167                         pointer_type md_data;
168                 };
169         }
170 }
171
172 #endif /* FM7b5_DEVICE_MEMORY_CUH */