Lift
Library of parallel computing primitives for GPUs and multi-core CPUs
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pointer.h
Go to the documentation of this file.
1 /*
2  * Lift
3  *
4  * Copyright (c) 2014-2015, NVIDIA CORPORATION
5  * Copyright (c) 2015, Nuno Subtil <subtil@gmail.com>
6  * Copyright (c) 2015, Roche Molecular Systems Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * * Neither the name of the copyright holders nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #pragma once
33 
34 #include "../types.h"
35 #include "../backends.h"
36 #include "../decorators.h"
37 
38 #include "thrust_wrappers.h"
39 #include "type_assignment_checks.h"
40 
41 namespace lift {
42 
54 template <target_system system,
55  typename T,
56  typename _index_type>
58 {
59  enum {
60  system_tag = system,
61  };
62 
63  typedef T value_type;
64  typedef const T const_value_type;
65  typedef _index_type index_type;
68  typedef T& reference_type;
69  typedef const T& const_reference_type;
70  typedef T* pointer_type;
71  typedef const T* const_pointer_type;
72  typedef T* iterator_type;
73  typedef const T* const_iterator_type;
74 
78 
81  : storage(nullptr), storage_size(0)
82  { }
83 
86  : storage(storage), storage_size(storage_size)
87  { }
88 
91  template <target_system other_system, typename other_value_type>
93  {
94  if (system == other_system)
95  {
96  storage = other.data();
97  storage_size = other.size();
98  } else {
99  // create a bad pointer when assigning across systems
100  storage = nullptr;
101  storage_size = 0;
102  }
103  }
104 
105  template <typename other_pointer>
106  LIFT_HOST_DEVICE tagged_pointer_base(other_pointer& other)
107  {
108  if (system == target_system(other_pointer::system_tag))
109  {
110  storage = other.data();
111  storage_size = other.size();
112  } else {
113  storage = nullptr;
114  storage_size = 0;
115  }
116  }
117 
120  template <target_system other_system, typename other_value_type>
122  {
123  if (system == other_system)
124  {
125  storage = other.data();
126  storage_size = other.size();
127  } else {
128  // create a bad pointer when assigning across systems
129  storage = nullptr;
130  storage_size = 0;
131  }
132 
133  return *this;
134  }
135 
137  {
138  return storage[pos];
139  }
140 
142  {
143  return storage[pos];
144  }
145 
147  {
148  return storage[pos];
149  }
150 
152  {
153  return storage[pos];
154  }
155 
157  {
158  return storage[0];
159  }
160 
162  {
163  return storage[0];
164  }
165 
167  {
168  return &storage[storage_size - 1];
169  }
170 
172  {
173  return &storage[storage_size - 1];
174  }
175 
177  {
179  }
180 
182  {
183  return iterator_type(storage);
184  }
185 
187  {
189  }
190 
192  {
194  }
195 
197  {
199  }
200 
202  {
204  }
205 
208  {
210  }
211 
214  {
216  }
217 
221  {
223  }
224 
228  {
230  }
231 
232  // TODO: reverse iterators?
233 
235  {
236  return storage_size;
237  }
238 
239  LIFT_HOST_DEVICE bool empty() const
240  {
241  return storage_size == 0;
242  }
243 
245  {
246  return storage;
247  }
248 
249 protected:
252 };
253 
273 template <target_system system,
274  typename T,
275  typename _index_type = uint32>
276 struct pointer : public tagged_pointer_base<system, T, _index_type>
277 {
278 // the following declarations are meant for documenting the interface
279 // all of these exist in template specializations only
280 #if DOXYGEN_ONLY
282 
285  typedef typename base::value_type value_type;
286  typedef typename base::index_type index_type;
287  typedef typename base::size_type size_type;
290 
291  using base::base;
292 
293  // return a pointer to a memory range within this pointer
294  LIFT_HOST_DEVICE pointer range(const size_type offset, size_type len = size_type(-1)) const;
295 
296  // pointer arithmetic
297  // note that we don't do any bounds checking
298  LIFT_HOST_DEVICE pointer operator+(off_t offset) const;
299  LIFT_HOST_DEVICE pointer operator-(off_t offset) const;
300  // return a truncated pointer
301  LIFT_HOST_DEVICE pointer truncate(size_t new_size);
302 
303  // read a value behind this memory pointer
304  // note: this is slow for cuda pointers!
306 
307  // poke a value behind this memory pointer
308  // note: this is slow for cuda pointers!
309  void poke(index_type pos, const value_type value);
310 #endif
311 };
312 
316 template <typename T,
317  typename _index_type>
318 struct pointer<host, T, _index_type> : public tagged_pointer_base<host, T, _index_type>
319 {
321 
324  typedef typename base::value_type value_type;
325  typedef typename base::index_type index_type;
326  typedef typename base::size_type size_type;
329 
330  using base::base;
331 
332  // return a pointer to a memory range within this pointer
334  {
335  pointer ret;
336  ret.storage = base::storage + offset;
337 
338  if (len == size_type(-1))
339  {
340  len = base::storage_size - offset;
341  }
342 
343  ret.storage_size = len;
344 
345  return ret;
346  }
347 
348  // pointer arithmetic
349  // note that we don't do any bounds checking
350  LIFT_HOST_DEVICE pointer operator+(off_t offset) const
351  {
352  pointer ret;
353  ret.storage = base::storage + offset;
354  ret.storage_size = base::storage_size - offset;
355 
356  return ret;
357  }
358 
359  LIFT_HOST_DEVICE pointer operator-(off_t offset) const
360  {
361  pointer ret;
362  ret.storage = base::storage - offset;
363  ret.storage_size = base::storage_size + offset;
364 
365  return ret;
366  }
367 
368  // return a truncated pointer
370  {
371  pointer ret;
372  ret.storage = base::storage;
373  ret.storage_size = new_size;
374 
375  return ret;
376  }
377 
378  // read a value behind this memory pointer
379  // note: this is slow for cuda pointers!
381  {
382  return base::storage[pos];
383  }
384 
385  // poke a value behind this memory pointer
386  // note: this is slow for cuda pointers!
387  void poke(index_type pos, const value_type value)
388  {
389  base::storage[pos] = value;
390  }
391 
392  // shortcut for peek, intended mostly for debug code
393  value_type operator() (const index_type idx) const
394  {
395  return peek(idx);
396  }
397 };
398 
399 template <typename T,
400  typename _index_type>
401 struct pointer<cuda, T, _index_type> : public tagged_pointer_base<cuda, T, _index_type>
402 {
404 
407  typedef typename base::value_type value_type;
408  typedef typename base::index_type index_type;
409  typedef typename base::size_type size_type;
412 
413  using base::base;
414 
415  // return a pointer to a memory range within this pointer
417  {
418  pointer ret;
419  ret.storage = base::storage + offset;
420 
421  if (len == size_type(-1))
422  {
423  len = base::storage_size - offset;
424  }
425 
426  ret.storage_size = len;
427 
428  return ret;
429  }
430 
431  // pointer arithmetic
432  // note that we don't do any bounds checking
433  LIFT_HOST_DEVICE pointer operator+(off_t offset) const
434  {
435  pointer ret;
436  ret.storage = base::storage + offset;
437  ret.storage_size = base::storage_size - offset;
438 
439  return ret;
440  }
441 
442  LIFT_HOST_DEVICE pointer operator-(off_t offset) const
443  {
444  pointer ret;
445  ret.storage = base::storage - offset;
446  ret.storage_size = base::storage_size + offset;
447 
448  return ret;
449  }
450 
451  // return a truncated pointer
453  {
454  pointer ret;
455  ret.storage = base::storage;
456  ret.storage_size = new_size;
457 
458  return ret;
459  }
460 
461  // read a value behind this memory pointer
462  // note: this is slow!
463  value_type peek(const size_type pos) const
464  {
465  return storage_read(pos);
466  }
467 
468  // poke a value behind this memory pointer
469  // note: this is slow!
470  void poke(const size_type pos, const value_type value)
471  {
472  cudaMemcpy(&base::storage[pos], &value, sizeof(value_type), cudaMemcpyHostToDevice);
473  }
474 
475  // shortcut for peek, intended mostly for debug code
476  // note: this is slow!
477  value_type operator() (const index_type idx)
478  {
479  return peek(idx);
480  }
481 
482 protected:
483  // this is slow!
485  {
486  value_type v = value_type();
487  cudaMemcpy((void *) &v, &base::storage[pos], sizeof(value_type), cudaMemcpyDeviceToHost);
488  return v;
489  }
490 };
491 
492 } // namespace lift
const T & const_reference_type
Definition: pointer.h:69
const T * const_pointer_type
Definition: pointer.h:71
LIFT_HOST_DEVICE const_reference_type operator[](size_type pos) const
Definition: pointer.h:146
LIFT_HOST_DEVICE tagged_pointer_base()
The default constructor initializes the pointer to null.
Definition: pointer.h:80
base::iterator_type iterator_type
Definition: pointer.h:288
base::reference_type reference_type
Definition: pointer.h:283
LIFT_HOST_DEVICE pointer range(const size_type offset, size_type len=size_type(-1)) const
base::const_reference_type const_reference_type
Definition: pointer.h:323
uint32_t uint32
Definition: types.h:43
base::const_iterator_type const_iterator_type
Definition: pointer.h:411
LIFT_HOST_DEVICE tagged_pointer_base & operator=(tagged_pointer_base< other_system, other_value_type, index_type > &other)
Copy constructor creates a copy of the pointer.
Definition: pointer.h:121
LIFT_HOST_DEVICE pointer range(const size_type offset, size_type len=size_type(-1)) const
Definition: pointer.h:333
LIFT_HOST_DEVICE thrust_const_iterator_type t_begin() const
Returns a Thrust-compatible iterator pointing at the base address of the pointer. ...
Definition: pointer.h:207
LIFT_HOST_DEVICE pointer truncate(size_t new_size)
Definition: pointer.h:452
LIFT_HOST_DEVICE iterator_type begin()
Definition: pointer.h:181
LIFT_HOST_DEVICE thrust_iterator_type t_begin()
Returns a Thrust-compatible iterator pointing at the base address of the pointer. ...
Definition: pointer.h:213
tagged_pointer_base< cuda, T, _index_type > base
Definition: pointer.h:403
base::const_iterator_type const_iterator_type
Definition: pointer.h:289
LIFT_HOST_DEVICE pointer operator+(off_t offset) const
LIFT_HOST_DEVICE const_reference_type front() const
Definition: pointer.h:156
LIFT_HOST_DEVICE pointer operator-(off_t offset) const
Definition: pointer.h:442
LIFT_HOST_DEVICE pointer range(const size_type offset, size_type len=size_type(-1)) const
Definition: pointer.h:416
Base class for tagged memory pointer implementation.
Definition: pointer.h:57
tagged_pointer_base< host, T, _index_type > base
Definition: pointer.h:281
LIFT_HOST_DEVICE pointer operator-(off_t offset) const
LIFT_HOST_DEVICE const_reference_type at(size_type pos) const
Definition: pointer.h:136
base::size_type size_type
Definition: pointer.h:287
value_type peek(const size_type pos) const
Definition: pointer.h:463
base::reference_type reference_type
Definition: pointer.h:405
LIFT_HOST_DEVICE reference_type back()
Definition: pointer.h:171
LIFT_HOST_DEVICE bool empty() const
Definition: pointer.h:239
LIFT_HOST_DEVICE pointer_type data() const
Definition: pointer.h:244
LIFT_HOST_DEVICE pointer operator+(off_t offset) const
Definition: pointer.h:350
index_type size_type
Definition: pointer.h:66
base::iterator_type iterator_type
Definition: pointer.h:327
value_type peek(index_type pos)
const T * const_iterator_type
Definition: pointer.h:73
base::const_reference_type const_reference_type
Definition: pointer.h:284
LIFT_HOST_DEVICE pointer truncate(size_t new_size)
base::value_type value_type
Definition: pointer.h:285
LIFT_HOST_DEVICE tagged_pointer_base(T *storage, size_type storage_size)
Construct a tagged pointer from a raw pointer.
Definition: pointer.h:85
base::const_iterator_type const_iterator_type
Definition: pointer.h:328
LIFT_HOST_DEVICE reference_type at(size_type pos)
Definition: pointer.h:141
LIFT_HOST_DEVICE const_iterator_type begin() const
Definition: pointer.h:176
value_type peek(index_type pos) const
Definition: pointer.h:380
LIFT_HOST_DEVICE pointer operator+(off_t offset) const
Definition: pointer.h:433
base::index_type index_type
Definition: pointer.h:286
Lift's tagged pointer class.
Definition: pointer.h:276
LIFT_HOST_DEVICE pointer operator-(off_t offset) const
Definition: pointer.h:359
void poke(const size_type pos, const value_type value)
Definition: pointer.h:470
LIFT_HOST_DEVICE size_type size() const
Definition: pointer.h:234
thrust_iterator_adaptor< system, value_type, iterator_type > thrust_iterator_type
Thrust-compatible iterator types.
Definition: pointer.h:76
thrust_iterator_adaptor< system, value_type, const_iterator_type > thrust_const_iterator_type
Definition: pointer.h:77
LIFT_HOST_DEVICE thrust_const_iterator_type t_end() const
Returns a Thrust-compatible iterator pointing at the end of the memory region covered by this pointer...
Definition: pointer.h:220
_index_type index_type
Definition: pointer.h:65
base::reference_type reference_type
Definition: pointer.h:322
base::iterator_type iterator_type
Definition: pointer.h:410
LIFT_HOST_DEVICE const_reference_type back() const
Definition: pointer.h:166
void poke(index_type pos, const value_type value)
#define LIFT_HOST_DEVICE
Definition: local_memory.h:40
base::const_reference_type const_reference_type
Definition: pointer.h:406
LIFT_HOST_DEVICE pointer truncate(size_t new_size)
Definition: pointer.h:369
LIFT_HOST_DEVICE tagged_pointer_base(other_pointer &other)
Definition: pointer.h:106
LIFT_HOST_DEVICE tagged_pointer_base(tagged_pointer_base< other_system, other_value_type, index_type > &other)
Copy constructor creates a copy of the pointer.
Definition: pointer.h:92
pointer_type storage
Definition: pointer.h:250
target_system
Definition: backends.h:36
LIFT_HOST_DEVICE const_iterator_type cend() const
Definition: pointer.h:201
tagged_pointer_base< host, T, _index_type > base
Definition: pointer.h:320
LIFT_HOST_DEVICE thrust_iterator_type t_end()
Returns a Thrust-compatible iterator pointing at the end of the memory region covered by this pointer...
Definition: pointer.h:227
value_type storage_read(size_type pos) const
Definition: pointer.h:484
void poke(index_type pos, const value_type value)
Definition: pointer.h:387
LIFT_HOST_DEVICE iterator_type end()
Definition: pointer.h:191
LIFT_HOST_DEVICE reference_type front()
Definition: pointer.h:161
LIFT_HOST_DEVICE const_iterator_type cbegin() const
Definition: pointer.h:196
LIFT_HOST_DEVICE const_iterator_type end() const
Definition: pointer.h:186
index_type difference_type
Definition: pointer.h:67