CellularAutomata
Loading...
Searching...
No Matches
common.inl
1#include "common.hpp"
2#include "exceptions.hpp"
3
4#ifdef __CUDACC__
5#include "../cuda/cuda.cuh"
6#endif
7
8#include <algorithm>
9#include <iostream>
10
11#define stateSize height * width * sizeof(T)
12#define kernelSize size * size * sizeof(T)
13
14template <typename T>
15inline void print2D(T* array, const unsigned int h, const unsigned int w)
16{
17 for (int y = 0; y < h; y++)
18 {
19 for (int x = 0; x < w; x++)
20 {
21 std::cout << array[y * w + x] << " ";
22 }
23 std::cout << std::endl;
24 }
25}
26
27namespace CellularAutomata
28{
29 template <typename T>
30 State<T>::State(const unsigned int height, const unsigned int width, stateFunc<T> fn, Device device) : height(height), width(width), device(device)
31 {
32 #ifdef __CUDACC__
33 initCUDA(fn);
34 #else
35 if (device == Device::CUDA)
37
38 initCPU(fn);
39 #endif
40 }
41
42 template <typename T>
43 void State<T>::initCPU(stateFunc<T> fn)
44 {
45 curr = new T[height * width]();
46 next = new T[height * width]();
47
48 if (fn != nullptr)
49 fn(curr, height, width);
50 }
51
52 template <typename T>
53 void State<T>::initCUDA(stateFunc<T> fn)
54 {
55 size_t bytes = stateSize;
56
57 if (device == Device::CUDA)
58 {
59 // allocate GPU memory
60
61 CellularAutomata::cuda::allocateCUDA(reinterpret_cast<void**>(&curr), bytes);
62 CellularAutomata::cuda::allocateCUDA(reinterpret_cast<void**>(&next), bytes);
63
64 if (fn != nullptr)
65 {
66 T* temp = new T[height * width]();
67
68 fn(temp, height, width);
69 CellularAutomata::cuda::copyCUDA(temp, Device::CPU, curr, Device::CUDA, bytes);
70
71 delete[] temp;
72 }
73 }
74 else
75 {
76 // allocate (pinned) CPU memory (for faster transfer)
77 // just always use pinned memory when CUDA is enabled (maybe use condition?)
78
79 CellularAutomata::cuda::allocateHost(reinterpret_cast<void**>(&curr), bytes);
80 CellularAutomata::cuda::allocateHost(reinterpret_cast<void**>(&next), bytes);
81
82 if (fn != nullptr)
83 fn(curr, height, width);
84 }
85 }
86
87 template <typename T>
89 {
90 #ifdef __CUDACC__
91 freeCUDA();
92 #else
93 freeCPU();
94 #endif
95 }
96
97 template <typename T>
99 {
100 delete[] curr;
101 delete[] next;
102 }
103
104 template <typename T>
105 void State<T>::freeCUDA()
106 {
107 if (device == Device::CUDA)
108 {
109 CellularAutomata::cuda::freeCUDA(curr);
110 CellularAutomata::cuda::freeCUDA(next);
111 }
112 else
113 {
116 }
117 }
118
119 template <typename T>
121 {
122 if (height != to->height && width != to->width)
124
125 if (device == Device::CUDA || to->device == Device::CUDA)
126 {
127 #ifdef __CUDACC__
128 size_t bytes = stateSize;
129 CellularAutomata::cuda::copyCUDA(curr, device, to->curr, to->device, bytes);
130 #endif
131 }
132 else
133 {
134 std::copy(curr, curr + height * width, to->curr);
135 }
136 }
137
138 template <typename T>
140 {
141 auto tmp = curr;
142 curr = next;
143 next = tmp;
144 }
145
146 template <typename T>
148 {
149 if (device == Device::CUDA)
150 {
151 // TODO: pinned memory is slower to allocate but faster to transfer
152 size_t bytes = stateSize;
153 T* temp = new T[height * width]();
154 CellularAutomata::cuda::copyCUDA(curr, device, temp, Device::CPU, bytes);
155
156 print2D(temp, height, width);
157
158 delete[] temp;
159 }
160 else
161 {
162 print2D(curr, height, width);
163 }
164 }
165
166
167 template <typename T>
168 Kernel<T>::Kernel(const unsigned int size, kernelFunc<T> fn, Device device) : size(size), device(device)
169 {
170 if (device == Device::CUDA)
171 {
172 #ifdef __CUDACC__
173 initCUDA(fn);
174 #else
175 throw exception::DeviceNotAvailable("CUDA");
176 #endif
177 }
178 else
179 {
180 initCPU(fn);
181 }
182 }
183
184 template <typename T>
185 void Kernel<T>::initCPU(kernelFunc<T> fn)
186 {
187 kernel = new T[size * size]();
188
189 if (fn != nullptr)
190 fn(kernel, size);
191 }
192
193 template <typename T>
194 void Kernel<T>::initCUDA(kernelFunc<T> fn)
195 {
196 size_t bytes = kernelSize;
197
198 CellularAutomata::cuda::allocateCUDA(reinterpret_cast<void**>(&kernel), bytes);
199
200 if (fn != nullptr)
201 {
202 T* temp = new T[size * size]();
203
204 fn(temp, size);
205 CellularAutomata::cuda::copyCUDA(temp, Device::CPU, kernel, Device::CUDA, bytes);
206
207 delete[] temp;
208 }
209 }
210
211 template <typename T>
213 {
214 if (device == Device::CUDA)
215 {
216 #ifdef __CUDACC__
217 freeCUDA();
218 #endif
219 }
220 else
221 {
222 freeCPU();
223 }
224 }
225
226 template <typename T>
227 void Kernel<T>::freeCPU()
228 {
229 delete[] kernel;
230 }
231
232 template <typename T>
233 void Kernel<T>::freeCUDA()
234 {
235 CellularAutomata::cuda::freeCUDA(kernel);
236 }
237
238 template <typename T>
240 {
241 if (size != to->size)
243
244 if (device == Device::CUDA)
245 {
246 #ifdef __CUDACC__
247 size_t bytes = kernelSize;
248 CellularAutomata::cuda::copyCUDA(kernel, device, to->kernel, to->device, bytes);
249 #endif
250 }
251 else
252 {
253 std::copy(kernel, kernel + size * size, to->kernel);
254 }
255 }
256
257 template <typename T>
259 {
260 if (device == Device::CUDA)
261 {
262 size_t bytes = kernelSize;
263 T* temp = new T[size * size]();
264 CellularAutomata::cuda::copyCUDA(kernel, device, temp, Device::CPU, bytes);
265
266 print2D(temp, size, size);
267
268 delete[] temp;
269 }
270 else
271 {
272 print2D(kernel, size, size);
273 }
274 }
275}
276
277#undef stateSize
278#undef kernelSize
2D convolution kernel
Definition common.hpp:130
const Device device
Computational device.
Definition common.hpp:143
~Kernel()
Frees dynamically allocated memory.
Definition common.inl:212
void print()
Prints the kernel array.
Definition common.inl:258
T * kernel
2D Matrix
Definition common.hpp:135
void copyTo(Kernel< T > *to)
Copy the own kernel array to another kernel array across devices.
Definition common.inl:239
const unsigned int size
Side length of matrix.
Definition common.hpp:139
Kernel(const unsigned int size, kernelFunc< T > fn, Device device)
Initalizes a kernel.
Definition common.inl:168
2D buffered matrices
Definition common.hpp:56
const unsigned int width
Width of 2D Matrix.
Definition common.hpp:76
T * curr
Current 2D Matrix buffer.
Definition common.hpp:61
void swap()
Swaps the current- and next state buffer.
Definition common.inl:139
void copyTo(State< T > *to)
Copy the own current state buffer to another current state buffer across devices.
Definition common.inl:120
void print()
Prints the current state buffer.
Definition common.inl:147
const unsigned int height
Height of 2D Matrix.
Definition common.hpp:71
const Device device
Computational device.
Definition common.hpp:81
State(const unsigned int height, const unsigned int width, stateFunc< T > fn, Device device)
Initalizes a state.
Definition common.inl:30
~State()
Frees dynamically allocated memory.
Definition common.inl:88
Requested device not available.
Definition exceptions.hpp:31
Shape of two matrices are not equal.
Definition exceptions.hpp:41
void allocateHost(void **arrayPtr, size_t bytes)
Allocated memory on the host device (CPU)
Definition cuda.inl:150
void freeHost(void *array)
Frees memory on the host device (CPU)
Definition cuda.inl:160
Main namespace.
Definition common.hpp:33
Device
Computational device.
Definition common.hpp:39
@ CPU
Allocation & computation on CPU/RAM.
Definition common.hpp:43
@ CUDA
Allocation & computation on NVIDIA GPU via CUDA.
Definition common.hpp:47