column_view.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2025, 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 #pragma once
17 
18 #include <cudf/types.hpp>
19 #include <cudf/utilities/error.hpp>
20 #include <cudf/utilities/span.hpp>
23 
24 #include <limits>
25 #include <type_traits>
26 #include <vector>
27 
32 namespace CUDF_EXPORT cudf {
33 namespace detail {
53  public:
70  template <typename T = void,
71  CUDF_ENABLE_IF(std::is_same_v<T, void> or is_rep_layout_compatible<T>())>
72  T const* head() const noexcept
73  {
74  return static_cast<T const*>(get_data());
75  }
76 
89  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
90  T const* data() const noexcept
91  {
92  return head<T>() + _offset;
93  }
94 
105  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
106  T const* begin() const noexcept
107  {
108  return data<T>();
109  }
110 
121  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
122  T const* end() const noexcept
123  {
124  return begin<T>() + size();
125  }
126 
132  [[nodiscard]] size_type size() const noexcept { return _size; }
133 
139  [[nodiscard]] bool is_empty() const noexcept { return size() == 0; }
140 
146  [[nodiscard]] data_type type() const noexcept { return _type; }
147 
157  [[nodiscard]] bool nullable() const noexcept { return nullptr != _null_mask; }
158 
164  [[nodiscard]] size_type null_count() const { return _null_count; }
165 
181  [[nodiscard]] size_type null_count(
182  size_type begin,
183  size_type end,
185 
193  [[nodiscard]] bool has_nulls() const { return null_count() > 0; }
194 
208  [[nodiscard]] bool has_nulls(size_type begin,
209  size_type end,
211  {
212  return null_count(begin, end, stream) > 0;
213  }
214 
223  [[nodiscard]] bitmask_type const* null_mask() const noexcept { return _null_mask; }
224 
231  [[nodiscard]] size_type offset() const noexcept { return _offset; }
232 
233  protected:
243  [[nodiscard]] virtual void const* get_data() const noexcept { return _data; }
244 
245  data_type _type{type_id::EMPTY};
246  size_type _size{};
247  void const* _data{};
248  bitmask_type const* _null_mask{};
251  mutable size_type _null_count{};
252  size_type _offset{};
254 
255  column_view_base() = default;
256  virtual ~column_view_base() = default;
257  column_view_base(column_view_base const&) = default;
271 
297  size_type size,
298  void const* data,
299  bitmask_type const* null_mask,
301  size_type offset = 0);
302 };
303 
304 } // namespace detail
305 
327  public:
328  column_view() = default;
329 
330  // these pragmas work around the nvcc issue where if a column_view is used
331  // inside of a __device__ code path, these functions will end up being created
332  // as __host__ __device__ because they are explicitly defaulted. However, if
333  // they then end up being called by a simple __host__ function
334  // (eg std::vector destructor) you get a compile error because you're trying to
335  // call a __host__ __device__ function from a __host__ function.
336 #ifdef __CUDACC__
337 #pragma nv_exec_check_disable
338 #endif
339  ~column_view() override = default;
340 #ifdef __CUDACC__
341 #pragma nv_exec_check_disable
342 #endif
343  column_view(column_view const&) = default;
344  column_view(column_view&&) = default;
350  column_view& operator=(column_view const&) = default;
357 
385  size_type size,
386  void const* data,
387  bitmask_type const* null_mask,
389  size_type offset = 0,
390  std::vector<column_view> const& children = {});
391 
398  [[nodiscard]] column_view child(size_type child_index) const noexcept
399  {
400  return _children[child_index];
401  }
402 
408  [[nodiscard]] size_type num_children() const noexcept { return _children.size(); }
409 
415  auto child_begin() const noexcept { return _children.cbegin(); }
416 
422  auto child_end() const noexcept { return _children.cend(); }
423 
432  template <typename T, CUDF_ENABLE_IF(cudf::is_numeric<T>() or cudf::is_chrono<T>())>
433  column_view(device_span<T const> data)
434  : column_view(
435  cudf::data_type{cudf::type_to_id<T>()}, data.size(), data.data(), nullptr, 0, 0, {})
436  {
437  CUDF_EXPECTS(
438  data.size() <= static_cast<std::size_t>(std::numeric_limits<cudf::size_type>::max()),
439  "Data exceeds the column size limit",
440  std::overflow_error);
441  }
442 
454  template <typename T, CUDF_ENABLE_IF(cudf::is_numeric<T>() or cudf::is_chrono<T>())>
455  [[nodiscard]] operator device_span<T const>() const
456  {
457  CUDF_EXPECTS(type() == cudf::data_type{cudf::type_to_id<T>()},
458  "Device span type must match column view type.");
459  CUDF_EXPECTS(!nullable(), "A nullable column view cannot be converted to a device span.");
460  return device_span<T const>(data<T>(), size());
461  }
462 
463  protected:
473  void const* get_data() const noexcept override;
474 
475  private:
476  friend column_view bit_cast(column_view const& input, data_type type);
477 
478  std::vector<column_view> _children{};
480 }; // namespace cudf
481 
503  public:
504  mutable_column_view() = default;
505 
506  ~mutable_column_view() override {
507  // Needed so that the first instance of the implicit destructor for any TU isn't 'constructed'
508  // from a host+device function marking the implicit version also as host+device
509  };
510 
525 
552  size_type size,
553  void* data,
554  bitmask_type* null_mask,
556  size_type offset = 0,
557  std::vector<mutable_column_view> const& children = {});
558 
574  template <typename T = void,
575  CUDF_ENABLE_IF(std::is_same_v<T, void> or is_rep_layout_compatible<T>())>
576  T* head() const noexcept
577  {
578  return const_cast<T*>(detail::column_view_base::head<T>());
579  }
580 
593  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
594  T* data() const noexcept
595  {
596  return const_cast<T*>(detail::column_view_base::data<T>());
597  }
598 
609  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
610  T* begin() const noexcept
611  {
612  return const_cast<T*>(detail::column_view_base::begin<T>());
613  }
614 
625  template <typename T, CUDF_ENABLE_IF(is_rep_layout_compatible<T>())>
626  T* end() const noexcept
627  {
628  return const_cast<T*>(detail::column_view_base::end<T>());
629  }
630 
640  [[nodiscard]] bitmask_type* null_mask() const noexcept
641  {
642  return const_cast<bitmask_type*>(detail::column_view_base::null_mask());
643  }
644 
652  void set_null_count(size_type new_null_count);
653 
660  [[nodiscard]] mutable_column_view child(size_type child_index) const noexcept
661  {
662  return mutable_children[child_index];
663  }
664 
670  [[nodiscard]] size_type num_children() const noexcept { return mutable_children.size(); }
671 
677  auto child_begin() const noexcept { return mutable_children.begin(); }
678 
684  auto child_end() const noexcept { return mutable_children.end(); }
685 
691  operator column_view() const;
692 
693  protected:
703  [[nodiscard]] void const* get_data() const noexcept override;
704 
705  private:
707 
708  std::vector<mutable_column_view> mutable_children;
709 };
710 
718 
741 
764 
765 namespace detail {
781 std::size_t shallow_hash(column_view const& input);
782 
804 bool is_shallow_equivalent(column_view const& lhs, column_view const& rhs);
805 
806 } // namespace detail
807 } // namespace CUDF_EXPORT cudf
A non-owning, immutable view of device data as a column of elements, some of which may be null as ind...
column_view(column_view &&)=default
Move constructor.
size_type num_children() const noexcept
Returns the number of child columns.
auto child_begin() const noexcept
Returns iterator to the beginning of the ordered sequence of child column-views.
column_view & operator=(column_view &&)=default
Move assignment operator.
column_view & operator=(column_view const &)=default
Copy assignment operator.
void const * get_data() const noexcept override
Returns pointer to the base device memory allocation.
auto child_end() const noexcept
Returns iterator to the end of the ordered sequence of child column-views.
column_view child(size_type child_index) const noexcept
Returns the specified child.
column_view(data_type type, size_type size, void const *data, bitmask_type const *null_mask, size_type null_count, size_type offset=0, std::vector< column_view > const &children={})
Construct a column_view from pointers to device memory for the elements and bitmask of the column.
column_view(column_view const &)=default
Copy constructor.
Indicator for the logical data type of an element in a column.
Definition: types.hpp:249
A non-owning, immutable view of device data as a column of elements, some of which may be null as ind...
Definition: column_view.hpp:52
T const * end() const noexcept
Return one past the last element after underlying data is casted to the specified type.
data_type type() const noexcept
Returns the element data_type
bool has_nulls(size_type begin, size_type end, rmm::cuda_stream_view stream=cudf::get_default_stream()) const
Indicates if the column contains null elements in the range [begin, end), i.e., null_count(begin,...
column_view_base(column_view_base &&)=default
Move constructor.
column_view_base(data_type type, size_type size, void const *data, bitmask_type const *null_mask, size_type null_count, size_type offset=0)
Construct a column_view_base from pointers to device memory for the elements and bitmask of the colum...
size_type null_count() const
Returns the count of null elements.
size_type null_count(size_type begin, size_type end, rmm::cuda_stream_view stream=cudf::get_default_stream()) const
Returns the count of null elements in the range [begin, end)
column_view_base & operator=(column_view_base const &)=default
Copy assignment operator.
column_view_base & operator=(column_view_base &&)=default
Move assignment operator.
size_type size() const noexcept
Returns the number of elements in the column.
T const * begin() const noexcept
Return first element (accounting for offset) after underlying data is casted to the specified type.
T const * data() const noexcept
Returns the underlying data casted to the specified type, plus the offset.
Definition: column_view.hpp:90
size_type offset() const noexcept
Returns the index of the first element relative to the base memory allocation, i.e....
virtual void const * get_data() const noexcept
Returns pointer to the base device memory allocation.
T const * head() const noexcept
Returns pointer to the base device memory allocation casted to the specified type.
Definition: column_view.hpp:72
bool has_nulls() const
Indicates if the column contains null elements, i.e., null_count() > 0
bitmask_type const * null_mask() const noexcept
Returns raw pointer to the underlying bitmask allocation.
bool nullable() const noexcept
Indicates if the column can contain null elements, i.e., if it has an allocated bitmask.
column_view_base(column_view_base const &)=default
Copy constructor.
bool is_empty() const noexcept
Returns true if size() returns zero, or false otherwise.
A non-owning, mutable view of device data as a column of elements, some of which may be null as indic...
T * head() const noexcept
Returns pointer to the base device memory allocation casted to the specified type.
size_type num_children() const noexcept
Returns the number of child columns.
T * begin() const noexcept
Return first element (accounting for offset) after underlying data is casted to the specified type.
void set_null_count(size_type new_null_count)
Set the null count.
auto child_begin() const noexcept
Returns iterator to the beginning of the ordered sequence of child column-views.
mutable_column_view(data_type type, size_type size, void *data, bitmask_type *null_mask, size_type null_count, size_type offset=0, std::vector< mutable_column_view > const &children={})
Construct a mutable_column_view from pointers to device memory for the elements and bitmask of the co...
T * data() const noexcept
Returns the underlying data casted to the specified type, plus the offset.
mutable_column_view(mutable_column_view const &)=default
Copy constructor.
mutable_column_view & operator=(mutable_column_view &&)=default
Move assignment operator.
mutable_column_view & operator=(mutable_column_view const &)=default
Copy assignment operator.
auto child_end() const noexcept
Returns iterator to the end of the ordered sequence of child column-views.
bitmask_type * null_mask() const noexcept
Returns raw pointer to the underlying bitmask allocation.
void const * get_data() const noexcept override
Returns pointer to the base device memory allocation.
mutable_column_view child(size_type child_index) const noexcept
Returns a reference to the specified child.
mutable_column_view(mutable_column_view &&)=default
Move constructor.
T * end() const noexcept
Return one past the last element after underlying data is casted to the specified type.
std::size_t shallow_hash(column_view const &input)
Computes a hash value from the shallow state of the specified column.
bool is_shallow_equivalent(column_view const &lhs, column_view const &rhs)
Uses only shallow state to determine if two column_views view equivalent columns.
cudf::size_type null_count(bitmask_type const *bitmask, size_type start, size_type stop, rmm::cuda_stream_view stream=cudf::get_default_stream())
Given a validity bitmask, counts the number of null elements (unset bits) in the range [start,...
rmm::cuda_stream_view const get_default_stream()
Get the current default stream.
#define CUDF_EXPECTS(...)
Macro for checking (pre-)conditions that throws an exception when a condition is violated.
Definition: error.hpp:154
int32_t size_type
Row index type for columns and tables.
Definition: types.hpp:95
uint32_t bitmask_type
Bitmask type stored as 32-bit unsigned integer.
Definition: types.hpp:96
constexpr CUDF_HOST_DEVICE bool is_chrono()
Indicates whether the type T is a chrono type.
Definition: traits.hpp:501
#define CUDF_ENABLE_IF(...)
Convenience macro for SFINAE as an unnamed template parameter.
Definition: traits.hpp:50
cuDF interfaces
Definition: host_udf.hpp:37
bool nullable(table_view const &view)
Returns True if any of the columns in the table is nullable. (not entire hierarchy)
mutable_column_view bit_cast(mutable_column_view const &input, data_type type)
Zero-copy cast between types with the same size and compatible underlying representations.
size_type count_descendants(column_view parent)
Counts the number of descendants of the specified parent.
APIs for spans.
Device version of C++20 std::span with reduced feature set.
Definition: span.hpp:355
Defines the mapping between cudf::type_id runtime type information and concrete C++ types.
Type declarations for libcudf.