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 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__ bool empty() const {
128 return m_numberOfElements == 0;
129 }
130
134 __host__ __device__ T& front()
135 {
136#ifndef NDEBUG
137 assertHasElements();
138#endif
139 return m_dataPtr[0];
140 }
141
145 __host__ __device__ T& back()
146 {
147#ifndef NDEBUG
148 assertHasElements();
149#endif
150 return m_dataPtr[m_numberOfElements-1];
151 }
152
156 __host__ __device__ T front() const
157 {
158#ifndef NDEBUG
159 assertHasElements();
160#endif
161 return m_dataPtr[0];
162 }
163
167 __host__ __device__ T back() const
168 {
169#ifndef NDEBUG
170 assertHasElements();
171#endif
172 return m_dataPtr[m_numberOfElements-1];
173 }
174
182 void copyFromHost(const T* dataPointer, size_t numberOfElements);
183
191 void copyToHost(T* dataPointer, size_t numberOfElements) const;
192
200 void copyFromHost(const std::vector<T>& data);
201
209 void copyToHost(std::vector<T>& data) const;
210
215 __host__ __device__ size_t size() const{
216 return m_numberOfElements;
217 }
218
223 std::vector<T> asStdVector() const;
225 class iterator {
226 public:
227 // Iterator typedefs
228 using iterator_category = std::forward_iterator_tag;
229 using difference_type = std::ptrdiff_t;
230 using value_type = T;
231 using pointer = T*;
232 using reference = T&;
233
237 __host__ __device__ iterator(T* ptr) : m_ptr(ptr) {}
238
241 __host__ __device__ reference operator*() const {
242 return *m_ptr;
243 }
244
247 __host__ __device__ iterator& operator++() {
248 ++m_ptr;
249 return *this;
250 }
251
255 __host__ __device__ iterator operator++(int) {
256 iterator tmp = *this;
257 ++m_ptr;
258 return tmp;
259 }
260
263 __host__ __device__ iterator& operator--() {
264 --m_ptr;
265 return *this;
266 }
267
271 __host__ __device__ iterator operator--(int) {
272 iterator tmp = *this;
273 --m_ptr;
274 return tmp;
275 }
276
279 __host__ __device__ bool operator!=(const iterator& other) const {
280 return !(m_ptr == other.m_ptr);
281 }
282
285 __host__ __device__ bool operator==(const iterator& other) const {
286 return m_ptr == other.m_ptr;
287 }
288
292 __host__ __device__ difference_type operator-(const iterator& other) const {
293 return std::distance(other.m_ptr, m_ptr);
294 }
295
299 __host__ __device__ iterator operator-(difference_type n) const {
300 return iterator(m_ptr-n);
301 }
302
306 __host__ __device__ iterator operator+(difference_type n) const {
307 return iterator(m_ptr + n);
308 }
309
313 __host__ __device__ bool operator<(const iterator& other) const {
314 return m_ptr < other.m_ptr;
315 }
316
320 __host__ __device__ bool operator>(const iterator& other) const {
321 return m_ptr > other.m_ptr;
322 }
323
324 private:
325 // Pointer to the current element
326 T* m_ptr;
327 };
328
333 __host__ __device__ iterator begin(){
334 return iterator(m_dataPtr);
335 }
336
341 __host__ __device__ iterator begin() const {
342 return iterator(m_dataPtr);
343 }
344
349 __host__ __device__ iterator end(){
350 return iterator(m_dataPtr + m_numberOfElements);
351 }
352
357 __host__ __device__ iterator end() const {
358 return iterator(m_dataPtr + m_numberOfElements);
359 }
360
361private:
362 T* m_dataPtr;
363 size_t m_numberOfElements;
364
367 __host__ __device__ void assertSameSize(const GpuView<T>& other) const
368 {
369 assertSameSize(other.m_numberOfElements);
370 }
373 __host__ __device__ void assertSameSize(size_t size) const
374 {
375#if OPM_IS_INSIDE_DEVICE_FUNCTION
376 // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
377 assert(size == m_numberOfElements && "Views did not have the same size");
378#else
379 if (size != m_numberOfElements) {
380 OPM_THROW(std::invalid_argument,
381 fmt::format(fmt::runtime("Given view has {}, while this View has {}."), size, m_numberOfElements));
382 }
383#endif
384 }
385
387 __host__ __device__ void assertHasElements() const
388 {
389#if OPM_IS_INSIDE_DEVICE_FUNCTION
390 // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
391 assert(m_numberOfElements > 0 && "View has 0 elements");
392#else
393 if (m_numberOfElements <= 0) {
394 OPM_THROW(std::invalid_argument, "View has 0 elements");
395 }
396#endif
397 }
398
400 __host__ __device__ void assertInRange(size_t idx) const
401 {
402#if OPM_IS_INSIDE_DEVICE_FUNCTION
403 // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
404 assert(idx < m_numberOfElements && "The index provided was not in the range [0, buffersize-1]");
405#else
406 if (idx >= m_numberOfElements) {
407 OPM_THROW(std::invalid_argument,
408 fmt::format(fmt::runtime("The index provided was not in the range [0, buffersize-1]")));
409 }
410#endif
411 }
412};
413
414} // namespace Opm::gpuistl
415
416#endif
Iterator class to make GpuViews more similar to std containers.
Definition: GpuView.hpp:225
std::ptrdiff_t difference_type
Definition: GpuView.hpp:229
__host__ __device__ bool operator>(const iterator &other) const
Greater than comparison.
Definition: GpuView.hpp:320
__host__ __device__ iterator operator--(int)
Post-decrement operator.
Definition: GpuView.hpp:271
__host__ __device__ bool operator==(const iterator &other) const
Inequality comparison operator.
Definition: GpuView.hpp:285
T * pointer
Definition: GpuView.hpp:231
std::forward_iterator_tag iterator_category
Definition: GpuView.hpp:228
__host__ __device__ reference operator*() const
Dereference operator.
Definition: GpuView.hpp:241
__host__ __device__ difference_type operator-(const iterator &other) const
subtraction operator
Definition: GpuView.hpp:292
__host__ __device__ iterator & operator++()
Pre-increment operator.
Definition: GpuView.hpp:247
T value_type
Definition: GpuView.hpp:230
T & reference
Definition: GpuView.hpp:232
__host__ __device__ iterator operator+(difference_type n) const
Addition operator with diffptr.
Definition: GpuView.hpp:306
__host__ __device__ iterator operator-(difference_type n) const
Subtraction of given number of elements from iterator.
Definition: GpuView.hpp:299
__host__ __device__ iterator operator++(int)
Post-increment operator.
Definition: GpuView.hpp:255
__host__ __device__ iterator & operator--()
Pre-decrement operator.
Definition: GpuView.hpp:263
__host__ __device__ bool operator!=(const iterator &other) const
Inequality comparison operator.
Definition: GpuView.hpp:279
__host__ __device__ iterator(T *ptr)
Create iterator from a pointer.
Definition: GpuView.hpp:237
__host__ __device__ bool operator<(const iterator &other) const
Less than comparison.
Definition: GpuView.hpp:313
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__ iterator begin()
Get an iterator pointing to the first element of the buffer.
Definition: GpuView.hpp:333
GpuView()=default
Default constructor that will initialize cublas and allocate 0 bytes of memory.
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__ bool empty() const
Definition: GpuView.hpp:127
__host__ __device__ size_t size() const
size returns the size (number of T elements) in the vector
Definition: GpuView.hpp:215
__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:357
__host__ __device__ T & front()
Definition: GpuView.hpp:134
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:145
__host__ __device__ T back() const
Definition: GpuView.hpp:167
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:156
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:349
__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:341
A small, fixed‑dimension MiniVector class backed by std::array that can be used in both host and CUDA...
Definition: AmgxInterface.hpp:38