Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract Syntax Tree Cleanup and Tests #7418

Merged
merged 22 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c2cec05
Large unit tests
codereport Feb 22, 2021
1eae304
Move AST plan initialization to ctor
codereport Feb 22, 2021
5af4c59
AST Plan docs + more cleanup
codereport Feb 22, 2021
6ce1add
Calculate offsets once
codereport Feb 23, 2021
ae896e5
Move more work to AST ctor, currently failing
codereport Feb 24, 2021
393cdb2
temp
codereport Mar 2, 2021
1697eb3
Merge branch 'branch-0.20' into ast-tests-cleanup
codereport Apr 8, 2021
33ce7cf
Merge remote-tracking branch 'origin/branch-0.20' into ast-tests-cleanup
vyasr Apr 17, 2021
c9315c5
Keep device buffer from going out of scope before compute.
vyasr Apr 17, 2021
314358b
Clean up comments.
vyasr Apr 19, 2021
9c004d0
Inline offset and host buffer creation.
vyasr Apr 19, 2021
2534773
Remove preprocessor elided code.
vyasr Apr 19, 2021
97e84f2
Merge remote-tracking branch 'origin/branch-0.20' into ast-tests-cleanup
vyasr Apr 21, 2021
f924671
Remove unnecessary forward declarations and friend relationships betw…
vyasr Apr 21, 2021
459eae1
Add more informative comment for why r-value expression constructors …
vyasr Apr 21, 2021
33bf98d
Move linearizer.hpp to nodes.hpp.
vyasr Apr 21, 2021
8781a3b
Make ast plan internals public and use them directly.
vyasr Apr 21, 2021
4ed23dd
Apply rename in meta.yaml.
vyasr Apr 21, 2021
8931591
Merge branch 'branch-0.20' into ast-tests-cleanup
vyasr May 3, 2021
f0a5c66
Change raw pointers in ast_plan to span.
vyasr May 3, 2021
d2a5e8b
Pass the spans through the code.
vyasr May 3, 2021
98b219a
Address PR comments.
vyasr May 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conda/recipes/libcudf/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ test:
- test -f $PREFIX/include/cudf/ast/transform.hpp
- test -f $PREFIX/include/cudf/ast/detail/linearizer.hpp
- test -f $PREFIX/include/cudf/ast/detail/operators.hpp
- test -f $PREFIX/include/cudf/ast/linearizer.hpp
- test -f $PREFIX/include/cudf/ast/nodes.hpp
- test -f $PREFIX/include/cudf/ast/operators.hpp
- test -f $PREFIX/include/cudf/binaryop.hpp
- test -f $PREFIX/include/cudf/labeling/label_bins.hpp
Expand Down
9 changes: 1 addition & 8 deletions cpp/include/cudf/ast/detail/linearizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ class linearizer;
* This class is a part of a "visitor" pattern with the `linearizer` class.
* Nodes inheriting from this class can accept visitors.
*/
class node {
friend class detail::linearizer;

private:
struct node {
virtual cudf::size_type accept(detail::linearizer& visitor) const = 0;
};

Expand All @@ -102,10 +99,6 @@ class node {
* resolved into intermediate data storage in shared memory.
*/
class linearizer {
friend class literal;
friend class column_reference;
friend class expression;

public:
/**
* @brief Construct a new linearizer object
Expand Down
47 changes: 0 additions & 47 deletions cpp/include/cudf/ast/detail/operators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,43 +753,6 @@ struct operator_functor<ast_operator::NOT> {
}
};

#if 0
/**
* @brief Functor used to double-type-dispatch binary operators.
*
* This functor's `operator()` is templated to validate calls to its operators based on the input
* type, as determined by the `is_valid_binary_op` trait.
*
* @tparam OperatorFunctor Binary operator functor.
*/
template <typename OperatorFunctor>
struct double_dispatch_binary_operator_types {
template <typename LHS,
typename RHS,
typename F,
typename... Ts,
std::enable_if_t<is_valid_binary_op<OperatorFunctor, LHS, RHS>>* = nullptr>
CUDA_HOST_DEVICE_CALLABLE void operator()(F&& f, Ts&&... args)
{
f.template operator()<OperatorFunctor, LHS, RHS>(std::forward<Ts>(args)...);
}

template <typename LHS,
typename RHS,
typename F,
typename... Ts,
std::enable_if_t<!is_valid_binary_op<OperatorFunctor, LHS, RHS>>* = nullptr>
CUDA_HOST_DEVICE_CALLABLE void operator()(F&& f, Ts&&... args)
{
#ifndef __CUDA_ARCH__
CUDF_FAIL("Invalid binary operation.");
#else
cudf_assert(false && "Invalid binary operation.");
#endif
}
};
#endif

/**
* @brief Functor used to single-type-dispatch binary operators.
*
Expand Down Expand Up @@ -856,16 +819,6 @@ struct type_dispatch_binary_op {
F&& f,
Ts&&... args)
{
#if 0
// Double dispatch
/*
double_type_dispatcher(lhs_type,
rhs_type,
detail::double_dispatch_binary_operator_types<operator_functor<op>>{},
std::forward<F>(f),
std::forward<Ts>(args)...);
*/
#endif
// Single dispatch (assume lhs_type == rhs_type)
type_dispatcher(lhs_type,
detail::single_dispatch_binary_operator_types<operator_functor<op>>{},
Expand Down
90 changes: 61 additions & 29 deletions cpp/include/cudf/ast/detail/transform.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
*/
#pragma once

#include <cudf/ast/detail/linearizer.hpp>
#include <cudf/ast/detail/operators.hpp>
#include <cudf/ast/linearizer.hpp>
#include <cudf/ast/nodes.hpp>
#include <cudf/ast/operators.hpp>
#include <cudf/column/column_device_view.cuh>
#include <cudf/column/column_factories.hpp>
Expand Down Expand Up @@ -305,8 +306,8 @@ __device__ void evaluate_row_expression(detail::row_evaluator const& evaluator,
cudf::size_type num_operators,
cudf::size_type row_index)
{
auto operator_source_index = cudf::size_type(0);
for (cudf::size_type operator_index(0); operator_index < num_operators; operator_index++) {
auto operator_source_index = static_cast<cudf::size_type>(0);
for (cudf::size_type operator_index = 0; operator_index < num_operators; operator_index++) {
// Execute operator
auto const op = operators[operator_index];
auto const arity = ast_operator_arity(op);
Expand Down Expand Up @@ -336,41 +337,72 @@ __device__ void evaluate_row_expression(detail::row_evaluator const& evaluator,
}
}

/**
* @brief The AST plan creates a device buffer of data needed to execute an AST.
*
* On construction, an AST plan creates a single "packed" host buffer of all necessary data arrays,
* and copies that to the device with a single host-device memory copy. Because the plan tends to be
* small, this is the most efficient approach for low latency.
*
*/
struct ast_plan {
public:
ast_plan() : sizes(), data_pointers() {}

using buffer_type = std::pair<std::unique_ptr<char[]>, int>;
ast_plan(linearizer const& expr_linearizer,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr)
: _sizes{}, _data_pointers{}
{
add_to_plan(expr_linearizer.data_references());
add_to_plan(expr_linearizer.literals());
add_to_plan(expr_linearizer.operators());
add_to_plan(expr_linearizer.operator_source_indices());

// Create device buffer
auto const buffer_size = std::accumulate(_sizes.cbegin(), _sizes.cend(), 0);
auto buffer_offsets = std::vector<int>(_sizes.size());
thrust::exclusive_scan(_sizes.cbegin(), _sizes.cend(), buffer_offsets.begin(), 0);

auto h_data_buffer = std::make_unique<char[]>(buffer_size);
for (unsigned int i = 0; i < _data_pointers.size(); ++i)
std::memcpy(h_data_buffer.get() + buffer_offsets[i], _data_pointers[i], _sizes[i]);
vyasr marked this conversation as resolved.
Show resolved Hide resolved

_device_data_buffer = rmm::device_buffer(h_data_buffer.get(), buffer_size, stream, mr);

stream.synchronize();

// Create device pointers to components of plan
auto device_data_buffer_ptr = static_cast<const char*>(_device_data_buffer.data());
_device_data_references = reinterpret_cast<const detail::device_data_reference*>(
device_data_buffer_ptr + buffer_offsets[0]);
_device_literals = reinterpret_cast<const cudf::detail::fixed_width_scalar_device_view_base*>(
device_data_buffer_ptr + buffer_offsets[1]);
_device_operators =
reinterpret_cast<const ast_operator*>(device_data_buffer_ptr + buffer_offsets[2]);
_device_operator_source_indices =
reinterpret_cast<const cudf::size_type*>(device_data_buffer_ptr + buffer_offsets[3]);
}

/**
* @brief Helper function for adding components (operators, literals, etc) to AST plan
*
* @tparam T The underlying type of the input `std::vector`
* @param v The `std::vector` containing components (operators, literals, etc)
*/
template <typename T>
void add_to_plan(std::vector<T> const& v)
{
auto const data_size = sizeof(T) * v.size();
sizes.push_back(data_size);
data_pointers.push_back(v.data());
_sizes.push_back(data_size);
_data_pointers.push_back(v.data());
}

buffer_type get_host_data_buffer() const
{
auto const total_size = std::accumulate(sizes.cbegin(), sizes.cend(), 0);
auto host_data_buffer = std::make_unique<char[]>(total_size);
auto const offsets = get_offsets();
for (unsigned int i = 0; i < data_pointers.size(); ++i) {
std::memcpy(host_data_buffer.get() + offsets[i], data_pointers[i], sizes[i]);
}
return std::make_pair(std::move(host_data_buffer), total_size);
}
std::vector<cudf::size_type> _sizes;
std::vector<const void*> _data_pointers;

std::vector<cudf::size_type> get_offsets() const
{
auto offsets = std::vector<int>(sizes.size());
thrust::exclusive_scan(sizes.cbegin(), sizes.cend(), offsets.begin(), 0);
return offsets;
}

private:
std::vector<cudf::size_type> sizes;
std::vector<const void*> data_pointers;
rmm::device_buffer _device_data_buffer;
const detail::device_data_reference* _device_data_references;
const cudf::detail::fixed_width_scalar_device_view_base* _device_literals;
const ast_operator* _device_operators;
const cudf::size_type* _device_operator_source_indices;
vyasr marked this conversation as resolved.
Show resolved Hide resolved
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,10 @@ enum class table_reference {
OUTPUT // Column index in the output table
};

// Forward declaration
class literal;
class column_reference;
class expression;

/**
* @brief A literal value used in an abstract syntax tree.
*/
class literal : public detail::node {
friend class detail::linearizer;

public:
/**
* @brief Construct a new literal object.
Expand Down Expand Up @@ -90,7 +83,6 @@ class literal : public detail::node {
*/
cudf::data_type get_data_type() const { return get_value().type(); }

private:
/**
* @brief Get the value object.
*
Expand All @@ -106,15 +98,14 @@ class literal : public detail::node {
*/
cudf::size_type accept(detail::linearizer& visitor) const override;

private:
const cudf::detail::fixed_width_scalar_device_view_base value;
};

/**
* @brief A node referring to data from a column in a table.
*/
class column_reference : public detail::node {
friend class detail::linearizer;

public:
/**
* @brief Construct a new column reference object
Expand Down Expand Up @@ -175,7 +166,6 @@ class column_reference : public detail::node {
return table.column(get_column_index()).type();
}

private:
/**
* @brief Accepts a visitor class.
*
Expand All @@ -184,6 +174,7 @@ class column_reference : public detail::node {
*/
cudf::size_type accept(detail::linearizer& visitor) const override;

private:
cudf::size_type column_index;
table_reference table_source;
};
Expand All @@ -192,8 +183,6 @@ class column_reference : public detail::node {
* @brief An expression node holds an operator and zero or more operands.
*/
class expression : public detail::node {
friend class detail::linearizer;

public:
/**
* @brief Construct a new unary expression object.
Expand All @@ -208,11 +197,6 @@ class expression : public detail::node {
}
}

/**
* @brief `expression` doesn't accept r-value references for expression nodes
*/
expression(ast_operator op, node&& input) = delete;

/**
* @brief Construct a new binary expression object.
*
Expand All @@ -227,19 +211,11 @@ class expression : public detail::node {
}
}

/**
* @brief `expression` doesn't accept r-value references for expression nodes
*/
expression(ast_operator op, node&& left, node&& right) = delete;

/**
* @brief `expression` doesn't accept r-value references for expression nodes
*/
// expression only stores references to nodes, so it does not accept r-value
// references: the calling code must own the nodes.
expression(ast_operator op, node&& input) = delete;
expression(ast_operator op, node&& left, node&& right) = delete;
expression(ast_operator op, node&& left, node const& right) = delete;

/**
* @brief `expression` doesn't accept r-value references for expression nodes
*/
expression(ast_operator op, node const& left, node&& right) = delete;

/**
Expand All @@ -256,7 +232,6 @@ class expression : public detail::node {
*/
std::vector<std::reference_wrapper<const node>> get_operands() const { return operands; }

private:
/**
* @brief Accepts a visitor class.
*
Expand All @@ -265,6 +240,7 @@ class expression : public detail::node {
*/
cudf::size_type accept(detail::linearizer& visitor) const override;

private:
const ast_operator op;
const std::vector<std::reference_wrapper<const node>> operands;
};
Expand Down
2 changes: 1 addition & 1 deletion cpp/include/cudf/ast/transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
#pragma once

#include <cudf/ast/linearizer.hpp>
#include <cudf/ast/nodes.hpp>
#include <cudf/table/table_view.hpp>

namespace cudf {
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/ast/linearizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/
#include <cudf/ast/detail/linearizer.hpp>
#include <cudf/ast/linearizer.hpp>
#include <cudf/ast/nodes.hpp>
#include <cudf/ast/operators.hpp>
#include <cudf/scalar/scalar.hpp>
#include <cudf/scalar/scalar_device_view.cuh>
Expand Down
Loading