From 012caf89988533b241d0208a682558027ffcd02b Mon Sep 17 00:00:00 2001 From: Alfred Xu Date: Fri, 6 Aug 2021 14:40:03 +0800 Subject: [PATCH] Fix concatenate empty structs (#8947) Closes #8929 Current PR is to fix the illegal memory access problem occurred when concatenating structs with empty children. Authors: - Alfred Xu (https://github.com/sperlingxx) Approvers: - Nghia Truong (https://github.com/ttnghia) - Mike Wilson (https://github.com/hyperbolic2346) URL: https://github.com/rapidsai/cudf/pull/8947 --- cpp/src/structs/copying/concatenate.cu | 7 ++++++- cpp/tests/copying/concatenate_tests.cu | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cpp/src/structs/copying/concatenate.cu b/cpp/src/structs/copying/concatenate.cu index 6f18c4bcbd4..fe5483b119d 100644 --- a/cpp/src/structs/copying/concatenate.cu +++ b/cpp/src/structs/copying/concatenate.cu @@ -28,6 +28,7 @@ #include #include +#include namespace cudf { namespace structs { @@ -53,7 +54,11 @@ std::unique_ptr concatenate(host_span columns, return cudf::detail::concatenate(cols, stream, mr); }); - size_type const total_length = children[0]->size(); + // get total length from concatenated children; if no child exists, we would compute it + auto const acc_size_fn = [](size_type s, column_view const& c) { return s + c.size(); }; + auto const total_length = + !children.empty() ? children[0]->size() + : std::accumulate(columns.begin(), columns.end(), size_type{0}, acc_size_fn); // if any of the input columns have nulls, construct the output mask bool const has_nulls = diff --git a/cpp/tests/copying/concatenate_tests.cu b/cpp/tests/copying/concatenate_tests.cu index 7d3b7beb2cb..5237c75e4d4 100644 --- a/cpp/tests/copying/concatenate_tests.cu +++ b/cpp/tests/copying/concatenate_tests.cu @@ -826,6 +826,22 @@ TEST_F(StructsColumnTest, ConcatenateStructs) cudf::test::expect_columns_equivalent(*result, *expected); } +TEST_F(StructsColumnTest, ConcatenateEmptyStructs) +{ + using namespace cudf::test; + + auto expected = cudf::make_structs_column(10, {}, 0, rmm::device_buffer()); + auto first = cudf::make_structs_column(5, {}, 0, rmm::device_buffer()); + auto second = cudf::make_structs_column(2, {}, 0, rmm::device_buffer()); + auto third = cudf::make_structs_column(0, {}, 0, rmm::device_buffer()); + auto fourth = cudf::make_structs_column(3, {}, 0, rmm::device_buffer()); + + // concatenate + auto result = cudf::concatenate(std::vector({*first, *second, *third, *fourth})); + CUDF_EXPECTS(result->size() == expected->size(), "column size changed after concat"); + cudf::test::expect_columns_equivalent(*result, *expected); +} + TEST_F(StructsColumnTest, ConcatenateSplitStructs) { using namespace cudf::test;