device_uvector.hpp
1 /*
2  * Copyright (c) 2020, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <rmm/cuda_stream_view.hpp>
20 #include <rmm/detail/error.hpp>
21 #include <rmm/device_buffer.hpp>
22 #include <rmm/mr/device/device_memory_resource.hpp>
24 
25 #include <vector>
26 
27 namespace rmm {
28 
66 template <typename T>
68  static_assert(std::is_trivially_copyable<T>::value,
69  "device_uvector only supports types that are trivially copyable.");
70 
71  public:
72  using value_type = T;
73  using size_type = std::size_t;
74  using reference = value_type&;
75  using const_reference = value_type const&;
76  using pointer = value_type*;
77  using const_pointer = value_type const*;
78  using iterator = pointer;
79  using const_iterator = const_pointer;
80 
81  ~device_uvector() = default;
82  device_uvector(device_uvector&&) = default;
83  device_uvector& operator=(device_uvector&&) = default;
84 
88  device_uvector(device_uvector const&) = delete;
89 
94 
98  device_uvector() = delete;
99 
111  explicit device_uvector(
112  std::size_t size,
113  cuda_stream_view stream,
114  rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource())
115  : _storage{elements_to_bytes(size), stream, mr}
116  {
117  }
118 
128  explicit device_uvector(
129  device_uvector const& other,
130  cuda_stream_view stream,
131  rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource())
132  : _storage{other._storage, stream, mr}
133  {
134  }
135 
144  pointer element_ptr(std::size_t element_index) noexcept
145  {
146  assert(element_index < size());
147  return data() + element_index;
148  }
149 
158  const_pointer element_ptr(std::size_t element_index) const noexcept
159  {
160  assert(element_index < size());
161  return data() + element_index;
162  }
163 
193  void set_element(std::size_t element_index, T const& v, cuda_stream_view s)
194  {
195  RMM_EXPECTS(
196  element_index < size(), rmm::out_of_range, "Attempt to access out of bounds element.");
197  RMM_CUDA_TRY(
198  cudaMemcpyAsync(element_ptr(element_index), &v, sizeof(v), cudaMemcpyDefault, s.value()));
200  }
201 
231  void set_element_async(std::size_t element_index, value_type const& v, cuda_stream_view s)
232  {
233  RMM_EXPECTS(
234  element_index < size(), rmm::out_of_range, "Attempt to access out of bounds element.");
235  RMM_CUDA_TRY(
236  cudaMemcpyAsync(element_ptr(element_index), &v, sizeof(v), cudaMemcpyDefault, s.value()));
237  }
238 
251  value_type element(std::size_t element_index, cuda_stream_view s) const
252  {
253  RMM_EXPECTS(
254  element_index < size(), rmm::out_of_range, "Attempt to access out of bounds element.");
255  value_type v;
256  RMM_CUDA_TRY(
257  cudaMemcpyAsync(&v, element_ptr(element_index), sizeof(v), cudaMemcpyDefault, s.value()));
258  s.synchronize();
259  return v;
260  }
261 
272  value_type front_element(cuda_stream_view s) const { return element(0, s); }
273 
284  value_type back_element(cuda_stream_view s) const { return element(size() - 1, s); }
285 
302  void resize(std::size_t new_size, cuda_stream_view stream)
303  {
304  _storage.resize(elements_to_bytes(new_size), stream);
305  }
306 
314  void shrink_to_fit(cuda_stream_view stream) { _storage.shrink_to_fit(stream); }
315 
321  device_buffer release() noexcept { return std::move(_storage); }
322 
329  std::size_t capacity() const noexcept { return bytes_to_elements(_storage.capacity()); }
330 
339  pointer data() noexcept { return static_cast<pointer>(_storage.data()); }
340 
349  const_pointer data() const noexcept { return static_cast<const_pointer>(_storage.data()); }
350 
358  iterator begin() noexcept { return data(); }
359 
367  const_iterator cbegin() const noexcept { return data(); }
368 
376  const_iterator begin() const noexcept { return cbegin(); }
377 
386  iterator end() noexcept { return data() + size(); }
387 
396  const_iterator cend() const noexcept { return data() + size(); }
397 
406  const_iterator end() const noexcept { return cend(); }
407 
413  std::size_t size() const noexcept { return bytes_to_elements(_storage.size()); }
414 
421  bool is_empty() const noexcept { return size() == 0; }
422 
429  {
430  return _storage.memory_resource();
431  }
432 
433  private:
434  device_buffer _storage{};
435 
436  std::size_t constexpr elements_to_bytes(std::size_t num_elements) const noexcept
437  {
438  return num_elements * sizeof(value_type);
439  }
440 
441  std::size_t constexpr bytes_to_elements(std::size_t num_bytes) const noexcept
442  {
443  return num_bytes / sizeof(value_type);
444  }
445 };
446 } // namespace rmm
rmm::device_uvector::data
const_pointer data() const noexcept
Returns const pointer to underlying device storage.
Definition: device_uvector.hpp:349
rmm::device_uvector::end
iterator end() noexcept
Returns an iterator to the element following the last element of the vector.
Definition: device_uvector.hpp:386
rmm::device_uvector::end
const_iterator end() const noexcept
Returns an iterator to the element following the last element of the vector.
Definition: device_uvector.hpp:406
device_buffer.hpp
RAII construct for device memory allocation.
rmm::device_uvector::operator=
device_uvector & operator=(device_uvector const &)=delete
Copy assignment is deleted as it doesn't allow a stream argument.
rmm::device_uvector::element
value_type element(std::size_t element_index, cuda_stream_view s) const
Returns the specified element from device memory.
Definition: device_uvector.hpp:251
rmm::device_uvector::begin
const_iterator begin() const noexcept
Returns a const_iterator to the first element.
Definition: device_uvector.hpp:376
rmm::device_buffer::memory_resource
mr::device_memory_resource * memory_resource() const noexcept
Returns pointer to the memory resource used to allocate and deallocate the device memory.
Definition: device_buffer.hpp:385
per_device_resource.hpp
Management of per-device device_memory_resources.
rmm::device_uvector::device_uvector
device_uvector(std::size_t size, cuda_stream_view stream, rmm::mr::device_memory_resource *mr=rmm::mr::get_current_device_resource())
Construct a new device_uvector with sufficient uninitialized storage for size elements.
Definition: device_uvector.hpp:111
rmm::cuda_stream_view
Strongly-typed non-owning wrapper for CUDA streams with default constructor.
Definition: cuda_stream_view.hpp:34
rmm::device_buffer::size
std::size_t size() const noexcept
Returns size in bytes that was requested for the device memory allocation.
Definition: device_buffer.hpp:346
rmm::device_uvector::memory_resource
mr::device_memory_resource * memory_resource() const noexcept
Returns pointer to the resource used to allocate and deallocate the device storage.
Definition: device_uvector.hpp:428
rmm::device_uvector::cbegin
const_iterator cbegin() const noexcept
Returns a const_iterator to the first element.
Definition: device_uvector.hpp:367
rmm::device_uvector::set_element
void set_element(std::size_t element_index, T const &v, cuda_stream_view s)
Performs a synchronous copy of v to the specified element in device memory.
Definition: device_uvector.hpp:193
rmm::device_uvector::resize
void resize(std::size_t new_size, cuda_stream_view stream)
Resizes the vector to contain new_size elements.
Definition: device_uvector.hpp:302
rmm::device_uvector::device_uvector
device_uvector(device_uvector const &)=delete
Copy ctor is deleted as it doesn't allow a stream argument.
rmm::device_uvector::is_empty
bool is_empty() const noexcept
Returns true if the vector contains no elements, i.e., size() == 0.
Definition: device_uvector.hpp:421
rmm::device_uvector
An uninitialized vector of elements in device memory.
Definition: device_uvector.hpp:67
rmm::device_buffer::shrink_to_fit
void shrink_to_fit(cuda_stream_view stream=cuda_stream_view{})
Forces the deallocation of unused memory.
Definition: device_buffer.hpp:320
rmm::device_uvector::size
std::size_t size() const noexcept
Returns the number of elements in the vector.
Definition: device_uvector.hpp:413
rmm::device_buffer
Definition: device_buffer.hpp:73
rmm::device_uvector::capacity
std::size_t capacity() const noexcept
Returns the number of elements that can be held in currently allocated storage.
Definition: device_uvector.hpp:329
rmm::device_uvector::set_element_async
void set_element_async(std::size_t element_index, value_type const &v, cuda_stream_view s)
Performs an asynchronous copy of v to the specified element in device memory.
Definition: device_uvector.hpp:231
rmm::device_uvector::cend
const_iterator cend() const noexcept
Returns a const_iterator to the element following the last element of the vector.
Definition: device_uvector.hpp:396
rmm::device_uvector::back_element
value_type back_element(cuda_stream_view s) const
Returns the last element.
Definition: device_uvector.hpp:284
rmm::device_uvector::device_uvector
device_uvector(device_uvector const &other, cuda_stream_view stream, rmm::mr::device_memory_resource *mr=rmm::mr::get_current_device_resource())
Construct a new device_uvector by deep copying the contents of another device_uvector.
Definition: device_uvector.hpp:128
rmm::device_buffer::resize
void resize(std::size_t new_size, cuda_stream_view stream=cuda_stream_view{})
Resize the device memory allocation.
Definition: device_buffer.hpp:289
rmm::device_uvector::device_uvector
device_uvector()=delete
Default constructor is deleted as it doesn't allow a stream argument.
rmm::device_uvector::release
device_buffer release() noexcept
Release ownership of device memory storage.
Definition: device_uvector.hpp:321
rmm::device_uvector::begin
iterator begin() noexcept
Returns an iterator to the first element.
Definition: device_uvector.hpp:358
rmm::device_uvector::front_element
value_type front_element(cuda_stream_view s) const
Returns the first element.
Definition: device_uvector.hpp:272
rmm::cuda_stream_view::synchronize
void synchronize() const
Synchronize the viewed CUDA stream.
Definition: cuda_stream_view.hpp:96
rmm::device_uvector::shrink_to_fit
void shrink_to_fit(cuda_stream_view stream)
Forces deallocation of unused device memory.
Definition: device_uvector.hpp:314
rmm::device_buffer::data
void const * data() const noexcept
Returns raw pointer to underlying device memory allocation.
Definition: device_buffer.hpp:335
rmm::device_uvector::element_ptr
const_pointer element_ptr(std::size_t element_index) const noexcept
Returns pointer to the specified element.
Definition: device_uvector.hpp:158
rmm::device_uvector::element_ptr
pointer element_ptr(std::size_t element_index) noexcept
Returns pointer to the specified element.
Definition: device_uvector.hpp:144
rmm::cuda_stream_view::value
constexpr cudaStream_t value() const noexcept
Get the wrapped stream.
Definition: cuda_stream_view.hpp:58
rmm::cuda_stream_view::synchronize_no_throw
void synchronize_no_throw() const noexcept
Synchronize the viewed CUDA stream. Does not throw if there is an error.
Definition: cuda_stream_view.hpp:103
rmm::mr::device_memory_resource
Base class for all libcudf device memory allocation.
Definition: device_memory_resource.hpp:83
rmm::device_buffer::capacity
std::size_t capacity() const noexcept
Returns actual size in bytes of device memory allocation.
Definition: device_buffer.hpp:362
rmm::out_of_range
Exception thrown when attempting to access outside of a defined range.
Definition: error.hpp:72
rmm::device_uvector::data
pointer data() noexcept
Returns pointer to underlying device storage.
Definition: device_uvector.hpp:339