GpuView.hpp
Go to the documentation of this file.
1/*
2 Copyright 2024 SINTEF AS
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef OPM_GPUVIEW_HEADER_HPP
20#define OPM_GPUVIEW_HEADER_HPP
21
22#include <dune/common/fvector.hh>
23
24#include <opm/common/ErrorMacros.hpp>
25
26#include <opm/common/utility/gpuDecorators.hpp>
28
29#include <stdexcept>
30#include <vector>
31
32#include <fmt/core.h>
33
34namespace Opm::gpuistl
35{
36
51template <typename T>
53{
54public:
55 using value_type = T;
59 explicit GpuView() = default;
60
61 //TODO: we probably dont need anything like this or is it useful to have views also be able to handle things on CPU?
64 GpuView(std::vector<T>& data);
65
71 __host__ __device__ T& operator[](size_t idx){
72#ifndef NDEBUG
73 assertInRange(idx);
74#endif
75 return m_dataPtr[idx];
76 }
77
83 __host__ __device__ T operator[](size_t idx) const {
84#ifndef NDEBUG
85 assertInRange(idx);
86#endif
87 return m_dataPtr[idx];
88 }
89
90
100 __host__ __device__ GpuView(T* dataOnHost, size_t numberOfElements)
101 : m_dataPtr(dataOnHost), m_numberOfElements(numberOfElements)
102 {
103 }
104
108 ~GpuView() = default;
109
113 __host__ __device__ T* data(){
114 return m_dataPtr;
115 }
116
120 __host__ __device__ const T* data() const{
121 return m_dataPtr;
122 }
123
127 __host__ __device__ T& front()
128 {
129#ifndef NDEBUG
130 assertHasElements();
131#endif
132 return m_dataPtr[0];
133 }
134
138 __host__ __device__ T& back()
139 {
140#ifndef NDEBUG
141 assertHasElements();
142#endif
143 return m_dataPtr[m_numberOfElements-1];
144 }
145
149 __host__ __device__ T front() const
150 {
151#ifndef NDEBUG
152 assertHasElements();
153#endif
154 return m_dataPtr[0];
155 }
156
160 __host__ __device__ T back() const
161 {
162#ifndef NDEBUG
163 assertHasElements();
164#endif
165 return m_dataPtr[m_numberOfElements-1];
166 }
167
175 void copyFromHost(const T* dataPointer, size_t numberOfElements);
176
184 void copyToHost(T* dataPointer, size_t numberOfElements) const;
185
193 void copyFromHost(const std::vector<T>& data);
194
202 void copyToHost(std::vector<T>& data) const;
203
208 __host__ __device__ size_t size() const{
209 return m_numberOfElements;
210 }
211
216 std::vector<T> asStdVector() const;
218 class iterator {
219 public:
220 // Iterator typedefs
221 using iterator_category = std::forward_iterator_tag;
222 using difference_type = std::ptrdiff_t;
223 using value_type = T;
224 using pointer = T*;
225 using reference = T&;
226
230 __host__ __device__ iterator(T* ptr) : m_ptr(ptr) {}
231
234 __host__ __device__ reference operator*() const {
235 return *m_ptr;
236 }
237
240 __host__ __device__ iterator& operator++() {
241 ++m_ptr;
242 return *this;
243 }
244
248 __host__ __device__ iterator operator++(int) {
249 iterator tmp = *this;
250 ++m_ptr;
251 return tmp;
252 }
253
256 __host__ __device__ iterator& operator--() {
257 --m_ptr;
258 return *this;
259 }
260
264 __host__ __device__ iterator operator--(int) {
265 iterator tmp = *this;
266 --m_ptr;
267 return tmp;
268 }
269
272 __host__ __device__ bool operator!=(const iterator& other) const {
273 return !(m_ptr == other.m_ptr);
274 }
275
278 __host__ __device__ bool operator==(const iterator& other) const {
279 return m_ptr == other.m_ptr;
280 }
281
285 __host__ __device__ difference_type operator-(const iterator& other) const {
286 return std::distance(other.m_ptr, m_ptr);
287 }
288
292 __host__ __device__ iterator operator-(difference_type n) const {
293 return iterator(m_ptr-n);
294 }
295
299 __host__ __device__ iterator operator+(difference_type n) const {
300 return iterator(m_ptr + n);
301 }
302
306 __host__ __device__ bool operator<(const iterator& other) const {
307 return m_ptr < other.m_ptr;
308 }
309
313 __host__ __device__ bool operator>(const iterator& other) const {
314 return m_ptr > other.m_ptr;
315 }
316
317 private:
318 // Pointer to the current element
319 T* m_ptr;
320 };
321
326 __host__ __device__ iterator begin(){
327 return iterator(m_dataPtr);
328 }
329
334 __host__ __device__ iterator begin() const {
335 return iterator(m_dataPtr);
336 }
337
342 __host__ __device__ iterator end(){
343 return iterator(m_dataPtr + m_numberOfElements);
344 }
345
350 __host__ __device__ iterator end() const {
351 return iterator(m_dataPtr + m_numberOfElements);
352 }
353
354private:
355 T* m_dataPtr;
356 size_t m_numberOfElements;
357
360 __host__ __device__ void assertSameSize(const GpuView<T>& other) const
361 {
362 assertSameSize(other.m_numberOfElements);
363 }
366 __host__ __device__ void assertSameSize(size_t size) const
367 {
368#if OPM_IS_INSIDE_DEVICE_FUNCTION
369 // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
370 assert(size == m_numberOfElements && "Views did not have the same size");
371#else
372 if (size != m_numberOfElements) {
373 OPM_THROW(std::invalid_argument,
374 fmt::format("Given view has {}, while this View has {}.", size, m_numberOfElements));
375 }
376#endif
377 }
378
380 __host__ __device__ void assertHasElements() const
381 {
382#if OPM_IS_INSIDE_DEVICE_FUNCTION
383 // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
384 assert(m_numberOfElements > 0 && "View has 0 elements");
385#else
386 if (m_numberOfElements <= 0) {
387 OPM_THROW(std::invalid_argument, "View has 0 elements");
388 }
389#endif
390 }
391
393 __host__ __device__ void assertInRange(size_t idx) const
394 {
395#if OPM_IS_INSIDE_DEVICE_FUNCTION
396 // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
397 assert(idx < m_numberOfElements && "The index provided was not in the range [0, buffersize-1]");
398#else
399 if (idx >= m_numberOfElements) {
400 OPM_THROW(std::invalid_argument,
401 fmt::format("The index provided was not in the range [0, buffersize-1]"));
402 }
403#endif
404 }
405};
406
407} // namespace Opm::gpuistl
408
409#endif
Iterator class to make GpuViews more similar to std containers.
Definition: GpuView.hpp:218
std::ptrdiff_t difference_type
Definition: GpuView.hpp:222
__host__ __device__ bool operator>(const iterator &other) const
Greater than comparison.
Definition: GpuView.hpp:313
__host__ __device__ iterator operator--(int)
Post-decrement operator.
Definition: GpuView.hpp:264
__host__ __device__ bool operator==(const iterator &other) const
Inequality comparison operator.
Definition: GpuView.hpp:278
T * pointer
Definition: GpuView.hpp:224
std::forward_iterator_tag iterator_category
Definition: GpuView.hpp:221
__host__ __device__ reference operator*() const
Dereference operator.
Definition: GpuView.hpp:234
__host__ __device__ difference_type operator-(const iterator &other) const
subtraction operator
Definition: GpuView.hpp:285
__host__ __device__ iterator & operator++()
Pre-increment operator.
Definition: GpuView.hpp:240
T value_type
Definition: GpuView.hpp:223
T & reference
Definition: GpuView.hpp:225
__host__ __device__ iterator operator+(difference_type n) const
Addition operator with diffptr.
Definition: GpuView.hpp:299
__host__ __device__ iterator operator-(difference_type n) const
Subtraction of given number of elements from iterator.
Definition: GpuView.hpp:292
__host__ __device__ iterator operator++(int)
Post-increment operator.
Definition: GpuView.hpp:248
__host__ __device__ iterator & operator--()
Pre-decrement operator.
Definition: GpuView.hpp:256
__host__ __device__ bool operator!=(const iterator &other) const
Inequality comparison operator.
Definition: GpuView.hpp:272
__host__ __device__ iterator(T *ptr)
Create iterator from a pointer.
Definition: GpuView.hpp:230
__host__ __device__ bool operator<(const iterator &other) const
Less than comparison.
Definition: GpuView.hpp:306
The GpuView class is provides a view of some data allocated on the GPU Essenstially is only stores a ...
Definition: GpuView.hpp:53
__host__ __device__ GpuView(T *dataOnHost, size_t numberOfElements)
GpuView allocates new GPU memory of size numberOfElements * sizeof(T) and copies numberOfElements fro...
Definition: GpuView.hpp:100
__host__ __device__ iterator begin()
Get an iterator pointing to the first element of the buffer.
Definition: GpuView.hpp:326
GpuView()=default
Default constructor that will initialize cublas and allocate 0 bytes of memory.
__host__ __device__ size_t size() const
size returns the size (number of T elements) in the vector
Definition: GpuView.hpp:208
__host__ __device__ T * data()
Definition: GpuView.hpp:113
void copyFromHost(const T *dataPointer, size_t numberOfElements)
copyFromHost copies numberOfElements from the CPU memory dataPointer
__host__ __device__ iterator end() const
Get a const iterator pointing to the address after the last element of the buffer.
Definition: GpuView.hpp:350
__host__ __device__ T & front()
Definition: GpuView.hpp:127
T value_type
Definition: GpuView.hpp:55
__host__ __device__ T operator[](size_t idx) const
operator[] to retrieve a copy of an item in the buffer
Definition: GpuView.hpp:83
void copyFromHost(const std::vector< T > &data)
copyToHost copies data from an std::vector
void copyToHost(T *dataPointer, size_t numberOfElements) const
copyFromHost copies numberOfElements to the CPU memory dataPointer
__host__ __device__ T & back()
Definition: GpuView.hpp:138
__host__ __device__ T back() const
Definition: GpuView.hpp:160
GpuView(std::vector< T > &data)
constructor based on std::vectors, this will make a view on the CPU
__host__ __device__ T front() const
Definition: GpuView.hpp:149
void copyToHost(std::vector< T > &data) const
copyToHost copies data to an std::vector
__host__ __device__ iterator end()
Get an iterator pointing to the address after the last element of the buffer.
Definition: GpuView.hpp:342
__host__ __device__ const T * data() const
Definition: GpuView.hpp:120
~GpuView()=default
~GpuView calls cudaFree
__host__ __device__ T & operator[](size_t idx)
operator[] to retrieve a reference to an item in the buffer
Definition: GpuView.hpp:71
std::vector< T > asStdVector() const
creates an std::vector of the same size and copies the GPU data to this std::vector
__host__ __device__ iterator begin() const
Get a const iterator pointing to the first element of the buffer.
Definition: GpuView.hpp:334
Definition: autotuner.hpp:29