OpenLB 1.7
Loading...
Searching...
No Matches
column.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2022 Adrian Kummerlaender
4 *
5 * E-mail contact: info@openlb.net
6 * The most recent release of OpenLB can be downloaded at
7 * <http://www.openlb.net/>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23*/
24
25#ifndef GPU_CUDA_COLUMN_HH
26#define GPU_CUDA_COLUMN_HH
27
28#include "column.h"
29#include "device.h"
30
31#include <thrust/gather.h>
32#include <thrust/scatter.h>
33
34#include <thrust/host_vector.h>
35#include <thrust/device_vector.h>
36#include <thrust/execution_policy.h>
37
38#include <cstring>
39
40namespace olb {
41
42namespace gpu {
43
44namespace cuda {
45
46template<typename T>
47struct Column<T>::Data {
48 thrust::host_vector<T> host;
49 thrust::device_vector<T> device;
50
51 Data(std::size_t count):
52 host(count),
53 device(count)
54 { }
55
56 void resize(std::size_t newCount)
57 {
58 host.resize(newCount);
59 device.resize(newCount);
60 }
62};
63
64template<typename T>
65Column<T>::Column(std::size_t count):
66 _count(count),
67 _data(new Data(count))
68{ }
70template<typename T>
72 _count(rhs._count),
73 _data(rhs._data.release())
74{ }
75
76template<typename T>
78 _count(rhs._count),
79 _data(new Data(*rhs._data))
80{ }
81
82template<typename T>
84{ }
85
86template<typename T>
89 _data->device.clear();
90 _data->host.clear();
91 _count = _data->host.size();
92}
93
94template<typename T>
95void Column<T>::resize(std::size_t newCount)
96{
97 _data->resize(newCount);
98 _count = newCount;
99}
100
101template<typename T>
103{
104 _data->host.push_back(value);
105 _count = _data->host.size();
106}
107
108template<typename T>
110{
111 std::sort(_data->host.begin(), _data->host.end());
112 _data->host.erase(std::unique(_data->host.begin(), _data->host.end()), _data->host.end());
113}
114
115template<typename T>
116const T& Column<T>::operator[](std::size_t i) const
117{
118 return _data->host[i];
119}
120
121template<typename T>
122T& Column<T>::operator[](std::size_t i)
123{
124 return _data->host[i];
125}
126
127template<typename T>
128std::size_t Column<T>::size() const
129{
130 return _count;
131}
132
133template<typename T>
134const T* Column<T>::data() const
135{
136 return _data->host.data();
137}
138
139template<typename T>
141{
142 return _data->host.data();
143}
144
145template<typename T>
146const T* Column<T>::deviceData() const
147{
148 return _data->device.data().get();
149}
150
151template<typename T>
153{
154 return _data->device.data().get();
155}
156
157template<typename T>
159{
160 if (_count != _data->device.size()) {
161 _data->device.resize(_count);
162 }
163 switch (context) {
165 device::copyToHost(_data->device.data().get(), _data->host.data(), size()*sizeof(T));
166 return;
168 device::copyToDevice(_data->host.data(), _data->device.data().get(), size()*sizeof(T));
169 return;
170 }
171}
172
173template<typename T>
175{
176 if (_count != _data->device.size()) {
177 _data->device.resize(_count);
178 }
179 switch (context) {
181 device::asyncCopyToHost(stream, _data->device.data().get(), _data->host.data(), size()*sizeof(T));
182 return;
184 device::asyncCopyToDevice(stream, _data->host.data(), _data->device.data().get(), size()*sizeof(T));
185 return;
186 }
187}
188
189template<typename T>
190std::size_t Column<T>::getNblock() const
191{
192 return 2;
193}
194
195template<typename T>
197{
198 return _count * sizeof(T) + sizeof(std::size_t);
199}
200
201template<typename T>
202bool* Column<T>::getBlock(std::size_t iBlock, std::size_t& sizeBlock, bool loadingMode)
203{
204 std::size_t currentBlock = 0;
205 bool* dataPtr = nullptr;
206
207 registerVar(iBlock, sizeBlock, currentBlock, dataPtr, _count);
208 if (loadingMode && iBlock == 1) {
209 resize(_count);
210 }
211 registerVar(iBlock, sizeBlock, currentBlock, dataPtr, *data(), _count);
212
213 return dataPtr;
214}
215
216
217template<typename T>
218struct CyclicColumn<T>::Data {
219 const std::size_t size;
220
221 std::unique_ptr<T[]> host;
222
223 CUmemGenericAllocationHandle handle;
224 CUmemAllocationProp prop{};
225 CUmemAccessDesc access{};
226 CUdeviceptr ptr;
227
228 Data(std::size_t count):
229 host(new T[count] { }),
230 size(count * sizeof(T))
231 {
232 const int device = device::get();
233
234 prop.type = CU_MEM_ALLOCATION_TYPE_PINNED;
235 prop.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
236 prop.location.id = device;
237 device::check(cuMemAddressReserve(&ptr, 2 * size, 0, 0, 0));
238
239 // per-population handle until cuMemMap accepts non-zero offset
240 device::check(cuMemCreate(&handle, size, &prop, 0));
241 device::check(cuMemMap(ptr, size, 0, handle, 0));
242 device::check(cuMemMap(ptr + size, size, 0, handle, 0));
243
244 access.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
245 access.location.id = device;
246 access.flags = CU_MEM_ACCESS_FLAGS_PROT_READWRITE;
247 device::check(cuMemSetAccess(ptr, 2 * size, &access, 1));
248 }
249
251 device::check(cuMemUnmap(ptr, 2 * size));
252 device::check(cuMemRelease(handle));
253 device::check(cuMemAddressFree(ptr, 2 * size));
254 }
255
256};
257
258template<typename T>
260 _count(device::getPageAlignedCount<T>(count)),
261 _size(_count * sizeof(T)),
262 _data(new Data(_count)),
263 _shift(0)
264{
265 _deviceBase = reinterpret_cast<T*>(_data->ptr);
266 _devicePopulation = _deviceBase;
267}
268
269template<typename T>
272
273template<typename T>
274const T& CyclicColumn<T>::operator[](std::size_t i) const
275{
276 return _data->host[i];
277}
278
279template<typename T>
281{
282 return _data->host[i];
283}
284
285template<typename T>
287{
288 switch (context) {
290 device::copyToHost(_devicePopulation, _data->host.get(), _size);
291 return;
293 device::copyToDevice(_data->host.get(), _devicePopulation, _size);
294 return;
295 }
296}
297
298template<typename T>
299std::size_t CyclicColumn<T>::getNblock() const
300{
301 return 3;
302}
303
304template<typename T>
306{
307 return _count * sizeof(T) + sizeof(std::ptrdiff_t) + sizeof(std::size_t);
308}
309
310template<typename T>
311bool* CyclicColumn<T>::getBlock(std::size_t iBlock, std::size_t& sizeBlock, bool loadingMode)
312{
313 std::size_t currentBlock = 0;
314 bool* dataPtr = nullptr;
315
316 registerVar(iBlock, sizeBlock, currentBlock, dataPtr, _shift);
317 registerVar(iBlock, sizeBlock, currentBlock, dataPtr, _count);
318 registerVar(iBlock, sizeBlock, currentBlock, dataPtr, *_data->host.get(), _count);
319
320 return dataPtr;
321}
322
323
324}
325
326}
327
328
329template <typename T>
331 std::uint8_t* buffer) const
332{
333 thrust::gather(thrust::device,
334 thrust::device_pointer_cast(indices.begin()),
335 thrust::device_pointer_cast(indices.end()),
336 thrust::device_pointer_cast(_column.deviceData()),
337 thrust::device_pointer_cast(reinterpret_cast<T*>(buffer)));
338 return indices.size() * sizeof(T);
339}
340
341template <typename T>
343 const std::uint8_t* buffer)
344{
345 thrust::scatter(thrust::device,
346 thrust::device_pointer_cast(reinterpret_cast<const T*>(buffer)),
347 thrust::device_pointer_cast(reinterpret_cast<const T*>(buffer) + indices.size()),
348 thrust::device_pointer_cast(indices.begin()),
349 thrust::device_pointer_cast(_column.deviceData()));
350 return indices.size() * sizeof(T);
351}
352
353
354template <typename T>
356 ConstSpan<CellID> indices,
357 std::uint8_t* buffer) const
358{
359 thrust::gather(thrust::device,
360 thrust::device_pointer_cast(indices.begin()),
361 thrust::device_pointer_cast(indices.end()),
362 thrust::device_pointer_cast(_column.deviceData()),
363 thrust::device_pointer_cast(reinterpret_cast<T*>(buffer)));
364 return indices.size() * sizeof(T);
365}
366
367template <typename T>
369 ConstSpan<CellID> indices,
370 const std::uint8_t* buffer)
371{
372 thrust::scatter(thrust::device,
373 thrust::device_pointer_cast(reinterpret_cast<const T*>(buffer)),
374 thrust::device_pointer_cast(reinterpret_cast<const T*>(buffer) + indices.size()),
375 thrust::device_pointer_cast(indices.begin()),
376 thrust::device_pointer_cast(_column.deviceData()));
377 return indices.size() * sizeof(T);
378}
379
380
381}
382
383#endif
const T * end() const
std::size_t size() const
const T * begin() const
Storage of any FIELD_TYPE data on PLATFORM.
Definition data.h:155
void setProcessingContext(ProcessingContext)
Definition column.h:111
const T * data() const
Definition column.h:101
void resize(std::size_t count)
Definition column.h:78
const T & operator[](std::size_t i) const override
Definition column.h:86
std::size_t size() const
Definition column.h:96
bool * getBlock(std::size_t iBlock, std::size_t &sizeBlock, bool loadingMode) override
Return a pointer to the memory of the current block and its size for the serializable interface.
Definition column.hh:51
std::size_t getSerializableSize() const override
Binary size for the serializer.
Definition column.hh:45
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
Definition column.hh:39
virtual ~Column()=default
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
Definition column.hh:67
CyclicColumn(std::size_t count)
Definition column.h:142
const T & operator[](std::size_t i) const override
Definition column.h:162
bool * getBlock(std::size_t iBlock, std::size_t &sizeBlock, bool loadingMode) override
Return a pointer to the memory of the current block and its size for the serializable interface.
Definition column.hh:79
std::size_t getSerializableSize() const override
Binary size for the serializer.
Definition column.hh:73
void setProcessingContext(ProcessingContext)
Definition column.h:211
Plain column for CUDA GPU targets.
Definition column.h:49
void clear()
Reset size to zero.
Definition column.hh:87
const T * data() const
Definition column.hh:134
void push_back(T value)
Definition column.hh:102
Virtual memory based cyclic column for usage in ColumnVector.
Definition column.h:102
std::size_t size() const
Definition column.h:134
Basic wrapper for device stream.
Definition device.h:121
void copyToHost(void *src, void *dst, std::size_t count)
Copy data from device to host.
Definition device.hh:78
void copyToDevice(void *src, void *dst, std::size_t count)
Copy data from host to device.
Definition device.hh:83
void asyncCopyToDevice(Stream &stream, void *src, void *dst, std::size_t count)
Copy data from host to device (async)
Definition device.hh:145
void asyncCopyToHost(Stream &stream, void *src, void *dst, std::size_t count)
Copy data from device to host (async)
Definition device.hh:141
void check()
Check errors.
Definition device.hh:48
int get()
Get current device.
Definition device.hh:71
Top level namespace for all of OpenLB.
ProcessingContext
OpenLB processing contexts.
Definition platform.h:55
@ Simulation
Data available on host for e.g. functor evaluation.
thrust::device_vector< T > device
Definition column.hh:49
Data(std::size_t count)
Definition column.hh:51
void resize(std::size_t newCount)
Definition column.hh:56
thrust::host_vector< T > host
Definition column.hh:48
CUmemGenericAllocationHandle handle
Definition column.hh:223
std::unique_ptr< T[]> host
Definition column.hh:221