expressions.hpp
转到此文件的文档。
1 /*
2  * Copyright (c) 2020-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  * https://apache.ac.cn/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/scalar/scalar.hpp>
21 #include <cudf/types.hpp>
22 #include <cudf/utilities/error.hpp>
23 
24 #include <cstdint>
25 #include <memory>
26 #include <vector>
27 
28 namespace CUDF_EXPORT cudf {
29 namespace ast {
36 // Forward declaration.
37 namespace detail {
38 class expression_parser;
39 class expression_transformer;
40 } // namespace detail
41 
48 struct expression {
55  virtual cudf::size_type accept(detail::expression_parser& visitor) const = 0;
56 
63  virtual std::reference_wrapper<expression const> accept(
64  detail::expression_transformer& visitor) const = 0;
65 
73  [[nodiscard]] bool may_evaluate_null(table_view const& left, rmm::cuda_stream_view stream) const
74  {
75  return may_evaluate_null(left, left, stream);
76  }
77 
86  [[nodiscard]] virtual bool may_evaluate_null(table_view const& left,
87  table_view const& right,
88  rmm::cuda_stream_view stream) const = 0;
89 
90  virtual ~expression() {}
91 };
92 
96 enum class ast_operator : int32_t {
97  // Binary operators
98  ADD,
99  SUB,
100  MUL,
101  DIV,
102  TRUE_DIV,
103  FLOOR_DIV,
105  MOD,
106  PYMOD,
107  POW,
108  EQUAL,
109  NULL_EQUAL,
112  NOT_EQUAL,
113  LESS,
114  GREATER,
115  LESS_EQUAL,
117  BITWISE_AND,
118  BITWISE_OR,
119  BITWISE_XOR,
120  LOGICAL_AND,
125  LOGICAL_OR,
130  // Unary operators
131  IDENTITY,
132  IS_NULL,
133  SIN,
134  COS,
135  TAN,
136  ARCSIN,
137  ARCCOS,
138  ARCTAN,
139  SINH,
140  COSH,
141  TANH,
142  ARCSINH,
143  ARCCOSH,
144  ARCTANH,
145  EXP,
146  LOG,
147  SQRT,
148  CBRT,
149  CEIL,
150  FLOOR,
151  ABS,
152  RINT,
153  BIT_INVERT,
154  NOT,
158 };
159 
165 enum class table_reference {
166  LEFT,
167  RIGHT,
168  OUTPUT
169 };
170 
175  public
182  template <typename T>
183  __device__ T const value() const noexcept
184  {
185  if constexpr (std::is_same_v<T, cudf::string_view>) {
186  return string_view(static_cast<char const*>(_data), _size);
187  }
188  return *static_cast<T const*>(_data);
189  }
190 
195  template <typename T>
197  : generic_scalar_device_view(s.type(), s.data(), s.validity_data())
198  {
199  }
200 
205  template <typename T>
207  : generic_scalar_device_view(s.type(), s.data(), s.validity_data())
208  {
209  }
210 
215  template <typename T>
217  : generic_scalar_device_view(s.type(), s.data(), s.validity_data())
218  {
219  }
220 
226  : generic_scalar_device_view(s.type(), s.data(), s.validity_data(), s.size())
227  {
228  }
229 
230  protected
231  void const* _data{};
232  size_type const _size{};
233 
242  generic_scalar_device_view(data_type type, void const* data, bool* is_valid)
243  : cudf::detail::scalar_device_view_base(type, is_valid), _data(data)
244  {
245  }
246 
255  generic_scalar_device_view(data_type type, void const* data, bool* is_valid, size_type size)
256  : cudf::detail::scalar_device_view_base(type, is_valid), _data(data), _size(size)
257  {
258  }
259 };
260 
264 class literal : public expression {
265  public
272  template <typename T>
273  literal(cudf::numeric_scalar<T>& value) : scalar(value), value(value)
274  {
275  }
276 
283  template <typename T>
284  literal(cudf::timestamp_scalar<T>& value) : scalar(value), value(value)
285  {
286  }
287 
294  template <typename T>
295  literal(cudf::duration_scalar<T>& value) : scalar(value), value(value)
296  {
297  }
298 
304  literal(cudf::string_scalar& value) : scalar(value), value(value) {}
305 
311  [[nodiscard]] cudf::data_type get_data_type() const { return get_value().type(); }
312 
318  [[nodiscard]] generic_scalar_device_view get_value() const { return value; }
319 
323  cudf::size_type accept(detail::expression_parser& visitor) const override;
324 
328  std::reference_wrapper<expression const> accept(
329  detail::expression_transformer& visitor) const override;
330 
331  [[nodiscard]] bool may_evaluate_null(table_view const& left,
332  table_view const& right,
333  rmm::cuda_stream_view stream) const override
334  {
335  return !is_valid(stream);
336  }
337 
344  [[nodiscard]] bool is_valid(rmm::cuda_stream_view stream) const
345  {
346  return scalar.is_valid(stream);
347  }
348 
349  private
350  cudf::scalar const& scalar;
351  generic_scalar_device_view const value;
352 };
353 
357 class column_reference : public expression {
358  public
367  table_reference table_source = table_reference::LEFT)
368  : column_index(column_index), table_source(table_source)
369  {
370  }
371 
377  [[nodiscard]] cudf::size_type get_column_index() const { return column_index; }
378 
384  [[nodiscard]] table_reference get_table_source() const { return table_source; }
385 
392  [[nodiscard]] cudf::data_type get_data_type(table_view const& table) const
393  {
394  return table.column(get_column_index()).type();
395  }
396 
404  [[nodiscard]] cudf::data_type get_data_type(table_view const& left_table,
405  table_view const& right_table) const
406  {
407  auto const table = [&] {
408  if (get_table_source() == table_reference::LEFT) {
409  return left_table;
410  } else if (get_table_source() == table_reference::RIGHT) {
411  return right_table;
412  } else {
413  CUDF_FAIL("Column reference data type cannot be determined from unknown table.");
414  }
415  }();
416  return table.column(get_column_index()).type();
417  }
418 
422  cudf::size_type accept(detail::expression_parser& visitor) const override;
423 
427  std::reference_wrapper<expression const> accept(
428  detail::expression_transformer& visitor) const override;
429 
430  [[nodiscard]] bool may_evaluate_null(table_view const& left,
431  table_view const& right,
432  rmm::cuda_stream_view stream) const override
433  {
434  return (table_source == table_reference::LEFT ? left : right).column(column_index).has_nulls();
435  }
436 
437  private
438  cudf::size_type column_index;
439  table_reference table_source;
440 };
441 
445 class operation : public expression {
446  public
453  operation(ast_operator op, expression const& input);
454 
462  operation(ast_operator op, expression const& left, expression const& right);
463 
464  // operation only stores references to expressions, so it does not accept r-value
465  // references: the calling code must own the expressions.
466  operation(ast_operator op, expression&& input) = delete;
467  operation(ast_operator op, expression&& left, expression&& right) = delete;
468  operation(ast_operator op, expression&& left, expression const& right) = delete;
469  operation(ast_operator op, expression const& left, expression&& right) = delete;
470 
476  [[nodiscard]] ast_operator get_operator() const { return op; }
477 
483  [[nodiscard]] std::vector<std::reference_wrapper<expression const>> const& get_operands() const
484  {
485  return operands;
486  }
487 
491  cudf::size_type accept(detail::expression_parser& visitor) const override;
492 
496  std::reference_wrapper<expression const> accept(
497  detail::expression_transformer& visitor) const override;
498 
499  [[nodiscard]] bool may_evaluate_null(table_view const& left,
500  table_view const& right,
501  rmm::cuda_stream_view stream) const override
502  {
503  return std::any_of(operands.cbegin(),
504  operands.cend(),
505  [&left, &right, &stream](std::reference_wrapper<expression const> subexpr) {
506  return subexpr.get().may_evaluate_null(left, right, stream);
507  });
508  };
509 
510  private
511  ast_operator op;
512  std::vector<std::reference_wrapper<expression const>> operands;
513 };
514 
519  public
526  column_name_reference(std::string column_name) : column_name(std::move(column_name)) {}
527 
533  [[nodiscard]] std::string get_column_name() const { return column_name; }
534 
538  cudf::size_type accept(detail::expression_parser& visitor) const override;
539 
543  std::reference_wrapper<expression const> accept(
544  detail::expression_transformer& visitor) const override;
545 
546  [[nodiscard]] bool may_evaluate_null(table_view const& left,
547  table_view const& right,
548  rmm::cuda_stream_view stream) const override
549  {
550  return true;
551  }
552 
553  private
554  std::string column_name;
555 };
556 
561 class tree {
562  public
566  tree() = default;
571  tree(tree&&) = default;
572 
577  tree& operator=(tree&&) = default;
578 
579  ~tree() = default;
580 
581  // the tree is not copyable
582  tree(tree const&) = delete;
583  tree& operator=(tree const&) = delete;
584 
590  template <typename Expr, typename... Args>
591  std::enable_if_t<std::is_base_of_v<expression, Expr>, Expr const&> emplace(Args&&... args)
592  {
593  auto expr = std::make_unique<Expr>(std::forward<Args>(args)...);
594  Expr const& expr_ref = *expr;
595  expressions.emplace_back(std::move(expr));
596  return expr_ref;
597  }
598 
604  template <typename Expr>
605  decltype(auto) push(Expr expr)
606  {
607  return emplace<Expr>(std::move(expr));
608  }
609 
614  [[nodiscard]] expression const& front() const { return *expressions.front(); }
615 
620  [[nodiscard]] expression const& back() const { return *expressions.back(); }
621 
626  [[nodiscard]] size_t size() const { return expressions.size(); }
627 
633  expression const& at(size_t index) { return *expressions.at(index); }
634 
640  expression const& operator[](size_t index) const { return *expressions[index]; }
641 
642  private
643  // TODO: use better ownership semantics, the unique_ptr here is redundant. Consider using a bump
644  // allocator with type-erased deleters.
645  std::vector<std::unique_ptr<expression>> expressions;
646 };
647  // end of group
649 } // namespace ast
650 
651 } // namespace CUDF_EXPORT cudf
cudf::ast::column_name_reference
cudf::ast::column_name_reference::accept
接受一个访问者类。
cudf::ast::column_name_reference::may_evaluate_null
如果表达式可能计算为 null,则返回 true。
cudf::ast::column_name_reference::get_column_name
获取列名。
std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const override
cudf::ast::column_name_reference::column_name_reference
cudf::ast::column_name_reference::may_evaluate_null
构造新的列名引用对象。
cudf::ast::column_reference
cudf::ast::column_reference::may_evaluate_null
如果表达式可能计算为 null,则返回 true。
cudf::ast::column_reference::get_data_type
接受一个访问者类。
cudf::ast::column_name_reference::may_evaluate_null
cudf::ast::column_name_reference::column_name_reference
cudf::ast::column_name_reference::may_evaluate_null
获取表来源。
cudf::ast::column_reference::column_reference
构造新的列引用对象。
cudf::ast::column_reference::get_column_index
获取列索引。
cudf::ast::generic_scalar_device_view
cudf::ast::generic_scalar_device_view::generic_scalar_device_view
从 duration scalar 构造新的通用 scalar device view 对象。
generic_scalar_device_view(data_type type, void const *data, bool *is_valid)
构造新的固定宽度 scalar device view 对象。
generic_scalar_device_view(string_scalar &s)
从 string scalar 构造新的通用 scalar device view 对象。
generic_scalar_device_view(timestamp_scalar< T > &s)
从 timestamp scalar 构造新的通用 scalar device view 对象。
generic_scalar_device_view(data_type type, void const *data, bool *is_valid, size_type size)
构造新的 string scalar device view 对象。
cudf::ast::generic_scalar_device_view::value
返回存储的值。
generic_scalar_device_view(numeric_scalar< T > &s)
从 numeric scalar 构造新的通用 scalar device view 对象。
cudf::ast::literal
构造新的字面值对象。
cudf::ast::literal::accept
接受一个访问者类。
cudf::ast::column_name_reference::may_evaluate_null
获取值对象。
cudf::ast::literal::get_data_type
literal(cudf::string_scalar &value)
literal(cudf::duration_scalar< T > &value)
检查底层 scalar 是否有效。
cudf::ast::literal::may_evaluate_null
cudf::ast::column_name_reference::column_name_reference
cudf::ast::column_name_reference::may_evaluate_null
如果表达式可能计算为 null,则返回 true。
literal(cudf::timestamp_scalar< T > &value)
如果表达式可能计算为 null,则返回 true。
cudf::ast::operation::get_operands
获取运算符。
cudf::ast::operation::operation
构造新的二元操作对象。
cudf::ast::operation::accept
cudf::ast::column_name_reference::column_name_reference
cudf::ast::column_name_reference::may_evaluate_null
接受一个访问者类。
cudf::ast::column_name_reference::may_evaluate_null
移动 AST 树。
cudf::ast::tree::operator=
移动赋值 AST 树
cudf::ast::tree::size
获取添加到树中的表达式数量
cudf::ast::tree::emplace
构造一个空的 AST 树
cudf::ast::tree::front
获取树中的第一个表达式
cudf::ast::tree::at
获取树中指定索引处的表达式。索引会被检查。
cudf::ast::tree::back
获取树中的最后一个表达式
cudf::ast::tree::operator[]
获取树中指定索引处的表达式。索引不会被检查。
cudf::data_type
定义: types.hpp:243
cudf::detail::scalar_device_view_base
表示设备内存中数值的拥有者类。
定义: scalar.hpp:239
表示单一值的拥有者类。
定义: scalar.hpp:51
bool is_valid(rmm::cuda_stream_view stream=cudf::get_default_stream()) const
指示标量是否包含有效值。
表示设备内存中字符串的拥有者类。
定义: scalar.hpp:421
设备数据的非拥有、不可变视图,是一个表示UTF-8的可变长度字符数组...
一组大小相同的 cudf::column_view。
一组大小相同的 cudf::column。
定义: table.hpp:40
表示设备内存中时间戳值的拥有者类。
定义: scalar.hpp:611
table_reference
表格引用的枚举。
ast_operator
支持的操作符枚举。
@ RIGHT
右表中的列索引。
@ OUTPUT
输出表中的列索引。
@ LEFT
左表中的列索引。
@ LOGICAL_OR
操作符 ||
@ TANH
双曲正切。
@ DIV
使用 lhs 和 rhs 的公共类型进行操作符 /
@ CBRT
立方根 (x^(1.0/3))
@ ARCSINH
反双曲正弦。
@ SQRT
平方根 (x^0.5)
@ PYMOD
使用 Python 的负数符号规则进行操作符 %
@ LOG
自然对数(底数为 e)
@ NOT_EQUAL
操作符 !=
@ FLOOR
不大于 arg 的最大整数值
@ CEIL
不小于 arg 的最小整数值。
@ RINT
将浮点参数 arg 四舍五入到整数值。
@ BIT_INVERT
按位非 (~)
@ BITWISE_XOR
操作符 ^
@ ARCTANH
反双曲正切。
@ GREATER_EQUAL
操作符 >=
@ LESS_EQUAL
操作符 <=
@ EXP
指数(底数为 e,欧拉数)
@ CAST_TO_FLOAT64
将值转换为 double。
@ TRUE_DIV
将类型提升为浮点后进行操作符 /
@ LOGICAL_AND
操作符 &&
@ BITWISE_AND
操作符 &
@ SINH
双曲正弦。
@ CAST_TO_UINT64
将值转换为 uint64_t。
@ COSH
双曲余弦。
@ ARCCOSH
反双曲余弦。
@ IDENTITY
恒等函数。
@ IS_NULL
检查操作数是否为空。
@ CAST_TO_INT64
将值转换为 int64_t。
std::unique_ptr< cudf::column > is_valid(cudf::column_view const &input, rmm::cuda_stream_view stream=cudf::get_default_stream(), rmm::device_async_resource_ref mr=cudf::get_current_device_resource_ref())
创建一个 type_id::BOOL8 元素的列,其中对于 input 中的每个元素,true 表示值...
#define CUDF_FAIL(...)
指示已执行错误的码路径。
定义: error.hpp:217
int32_t size_type
列和表格的行索引类型。
定义: types.hpp:95
cuDF 接口
定义: host_udf.hpp:37
cudf::scalar 的类定义。
标量设备视图类定义。
可以求值以返回值的通用表达式。
bool may_evaluate_null(table_view const &left, rmm::cuda_stream_view stream) const
virtual cudf::size_type accept(detail::expression_parser &visitor) const =0
cudf::ast::column_name_reference::may_evaluate_null
virtual std::reference_wrapper< expression const > accept(detail::expression_transformer &visitor) const =0
cudf::ast::column_name_reference::may_evaluate_null
virtual bool may_evaluate_null(table_view const &left, table_view const &right, rmm::cuda_stream_view stream) const =0
(mutable)_table_view 的类定义
libcudf 的类型声明。