Lift
Library of parallel computing primitives for GPUs and multi-core CPUs
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
allocation.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 "default_allocator.h"
39 #include "pointer.h"
40 #include "thrust_wrappers.h"
41 #include "type_assignment_checks.h"
42 
43 namespace lift {
44 
45 // tagged mutable memory pointer interface
46 // exposes some of the std::vector interface, except for anything where the semantics differ from a plain pointer
47 template <target_system system,
48  typename T,
49  typename _index_type = uint32,
50  typename allocator = typename default_memory_allocator<system>::type>
51 struct allocation : public pointer<system, T, _index_type>
52 {
54 
55  typedef typename base::pointer_type pointer_type;
56  typedef typename base::value_type value_type;
57  typedef typename base::size_type size_type;
58  typedef typename base::index_type index_type;
59 
60  typedef allocator allocator_type;
61 
62  using base::base;
63  using base::storage;
64  using base::storage_size;
65 
67  : base()
68  { }
69 
71  : base()
72  {
73  resize(count);
74  }
75 
77  {
78  storage = other.storage;
79  storage_size = other.storage_size;
80  }
81 
82  // create allocation from pointer
83  // this should probably be disallowed and done differently
84  template <typename value_type>
86  {
87  *this = other;
88  }
89 
90  // initializer list semantics: make a copy of the contents
91  allocation(const std::initializer_list<value_type>& l)
92  : base()
93  {
94  resize(l.size());
95  index_type offset = 0;
96  for(auto i : l)
97  {
98  base::poke(offset, i);
99  offset++;
100  }
101  }
102 
103  // assign allocation from pointer
104  // this should probably be disallowed and done differently
105  template <typename value_type>
107  {
108  storage = other.data();
109  storage_size = other.size();
110 
111  return *this;
112  }
113 
114  // initializer list semantics: make a copy of the contents
115  allocation& operator=(const std::initializer_list<value_type>& l)
116  {
117  resize(l.size());
118  index_type offset = 0;
119  for(auto i : l)
120  {
121  base::poke(offset, i);
122  offset++;
123  }
124 
125  return *this;
126  }
127 
128  virtual void resize(size_type count)
129  {
130  size_type old_storage_size;
131  pointer_type old_storage;
132 
133  old_storage = storage;
134  old_storage_size = storage_size;
135 
136  storage = (pointer_type) allocator_type().allocate(sizeof(value_type) * count);
137 
138  if (old_storage != nullptr)
139  {
140  device_memory_copy((void *)storage, old_storage, sizeof(value_type) * std::min(count, old_storage_size));
141  allocator_type().deallocate((pointer_type)old_storage);
142  }
143 
144  storage_size = count;
145  }
146 
147  // release the memory allocation
148  virtual void free(void)
149  {
150  if (storage)
151  {
152  allocator_type().deallocate(storage);
153  }
154 
155  storage = nullptr;
156  storage_size = 0;
157  }
158 
159  // cross-memory-space copy from another pointer
160  // note that this does not handle copies across different GPUs
161  template <typename other_allocation>
162  void copy(const other_allocation& other)
163  {
164  __internal::check_value_type_assignment_compatible<value_type, typename other_allocation::value_type>();
165 
166  resize(other.size());
167 
168  if (system == cuda)
169  {
170  // copying to GPU...
171  if (target_system(other_allocation::system_tag) == cuda)
172  {
173  // ... from the GPU
174  cudaMemcpy((void *) base::data(), other.data(), sizeof(value_type) * other.size(), cudaMemcpyDeviceToDevice);
175  } else {
176  // ... from the host
177  cudaMemcpy((void *) base::data(), other.data(), sizeof(value_type) * other.size(), cudaMemcpyHostToDevice);
178  }
179  } else {
180  // copying to host...
181  if (target_system(other_allocation::system_tag) == cuda)
182  {
183  // ... from the GPU
184  cudaMemcpy((void *) base::data(), other.data(), sizeof(value_type) * other.size(), cudaMemcpyDeviceToHost);
185  } else {
186  // ... from the host
187  memcpy((void *) base::data(), other.data(), sizeof(value_type) * other.size());
188  }
189  }
190  }
191 
192 protected:
193  void device_memory_copy(void *dst, const void *src, size_t size)
194  {
195  if (system == cuda)
196  {
197  cudaMemcpy(dst, src, size, cudaMemcpyDeviceToDevice);
198  } else {
199  memcpy(dst, src, size);
200  }
201  }
202 };
203 
204 } // namespace lift
base::value_type value_type
Definition: allocation.h:56
allocator allocator_type
Definition: allocation.h:60
uint32_t uint32
Definition: types.h:43
pointer< system, T, _index_type > base
Definition: allocation.h:53
LIFT_HOST_DEVICE allocation(const allocation &other)
Definition: allocation.h:76
LIFT_HOST_DEVICE allocation()
Definition: allocation.h:66
tagged_pointer_base< host, T, _index_type > base
Definition: pointer.h:281
allocation(const std::initializer_list< value_type > &l)
Definition: allocation.h:91
LIFT_HOST_DEVICE pointer_type data() const
Definition: pointer.h:244
virtual void resize(size_type count)
Definition: allocation.h:128
allocation(const pointer< system, value_type, index_type > &other)
Definition: allocation.h:85
allocation(size_type count)
Definition: allocation.h:70
base::pointer_type pointer_type
Definition: allocation.h:55
Lift's tagged pointer class.
Definition: pointer.h:276
void device_memory_copy(void *dst, const void *src, size_t size)
Definition: allocation.h:193
LIFT_HOST_DEVICE size_type size() const
Definition: pointer.h:234
allocation & operator=(const pointer< system, value_type, index_type > &other)
Definition: allocation.h:106
virtual void free(void)
Definition: allocation.h:148
void poke(index_type pos, const value_type value)
#define LIFT_HOST_DEVICE
Definition: local_memory.h:40
base::size_type size_type
Definition: allocation.h:57
pointer_type storage
Definition: pointer.h:250
target_system
Definition: backends.h:36
void copy(const other_allocation &other)
Definition: allocation.h:162
allocation & operator=(const std::initializer_list< value_type > &l)
Definition: allocation.h:115
base::index_type index_type
Definition: allocation.h:58