column_device_view.cuh
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #pragma once
6 
9 #include <cudf/detail/utilities/alignment.hpp>
10 #include <cudf/lists/list_view.hpp>
15 #include <cudf/utilities/span.hpp>
17 
18 #include <rmm/resource_ref.hpp>
19 
20 #include <cuda/iterator>
21 #include <cuda/std/utility>
22 #include <cuda/stream>
23 
24 #include <functional>
25 
31 namespace CUDF_EXPORT cudf {
32 
39 class alignas(16) column_device_view : public column_device_view_core {
40  public:
42 
43  column_device_view() = delete;
44  ~column_device_view() = default;
59 
69  column_device_view(column_view column, void* h_ptr, void* d_ptr);
70 
88  size_type size) const noexcept
89  {
90  return column_device_view{this->type(),
91  size,
92  this->head(),
93  this->null_count(),
94  this->null_mask(),
95  this->offset() + offset,
96  static_cast<column_device_view*>(_children),
97  this->num_child_columns()};
98  }
99 
117  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
118  [[nodiscard]] __device__ T element(size_type element_index) const noexcept
119  {
120  return base::element<T>(element_index);
121  }
122 
134  template <typename T, CUDF_ENABLE_IF(cuda::std::is_same_v<T, string_view>)>
135  [[nodiscard]] __device__ T element(size_type element_index) const noexcept
136  {
137  return base::element<T>(element_index);
138  }
139 
150  template <typename T, CUDF_ENABLE_IF(cudf::is_fixed_point<T>())>
151  [[nodiscard]] __device__ T element(size_type element_index) const noexcept
152  {
153  return base::element<T>(element_index);
154  }
155 
156  private:
162  struct index_element_fn {
163  template <typename IndexType,
164  CUDF_ENABLE_IF(is_index_type<IndexType>() and cuda::std::is_signed_v<IndexType>)>
165  __device__ size_type operator()(column_device_view const& indices, size_type index)
166  {
167  return static_cast<size_type>(indices.element<IndexType>(index));
168  }
169 
170  template <typename IndexType,
171  typename... Args,
172  CUDF_ENABLE_IF(not(is_index_type<IndexType>() and cuda::std::is_signed_v<IndexType>))>
173  __device__ size_type operator()(Args&&... args)
174  {
175  CUDF_UNREACHABLE("dictionary indices must be a signed integral type");
176  }
177  };
178 
179  public:
204  template <typename T, CUDF_ENABLE_IF(cuda::std::is_same_v<T, dictionary32>)>
205  [[nodiscard]] __device__ T element(size_type element_index) const noexcept
206  {
207  size_type index = element_index + offset(); // account for this view's _offset
208  auto const indices = child(0);
209  return dictionary32{type_dispatcher(indices.type(), index_element_fn{}, indices, index)};
210  }
211 
218  template <typename T>
219  CUDF_HOST_DEVICE static constexpr bool has_element_accessor()
220  {
221  return has_element_accessor_impl<column_device_view, T>::value;
222  }
223 
225  using count_it = cuda::counting_iterator<size_type>;
229  template <typename T>
230  using const_iterator = cuda::transform_iterator<detail::value_accessor<T>, count_it>;
231 
247  template <typename T, CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
248  [[nodiscard]] const_iterator<T> begin() const
249  {
251  }
252 
267  template <typename T, CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
268  [[nodiscard]] const_iterator<T> end() const
269  {
270  return const_iterator<T>{count_it{size()}, detail::value_accessor<T>{*this}};
271  }
272 
276  template <typename T, typename Nullate>
278  cuda::transform_iterator<detail::optional_accessor<T, Nullate>, count_it>;
279 
283  template <typename T, bool has_nulls>
285  cuda::transform_iterator<detail::pair_accessor<T, has_nulls>, count_it>;
286 
292  template <typename T, bool has_nulls>
294  cuda::transform_iterator<detail::pair_rep_accessor<T, has_nulls>, count_it>;
295 
350  template <typename T,
351  typename Nullate,
352  CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
353  auto optional_begin(Nullate has_nulls) const
354  {
357  }
358 
380  template <typename T,
381  bool has_nulls,
382  CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
384  {
387  }
388 
412  template <typename T,
413  bool has_nulls,
414  CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
416  {
419  }
420 
437  template <typename T,
438  typename Nullate,
439  CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
440  auto optional_end(Nullate has_nulls) const
441  {
444  }
445 
457  template <typename T,
458  bool has_nulls,
459  CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
461  {
464  }
465 
478  template <typename T,
479  bool has_nulls,
480  CUDF_ENABLE_IF(column_device_view::has_element_accessor<T>())>
482  {
485  }
486 
506  static std::unique_ptr<column_device_view, std::function<void(column_device_view*)>> create(
507  column_view source_view,
508  cuda::stream_ref stream = cudf::get_default_stream(),
510 
517  void destroy();
518 
526  static std::size_t extent(column_view const& source_view);
527 
534  [[nodiscard]] __device__ column_device_view child(size_type child_index) const noexcept
535  {
536  return static_cast<column_device_view*>(_children)[child_index];
537  }
538 
544  [[nodiscard]] __device__ device_span<column_device_view const> children() const noexcept
545  {
546  return {static_cast<column_device_view*>(_children), static_cast<std::size_t>(_num_children)};
547  }
548 
554  [[nodiscard]] CUDF_HOST_DEVICE size_type num_child_columns() const noexcept
555  {
556  return _num_children;
557  }
558 
559  private:
574  size_type size,
575  void const* data,
577  bitmask_type const* null_mask,
578  size_type offset,
579  column_device_view* children,
580  size_type num_children)
582  type, size, data, null_count, null_mask, offset, children, num_children}
583  {
584  }
585 
596  column_device_view(column_view source);
597 };
598 
606  public:
608 
609  mutable_column_device_view() = delete;
610  ~mutable_column_device_view() = default;
625 
636 
656  static std::unique_ptr<mutable_column_device_view,
657  std::function<void(mutable_column_device_view*)>>
659  cuda::stream_ref stream = cudf::get_default_stream(),
661 
679  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
680  [[nodiscard]] __device__ T& element(size_type element_index) const noexcept
681  {
682  return base::element<T>(element_index);
683  }
684 
691  template <typename T>
692  CUDF_HOST_DEVICE static constexpr bool has_element_accessor()
693  {
694  return has_element_accessor_impl<mutable_column_device_view, T>::value;
695  }
696 
698  using count_it = cuda::counting_iterator<size_type>;
702  template <typename T>
703  using iterator = cuda::transform_iterator<detail::mutable_value_accessor<T>, count_it>;
704 
715  template <typename T, CUDF_ENABLE_IF(mutable_column_device_view::has_element_accessor<T>())>
717  {
719  }
720 
731  template <typename T, CUDF_ENABLE_IF(mutable_column_device_view::has_element_accessor<T>())>
733  {
735  }
736 
743  [[nodiscard]] __device__ mutable_column_device_view child(size_type child_index) const noexcept
744  {
745  return static_cast<mutable_column_device_view*>(_children)[child_index];
746  }
747 
756  static std::size_t extent(mutable_column_view source_view);
757 
772  [[nodiscard]] static auto create(data_type type,
773  size_type size,
774  void const* data,
775  bitmask_type const* null_mask,
776  size_type offset,
777  mutable_column_device_view* children,
778  size_type num_children)
779  {
780  return mutable_column_device_view{type, size, data, null_mask, offset, children, num_children};
781  }
782 
789  void destroy();
790 
791  private:
801 
815  size_type size,
816  void const* data,
817  bitmask_type const* null_mask,
818  size_type offset,
819  mutable_column_device_view* children,
820  size_type num_children)
821  : mutable_column_device_view_core{type, size, data, null_mask, offset, children, num_children}
822  {
823  }
824 };
825 
826 namespace detail {
827 
842 template <typename T>
845 
851  value_accessor(column_device_view const& _col) : col{_col}
852  {
853  CUDF_EXPECTS(type_id_matches_device_storage_type<T>(col.type().id()), "the data type mismatch");
854  }
855 
861  __device__ T operator()(cudf::size_type i) const { return col.element<T>(i); }
862 };
863 
890 template <typename T, typename Nullate>
893 
900  optional_accessor(column_device_view const& _col, Nullate with_nulls)
901  : col{_col}, has_nulls{with_nulls}
902  {
903  CUDF_EXPECTS(type_id_matches_device_storage_type<T>(col.type().id()), "the data type mismatch");
904  if (with_nulls) { CUDF_EXPECTS(_col.nullable(), "Unexpected non-nullable column."); }
905  }
906 
914  __device__ inline cuda::std::optional<T> operator()(cudf::size_type i) const
915  {
916  if (has_nulls) {
917  return (col.is_valid_nocheck(i)) ? cuda::std::optional<T>{col.element<T>(i)}
918  : cuda::std::optional<T>{cuda::std::nullopt};
919  }
920  return cuda::std::optional<T>{col.element<T>(i)};
921  }
922 
923  Nullate has_nulls{};
924 };
925 
945 template <typename T, bool has_nulls = false>
948 
954  pair_accessor(column_device_view const& _col) : col{_col}
955  {
956  CUDF_EXPECTS(type_id_matches_device_storage_type<T>(col.type().id()), "the data type mismatch");
957  if (has_nulls) { CUDF_EXPECTS(_col.nullable(), "Unexpected non-nullable column."); }
958  }
959 
966  __device__ inline cuda::std::pair<T, bool> operator()(cudf::size_type i) const
967  {
968  return {col.element<T>(i), (has_nulls ? col.is_valid_nocheck(i) : true)};
969  }
970 };
971 
991 template <typename T, bool has_nulls = false>
994 
996 
1002  pair_rep_accessor(column_device_view const& _col) : col{_col}
1003  {
1004  CUDF_EXPECTS(type_id_matches_device_storage_type<T>(col.type().id()), "the data type mismatch");
1005  if (has_nulls) { CUDF_EXPECTS(_col.nullable(), "Unexpected non-nullable column."); }
1006  }
1007 
1014  __device__ inline cuda::std::pair<rep_type, bool> operator()(cudf::size_type i) const
1015  {
1016  return {get_rep<T>(i), (has_nulls ? col.is_valid_nocheck(i) : true)};
1017  }
1018 
1019  private:
1020  template <typename R>
1021  [[nodiscard]] __device__ inline auto get_rep(cudf::size_type i) const
1022  requires(std::is_same_v<R, rep_type>)
1023  {
1024  return col.element<R>(i);
1025  }
1026 
1027  template <typename R>
1028  [[nodiscard]] __device__ inline auto get_rep(cudf::size_type i) const
1029  requires(not std::is_same_v<R, rep_type>)
1030  {
1031  return col.element<R>(i).value();
1032  }
1033 };
1034 
1046 template <typename T>
1049 
1056  {
1057  CUDF_EXPECTS(type_id_matches_device_storage_type<T>(col.type().id()), "the data type mismatch");
1058  }
1059 
1066  __device__ T& operator()(cudf::size_type i) { return col.element<T>(i); }
1067 };
1068 
1094 template <typename ColumnDeviceView, typename ColumnViewIterator>
1095 ColumnDeviceView* child_columns_to_device_array(ColumnViewIterator child_begin,
1096  ColumnViewIterator child_end,
1097  void* h_ptr,
1098  void* d_ptr)
1099 {
1100  ColumnDeviceView* d_children = detail::align_ptr_for_type<ColumnDeviceView>(d_ptr);
1101  auto num_children = std::distance(child_begin, child_end);
1102  if (num_children > 0) {
1103  // The beginning of the memory must be the fixed-sized ColumnDeviceView
1104  // struct objects in order for d_children to be used as an array.
1105  auto h_column = detail::align_ptr_for_type<ColumnDeviceView>(h_ptr);
1106  auto d_column = d_children;
1107 
1108  // Any child data is assigned past the end of this array: h_end and d_end.
1109  auto h_end = reinterpret_cast<int8_t*>(h_column + num_children);
1110  auto d_end = reinterpret_cast<int8_t*>(d_column + num_children);
1111  std::for_each(child_begin, child_end, [&](auto const& col) {
1112  // inplace-new each child into host memory
1113  new (h_column) ColumnDeviceView(col, h_end, d_end);
1114  h_column++; // advance to next child
1115  // update the pointers for holding this child column's child data
1116  auto col_child_data_size = ColumnDeviceView::extent(col) - sizeof(ColumnDeviceView);
1117  h_end += col_child_data_size;
1118  d_end += col_child_data_size;
1119  });
1120  }
1121  return d_children;
1122 }
1123 
1124 } // namespace detail
1125 } // namespace CUDF_EXPORT cudf
An immutable, non-owning view of device data as a column of elements that is trivially copyable and u...
An immutable, non-owning view of device data as a column of elements that is trivially copyable and u...
column_device_view child(size_type child_index) const noexcept
Returns the specified child.
void destroy()
Destroy the column_device_view object.
column_device_view & operator=(column_device_view &&)=default
Move assignment operator.
static constexpr CUDF_HOST_DEVICE bool has_element_accessor()
For a given T, indicates if column_device_view::element<T>() has a valid overload.
const_pair_iterator< T, has_nulls > pair_end() const
Return a pair iterator to the element following the last element of the column.
const_pair_rep_iterator< T, has_nulls > pair_rep_end() const
Return a pair iterator to the element following the last element of the column.
const_pair_iterator< T, has_nulls > pair_begin() const
Return a pair iterator to the first element of the column.
T element(size_type element_index) const noexcept
Returns a copy of the element at the specified index.
cuda::counting_iterator< size_type > count_it
Counting iterator.
column_device_view & operator=(column_device_view const &)=default
Copy assignment operator.
CUDF_HOST_DEVICE column_device_view slice(size_type offset, size_type size) const noexcept
Get a new column_device_view which is a slice of this column.
auto optional_end(Nullate has_nulls) const
Return an optional iterator to the element following the last element of the column.
const_pair_rep_iterator< T, has_nulls > pair_rep_begin() const
Return a pair iterator to the first element of the column.
CUDF_HOST_DEVICE size_type num_child_columns() const noexcept
Returns the number of child columns.
cuda::transform_iterator< detail::pair_accessor< T, has_nulls >, count_it > const_pair_iterator
Pair iterator for navigating this column.
cuda::transform_iterator< detail::optional_accessor< T, Nullate >, count_it > const_optional_iterator
Optional iterator for navigating this column.
auto optional_begin(Nullate has_nulls) const
Return an optional iterator to the first element of the column.
cuda::transform_iterator< detail::value_accessor< T >, count_it > const_iterator
Iterator for navigating this column.
column_device_view(column_device_view const &)=default
Copy constructor.
column_device_view(column_device_view &&)=default
Move constructor.
const_iterator< T > begin() const
Return an iterator to the first element of the column.
static std::unique_ptr< column_device_view, std::function< void(column_device_view *)> > create(column_view source_view, cuda::stream_ref stream=cudf::get_default_stream(), rmm::device_async_resource_ref mr=cudf::get_current_device_resource_ref())
Factory to construct a column view that is usable in device memory.
static std::size_t extent(column_view const &source_view)
Return the size in bytes of the amount of memory needed to hold a device view of the specified column...
column_device_view(column_view column, void *h_ptr, void *d_ptr)
Creates an instance of this class using the specified host memory pointer (h_ptr) to store child obje...
cuda::transform_iterator< detail::pair_rep_accessor< T, has_nulls >, count_it > const_pair_rep_iterator
Pair rep iterator for navigating this column.
const_iterator< T > end() const
Returns an iterator to the element following the last element of the column.
device_span< column_device_view const > children() const noexcept
Returns a span containing the children of this column.
A non-owning, immutable view of device data as a column of elements, some of which may be null as ind...
A container of nullable device data as a column of elements.
Definition: column.hpp:37
Indicator for the logical data type of an element in a column.
Definition: types.hpp:279
constexpr CUDF_HOST_DEVICE type_id id() const noexcept
Returns the type identifier.
Definition: types.hpp:323
CUDF_HOST_DEVICE data_type type() const noexcept
Returns the element type.
bool is_valid_nocheck(size_type element_index) const noexcept
Returns whether the specified element holds a valid value (i.e., not null)
CUDF_HOST_DEVICE bool nullable() const noexcept
Indicates whether the column can contain null elements, i.e., if it has an allocated bitmask.
A mutable, non-owning view of device data as a column of elements that is trivially copyable and usab...
A mutable, non-owning view of device data as a column of elements that is trivially copyable and usab...
cuda::transform_iterator< detail::mutable_value_accessor< T >, count_it > iterator
Iterator for navigating this column.
static constexpr CUDF_HOST_DEVICE bool has_element_accessor()
For a given T, indicates if mutable_column_device_view::element<T>() has a valid overload.
static auto create(data_type type, size_type size, void const *data, bitmask_type const *null_mask, size_type offset, mutable_column_device_view *children, size_type num_children)
Factory to construct a mutable column view that is usable in device memory from pre-existing device m...
void destroy()
Destroy the mutable_column_device_view object.
mutable_column_device_view(mutable_column_view column, void *h_ptr, void *d_ptr)
Creates an instance of this class using the specified host memory pointer (h_ptr) to store child obje...
static std::size_t extent(mutable_column_view source_view)
Return the size in bytes of the amount of memory needed to hold a device view of the specified column...
mutable_column_device_view child(size_type child_index) const noexcept
Returns the specified child.
mutable_column_device_view(mutable_column_device_view const &)=default
Copy constructor.
T & element(size_type element_index) const noexcept
Returns reference to element at the specified index.
iterator< T > end()
Return one past the last element after underlying data is casted to the specified type.
mutable_column_device_view & operator=(mutable_column_device_view &&)=default
Move assignment operator.
mutable_column_device_view(mutable_column_device_view &&)=default
Move constructor.
static std::unique_ptr< mutable_column_device_view, std::function< void(mutable_column_device_view *)> > create(mutable_column_view source_view, cuda::stream_ref stream=cudf::get_default_stream(), rmm::device_async_resource_ref mr=cudf::get_current_device_resource_ref())
Factory to construct a column view that is usable in device memory.
cuda::counting_iterator< size_type > count_it
Counting iterator.
mutable_column_device_view & operator=(mutable_column_device_view const &)=default
Copy assignment operator.
iterator< T > begin()
Return first element (accounting for offset) after underlying data is casted to the specified type.
A non-owning, mutable view of device data as a column of elements, some of which may be null as indic...
ColumnDeviceView * child_columns_to_device_array(ColumnViewIterator child_begin, ColumnViewIterator child_end, void *h_ptr, void *d_ptr)
Helper function for use by column_device_view and mutable_column_device_view constructors to build de...
Column device view class definitions.
column view class definitions
APIs for querying the default CUDA stream and per-thread default stream status.
size_type null_count(bitmask_type const *bitmask, size_type start, size_type stop, cuda::stream_ref stream=cudf::get_default_stream())
Given a validity bitmask, counts the number of null elements (unset bits) in the range [start,...
cuda::stream_ref const get_default_stream()
Get the current default stream.
rmm::device_async_resource_ref get_current_device_resource_ref()
Get the current device memory resource reference.
cuda::mr::resource_ref< cuda::mr::device_accessible > device_async_resource_ref
CUDF_HOST_DEVICE constexpr decltype(auto) __forceinline__ type_dispatcher(cudf::data_type dtype, Functor f, Ts &&... args)
Invokes an operator() template with the type instantiation based on the specified cudf::data_type's i...
std::conditional_t< std::is_same_v< numeric::decimal32, T >, int32_t, std::conditional_t< std::is_same_v< numeric::decimal64, T >, int64_t, std::conditional_t< std::is_same_v< numeric::decimal128, T >, __int128_t, T > >> device_storage_type_t
"Returns" the corresponding type that is stored on the device when using cudf::column
#define CUDF_EXPECTS(...)
Macro for checking (pre-)conditions that throws an exception when a condition is violated.
Definition: error.hpp:182
cuda::std::span< T, Extent > device_span
Device span is an alias of cuda::std::span.
Definition: span.hpp:300
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:76
uint32_t bitmask_type
Bitmask type stored as 32-bit unsigned integer.
Definition: types.hpp:77
size_type distance(T f, T l)
Similar to std::distance but returns cudf::size_type and performs static_cast
Definition: types.hpp:91
#define CUDF_ENABLE_IF(...)
Convenience macro for SFINAE as an unnamed template parameter.
Definition: traits.hpp:43
Class definition for cudf::list_view.
APIs for getting and setting the current device memory resource.
cuDF interfaces
Definition: host_udf.hpp:27
bool has_nulls(table_view const &view)
Returns True if the table has nulls in any of its columns.
requires(is_index_type< IndexType >() &&is_relationally_comparable< KeyType, KeyType >()) struct dictionary_element
A type tag to specify that a column should be treated as a dictionary column.
APIs for spans.
Class definition for cudf::strings_column_view.
Class definition for cudf::struct_view.
Mutable value accessor of column without null bitmask.
T & operator()(cudf::size_type i)
Accessor.
mutable_value_accessor(mutable_column_device_view &_col)
Constructor.
mutable_column_device_view col
mutable column view of column in device
optional accessor of a column
cuda::std::optional< T > operator()(cudf::size_type i) const
Returns a cuda::std::optional of column[i].
column_device_view const col
column view of column in device
optional_accessor(column_device_view const &_col, Nullate with_nulls)
Constructor.
pair accessor of column with/without null bitmask
cuda::std::pair< T, bool > operator()(cudf::size_type i) const
Pair accessor.
column_device_view const col
column view of column in device
pair_accessor(column_device_view const &_col)
constructor
pair accessor of column with/without null bitmask
cuda::std::pair< rep_type, bool > operator()(cudf::size_type i) const
Pair accessor.
column_device_view const col
column view of column in device
device_storage_type_t< T > rep_type
representation type
pair_rep_accessor(column_device_view const &_col)
constructor
value accessor of column without null bitmask
column_device_view const col
column view of column in device
value_accessor(column_device_view const &_col)
constructor
T operator()(cudf::size_type i) const
Returns the value of element at index i
A strongly typed wrapper for indices in a DICTIONARY type column.
Definition: dictionary.hpp:39
Defines the mapping between cudf::type_id runtime type information and concrete C++ types.
#define CUDF_HOST_DEVICE
Indicates that the function or method is usable on host and device.
Definition: types.hpp:21